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

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

memory leak in clusterENet fixed

File size: 10.0 KB
Line 
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
17#include "dataIO_clusterENet_implementation.h"
18
19using namespace osgVisual;
20
21int dataIO_clusterENet_implementation::activeENetInstances = 0;
22
23dataIO_clusterENet_implementation::dataIO_clusterENet_implementation(std::string& receivedTransportContainer_)
24: receivedTransportContainer(receivedTransportContainer_)
25{
26        std::cout << "Instantiated server class# "<< activeENetInstances << std::endl;
27
28        enetInitialized = false;
29        host = NULL;
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
44dataIO_clusterENet_implementation::~dataIO_clusterENet_implementation()
45{
46        // Delete Host Object if instantiated
47        if(host)
48                enet_host_destroy(host);
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
59bool dataIO_clusterENet_implementation::init(dataIO_clusterENet_implementation::role role_, unsigned short port_, int maxClients_, int maxChannels_, int maxInBandwidth_, int maxOutBandwidth_)
60{
61        port = port_;
62        currentRole = role_;
63
64        if(currentRole == dataIO_clusterENet_implementation::SERVER)
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
86        if(currentRole == dataIO_clusterENet_implementation::CLIENT)
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
101        enetInitialized = true;
102        return true;
103}
104
105void dataIO_clusterENet_implementation::processEvents(int timeout_ms_)
106{
107        if(!enetInitialized)
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
141void dataIO_clusterENet_implementation::sendPacket( ENetPacket* packet_, enet_uint8 channelID_, unsigned int peerID_, bool autoFlush_ )
142{
143        // are connected peers available?
144        if( peerList.size() == 0 )
145        {
146                //std::cout << "dataIO_clusterENet_implementation::sendPacket() - ERROR: No connected peer available!" << std::endl;
147               
148                // If we can't send the packet, we have to destroy it to free it's memory (In a case of send ENet takes ownership and frees after sending.).
149                enet_packet_destroy (packet_);
150
151                return;
152        }
153
154        // Client
155        if(currentRole == dataIO_clusterENet_implementation::CLIENT)
156        {
157                enet_peer_send (peerList[0], channelID_, packet_);
158        }
159
160        // Server
161        if(currentRole == dataIO_clusterENet_implementation::SERVER)
162        {
163                if(peerID_ < peerList.size())
164                        enet_peer_send (peerList[peerID_], channelID_, packet_);
165                else
166                        std::cout << "dataIO_clusterENet_implementation::sendPacket() - ERROR: Peer #"<<peerID_<<" is not available, only peers 0-"<<(peerList.size()-1)<<" are connected!" << std::endl;
167        }
168
169        if(autoFlush_)
170                enet_host_flush( host );
171}
172
173void dataIO_clusterENet_implementation::sendPacket( ENetPacket* packet_, enet_uint8 channelID_, std::string peerName_, bool autoFlush_ )
174{
175                // are connected peers available?
176        if( peerList.size() == 0 )
177        {
178                std::cout << "dataIO_clusterENet_implementation::sendPacket() - ERROR: No connected peer available!" << std::endl;
179                return;
180        }
181
182        // Client
183        if(currentRole == dataIO_clusterENet_implementation::CLIENT)
184        {
185                enet_peer_send (peerList[0], channelID_, packet_);
186        }
187
188        // Server
189        if(currentRole == dataIO_clusterENet_implementation::SERVER)
190        {
191                int peerID_=-1;
192                for(unsigned int i=0;i<peerList.size();i++)     // Search peer
193                {
194                        if( *((std::string*)peerList[i]->data) == peerName_ )
195                        {
196                                peerID_ = i;
197                                break;
198                        }
199                }
200                if( peerID_ >= 0 && peerID_ < (int)peerList.size())
201                        enet_peer_send (peerList[peerID_], channelID_, packet_);
202                else
203                        std::cout << "dataIO_clusterENet_implementation::sendPacket() - ERROR: Peer #"<<peerID_<<" is not available, only peers 0-"<<(peerList.size()-1)<<" are connected!" << std::endl;
204        }
205
206        if(autoFlush_)
207                enet_host_flush( host );
208}
209
210void dataIO_clusterENet_implementation::broadcastPacket( enet_uint8 channelID_, ENetPacket* packet_, bool autoFlush_ )
211{
212        if(currentRole != dataIO_clusterENet_implementation::SERVER)
213                return;
214
215        enet_host_broadcast( host, channelID_, packet_ );
216        if(autoFlush_)
217                enet_host_flush( host );
218}
219
220bool dataIO_clusterENet_implementation::connectTo( const char* remoteAddr_, int connectTimeout_ms_, int clientInfo_,  int channelToAlloc_ )
221{
222        if(currentRole != dataIO_clusterENet_implementation::CLIENT)
223        {
224                std::cout << "dataIO_clusterENet_implementation::connectTo() : ERROR: ENet does not work as client - ignoring to connect!" << std::endl;
225                return false;
226        }
227
228        ENetAddress address;
229        enet_address_set_host (& address, remoteAddr_);
230    address.port = port;
231
232       
233        ENetPeer* tmpPeer = enet_host_connect( host, &address, channelToAlloc_, clientInfo_ );    // host, remote address, number of channels, describing data.
234   
235    if (tmpPeer == NULL)
236    {
237                std::cout << "No available peers for initiating an ENet connection." << std::endl;
238       return false;
239    }
240   
241    /* Wait up to 5 seconds for the connection attempt to succeed. */
242    if (enet_host_service (host, & event, connectTimeout_ms_) > 0
243                && event.type == ENET_EVENT_TYPE_CONNECT)
244    {
245                peerList.push_back( tmpPeer );
246                std::cout << "Connection to " << remoteAddr_ << ":"<<port<<" succeeded." << std::endl;
247                // Note down peers remote IP.
248                char *hostIP = new char[20];
249                enet_address_get_host_ip( &address, hostIP, 20 );
250                tmpPeer->data = hostIP;
251
252                return true;
253    }
254    else
255    {
256        /* Either the n seconds are up or a disconnect event was */
257        /* received. Reset the peer in the event the n seconds   */
258        /* had run out without any significant event.            */
259        enet_peer_reset (tmpPeer);
260
261                std::cout << "Connection to " << remoteAddr_ << ":"<<port<<" failed." << std::endl;
262                return false;
263    }
264}
265
266void dataIO_clusterENet_implementation::onReceivePacket(ENetEvent* event_)
267{
268                receivedTransportContainer.assign((char*)(event_->packet->data), event_->packet->dataLength);
269                enet_packet_destroy(event_->packet);   
270                //std::cout << "A packet of length "<<receivedTransportContainer.size()<<" containing "<<receivedTransportContainer<<" was received from "<<receivedTransportContainer<<" on channel "<<(int)(event_->channelID)<<std::endl;
271}
272
273void dataIO_clusterENet_implementation::onConnect(ENetEvent* event_)
274{
275        /* Get connect remote IP */
276        char *hostIP = new char[20];
277        enet_address_get_host_ip(&(event_->peer->address), hostIP, 20);
278
279        /* debug output */
280        std::cout << "A new client connected from "<<hostIP<<"." << std::endl; 
281               
282        /* Store any relevant client information here. */
283        event_->peer ->data = hostIP;   
284
285        /* note peer for duplex usage of the connection */
286        peerList.push_back(event_->peer);       
287}
288
289void dataIO_clusterENet_implementation::onDisconnect(ENetEvent* event_)
290{
291        // remove peer pionter from peerList
292        int foundOn = -1;
293        for(unsigned int i=0;i<peerList.size();i++)
294        {
295                if(peerList[0] == event_->peer)
296                {
297                        peerList.erase(peerList.begin()+i);
298                        break;
299                }
300        }
301
302
303        if(currentRole == dataIO_clusterENet_implementation::SERVER)
304        {
305                std::cout << "Client " << (char*)event_->peer->data << " disconnected." << std::endl;
306        }
307
308        if(currentRole == dataIO_clusterENet_implementation::CLIENT)
309        {
310                std::cout << "Server "<< (char*)event_->peer->data<<"disconnected." << std::endl;
311        }
312
313        // Reset the peer information
314        event_->peer->data = NULL;
315}
Note: See TracBrowser for help on using the repository browser.