Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/network/ClientConnection.cc @ 1638

Last change on this file since 1638 was 1638, checked in by rgrieder, 16 years ago

merged input branch into gui test branch (was about time)
svn save (it's still a mess and CMLs haven't been updated)
I'll have to create a special project to create the tolua_bind files for tolua itself anyway..

  • Property svn:eol-style set to native
File size: 7.5 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 *      Oliver Scheuss, (C) 2007
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29//
30// C++ Interface: ClientConnection
31//
32// Description: The Class ClientConnection manages the servers conenctions to the clients.
33// each connection is provided by a new process. communication between master process and
34// connection processes is provided by ...
35//
36//
37// Author:  Oliver Scheuss
38//
39
40#include "ClientConnection.h"
41
42#include <iostream>
43// boost.thread library for multithreading support
44#include <boost/thread/thread.hpp>
45#include <boost/bind.hpp>
46
47#include "util/Sleep.h"
48#include "core/Debug.h"
49
50namespace network
51{
52  //static boost::thread_group network_threads;
53
54  boost::recursive_mutex ClientConnection::enet_mutex_;
55
56  ClientConnection::ClientConnection(int port, std::string address) {
57    quit=false;
58    server=NULL;
59    enet_address_set_host(&serverAddress, address.c_str());
60    serverAddress.port = port;
61    established=false;
62  }
63
64  ClientConnection::ClientConnection(int port, const char *address) {
65    quit=false;
66    server=NULL;
67    enet_address_set_host(&serverAddress, address);
68    serverAddress.port = port;
69    established=false;
70  }
71
72  bool ClientConnection::waitEstablished(int milisec) {
73    for(int i=0; i<=milisec && !established; i++)
74      usleep(1000);
75
76    return established;
77  }
78
79
80  /*ENetPacket *ClientConnection::getPacket(ENetAddress &address) {
81    if(!buffer.isEmpty()) {
82      //std::cout << "###BUFFER IS NOT EMPTY###" << std::endl;
83      return buffer.pop(address);
84    }
85    else{
86      return NULL;
87    }
88  }
89
90  ENetPacket *ClientConnection::getPacket() {
91    ENetAddress address; //sems that address is not needed
92    return getPacket(address);
93  }*/
94 
95  ENetEvent *ClientConnection::getEvent(){
96    if(!buffer.isEmpty())
97      return buffer.pop();
98    else
99      return NULL;
100  }
101
102  bool ClientConnection::queueEmpty() {
103    return buffer.isEmpty();
104  }
105
106  bool ClientConnection::createConnection() {
107    receiverThread_ = new boost::thread(boost::bind(&ClientConnection::receiverThread, this));
108    //network_threads.create_thread(boost::bind(boost::mem_fn(&ClientConnection::receiverThread), this));
109    // wait 10 seconds for the connection to be established
110    return waitEstablished(NETWORK_CLIENT_CONNECT_TIMEOUT);
111  }
112
113  bool ClientConnection::closeConnection() {
114    quit=true;
115    //network_threads.join_all();
116    receiverThread_->join();
117    established=false;
118    return true;
119  }
120
121
122  bool ClientConnection::addPacket(ENetPacket *packet) {
123    if(server==NULL)
124      return false;
125    if(packet==NULL){
126      COUT(3) << "Cl.con: addpacket: invalid packet" << std::endl;
127      return false;
128    }
129    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
130    if(enet_peer_send(server, 0, packet)<0)
131      return false;
132    else
133      return true;
134  }
135
136  bool ClientConnection::sendPackets() {
137    if(server==NULL)
138      return false;
139    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
140    enet_host_flush(client);
141    lock.unlock();
142    return true;
143  }
144
145  void ClientConnection::receiverThread() {
146    // what about some error-handling here ?
147    atexit(enet_deinitialize);
148    ENetEvent *event;
149    {
150      boost::recursive_mutex::scoped_lock lock(enet_mutex_);
151      enet_initialize();
152      client = enet_host_create(NULL, NETWORK_CLIENT_MAX_CONNECTIONS, 0, 0);
153      lock.unlock();
154    }
155    if(client==NULL) {
156      COUT(2) << "ClientConnection: could not create client host" << std::endl;
157      // add some error handling here ==========================
158      quit=true;
159    }
160    //connect to the server
161    if(!establishConnection()){
162      COUT(2) << "clientConn: receiver thread: could not establishConnection" << std::endl;
163      quit=true;
164      return;
165    }
166    event = new ENetEvent;
167    //main loop
168    while(!quit){
169      //std::cout << "connection loop" << std::endl;
170      {
171        boost::recursive_mutex::scoped_lock lock(enet_mutex_);
172        if(enet_host_service(client, event, NETWORK_CLIENT_WAIT_TIME)<0){
173          // we should never reach this point
174          quit=true;
175          continue;
176          // add some error handling here ========================
177        }
178        lock.unlock();
179      }
180      switch(event->type){
181        // log handling ================
182      case ENET_EVENT_TYPE_CONNECT:
183        break;
184      case ENET_EVENT_TYPE_RECEIVE:
185        COUT(5) << "Cl.Con: receiver-Thread while loop: got new packet" << std::endl;
186        if ( !processData(event) ) COUT(2) << "Current packet was not pushed to packetBuffer -> ev ongoing SegFault" << std::endl;
187        COUT(5) << "Cl.Con: processed Data in receiver-thread while loop" << std::endl;
188        event = new ENetEvent;
189        break;
190      case ENET_EVENT_TYPE_DISCONNECT:
191        quit=true;
192        // server closed the connection
193        return;
194        break;
195      case ENET_EVENT_TYPE_NONE:
196        //receiverThread_->yield();
197        usleep(1000);
198        break;
199      }
200    }
201    // now disconnect
202
203    if(!disconnectConnection())
204      // if disconnecting failed destroy conn.
205      boost::recursive_mutex::scoped_lock lock(enet_mutex_);
206      enet_peer_reset(server);
207    return;
208  }
209
210  bool ClientConnection::disconnectConnection() {
211    ENetEvent event;
212    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
213    enet_peer_disconnect(server, 0);
214    while(enet_host_service(client, &event, NETWORK_CLIENT_WAIT_TIME) > 0){
215      switch (event.type)
216      {
217      case ENET_EVENT_TYPE_NONE:
218      case ENET_EVENT_TYPE_CONNECT:
219      case ENET_EVENT_TYPE_RECEIVE:
220        enet_packet_destroy(event.packet);
221        break;
222      case ENET_EVENT_TYPE_DISCONNECT:
223        return true;
224      }
225    }
226    enet_peer_reset(server);
227    return false;
228  }
229
230  bool ClientConnection::establishConnection() {
231    ENetEvent event;
232    // connect to peer (server is type ENetPeer*)
233    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
234    server = enet_host_connect(client, &serverAddress, NETWORK_CLIENT_CHANNELS);
235    if(server==NULL) {
236      COUT(2) << "ClientConnection: server == NULL" << std::endl;
237      // error handling
238      return false;
239    }
240    // handshake
241    while(enet_host_service(client, &event, NETWORK_CLIENT_WAIT_TIME)>=0 && !quit){
242      if( event.type == ENET_EVENT_TYPE_CONNECT ){
243        established=true;
244        return true;
245      }
246    }
247    COUT(2) << "ClientConnection: enet_host_service < 0 or event.type != ENET_EVENT_TYPE_CONNECT # EVENT:" << event.type << std::endl;
248    return false;
249  }
250
251  bool ClientConnection::processData(ENetEvent *event) {
252    COUT(5) << "Cl.Con: got packet, pushing to queue" << std::endl;
253    // just add packet to the buffer
254    // this can be extended with some preprocessing
255    return buffer.push(event);
256  }
257
258}
Note: See TracBrowser for help on using the repository browser.