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

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

new cluster implementation added: ENet
ENet is a reliable UDP implementation with quite simple usage and high performance for transmission with small or medium size packet.

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