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 #include <engine.h>
00012 #include <listener.h>
00013 #include <sender.h>
00014 
00015 #include <messages.h>
00016 #include <utils.h>
00017 #include "DEBUG.h"
00018 
00019 using boost::asio::ip::udp;
00020 
00021 udp::endpoint FastEcslent::NetThread::getMyIP(){
00022 
00023         udp::endpoint me;
00024         try {
00025                 boost::asio::io_service netService;
00026                 udp::resolver   resolver(netService);
00027                 udp::resolver::query query(udp::v4(), boost::asio::ip::host_name(), "");
00028                 udp::resolver::iterator endpoints = resolver.resolve(query);
00029                 DEBUG(std::cout << "Got endPoint:" << boost::asio::ip::host_name() << std::endl;)
00030                 udp::endpoint ep = *endpoints;
00031                 DEBUG(std::cout << "Address: " << ep.address() << std::endl;)
00032                 DEBUG(std::cout << "IP Address:" << boost::asio::ip::address_v4().to_string() << std::endl;)
00033 
00034                 if (ep.address().to_string().substr(0,3) != "127"){
00035                         me = ep;
00036 
00037                 }
00038         } catch (std::exception& e){
00039                 DEBUG(std::cerr << "getMyIP could not deal with socket. Exception: " << e.what() << std::endl;)
00040         }
00041         try {
00042                 boost::asio::io_service netService;
00043                 udp::resolver   resolver(netService);
00044                 udp::resolver::query query(udp::v4(), "google.com", "");
00045                 udp::resolver::iterator endpoints = resolver.resolve(query);
00046                 udp::endpoint ep = *endpoints;
00047                 udp::socket socket(netService);
00048                 socket.connect(ep);
00049                 boost::asio::ip::address addr = socket.local_endpoint().address();
00050                 DEBUG(std::cout << "My IP according to google is: " << addr.to_string() << std::endl;)
00051                 me =  ep;
00052 
00053         } catch (std::exception& e){
00054                 DEBUG(std::cerr << "getMyIP could not deal with socket. Exception: " << e.what() << std::endl;)
00055         }
00056         return me;
00057 }
00058 
00059 //something to make udpsockets
00060 
00061 void FastEcslent::NetThread::init() { //initialize sockets, public
00062         DEBUG(std::cout << "Initializing Net before starting thread. Engine instance Id: " << engine->instanceId << std::endl;)
00063         udp::endpoint myIP = getMyIP();
00064         listener = new Listener(myIP, engine->options.networkPort, engine->options.isServer);
00065         listener->init();
00066         sender   = new Sender(myIP, engine->options.networkPort, engine->options.isServer); // if isServer -> broadcast
00067         sender->init();
00068         quit = false;
00069         serverSleepTime = new boost::posix_time::milliseconds(50);
00070         startTime = getCurrentTime();
00071 
00072 }
00073 
00074 
00075 void FastEcslent::NetThread::run() { //start thread, public
00076         netThread = boost::thread(&FastEcslent::NetThread::runThread, this);
00077         DEBUG(std::cout << "Running thread: " << netThread.get_id() << " Engine instance Id: " << engine->instanceId << std::endl;)
00078 }
00079 
00080 void FastEcslent::NetThread::runThread(){ // run the netManaager thread, private (each tick)
00081         listener->run();
00082         sender->run();
00083 
00084         if (engine->options.isServer) {
00085                 serverTick();
00086         } else {
00087                 clientTick();
00088         }
00089 }
00090 
00091 namespace FastEcslent {
00092 
00093         State* fillStateFromEnt(FastEcslent::Entity *ent){
00094                 State *s = new State();
00095 
00096                 s->id = ent->entityId.id;
00097                 //pos
00098                 s->px = ent->pos.x;
00099                 s->py = ent->pos.y;
00100                 s->pz = ent->pos.z;
00101 
00102                 s->vx = ent->vel.x;
00103                 s->vy = ent->vel.y;
00104                 s->vz = ent->vel.z;
00105 
00106                 s->dh = ent->desiredHeading;
00107                 s->ds = ent->desiredSpeed;
00108 
00109                 s->rSpeed = 0.0;
00110                 s->yaw    = ent->yaw;
00111 
00112                 s->flags  = (unsigned short) 0;
00113 
00114                 return s;
00115         }
00116 
00117         Info *fillInfoFromEnt(FastEcslent::Entity *ent){
00118                 Info *info = new Info();
00119                 char tmp[256];
00120                 sprintf(tmp, "%256i", ent->entityType);
00121                 strcpy(info->type, tmp);// = makeTypeStringFromEntityType(ent->entityType);
00122                 sprintf(tmp, "%256s", ent->uiname.c_str());
00123                 strcpy(info->label, tmp);
00124                 //strcpy(info->label, ent->uiname.c_str());
00125                 //pad(info->label, 256);
00126                 info->beam = ent->width;
00127                 info->draft = ent->depth;
00128                 info->id    = ent->entityId.id;
00129                 info->length = ent->length;
00130                 info->playerId = 0;
00131                 info->side = 0;
00132                 info->maxSpeed = ent->maxSpeed;
00133                 info->maxSpeedReverse = ent->minSpeed;
00134                 return info;
00135         }
00136 
00137         Message *makeMessageWithStateHeader(int nEnts, long dtime){
00138                 Message *m = new Message();
00139                 m->head.msgType = STATEMESSAGETYPE;
00140                 m->head.millisecondsFromStart = dtime; //boost::posix_time::milliseconds(500)
00141                 m->head.numberOfStructs = nEnts;
00142                 m->head.sizeOfStruct    = StateSize;
00143                 return m;
00144         }
00145 
00146         Message *makeMessageWithInfoHeader(int nEnts, long dtime){
00147                 Message *m = new Message();
00148                 m->head.msgType = INFOMESSAGETYPE;
00149                 m->head.millisecondsFromStart = dtime; //boost::posix_time::milliseconds(500)
00150                 m->head.numberOfStructs = nEnts;
00151                 m->head.sizeOfStruct    = InfoSize;
00152                 return m;
00153         }
00154 
00155 }
00156 
00157 void FastEcslent::NetThread::clientTick(){
00158         updateState();
00159         sendCommands();
00160 }
00161 
00162 void FastEcslent::NetThread::updateState(){
00163 
00164 }
00165 
00166 void FastEcslent::NetThread::sendCommands(){
00167 }
00168 
00169 void FastEcslent::NetThread::serverTick(){
00170         while (!quit) {
00171                 handleClientMessages();
00172                 serve();
00173         }
00174 }
00175 
00176 void FastEcslent::NetThread::serve(){
00177 
00178         Message *message;
00179         State   *state;
00180         unsigned int offset = 0;
00181 
00182         int n = engine->entityMgr->nEnts;
00183 
00184         ptime currentTime = getCurrentTime();
00185         time_duration dtime = currentTime - startTime;
00186 
00187         DEBUG(std::cout << "Serving at dtime: " << dtime.total_milliseconds() << std::endl;)
00188         message = makeMessageWithStateHeader(n, dtime.total_milliseconds());
00189         offset = 0;
00190         for (int i = 0; i < n; i++) {
00191                 state = fillStateFromEnt(engine->entityMgr->ents[i]);
00192                 //engine->entityMgr->dumpOne(i);
00193                 memcpy((void*)(message->data + offset), (void *)state, StateSize);
00194                 offset += StateSize;
00195                 delete state;
00196         }
00197         //printMessage(message);
00198         sender->addMessage(message);
00199         boost::this_thread::sleep(*serverSleepTime);
00200 
00201 
00202 }
00203 
00204 void FastEcslent::NetThread::handleClientMessages(){
00205         Message *m;
00206         while (!listener->recBuffer.empty()) {
00207                 m = getMessage();
00208                 if((int) m->head.msgType != 1) {
00209                         handleMessage(m);
00210                 }
00211                 delete m;
00212         }
00213 }
00214 
00215 FastEcslent::Message *FastEcslent::NetThread::getMessage(){
00216         Message *m = new Message();
00217         m = listener->recBuffer.front();
00218         listener->recBuffer.pop_front();
00219         return m;
00220 }
00221 
00222 void FastEcslent::NetThread::handleMessage(Message *m){
00223         switch((int) m->head.msgType) {
00224         case FastEcslent::REQUESTINFOMESSAGETYPE:
00225                 sendInfo(m);
00226                 break;
00227         default:
00228                 break;
00229 
00230         }
00231 }
00232 
00233 void FastEcslent::NetThread::sendInfo(Message *m){
00234         Entity *ent;
00235         Info   *info;
00236         ptime currentTime = getCurrentTime();
00237         time_duration diff = currentTime - startTime;
00238         Message *sendInfoMessage = makeMessageWithInfoHeader(m->head.numberOfStructs, diff.total_milliseconds());
00239 
00240         int offset = HeaderSize;
00241         DEBUG(std::cout << "Readying info to be sent" << std::endl;)
00242         FastEcslent::printMessageHeader(m->head);
00243         FastEcslent::printMessageData(m);
00244         for(int i = 0; i < m->head.numberOfStructs; i++){
00245                 ent = engine->entityMgr->ents[*((int *)m->data + i)];//convert to int pointer, add i, then dereference
00246                 info = fillInfoFromEnt(ent);
00247                 DEBUG(std::cout << "Sending info message about ent with id: " << ent->entityId.id << std::endl;)
00248                 memcpy((void* ) ((char*)sendInfoMessage + offset), info, InfoSize);
00249                 offset += InfoSize;
00250 
00251                 delete info;
00252         }
00253 
00254         sender->addMessage(sendInfoMessage);
00255 }
00256 
00257 void FastEcslent::NetThread::stop(){ // end thread, public
00258         quit = true;
00259 }
00260 
00261 
00262 void FastEcslent::NetThread::stopAndJoin(){ // end thread, public
00263         stop();
00264         DEBUG(std::cout << "NetThread Stopping...Quit = " << std::endl;)
00265         boost::this_thread::sleep(boost::posix_time::seconds(2));
00266         sender->stop();
00267         boost::this_thread::sleep(boost::posix_time::seconds(2));
00268         listener->stop();
00269         boost::this_thread::sleep(boost::posix_time::seconds(2));
00270 
00271         DEBUG(std::cout << "NetThread Joining..." << std::endl;)
00272 
00273 
00274         sender->join();
00275         boost::this_thread::sleep(boost::posix_time::seconds(2));
00276         //listener->join();
00277         //boost::this_thread::sleep(boost::posix_time::seconds(2));
00278         listener->kill();
00279         sender->kill();
00280 
00281         boost::this_thread::sleep(boost::posix_time::seconds(2));
00282         //listener->listenerThread.interrupt();//I would like to join listener but that keeps crashing
00283         netThread.join();
00284 }

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