netThread.cpp

Go to the documentation of this file.
00001 /*
00002  * netThread.cpp
00003  *
00004  *  Created on: Jan 10, 2012
00005  *      Author: sushil
00006  */
00007 #include <boost/thread.hpp>
00008 #include <boost/asio.hpp>
00009 
00010 #include <netThread.h>
00011 
00012 #include <engine.h>
00013 #include <listener.h>
00014 #include <sender.h>
00015 #include <enums.h>
00016 #include <messages.h>
00017 #include <utils.h>
00018 #include <GraphicsInteractionManager.h>
00019 
00020 using boost::asio::ip::udp;
00021 
00022 
00023 void FastEcslent::NetThread::init() { //initialize sockets, public
00024         std::cout << "Initializing Net before starting thread. Engine instance Id: " << engine->instanceId << std::endl;
00025         netCommon = new NetCommon();
00026         std::pair<udp::endpoint, std::string> ippair = netCommon->getMyIP();
00027         udp::endpoint myIP = ippair.first;
00028         myIPAddress = ippair.second;
00029 
00030         listener = new Listener(myIP, engine->options.networkPort, engine->options.isServer);
00031         listener->init(myIPAddress);
00032         sender   = new Sender(myIP, engine->options.networkPort, engine->options.isServer); // if isServer -> broadcast
00033         sender->init();
00034         quit = false;
00035         startTime = getCurrentTime();
00036         TICK_SLEEP_TIME = 10;
00037         sleepTime = new boost::posix_time::milliseconds(20);
00038         insideLobby = false;
00039 }
00040 
00041 
00042 void FastEcslent::NetThread::run() { //start thread, public
00043         netThread = boost::thread(&FastEcslent::NetThread::runThread, this);
00044         std::cout << "Running thread: " << netThread.get_id() << " Engine instance Id: " << engine->instanceId << std::endl;
00045 }
00046 
00047 void FastEcslent::NetThread::runThread(){ // run the netManaager thread, private (each tick)
00048         listener->run();
00049         sender->run();
00050 
00051         while (!quit){
00052                 gameTick();
00053         }
00054 }
00055 
00056 void FastEcslent::NetThread::gameTick(){
00057         if (engine->options.isServer) {
00058                 serverTick();
00059         } else {
00060                 clientTick();
00061         }
00062 }
00063 
00064 namespace FastEcslent {
00065 
00066         State* fillStateFromEnt(FastEcslent::Entity *ent){
00067                 State *s = new State();
00068 
00069                 s->id = ent->entityId.id;
00070 
00071                 s->px = ent->pos.x;
00072                 s->py = ent->pos.y;
00073                 s->pz = ent->pos.z;
00074 
00075                 s->vx = ent->vel.x;
00076                 s->vy = ent->vel.y;
00077                 s->vz = ent->vel.z;
00078 
00079                 s->dh = ent->desiredHeading;
00080                 s->ds = ent->desiredSpeed;
00081 
00082                 s->rSpeed = 0.0;
00083                 s->yaw    = ent->yaw;
00084 
00085                 s->flag  = 0;//(unsigned short) 0;
00086 
00087                 return s;
00088         }
00089 
00090         Info *fillInfoFromEnt(FastEcslent::Entity *ent){
00091                 Info *info = new Info();
00092                 char tmp[256];
00093                 sprintf(tmp, "%256i", ent->entityType);
00094                 strcpy(info->type, tmp);// = makeTypeStringFromEntityType(ent->entityType);
00095                 sprintf(tmp, "%255s", ent->uiname.c_str()); //"%256s" convert to 256 + '/0'= 257, overlapped 1 char in type
00096                 strcpy(info->label, tmp);
00097                 //strcpy(info->label, ent->uiname.c_str());
00098                 //pad(info->label, 256);
00099                 info->beam = ent->width;
00100                 info->draft = ent->depth;
00101                 info->id    = ent->entityId.id;
00102                 info->length = ent->length;
00103                 info->playerId = ent->entityId.player;
00104                 info->side = ent->entityId.side;
00105                 info->maxSpeed = ent->maxSpeed;
00106                 info->maxSpeedReverse = 0.0f;
00107                 return info;
00108         }
00109 
00110         Message *makeMessageWithStateHeader(int nEnts, long dtime){
00111                 Message *m = new Message();
00112                 m->head.msgType = STATEMESSAGETYPE;
00113                 m->head.millisecondsFromStart = dtime; //boost::posix_time::milliseconds(500)
00114                 m->head.numberOfStructs = nEnts;
00115                 m->head.sizeOfStruct    = StateSize;
00116                 return m;
00117         }
00118 
00119         Message *makeMessageWithInfoHeader(int nEnts, long dtime){
00120                 Message *m = new Message();
00121                 m->head.msgType = INFOMESSAGETYPE;
00122                 m->head.millisecondsFromStart = dtime; //boost::posix_time::milliseconds(500)
00123                 m->head.numberOfStructs = nEnts;
00124                 m->head.sizeOfStruct    = InfoSize;
00125                 return m;
00126         }
00127 
00128 }
00129 
00130 void FastEcslent::NetThread::sendCommands(){
00131         sendUnknownEntQueries();
00132         combineCommandsIntoNetMessage();
00133         combineSquelchesIntoNetMessage();
00134 }
00135 
00136 void FastEcslent::NetThread::combineCommandsIntoNetMessage(){
00137         if (commandQueue.size() > 0){
00138                 Message *m = new Message();
00139 
00140                 m->head.msgType = COMMANDENTITYMESSAGETYPE;
00141                 m->head.millisecondsFromStart = netCommon->getCurrentTimeLong();
00142                 m->head.numberOfStructs = commandQueue.size() ;
00143                 m->head.sizeOfStruct = CommandEntitySize;
00144                 unsigned int offset = 0;
00145                 for(int i=0; i< m->head.numberOfStructs; i++){
00146                         CommandEntity* cmd = commandQueue.front();
00147                         commandQueue.pop_front();
00148                         memcpy((void*)(m->data + offset), (void *)cmd, CommandEntitySize);
00149                         offset += CommandEntitySize;
00150                         delete cmd;
00151                 }
00152 
00153                 sender->addMessage(m);
00154         }
00155 }
00156 
00157 void FastEcslent::NetThread::combineSquelchesIntoNetMessage(){
00158         if (squelchQueue.size() > 0){
00159                 Message *m = new Message();
00160 
00161                 m->head.msgType = SQUELCHMESSAGETYPE;
00162                 m->head.millisecondsFromStart = netCommon->getCurrentTimeLong();
00163                 m->head.numberOfStructs = squelchQueue.size() ;
00164                 m->head.sizeOfStruct = SquelchEntitySize;
00165                 unsigned int offset = 0;
00166                 for(int i=0; i< m->head.numberOfStructs; i++){
00167                         SquelchEntity* squelch = squelchQueue.front();
00168                         squelchQueue.pop_front();
00169                         memcpy((void*)(m->data + offset), (void *)squelch, SquelchEntitySize);
00170                         offset += SquelchEntitySize;
00171                         delete squelch;
00172                 }
00173 
00174                 sender->addMessage(m);
00175         }
00176 }
00177 
00178 
00179 void FastEcslent::NetThread::addCommand(CommandEntity* m){
00180         commandQueue.push_back(m);
00181 }
00182 
00183 void FastEcslent::NetThread::addSquelch(SquelchEntity* s){
00184         squelchQueue.push_back(s);
00185 }
00186 
00187 
00188 void FastEcslent::NetThread::sendUnknownEntQueries(){
00189         if(unknows.size()> 0) {
00190                 std::cout<<"Unknowns entity count: "<< unknows.size() <<std::endl;
00191 
00192                 unsigned int offset = 0;
00193 
00194                 Message *m = new Message();
00195                 m->head.msgType = REQUESTINFOMESSAGETYPE;
00196                 m->head.millisecondsFromStart = netCommon->getCurrentTimeLong();
00197                 m->head.numberOfStructs = unknows.size();
00198                 m->head.sizeOfStruct    = ReqInfoSize;
00199 
00200                 for (std::map<int, State*>::iterator i= unknows.begin(); i!=unknows.end();i++) {
00201                         ReqInfo* reqInfo = new ReqInfo();
00202                         reqInfo->id = i->first;
00203                         memcpy((void*)(m->data + offset), (void *)reqInfo, ReqInfoSize);
00204                         offset += ReqInfoSize;
00205                         delete reqInfo;
00206                 }
00207 
00208                 sender->addPriorityMessage(m);
00209         }
00210 }
00211 
00212 void FastEcslent::NetThread::sendCommand(int id, float dh, float ds){
00213         Message *m = new Message();
00214         m->head.msgType = COMMANDENTITYMESSAGETYPE;
00215         m->head.millisecondsFromStart = (getCurrentTime() - startTime).total_milliseconds();
00216         m->head.numberOfStructs = 1;
00217         m->head.sizeOfStruct = CommandEntitySize;
00218 
00219         CommandEntity* cmd = new CommandEntity();
00220         cmd->id = id;
00221         cmd->dh = dh;
00222         cmd->ds = ds;
00223         memcpy((void*)(m->data), (void *)cmd, CommandEntitySize);
00224         delete cmd;
00225 
00226         sender->addMessage(m);
00227 }
00228 
00229 void FastEcslent::NetThread::serverTick(){
00230         handleClientMessages();
00231         serve();
00232         boost::this_thread::sleep(*sleepTime);
00233 }
00234 
00235 void FastEcslent::NetThread::clientTick(){
00236         this->handleServerMessages();
00237         sendCommands();
00238         boost::this_thread::sleep(*sleepTime);
00239 }
00240 
00241 void FastEcslent::NetThread::serve(){
00242 
00243         Message *message;
00244         State   *state;
00245         unsigned int offset = 0;
00246 
00247         int n = engine->entityMgr->nEnts;
00248 
00249         //std::cout << "Serving at dtime: " << dtime.total_milliseconds() << std::endl;
00250         long dt = netCommon->getCurrentTimeLong();
00251         message = makeMessageWithStateHeader(n, netCommon->getCurrentTimeLong());
00252         offset = 0;
00253         for (int i = 0; i < n; i++) {
00254                 state = fillStateFromEnt(engine->entityMgr->ents[i]);
00255                 //engine->entityMgr->dumpOne(i);
00256                 memcpy((void*)(message->data + offset), (void *)state, StateSize);
00257                 offset += StateSize;
00258                 delete state;
00259         }
00260         //printMessage(message);
00261         sender->addMessage(message);
00262 }
00263 
00264 void FastEcslent::NetThread::handleClientMessages(){
00265         Message *m = listener->dequeMessage();
00266         while (m) {
00267                 if((int) m->head.msgType != FastEcslent::STATEMESSAGETYPE) {
00268                         handleMessage(m);
00269                 }
00270                 delete m;
00271                 m = listener->dequeMessage();
00272         }
00273 }
00274 
00275 void FastEcslent::NetThread::handleServerMessages(){
00276         Message *m = listener->dequeMessage();
00277         while (m) {
00278                 if((int) m->head.msgType == FastEcslent::STATEMESSAGETYPE) {
00279                         updateState(m);
00280                 }else if((int) m->head.msgType == FastEcslent::INFOMESSAGETYPE) {
00281                         createEnt(m);
00282                 }else if ((int) m->head.msgType == FastEcslent::SQUELCHMESSAGETYPE){
00283                         squelchEnts(m);
00284                 }
00285                 delete m;
00286                 m = listener->dequeMessage();
00287         }
00288 }
00289 
00290 void FastEcslent::NetThread::updateState(Message *m){
00291         unsigned int offset = 0;
00292         for(int i=0;i<m->head.numberOfStructs;i++){
00293                 State *state = new State(); //remember to delete, now it is used in unknows
00294                 memcpy((void *)state, (void*)(m->data + offset), StateSize);
00295                 offset += StateSize;
00296                 state->flag =  m->head.millisecondsFromStart;
00297                 updateState(state);
00298                 //delete state;
00299         }
00300 }
00301 
00302 void FastEcslent::NetThread::updateState(State *s){
00303         if(netIdToEntMap.find(s->id) != netIdToEntMap.end()){
00304                 FastEcslent::Entity *ent= netIdToEntMap[s->id];
00305                 NetAspect *na = dynamic_cast<NetAspect *> (ent->getAspect(NET));
00306                 if(na){
00307                         ent->netAspect->updateQueue.push_back(s);
00308                 }else{
00309                         delete s;
00310                 }
00311         }
00312         else{
00313                 State *tmp = unknows[s->id];
00314                 unknows[s->id] = s;
00315                 if (tmp != NULL)
00316                         delete tmp;
00317         }
00318 }
00319 
00320 void FastEcslent::NetThread::createEnt(Message *m){
00321         unsigned int offset = 0;
00322         for(int i=0;i<m->head.numberOfStructs;i++){
00323                 Info *info = new Info(); //remember to delete, now it is used in unknows
00324                 memcpy((void *)info, (void*)(m->data + offset), InfoSize);
00325                 offset += InfoSize;
00326                 createEnt(info);
00327         }
00328 }
00329 
00330 void FastEcslent::NetThread::createEnt(Info *info){
00331         if(unknows.find(info->id) != unknows.end()){
00332                 int type = atoi(info->type);
00333                 EntityType et = (EntityType)type;
00334                 Side side = (Side)(info->side);
00335                 Player player = (Player)(info->playerId);
00336                 State *s = unknows[info->id];
00337 
00338                 Ogre::Vector3 pos(s->px,s->py,s->pz);
00339 
00340                 Entity* ent = engine->entityMgr->createEntityForPlayerAndSide(et, pos, s->yaw, side, player );
00341                 ent->width = info->beam;
00342                 ent->depth = info->draft;
00343                 ent->uiname = info->label;
00344                 ent->length = info->length;
00345                 ent->maxSpeed = info->maxSpeed;
00346 
00347                 netIdToEntMap[info->id] = ent;
00348                 netEntToIdMap[ent] = info->id;
00349 
00350                 ent->vel.x = s->vx;
00351                 ent->vel.y = s->vy;
00352                 ent->vel.z = s->vz;
00353 
00354                 ent->desiredHeading = s->dh;
00355                 ent->desiredSpeed = s->ds;
00356 
00357                 ent->init();
00358 
00359                 if(ent->entityType == SCV){ //building has no ai
00360                         ent->ai->state = NETSLAVE;
00361                 }
00362 
00363                 delete s;
00364                 unknows.erase(info->id);
00365                 delete info;
00366 
00367                 std::cout<<"Create Entity from Network: "<< ent->idNumber << ", " << ent->entityType << std::endl;
00368         }
00369 }
00370 
00371 void FastEcslent::NetThread::squelchEnts(Message *m){
00372         unsigned int offset = 0;
00373         for(int i=0;i<m->head.numberOfStructs;i++){
00374                 SquelchEntity *squelch = new SquelchEntity();
00375                 memcpy((void *)squelch, (void*)(m->data + offset), SquelchEntitySize);
00376                 offset += SquelchEntitySize;
00377                 netIdToEntMap[squelch->id]->netAspect->squalch();
00378                 delete squelch;
00379         }
00380 }
00381 
00382 void FastEcslent::NetThread::handleMessage(Message *m){
00383         switch((int) m->head.msgType) {
00384         case FastEcslent::REQUESTINFOMESSAGETYPE:
00385                 sendInfo(m);
00386                 break;
00387         case FastEcslent::COMMANDENTITYMESSAGETYPE:
00388                 propagateCommand(m);
00389                 break;
00390         case FastEcslent::SQUELCHMESSAGETYPE:
00391                 //server does nothing about squelch
00392                 break;
00393         default:
00394                 break;
00395 
00396         }
00397 }
00398 
00399 void FastEcslent::NetThread::sendInfo(Message *m){
00400         Entity *ent;
00401         Info   *info;
00402         ptime currentTime = getCurrentTime();
00403         time_duration diff = currentTime - startTime;
00404         Message *sendInfoMessage = makeMessageWithInfoHeader(m->head.numberOfStructs, diff.total_milliseconds());
00405 
00406         int offset = HeaderSize;
00407         //std::cout << "Readying info to be sent" << std::endl;
00408         FastEcslent::printMessageHeader(m->head);
00409         FastEcslent::printMessageData(m);
00410         for(int i = 0; i < m->head.numberOfStructs; i++){
00411                 ent = engine->entityMgr->ents[*((int *)m->data + i)];//convert to int pointer, add i, then dereference
00412                 info = fillInfoFromEnt(ent);
00413                 std::cout << "Sending info message about ent with id: " << ent->entityId.id << std::endl;
00414                 memcpy((void* ) ((char*)sendInfoMessage + offset), info, InfoSize);
00415                 offset += InfoSize;
00416 
00417                 delete info;
00418         }
00419 
00420         sender->addMessage(sendInfoMessage);
00421 }
00422 
00423 void FastEcslent::NetThread::propagateCommand(Message *m){
00424         unsigned int offset = 0;
00425         for(int i=0;i<m->head.numberOfStructs;i++){
00426                 CommandEntity *cmd = new CommandEntity(); //remember to delete, now it is used in unknows
00427                 memcpy((void *)cmd, (void*)(m->data + offset), CommandEntitySize);
00428                 offset += CommandEntitySize;
00429                 Entity* ent = engine->entityMgr->getEntityById(cmd->id);
00430                 ent->desiredHeading = cmd->dh;
00431                 ent->desiredSpeed = cmd->ds;
00432                 ent->ai->state = NETSLAVE;
00433                 delete cmd;
00434         }
00435 }
00436 
00437 void FastEcslent::NetThread::stop(){ // end thread, public
00438         quit = true;
00439 }
00440 
00441 
00442 void FastEcslent::NetThread::stopAndJoin(){ // end thread, public
00443         stop();
00444         std::cout << "NetThread Stopping...Quit = " << std::endl;
00445         boost::this_thread::sleep(boost::posix_time::seconds(2));
00446         sender->stop();
00447         boost::this_thread::sleep(boost::posix_time::seconds(2));
00448         listener->stop();
00449         boost::this_thread::sleep(boost::posix_time::seconds(2));
00450 
00451         std::cout << "NetThread Joining..." << std::endl;
00452 
00453 
00454         sender->join();
00455         boost::this_thread::sleep(boost::posix_time::seconds(2));
00456         //listener->join();
00457         //boost::this_thread::sleep(boost::posix_time::seconds(2));
00458         listener->kill();
00459         sender->kill();
00460 
00461         boost::this_thread::sleep(boost::posix_time::seconds(2));
00462         //listener->listenerThread.interrupt();//I would like to join listener but that keeps crashing
00463         netThread.join();
00464 }
00465 
00466 int FastEcslent::NetThread::getNetId(Entity* ent){
00467         for(std::map<int, Entity*>::iterator i = netIdToEntMap.begin(); i!= netIdToEntMap.end(); i++){
00468                 if(i->second == ent)
00469                         return i->first;
00470         }
00471         return -1;
00472 }
00473 

Generated on Fri Dec 13 14:54:18 2013 for FastECSLent by  doxygen 1.5.4