Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/network/ClientConnection.cc @ 1494

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