Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/network/MasterServerComm.cc @ 11071

Last change on this file since 11071 was 11071, checked in by landauf, 8 years ago

merged branch cpp11_v3 back to trunk

  • 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#include "WANDiscovery.h"
32
33namespace orxonox
34{
35
36  MasterServerComm::MasterServerComm()
37  { /* nothing anymore, everything's been outsourced to
38     * the initialize method to facilitate debugging
39     */
40    /* register object in orxonox */
41  } 
42
43  int MasterServerComm::initialize()
44  {
45    /* initialize Enet */
46    if( enet_initialize () != 0 )
47    { orxout(internal_error, context::master_server) << "An error occurred while initializing ENet." << endl;
48      return 1;
49    }
50
51    /* initialize the event holder */
52//     this->event = (ENetEvent *)calloc( sizeof(ENetEvent), 1 );
53   
54
55    /* initiate the client */
56    this->client = enet_host_create( nullptr /* create a client host */,
57        1,
58        2, /* allow up 2 channels to be used, 0 and 1 */
59        0, 
60        0 ); 
61
62    /* see if it worked */
63    if (this->client == nullptr)
64    { orxout(internal_error, context::master_server) << "An error occurred while trying to create an " 
65        << "ENet client host." << endl;
66      return 1;
67    }
68
69    return 0;
70  }
71
72  MasterServerComm::~MasterServerComm()
73  {
74    /* destroy the enet facilities */
75    enet_host_destroy(this->client);
76  }
77
78  int MasterServerComm::connect( const char *address, unsigned int port )
79  {
80    /* Connect to address:port. */
81    enet_address_set_host( &this->address, address );
82    this->address.port = port;
83
84    /* Initiate the connection, allocating the two channels 0 and 1. */
85    this->peer = enet_host_connect(this->client, &this->address, 2, 0);   
86
87    if( this->peer == nullptr )
88    { orxout(internal_error, context::master_server) << "No available peers for initiating an ENet"
89        << " connection." << endl;
90      return -1;
91    }
92
93    /* Wait up to 2 seconds for the connection attempt to succeed. */
94    if (enet_host_service (this->client, &this->event, 500) > 0 &&
95        this->event.type == ENET_EVENT_TYPE_CONNECT )
96      orxout(internal_info, context::master_server) << "Connection to master server succeeded." << endl;
97    else
98    {
99      enet_peer_reset (this->peer);
100      orxout(internal_warning, context::master_server) << "Connection to " << address << " failed." << endl;
101      return -1;
102    }
103
104    /* all fine */
105    return 0;
106  }
107 
108void MasterServerComm::update()
109{
110  while( enet_host_service( this->client, &this->event, 1 ) );
111}
112
113
114  int MasterServerComm::disconnect( void )
115  {
116    while( enet_host_service( this->client, &this->event, 1 ) );
117    enet_peer_disconnect( this->peer, 0 );
118
119    /* Allow up to 1 second for the disconnect to succeed
120     * and drop any packets received packets.
121     */
122    while (enet_host_service (this->client, &this->event, 1000) > 0)
123    {
124      switch (this->event.type)
125      {
126        case ENET_EVENT_TYPE_RECEIVE:
127          enet_packet_destroy (event.packet);
128          break;
129
130        case ENET_EVENT_TYPE_DISCONNECT:
131          orxout(verbose, context::master_server) << "Disconnect from master server successful." << endl; 
132          return 0;
133        default: break;
134      }
135    }
136
137    /* We've arrived here, so the disconnect attempt didn't
138     * succeed yet, hence: force the connection down.           
139     */
140    enet_peer_reset( this->peer );
141
142    /* done */
143    return 0;
144  }
145
146  /* NOTE this is to be reimplemented soon to return
147   * a structure containing
148   * - addrconv
149   * - the event
150   * so we can also make callbacks from objects
151   */
152  int MasterServerComm::pollForReply( WANDiscovery* listener, 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 = nullptr;
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( listener != nullptr )
196            retval = listener->rhandler( 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.