00001
00002
00003
00004
00005
00006
00007 #include <boost/thread.hpp>
00008 #include <boost/asio.hpp>
00009
00010
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
00060
00061 void FastEcslent::NetThread::init() {
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);
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() {
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(){
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
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);
00122 sprintf(tmp, "%256s", ent->uiname.c_str());
00123 strcpy(info->label, tmp);
00124
00125
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;
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;
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
00193 memcpy((void*)(message->data + offset), (void *)state, StateSize);
00194 offset += StateSize;
00195 delete state;
00196 }
00197
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)];
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(){
00258 quit = true;
00259 }
00260
00261
00262 void FastEcslent::NetThread::stopAndJoin(){
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
00277
00278 listener->kill();
00279 sender->kill();
00280
00281 boost::this_thread::sleep(boost::posix_time::seconds(2));
00282
00283 netThread.join();
00284 }