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

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

documented the ENet implementation

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