Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/libraries/network/MasterServerComm.cc @ 7765

Last change on this file since 7765 was 7765, checked in by smerkli, 14 years ago

prepared MSC for singleton usage.

File size: 6.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Sandro 'smerkli' Merkli
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "MasterServerComm.h"
30
31namespace orxonox
32{
33  ManageScopedSingleton(MasterServerComm, ScopeID::Root, true);
34 
35  MasterServerComm::MasterServerComm()
36  { /* nothing anymore, everything's been outsourced to
37     * the initialize method to facilitate debugging
38     */
39  } 
40
41  int MasterServerComm::initialize()
42  {
43    /* initialize Enet */
44    if( enet_initialize () != 0 )
45    { COUT(1) << "An error occurred while initializing ENet.\n";
46      return 1;
47    }
48
49    /* initialize the event holder */
50    this->event = (ENetEvent *)calloc( sizeof(ENetEvent), 1 );
51   
52
53    /* initiate the client */
54    this->client = enet_host_create( NULL /* create a client host */,
55        1,
56        2, /* allow up 2 channels to be used, 0 and 1 */
57        0, 
58        0 ); 
59
60    /* see if it worked */
61    if (this->client == NULL)
62    { COUT(1) << "An error occurred while trying to create an " 
63        << "ENet client host.\n";
64      return 1;
65    }
66
67    return 0;
68  }
69
70  MasterServerComm::~MasterServerComm()
71  {
72    /* destroy the enet facilities */
73    enet_host_destroy(this->client);
74  }
75
76  int MasterServerComm::connect( const char *address, unsigned int port )
77  {
78    /* Connect to address:port. */
79    enet_address_set_host( &this->address, address );
80    this->address.port = port;
81
82    /* Initiate the connection, allocating the two channels 0 and 1. */
83    this->peer = enet_host_connect(this->client, &this->address, 2, 0);   
84
85    if( this->peer == NULL )
86    { COUT(2) << "ERROR: No available peers for initiating an ENet"
87        << " connection.\n";
88      return -1;
89    }
90
91    /* Wait up to 2 seconds for the connection attempt to succeed. */
92    if (enet_host_service (this->client, this->event, 2000) > 0 &&
93        this->event->type == ENET_EVENT_TYPE_CONNECT )
94      COUT(3) << "Connection to master server succeeded.\n";
95    else
96    {
97      enet_peer_reset (this->peer);
98      COUT(2) << "ERROR: connection to " << address << " failed.\n";
99      return -1;
100    }
101
102    /* all fine */
103    return 0;
104  }
105
106  int MasterServerComm::disconnect( void )
107  {
108    enet_peer_disconnect( this->peer, 0 );
109
110    /* Allow up to 1 second for the disconnect to succeed
111     * and drop any packets received packets.
112     */
113    while (enet_host_service (this->client, this->event, 1000) > 0)
114    {
115      switch (this->event->type)
116      {
117        case ENET_EVENT_TYPE_RECEIVE:
118          enet_packet_destroy (event->packet);
119          break;
120
121        case ENET_EVENT_TYPE_DISCONNECT:
122          COUT(4) << "Disconnect from master server successful.\n"; 
123          return 0;
124        default: break;
125      }
126    }
127
128    /* We've arrived here, so the disconnect attempt didn't
129     * succeed yet, hence: force the connection down.           
130     */
131    enet_peer_reset( this->peer );
132
133    /* done */
134    return 0;
135  }
136
137  /* NOTE this is to be reimplemented soon to return
138   * a structure containing
139   * - addrconv
140   * - the event
141   * so we can also make callbacks from objects
142   */
143  int MasterServerComm::pollForReply( int (*callback)( char*, ENetEvent* ),
144    int delayms )
145  { 
146    /* see whether anything happened */
147    /* WORK MARK REMOVE THIS OUTPUT */
148    COUT(2) << "polling masterserver...\n";
149
150    /* address buffer */
151    char *addrconv = NULL;
152    int retval = 0;
153
154    /* enet_host_service returns 0 if no event occured */
155    /* just newly set below test to >0 from >= 0, to be tested */
156    if( enet_host_service( this->client, this->event, delayms ) > 0 )
157    { 
158      /* check what type of event it is and react accordingly */
159      switch (this->event->type)
160      { /* new connection, not supposed to happen. */
161        case ENET_EVENT_TYPE_CONNECT: break;
162
163        /* disconnect */
164        case ENET_EVENT_TYPE_DISCONNECT: /* ?? */ break;
165
166        /* incoming data */
167        case ENET_EVENT_TYPE_RECEIVE: 
168          addrconv = (char *) calloc( 50, 1 );
169          if( !addrconv ) 
170          { COUT(2) << "MasterServerComm.cc: Could not allocate memory!\n";
171            break;
172          }
173
174          /* resolve IP */
175          enet_address_get_host_ip( &(this->event->peer->address), 
176            addrconv, 49 );
177
178          /* DEBUG */
179          COUT(3) << "MasterServer Debug: A packet of length " 
180            << this->event->packet->dataLength
181            << " containing " << this->event->packet->data
182            << " was received from " << addrconv
183            << " on channel " << this->event->channelID;
184          /* END DEBUG */
185
186          /* call the supplied callback, if any. */
187          if( (*callback) != NULL )
188            retval = (*callback)( addrconv, (this->event) );
189
190          /* clean up */
191          enet_packet_destroy( event->packet );
192          if( addrconv ) 
193            free( addrconv );
194
195          break;
196        default: break;
197      }
198
199      /* event handled, return 0 */
200      return retval;
201    }
202
203    /* show that no event occured */
204    return 0;
205  }
206
207  int MasterServerComm::sendRequest( const char *data )
208  {
209    /* send the data to the friend */
210    /* Create a reliable packet of size 7 containing "packet\0" */
211    ENetPacket * packet = enet_packet_create( data, 
212        strlen( data ) + 1, 
213        ENET_PACKET_FLAG_RELIABLE);
214
215    /* Send the packet to the peer over channel id 0. */
216    enet_peer_send (this->peer, 0, packet);
217
218    /* One could just use enet_host_service() instead. */
219    enet_host_flush( this->client );
220   
221    /* free the packet */
222    enet_packet_destroy( packet );
223
224    /* all done. */
225    return 0;
226  }
227
228  int MasterServerComm::sendRequest( std::string data )
229  {
230    /* send the data to the friend */
231    /* Create a reliable packet of size 7 containing "packet\0" */
232    ENetPacket * packet = enet_packet_create( data.c_str(), 
233        data.length() + 1, 
234        ENET_PACKET_FLAG_RELIABLE);
235
236    /* Send the packet to the peer over channel id 0. */
237    enet_peer_send (this->peer, 0, packet);
238
239    /* One could just use enet_host_service() instead. */
240    enet_host_flush( this->client );
241    enet_packet_destroy( packet );
242
243    /* all done. */
244    return 0;
245  }
246
247}
Note: See TracBrowser for help on using the repository browser.