Changeset 1502 for code/trunk/src/network/ConnectionManager.cc
- Timestamp:
- Jun 1, 2008, 3:54:20 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk/src/network/ConnectionManager.cc
r1360 r1502 44 44 #include "core/CoreIncludes.h" 45 45 #include "core/BaseObject.h" 46 #include "objects/SpaceShip.h" 46 47 #include "util/Math.h" 47 #include " objects/SpaceShip.h"48 #include "util/Sleep.h" 48 49 #include "ClientInformation.h" 49 50 #include "ConnectionManager.h" … … 65 66 66 67 ConnectionManager::ConnectionManager():receiverThread_(0){} 68 boost::recursive_mutex ConnectionManager::enet_mutex_; 67 69 68 70 ConnectionManager::ConnectionManager(ClientInformation *head) : receiverThread_(0) { … … 72 74 head_ = head; 73 75 } 76 77 ConnectionManager::ConnectionManager(ClientInformation *head, int port){ 78 quit=false; 79 bindAddress.host = ENET_HOST_ANY; 80 bindAddress.port = port; 81 head_ = head; 82 } 74 83 75 84 ConnectionManager::ConnectionManager(int port, std::string address, ClientInformation *head) :receiverThread_(0) { … … 87 96 } 88 97 89 ENetPacket *ConnectionManager::getPacket(ENetAddress &address) {98 /*ENetPacket *ConnectionManager::getPacket(ENetAddress &address) { 90 99 if(!buffer.isEmpty()) 91 100 return buffer.pop(address); 92 101 else 93 102 return NULL; 94 } 103 }*/ 95 104 /** 96 105 This function only pops the first element in PacketBuffer (first in first out) 97 106 used by processQueue in Server.cc 98 107 */ 99 ENetPacket *ConnectionManager::getPacket(int &clientID) {108 /*ENetPacket *ConnectionManager::getPacket(int &clientID) { 100 109 ENetAddress address; 101 110 ENetPacket *packet=getPacket(address); … … 105 114 clientID=temp->getID(); 106 115 return packet; 116 }*/ 117 118 ENetEvent *ConnectionManager::getEvent(){ 119 if(!buffer.isEmpty()) 120 return buffer.pop(); 121 else 122 return NULL; 107 123 } 108 124 … … 129 145 if(!temp) 130 146 return false; 147 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 131 148 if(enet_peer_send(peer, (enet_uint8)temp->getID() , packet)!=0) 132 149 return false; … … 136 153 bool ConnectionManager::addPacket(ENetPacket *packet, int clientID) { 137 154 ClientInformation *temp = head_->findClient(clientID); 138 if(!temp) 139 return false; 140 if(enet_peer_send(temp->getPeer(), (enet_uint8)clientID, packet)!=0) 141 return false; 155 if(!temp){ 156 COUT(3) << "C.Man: addPacket findClient failed" << std::endl; 157 return false; 158 } 159 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 160 if(enet_peer_send(temp->getPeer(), 0, packet)!=0){ 161 COUT(3) << "C.Man: addPacket enet_peer_send failed" << std::endl; 162 return false; 163 } 142 164 return true; 143 165 } 144 166 145 167 bool ConnectionManager::addPacketAll(ENetPacket *packet) { 168 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 146 169 for(ClientInformation *i=head_->next(); i!=0; i=i->next()){ 147 170 if(enet_peer_send(i->getPeer(), (enet_uint8)i->getID(), packet)!=0) … … 151 174 } 152 175 153 bool ConnectionManager::sendPackets(ENetEvent *event) { 176 // we actually dont need that function, because host_service does that for us 177 bool ConnectionManager::sendPackets() { 154 178 if(server==NULL) 155 179 return false; 156 if(enet_host_service(server, event, NETWORK_SEND_WAIT)>=0) 157 return true; 158 else 159 return false; 160 } 161 162 bool ConnectionManager::sendPackets() { 163 ENetEvent event; 164 if(server==NULL) 165 return false; 166 if(enet_host_service(server, &event, NETWORK_SEND_WAIT)>=0) 167 return true; 168 else 169 return false; 180 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 181 enet_host_flush(server); 182 lock.unlock(); 183 return true; 170 184 } 171 185 172 186 void ConnectionManager::receiverThread() { 173 187 // what about some error-handling here ? 174 enet_initialize();188 ENetEvent *event; 175 189 atexit(enet_deinitialize); 176 ENetEvent *event = new ENetEvent; 177 server = enet_host_create(&bindAddress, NETWORK_MAX_CONNECTIONS, 0, 0); 190 { //scope of the mutex 191 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 192 enet_initialize(); 193 server = enet_host_create(&bindAddress, NETWORK_MAX_CONNECTIONS, 0, 0); 194 lock.unlock(); 195 } 178 196 if(server==NULL){ 179 197 // add some error handling here ========================== … … 182 200 } 183 201 202 event = new ENetEvent; 184 203 while(!quit){ 185 if(enet_host_service(server, event, NETWORK_WAIT_TIMEOUT)<0){ 186 // we should never reach this point 187 quit=true; 188 // add some error handling here ======================== 204 { //mutex scope 205 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 206 if(enet_host_service(server, event, NETWORK_WAIT_TIMEOUT)<0){ 207 // we should never reach this point 208 quit=true; 209 continue; 210 // add some error handling here ======================== 211 } 212 lock.unlock(); 189 213 } 190 214 switch(event->type){ 191 215 // log handling ================ 192 216 case ENET_EVENT_TYPE_CONNECT: 193 addClient(event); 217 COUT(3) << "adding event_type_connect to queue" << std::endl; 218 case ENET_EVENT_TYPE_DISCONNECT: 219 //addClient(event); 194 220 //this is a workaround to ensure thread safety 195 COUT(5) << "Con.Man: connection event has occured" << std::endl;196 break;221 //COUT(5) << "Con.Man: connection event has occured" << std::endl; 222 //break; 197 223 case ENET_EVENT_TYPE_RECEIVE: 198 224 //std::cout << "received data" << std::endl; 199 225 COUT(5) << "Con.Man: receive event has occured" << std::endl; 200 226 // only add, if client has connected yet and not been disconnected 201 if(head_->findClient(&event->peer->address))227 //if(head_->findClient(&event->peer->address)) 202 228 processData(event); 203 else 204 COUT(3) << "received a packet from a client we don't know" << std::endl; 229 event = new ENetEvent; 230 // else 231 // COUT(3) << "received a packet from a client we don't know" << std::endl; 205 232 break; 206 case ENET_EVENT_TYPE_DISCONNECT: 207 clientDisconnect(event->peer); 233 //case ENET_EVENT_TYPE_DISCONNECT: 234 //clientDisconnect(event->peer); 235 //break; 236 case ENET_EVENT_TYPE_NONE: 237 //receiverThread_->yield(); 238 usleep(1000); 208 239 break; 209 case ENET_EVENT_TYPE_NONE:210 receiverThread_->yield();211 break;212 240 } 213 241 // usleep(100); 214 receiverThread_->yield(); //TODO: find apropriate242 //receiverThread_->yield(); //TODO: find apropriate 215 243 } 216 244 disconnectClients(); 217 245 // if we're finishied, destroy server 218 enet_host_destroy(server); 246 { 247 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 248 enet_host_destroy(server); 249 lock.unlock(); 250 } 219 251 } 220 252 … … 226 258 ClientInformation *temp = head_->next(); 227 259 while(temp!=0){ 228 enet_peer_disconnect(temp->getPeer(), 0); 260 { 261 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 262 enet_peer_disconnect(temp->getPeer(), 0); 263 lock.unlock(); 264 } 229 265 temp = temp->next(); 230 266 } 231 267 //bugfix: might be the reason why server crashes when clients disconnects 232 //temp = temp->next();233 268 temp = head_->next(); 234 while( temp!=0 && enet_host_service(server, &event, NETWORK_WAIT_TIMEOUT) > 0){ 269 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 270 while( temp!=0 && enet_host_service(server, &event, NETWORK_WAIT_TIMEOUT) >= 0){ 235 271 switch (event.type) 236 272 { … … 258 294 } 259 295 260 bool ConnectionManager::clientDisconnect(ENetPeer *peer) { 261 COUT(4) << "removing client from list" << std::endl; 262 return removeClient(head_->findClient(&(peer->address))->getID()); 263 } 264 /** 265 This function adds a client that connects to the clientlist of the server 266 NOTE: if you change this, don't forget to change the test function 267 addClientTest in diffTest.cc since addClient is not good for testing because of syncClassid 268 */ 269 bool ConnectionManager::addClient(ENetEvent *event) { 270 ClientInformation *temp = head_->insertBack(new ClientInformation); 271 if(!temp){ 272 COUT(2) << "Conn.Man. could not add client" << std::endl; 273 return false; 274 } 275 if(temp->prev()->getHead()) { //not good if you use anything else than insertBack 276 temp->prev()->setID(0); //bugfix: not necessary but usefull 277 temp->setID(1); 278 } 279 else 280 temp->setID(temp->prev()->getID()+1); 281 temp->setPeer(event->peer); 282 COUT(3) << "Con.Man: added client id: " << temp->getID() << std::endl; 283 return true; 284 } 296 285 297 286 298 int ConnectionManager::getClientID(ENetPeer peer) { … … 316 328 ++it; 317 329 } 318 sendPackets();330 //sendPackets(); 319 331 COUT(4) << "syncClassid:\tall synchClassID packets have been sent" << std::endl; 320 332 } 321 333 322 bool ConnectionManager::createClient(int clientID){ 323 ClientInformation *temp = head_->findClient(clientID); 324 if(!temp){ 325 COUT(2) << "Conn.Man. could not create client with id: " << clientID << std::endl; 326 return false; 327 } 328 COUT(4) << "Con.Man: creating client id: " << temp->getID() << std::endl; 329 syncClassid(temp->getID()); 330 COUT(4) << "creating spaceship for clientid: " << temp->getID() << std::endl; 331 // TODO: this is only a hack, untill we have a possibility to define default player-join actions 332 if(!createShip(temp)) 333 COUT(2) << "Con.Man. could not create ship for clientid: " << clientID << std::endl; 334 else 335 COUT(3) << "created spaceship" << std::endl; 336 temp->setSynched(true); 337 COUT(3) << "sending welcome" << std::endl; 338 sendWelcome(temp->getID(), temp->getShipID(), true); 339 return true; 340 } 341 342 bool ConnectionManager::removeClient(int clientID){ 343 orxonox::Iterator<orxonox::SpaceShip> it = orxonox::ObjectList<orxonox::SpaceShip>::start(); 344 ClientInformation *client = head_->findClient(clientID); 345 if(!client) 346 return false; 347 while(it){ 348 if(it->objectID!=client->getShipID()){ 349 ++it; 350 continue; 351 } 352 orxonox::Iterator<orxonox::SpaceShip> temp=it; 353 ++it; 354 delete *temp; 355 return head_->removeClient(clientID); 356 } 357 return false; 358 } 359 360 bool ConnectionManager::createShip(ClientInformation *client){ 361 if(!client) 362 return false; 363 orxonox::Identifier* id = ID("SpaceShip"); 364 if(!id){ 365 COUT(4) << "We could not create the SpaceShip for client: " << client->getID() << std::endl; 366 return false; 367 } 368 orxonox::SpaceShip *no = dynamic_cast<orxonox::SpaceShip *>(id->fabricate()); 369 no->setPosition(orxonox::Vector3(0,80,0)); 370 no->setScale(10); 371 no->setYawPitchRoll(orxonox::Degree(-90),orxonox::Degree(-90),orxonox::Degree(0)); 372 no->setMesh("assff.mesh"); 373 no->setMaxSpeed(500); 374 no->setMaxSideAndBackSpeed(50); 375 no->setMaxRotation(1.0); 376 no->setTransAcc(200); 377 no->setRotAcc(3.0); 378 no->setTransDamp(75); 379 no->setRotDamp(1.0); 380 no->setCamera("cam_"+client->getID()); 381 no->classID = id->getNetworkID(); 382 no->create(); 383 384 client->setShipID(no->objectID); 385 return true; 386 } 334 387 335 388 336 bool ConnectionManager::removeShip(ClientInformation *client){ … … 399 347 bool ConnectionManager::sendWelcome(int clientID, int shipID, bool allowed){ 400 348 if(addPacket(packet_gen.generateWelcome(clientID, shipID, allowed),clientID)){ 401 sendPackets();349 //sendPackets(); 402 350 return true; 403 351 }else … … 406 354 407 355 void ConnectionManager::disconnectClient(ClientInformation *client){ 408 enet_peer_disconnect(client->getPeer(), 0); 356 { 357 boost::recursive_mutex::scoped_lock lock(enet_mutex_); 358 enet_peer_disconnect(client->getPeer(), 0); 359 lock.unlock(); 360 } 409 361 removeShip(client); 410 362 } … … 418 370 419 371 420 // int ConnectionManager::getNumberOfClients() { 421 // 422 // return clientsShip.size(); 423 // } 424 425 /*void ConnectionManager::addClientsObjectID( int clientID, int objectID ) { 426 COUT(4) << "ship of client: " << clientID << ": " << objectID << " mapped" << std::endl; 427 clientsShip.insert( std::make_pair( clientID, objectID ) ); 372 428 373 } 429 430 int ConnectionManager::getClientsShipID( int clientID ) {431 return clientsShip[clientID];432 }433 434 int ConnectionManager::getObjectsClientID( int objectID ) {435 std::map<int, int>::iterator iter;436 for( iter = clientsShip.begin(); iter != clientsShip.end(); iter++ ) {437 if( iter->second == objectID ) return iter->first;438 }439 return -99;440 }441 442 void ConnectionManager::deleteClientIDReg( int clientID ) {443 clientsShip.erase( clientID );444 }445 446 void ConnectionManager::deleteObjectIDReg( int objectID ) {447 std::map<int, int>::iterator iter = clientsShip.begin();448 for( iter = clientsShip.begin(); iter != clientsShip.end(); iter++ ) {449 if( iter->second == objectID ) break;450 }451 clientsShip.erase( iter->first );452 }*/453 }
Note: See TracChangeset
for help on using the changeset viewer.