source: osgVisual/src/cluster/dataIO_clusterENet_implementation.cpp @ 94

Last change on this file since 94 was 88, checked in by Torben Dannhauer, 14 years ago

Moved memory leak detection from source file to headerfile. Its still in the class but at least not in the source file.

The leak detection works, but the false positives are not stopped.
Use Linux/Valgrind? to make your final leak detection beyond the easy first approach in MSVC

File size: 9.9 KB
RevLine 
[68]1/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
2 *
3 * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
9 * You have to aquire licenses for all used proprietary modules.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * OpenSceneGraph Public License for more details.
15*/
16
[65]17#include "dataIO_clusterENet_implementation.h"
18
[66]19using namespace osgVisual;
[65]20
[66]21int dataIO_clusterENet_implementation::activeENetInstances = 0;
22
[69]23dataIO_clusterENet_implementation::dataIO_clusterENet_implementation(std::string& receivedTransportContainer_)
24: receivedTransportContainer(receivedTransportContainer_)
[65]25{
26        std::cout << "Instantiated server class# "<< activeENetInstances << std::endl;
[88]27
[77]28        enetInitialized = false;
[67]29        host = NULL;
[65]30        // Start ENet
31        if (activeENetInstances++ == 0)
32        {
33                if( enet_initialize() != 0)
34                {
35                        std::cout <<  "An error occurred while initializing ENet." << std::endl;
36                }
37                else
38                {
39                        std::cout << "Starting ENet subsystem successful" << std::endl;
40                }
41        }
42}
43
[66]44dataIO_clusterENet_implementation::~dataIO_clusterENet_implementation()
[65]45{
[67]46        // Delete Host Object if instantiated
47        if(host)
48                enet_host_destroy(host);
[65]49
50        // Stop ENet if it is the last element.
51        if(--activeENetInstances == 0)
52        {
53                std::cout << "Close ENet subsystem" << std::endl;
54                enet_deinitialize();
55        }
56        std::cout << "Destroyed server class# "<< activeENetInstances << std::endl;
57}
58
[66]59bool dataIO_clusterENet_implementation::init(dataIO_clusterENet_implementation::role role_, unsigned short port_, int maxClients_, int maxChannels_, int maxInBandwidth_, int maxOutBandwidth_)
[65]60{
61        port = port_;
62        currentRole = role_;
63
[66]64        if(currentRole == dataIO_clusterENet_implementation::SERVER)
[65]65        {
66                /* Bind the server to the default localhost.     */
67                /* A specific host address can be specified by   */
68                /* enet_address_set_host (& address, "x.x.x.x"); */
69
70                address.host = ENET_HOST_ANY;
71                /* Bind the server to port. */
72                address.port = port;
73
74                host = enet_host_create (& address /* the address to bind the server host to */, 
75                                                                         maxClients_      /* allow up to 32 clients and/or outgoing connections */,
76                                                                         maxChannels_      /* allow up to 2 channels to be used, 0 and 1 */,
77                                                                         maxInBandwidth_      /* assume any amount of incoming bandwidth */,
78                                                                         maxOutBandwidth_      /* assume any amount of outgoing bandwidth */);
79                if (host == NULL)
80                {
81                        std::cout <<  "An error occurred while trying to create an ENet server." << std::endl;
82                        return false;
83                }
84        }       // IF SERVER END
85
[66]86        if(currentRole == dataIO_clusterENet_implementation::CLIENT)
[65]87        {
88                 host = enet_host_create (NULL /* create a client host */,
89                                                                         maxClients_      /* allow up to 32 clients and/or outgoing connections */,
90                                                                         maxChannels_      /* allow up to 2 channels to be used, 0 and 1 */,
91                                                                         maxInBandwidth_      /* assume any amount of incoming bandwidth */,
92                                                                         maxOutBandwidth_      /* assume any amount of outgoing bandwidth */);
93                 if (host == NULL)
94                {
95                        std::cout <<  "An error occurred while trying to create an ENet client." << std::endl;
96                        return false;
97                }
98
99        }       // IF CLIENT END
100
[77]101        enetInitialized = true;
[65]102        return true;
103}
104
[66]105void dataIO_clusterENet_implementation::processEvents(int timeout_ms_)
[65]106{
[77]107        if(!enetInitialized)
[65]108                return;
109
110        ENetEvent event;
111        while(enet_host_service (host, & event, timeout_ms_) > 0)
112        {
113                switch (event.type)
114                {
115                        case ENET_EVENT_TYPE_CONNECT:
116                                onConnect(&event);
117                                break;
118
119                        case ENET_EVENT_TYPE_RECEIVE:
120                                onReceivePacket(&event);
121                       
122                                /* Clean up the packet now that we're done using it. */
123                                enet_packet_destroy (event.packet);
124                                break;
125
126                        case ENET_EVENT_TYPE_DISCONNECT:
127                                onDisconnect(&event);
128                                break;
129                       
130                        case ENET_EVENT_TYPE_NONE:
131                                // nothing to do
132                                break;
133
134                        default: 
135                                std::cout << "Unknown Eventtype" << std::endl;
136                }       // SWITCH CASE END
137        }       // WHILE EVENT END
138
139}
140
[66]141void dataIO_clusterENet_implementation::sendPacket( ENetPacket* packet_, enet_uint8 channelID_, unsigned int peerID_, bool autoFlush_ )
[65]142{
143        // are connected peers available?
144        if( peerList.size() == 0 )
145        {
[69]146                //std::cout << "dataIO_clusterENet_implementation::sendPacket() - ERROR: No connected peer available!" << std::endl;
[65]147                return;
148        }
149
150        // Client
[66]151        if(currentRole == dataIO_clusterENet_implementation::CLIENT)
[65]152        {
153                enet_peer_send (peerList[0], channelID_, packet_);
154        }
155
156        // Server
[66]157        if(currentRole == dataIO_clusterENet_implementation::SERVER)
[65]158        {
159                if(peerID_ < peerList.size())
160                        enet_peer_send (peerList[peerID_], channelID_, packet_);
161                else
[66]162                        std::cout << "dataIO_clusterENet_implementation::sendPacket() - ERROR: Peer #"<<peerID_<<" is not available, only peers 0-"<<(peerList.size()-1)<<" are connected!" << std::endl;
[65]163        }
164
165        if(autoFlush_)
166                enet_host_flush( host );
167}
168
[66]169void dataIO_clusterENet_implementation::sendPacket( ENetPacket* packet_, enet_uint8 channelID_, std::string peerName_, bool autoFlush_ )
[65]170{
171                // are connected peers available?
172        if( peerList.size() == 0 )
173        {
[66]174                std::cout << "dataIO_clusterENet_implementation::sendPacket() - ERROR: No connected peer available!" << std::endl;
[65]175                return;
176        }
177
178        // Client
[66]179        if(currentRole == dataIO_clusterENet_implementation::CLIENT)
[65]180        {
181                enet_peer_send (peerList[0], channelID_, packet_);
182        }
183
184        // Server
[66]185        if(currentRole == dataIO_clusterENet_implementation::SERVER)
[65]186        {
187                int peerID_=-1;
188                for(unsigned int i=0;i<peerList.size();i++)     // Search peer
189                {
190                        if( *((std::string*)peerList[i]->data) == peerName_ )
191                        {
192                                peerID_ = i;
193                                break;
194                        }
195                }
196                if( peerID_ >= 0 && peerID_ < (int)peerList.size())
197                        enet_peer_send (peerList[peerID_], channelID_, packet_);
198                else
[66]199                        std::cout << "dataIO_clusterENet_implementation::sendPacket() - ERROR: Peer #"<<peerID_<<" is not available, only peers 0-"<<(peerList.size()-1)<<" are connected!" << std::endl;
[65]200        }
201
202        if(autoFlush_)
203                enet_host_flush( host );
204}
205
[66]206void dataIO_clusterENet_implementation::broadcastPacket( enet_uint8 channelID_, ENetPacket* packet_, bool autoFlush_ )
[65]207{
[66]208        if(currentRole != dataIO_clusterENet_implementation::SERVER)
[65]209                return;
210
211        enet_host_broadcast( host, channelID_, packet_ );
212        if(autoFlush_)
213                enet_host_flush( host );
214}
215
[66]216bool dataIO_clusterENet_implementation::connectTo( const char* remoteAddr_, int connectTimeout_ms_, int clientInfo_,  int channelToAlloc_ )
[65]217{
[66]218        if(currentRole != dataIO_clusterENet_implementation::CLIENT)
[69]219        {
220                std::cout << "dataIO_clusterENet_implementation::connectTo() : ERROR: ENet does not work as client - ignoring to connect!" << std::endl;
[65]221                return false;
[69]222        }
[65]223
224        ENetAddress address;
225        enet_address_set_host (& address, remoteAddr_);
226    address.port = port;
227
228       
229        ENetPeer* tmpPeer = enet_host_connect( host, &address, channelToAlloc_, clientInfo_ );    // host, remote address, number of channels, describing data.
230   
231    if (tmpPeer == NULL)
232    {
233                std::cout << "No available peers for initiating an ENet connection." << std::endl;
234       return false;
235    }
236   
237    /* Wait up to 5 seconds for the connection attempt to succeed. */
238    if (enet_host_service (host, & event, connectTimeout_ms_) > 0
239                && event.type == ENET_EVENT_TYPE_CONNECT)
240    {
241                peerList.push_back( tmpPeer );
242                std::cout << "Connection to " << remoteAddr_ << ":"<<port<<" succeeded." << std::endl;
243                // Note down peers remote IP.
244                char *hostIP = new char[20];
245                enet_address_get_host_ip( &address, hostIP, 20 );
246                tmpPeer->data = hostIP;
247
248                return true;
249    }
250    else
251    {
252        /* Either the n seconds are up or a disconnect event was */
253        /* received. Reset the peer in the event the n seconds   */
254        /* had run out without any significant event.            */
255        enet_peer_reset (tmpPeer);
256
257                std::cout << "Connection to " << remoteAddr_ << ":"<<port<<" failed." << std::endl;
258                return false;
259    }
260}
261
[66]262void dataIO_clusterENet_implementation::onReceivePacket(ENetEvent* event_)
[65]263{
[69]264                receivedTransportContainer.assign((char*)(event_->packet->data), event_->packet->dataLength);   
265                //std::cout << "A packet of length "<<event_->packet->dataLength<<" containing "<<receivedTransportContainer<<" was received from "<<receivedTransportContainer<<" on channel "<<(int)(event_->channelID)<<std::endl;
[65]266}
267
[66]268void dataIO_clusterENet_implementation::onConnect(ENetEvent* event_)
[65]269{
270        /* Get connect remote IP */
271        char *hostIP = new char[20];
272        enet_address_get_host_ip(&(event_->peer->address), hostIP, 20);
273
274        /* debug output */
275        std::cout << "A new client connected from "<<hostIP<<"." << std::endl; 
276               
277        /* Store any relevant client information here. */
278        event_->peer ->data = hostIP;   
279
280        /* note peer for duplex usage of the connection */
281        peerList.push_back(event_->peer);       
282}
283
[66]284void dataIO_clusterENet_implementation::onDisconnect(ENetEvent* event_)
[65]285{
286        // remove peer pionter from peerList
287        int foundOn = -1;
288        for(unsigned int i=0;i<peerList.size();i++)
289        {
290                if(peerList[0] == event_->peer)
291                {
292                        peerList.erase(peerList.begin()+i);
293                        break;
294                }
295        }
296
297
[66]298        if(currentRole == dataIO_clusterENet_implementation::SERVER)
[65]299        {
300                std::cout << "Client " << (char*)event_->peer->data << " disconnected." << std::endl;
301
302                /* Reset the peer's client information. */
303                delete event_->peer->data;
304                event_->peer->data = NULL;
305        }
306
[66]307        if(currentRole == dataIO_clusterENet_implementation::CLIENT)
[65]308        {
309                std::cout << "Server "<< (char*)event_->peer->data<<"disconnected." << std::endl;
310
311                // Reset the server information
312                delete event_->peer->data;
313                event_->peer->data = NULL;
314        }
315}
Note: See TracBrowser for help on using the repository browser.