Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/output/src/libraries/network/MasterServerComm.cc @ 8808

Last change on this file since 8808 was 8807, checked in by landauf, 13 years ago

Replaced COUT with orxout in network library. Tried to set levels and contexts in a more or less useful way, but not really optimized. Used contexts network, packets, and master_server.
Please use endl instead of \n in the future (@smerkli) ;)

  • Property svn:eol-style set to native
File size: 7.6 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#include "util/Output.h"
31
32namespace orxonox
33{
34
35  MasterServerComm::MasterServerComm()
36  { /* nothing anymore, everything's been outsourced to
37     * the initialize method to facilitate debugging
38     */
39    /* register object in orxonox */
40  } 
41
42  int MasterServerComm::initialize()
43  {
44    /* initialize Enet */
45    if( enet_initialize () != 0 )
46    { orxout(internal_error, context::master_server) << "An error occurred while initializing ENet." << endl;
47      return 1;
48    }
49
50    /* initialize the event holder */
51//     this->event = (ENetEvent *)calloc( sizeof(ENetEvent), 1 );
52   
53
54    /* initiate the client */
55    this->client = enet_host_create( NULL /* create a client host */,
56        1,
57        2, /* allow up 2 channels to be used, 0 and 1 */
58        0, 
59        0 ); 
60
61    /* see if it worked */
62    if (this->client == NULL)
63    { orxout(internal_error, context::master_server) << "An error occurred while trying to create an " 
64        << "ENet client host." << endl;
65      return 1;
66    }
67
68    return 0;
69  }
70
71  MasterServerComm::~MasterServerComm()
72  {
73    /* destroy the enet facilities */
74    enet_host_destroy(this->client);
75  }
76
77  int MasterServerComm::connect( const char *address, unsigned int port )
78  {
79    /* Connect to address:port. */
80    enet_address_set_host( &this->address, address );
81    this->address.port = port;
82
83    /* Initiate the connection, allocating the two channels 0 and 1. */
84    this->peer = enet_host_connect(this->client, &this->address, 2, 0);   
85
86    if( this->peer == NULL )
87    { orxout(internal_error, context::master_server) << "No available peers for initiating an ENet"
88        << " connection." << endl;
89      return -1;
90    }
91
92    /* Wait up to 2 seconds for the connection attempt to succeed. */
93    if (enet_host_service (this->client, &this->event, 500) > 0 &&
94        this->event.type == ENET_EVENT_TYPE_CONNECT )
95      orxout(internal_info, context::master_server) << "Connection to master server succeeded." << endl;
96    else
97    {
98      enet_peer_reset (this->peer);
99      orxout(internal_warning, context::master_server) << "Connection to " << address << " failed." << endl;
100      return -1;
101    }
102
103    /* all fine */
104    return 0;
105  }
106 
107void MasterServerComm::update()
108{
109  while( enet_host_service( this->client, &this->event, 1 ) );
110}
111
112
113  int MasterServerComm::disconnect( void )
114  {
115    while( enet_host_service( this->client, &this->event, 1 ) );
116    enet_peer_disconnect( this->peer, 0 );
117
118    /* Allow up to 1 second for the disconnect to succeed
119     * and drop any packets received packets.
120     */
121    while (enet_host_service (this->client, &this->event, 1000) > 0)
122    {
123      switch (this->event.type)
124      {
125        case ENET_EVENT_TYPE_RECEIVE:
126          enet_packet_destroy (event.packet);
127          break;
128
129        case ENET_EVENT_TYPE_DISCONNECT:
130          orxout(verbose, context::master_server) << "Disconnect from master server successful." << endl; 
131          return 0;
132        default: break;
133      }
134    }
135
136    /* We've arrived here, so the disconnect attempt didn't
137     * succeed yet, hence: force the connection down.           
138     */
139    enet_peer_reset( this->peer );
140
141    /* done */
142    return 0;
143  }
144
145  /* NOTE this is to be reimplemented soon to return
146   * a structure containing
147   * - addrconv
148   * - the event
149   * so we can also make callbacks from objects
150   */
151  int MasterServerComm::pollForReply( int (*callback)( char*, ENetEvent* ),
152    int delayms )
153  { 
154    /* see whether anything happened */
155    /* WORK MARK REMOVE THIS OUTPUT */
156    orxout(verbose, context::master_server) << "polling masterserver..." << endl;
157
158    /* address buffer */
159    char *addrconv = NULL;
160    int retval = 0;
161
162    /* enet_host_service returns 0 if no event occured */
163    /* just newly set below test to >0 from >= 0, to be tested */
164    if( enet_host_service( this->client, &this->event, delayms ) > 0 )
165    { 
166      /* check what type of event it is and react accordingly */
167      switch (this->event.type)
168      { /* new connection, not supposed to happen. */
169        case ENET_EVENT_TYPE_CONNECT: break;
170
171        /* disconnect */
172        case ENET_EVENT_TYPE_DISCONNECT: /* ?? */ break;
173
174        /* incoming data */
175        case ENET_EVENT_TYPE_RECEIVE: 
176          addrconv = (char *) calloc( 50, 1 );
177          if( !addrconv ) 
178          { orxout(internal_warning, context::master_server) << "MasterServerComm.cc: Could not allocate memory!" << endl;
179            break;
180          }
181
182          /* resolve IP */
183          enet_address_get_host_ip( &(this->event.peer->address), 
184            addrconv, 49 );
185
186          /* DEBUG */
187          orxout(verbose, context::master_server) << "MasterServer Debug: A packet of length " 
188            << this->event.packet->dataLength
189            << " containing " << this->event.packet->data
190            << " was received from " << addrconv
191            << " on channel " << this->event.channelID;
192          /* END DEBUG */
193
194          /* call the supplied callback, if any. */
195          if( (*callback) != NULL )
196            retval = (*callback)( addrconv, &(this->event) );
197
198          /* clean up */
199          enet_packet_destroy( event.packet );
200          if( addrconv ) 
201            free( addrconv );
202
203          break;
204        default: break;
205      }
206
207      /* event handled, return 0 */
208      return retval;
209    }
210
211    /* show that no event occured */
212    return 0;
213  }
214
215  int MasterServerComm::sendRequest( const char *data )
216  {
217    /* send the data to the friend */
218    /* Create a reliable packet of size 7 containing "packet\0" */
219    ENetPacket * packet = enet_packet_create( data, 
220        strlen( data ) + 1, 
221        ENET_PACKET_FLAG_RELIABLE);
222
223    /* Send the packet to the peer over channel id 0. */
224    enet_peer_send (this->peer, 0, packet);
225
226    /* One could just use enet_host_service() instead. */
227    enet_host_flush( this->client );
228   
229    /* free the packet */
230    // PLEASE: never do this, because enet will free the packet once it's delivered. this will cause double frees
231//     enet_packet_destroy( packet );
232
233    /* all done. */
234    return 0;
235  }
236
237  int MasterServerComm::sendRequest( std::string data )
238  {
239    /* send the data to the friend */
240    /* Create a reliable packet of size 7 containing "packet\0" */
241    ENetPacket * packet = enet_packet_create( data.c_str(), 
242        data.length() + 1, 
243        ENET_PACKET_FLAG_RELIABLE);
244
245    /* Send the packet to the peer over channel id 0. */
246    enet_peer_send (this->peer, 0, packet);
247
248    /* One could just use enet_host_service() instead. */
249    enet_host_flush( this->client );
250    // PLEASE: never do this, because enet will free the packet once it's delivered. this will cause double frees
251//     enet_packet_destroy( packet );
252
253    /* all done. */
254    return 0;
255  }
256
257}
Note: See TracBrowser for help on using the repository browser.