Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/masterserver2/src/libraries/network/MasterServerComm.cc @ 8344

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

ms-delserver command implemented to kick servers from the master server list

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