00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00016 #ifndef NETLINK_H
00017 #define NETLINK_H
00018
00019 #ifdef ADSO_WINDOWS
00020 #include <winsock.h>
00021 #else
00022 #include <sys/socket.h>
00023 #include <sys/un.h>
00024 #include <netinet/in.h>
00025 #include <arpa/inet.h>
00026 #include <unistd.h>
00027 #endif
00028 #include <queue>
00029 #include <list>
00030 #include <sys/types.h>
00031 #include <SDL/SDL.h>
00032 #include <adsomath.h>
00033 #include <adsofont.h>
00034 #include "vehicle.h"
00035 #include "config.h"
00036 #include "photon.h"
00037 #include "view.h"
00038
00039 using namespace std;
00040
00041 #define STATE_MAX_PHOTONS 4
00042
00043 #define NETLINK_MAGIC ( ('a'<<24) | ('d'<<16) | ('s'<<8) | 'o' )
00044 #define NL_PACKET_VERSION 3
00045
00046 #define NL_DELTATIME_INVALID 0x7fffffff
00047
00048
00049 #define NLM_CONNECT 1
00050 #define NLM_DISCONNECT 2
00051 #define NLM_ACKNOWLEDGE 3
00052 #define NLM_ACCEPT 4
00053 #define NLM_REJECT 5
00054 #define NLM_ABORT 6
00055
00056
00057 #define NL_CB 1024
00058 #define NLC_NIL (0|NL_CB)
00059 #define NLC_STARTGAME (1|NL_CB)
00060 #define NLC_DEATHMATCH (2|NL_CB)
00061 #define NLC_ABORTGAME (3|NL_CB)
00062 #define NLC_GOT_EPSILON (4|NL_CB)
00063 #define NLC_SET_EPSILON (5|NL_CB)
00064 #define NLC_IFAILED (6|NL_CB)
00065 #define NLC_RESETPOS (7|NL_CB)
00066 #define NLC_DM_IWIN (8|NL_CB)
00067 #define NLC_DM_YOUWIN (9|NL_CB)
00068 #define NLC_RESCUE (10|NL_CB)
00069 #define NLC_CHAT (11|NL_CB)
00070 #define NLC_UFO (12|NL_CB)
00071 #define NLC_PHOTON_HIT (13|NL_CB)
00072 #define NLC_GAMETYPE (14|NL_CB)
00073
00074
00075 #define NLSTATE_INACTIVE 0
00076 #define NLSTATE_IDLE 1
00077 #define NLSTATE_RCON 2
00078 #define NLSTATE_LCON 3
00079 #define NLSTATE_RACK 4
00080 #define NLSTATE_LACC 5
00081 #define NLSTATE_LREJ 6
00082 #define NLSTATE_CONNECTED 7
00083
00084
00085
00086 #define NLTEST_PACKET_DELAY 100
00087 #define NLTEST_PACKET_DVAR 10
00088 #define NLTEST_DROP_INTERVAL 1000000
00089
00091
00093
00094 #define NLS_DTA_SIZE 141
00095
00096 class NetLinkStat : public Overlay {
00097 double pingTime;
00098 int lostPackets;
00099 int packetNum;
00100 int msgSendCount;
00101 int msgRecvCount;
00102 int msgResendCount;
00103 int msgReackCount;
00104 const char *lastMessage;
00105
00106 int sendQueueMax;
00107 int recvQueueMax;
00108 int sendAckQueueMax;
00109 int recvAckQueueMax;
00110
00111
00112 int adt_array[NLS_DTA_SIZE];
00113 int dt_array[NLS_DTA_SIZE];
00114 int dtaHead, dtaTail;
00115
00116 public:
00117 bool visible;
00118
00119 void draw();
00120 void newConnection();
00121 void addTime(int dt, int adt);
00122 NetLinkStat(){ pingTime = 0.0; lostPackets = 0; visible = false; }
00123
00124 friend class NetLink;
00125 };
00126
00128
00130
00131 #ifdef ADSO_WINDOWS
00132 struct sockaddr_un {
00133 int sun_family;
00134 char sun_path[32];
00135 };
00136
00137 typedef int socklen_t;
00138 #endif
00139
00140 class NetLinkAddr {
00141 sockaddr_un uaddr;
00142 sockaddr_in iaddr;
00143 socklen_t addrLen;
00144 int local,valid;
00145 public:
00146 int isValid(){ return valid; }
00147
00148 sockaddr *getSockAddr(){
00149 if(local) return (sockaddr*)&uaddr;
00150 else return (sockaddr*)&iaddr;
00151 }
00152
00153 socklen_t *recvSockAddrLen(){
00154 if(local) addrLen = sizeof(sockaddr_un);
00155 else addrLen = sizeof(sockaddr_in);
00156 return &addrLen;
00157 }
00158
00159 socklen_t *getSockAddrLen(){
00160 return &addrLen;
00161 }
00162
00163 void unlink(){
00164 if(local) ::unlink(uaddr.sun_path);
00165 }
00166
00167 const char *toString(){
00168 if(local){
00169 return uaddr.sun_path;
00170 }
00171 else {
00172 return inet_ntoa(iaddr.sin_addr);
00173 }
00174 }
00175
00176 #ifdef ADSO_WINDOWS
00177 bool operator==(const NetLinkAddr& b){
00178 if(local!=b.local) return 0;
00179 if(local){
00180 if(uaddr.sun_family == b.uaddr.sun_family &&
00181 strncmp(uaddr.sun_path,b.uaddr.sun_path,addrLen)==0) return 1;
00182 else return 0;
00183 }
00184 else if(iaddr.sin_addr.s_addr == b.iaddr.sin_addr.s_addr
00185 && iaddr.sin_port == b.iaddr.sin_port) return 1;
00186 else return 0;
00187 }
00188
00189 bool operator!=(const NetLinkAddr b){ return !operator==(b); }
00190 #else
00191 friend bool operator==(const NetLinkAddr& a, const NetLinkAddr& b){
00192 if(a.local!=b.local) return 0;
00193 if(a.local){
00194 if(a.uaddr.sun_family == b.uaddr.sun_family &&
00195 strncmp(a.uaddr.sun_path,b.uaddr.sun_path,a.addrLen)==0) return 1;
00196 else return 0;
00197 }
00198 else if(a.iaddr.sin_addr.s_addr == b.iaddr.sin_addr.s_addr
00199 && a.iaddr.sin_port == b.iaddr.sin_port) return 1;
00200 else return 0;
00201 }
00202
00203 friend bool operator!=(const NetLinkAddr& a, const NetLinkAddr& b) { return !(a==b); }
00204 #endif
00205
00206 NetLinkAddr(){
00207 valid = 1;
00208 if(config.localAddr) local = 1;
00209 else local = 0;
00210
00211 if(local){
00212 #ifdef ADSO_WINDOWS
00213 fatal("Can not use unix sockets in windows");
00214 #else
00215 uaddr.sun_family = AF_UNIX;
00216 #endif
00217 addrLen = sizeof(sockaddr_un);
00218 }
00219 else {
00220 memset((void*)&iaddr, 0, sizeof(iaddr));
00221 addrLen = sizeof(sockaddr_in);
00222 iaddr.sin_family = AF_INET;
00223 iaddr.sin_addr.s_addr = INADDR_ANY;
00224 iaddr.sin_port = htons(config.netLinkPort);
00225 }
00226 }
00227
00228 NetLinkAddr(const char *addr_str) {
00229 valid = 1;
00230 if(config.localAddr) local = 1;
00231 else local = 0;
00232
00233 if(local){
00234 #ifdef ADSO_WINDOWS
00235 fatal("Can not use unix sockets in windows");
00236 #else
00237 uaddr.sun_family = AF_UNIX;
00238 #endif
00239 strcpy(uaddr.sun_path, addr_str);
00240 addrLen = strlen(uaddr.sun_path) + sizeof(uaddr.sun_family);
00241 }
00242 else {
00243 memset((char *)&iaddr, 0, sizeof (iaddr));
00244 addrLen = sizeof(sockaddr_in);
00245 iaddr.sin_family = AF_INET;
00246 if(config.netLinkRemotePort) iaddr.sin_port = htons(config.netLinkRemotePort);
00247 else iaddr.sin_port = htons(config.netLinkPort);
00248
00249
00250 iaddr.sin_addr.s_addr = inet_addr(addr_str);
00251 if(iaddr.sin_addr.s_addr == INADDR_NONE) valid = 0;
00252 }
00253 }
00254 };
00255
00257
00259
00260 struct State {
00261 v3f pos, r_x, r_y, r_z;
00262 v3f massPos;
00263 sqm3f R;
00264 float wheel, cannonBearing, cannonTilt;
00265 u_int time;
00266 int deltaTime;
00267 int photonCount;
00268 PhotonDef photonList[STATE_MAX_PHOTONS];
00269
00270 void interpolate(double w, State *a, State *b){
00271 pos = (1.0-w)*a->pos + w*b->pos;
00272 r_x = (1.0-w)*a->r_x + w*b->r_x;
00273 r_y = (1.0-w)*a->r_y + w*b->r_y;
00274 r_z = (1.0-w)*a->r_z + w*b->r_z;
00275
00276 wheel = (1.0-w)*a->wheel + w*b->wheel;
00277 cannonBearing = (1.0-w)*a->cannonBearing + w*b->cannonBearing;
00278 cannonTilt = (1.0-w)*a->cannonTilt + w*b->cannonTilt;
00279
00280
00281
00282
00283 massPos = (1.0-w)*a->massPos + w*b->massPos;
00284 R = a->R*(1.0-w) + b->R*w;
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 time = (u_int)((1.0-w)*a->time + w*b->time);
00295 }
00296 };
00297
00298 struct StateStream {
00299 int pos;
00300 u_int time;
00301 State state;
00302 };
00303
00305
00307
00308 struct Message {
00309 int type;
00310 char data[64];
00311 Message(){ type = 0; }
00312 Message(int t){ type = t; }
00313
00314 const char *toString(){
00315 switch(type){
00316 case NLM_CONNECT: return "Connect";
00317 case NLM_DISCONNECT: return "Disconnect";
00318 case NLM_ACKNOWLEDGE: return "Acknowledge";
00319 case NLM_ACCEPT: return "Accept";
00320 case NLM_REJECT: return "Reject";
00321 case NLM_ABORT: return "Abort";
00322
00323 case NLC_STARTGAME: return "Start game";
00324 case NLC_DEATHMATCH: return "Death match";
00325 case NLC_ABORTGAME: return "Abort game";
00326 case NLC_GOT_EPSILON: return "Got epsilon";
00327 case NLC_SET_EPSILON: return "Set epsilon";
00328 case NLC_IFAILED: return "I failed";
00329 case NLC_RESETPOS: return "Reset pos";
00330 case NLC_DM_IWIN: return "DM: I win";
00331 case NLC_DM_YOUWIN: return "DM: you win";
00332 case NLC_RESCUE: return "Rescue";
00333 case NLC_CHAT: return "Chat";
00334 case NLC_UFO: return "Ufo";
00335 case NLC_PHOTON_HIT: return "Photon hit";
00336 case NLC_GAMETYPE: return "Game type";
00337 default: return "<unknown>";
00338 }
00339 }
00340 };
00341
00342 struct MsgSetEpsilon : public Message {
00343 s2f getPos(){ return *((s2f*)data); }
00344 void setPos(s2f ep){ *((s2f*)data) = ep; }
00345 MsgSetEpsilon(){ type = NLC_SET_EPSILON; }
00346 MsgSetEpsilon(s2f ep){
00347 type = NLC_SET_EPSILON;
00348 *((s2f*)data) = ep;
00349 }
00350 };
00351
00352 struct MsgGotEpsilon : public Message {
00353 float getTime(){ return *((float*)data); }
00354 void setPos(float time){ *((float*)data) = time; }
00355 MsgGotEpsilon(){ type = NLC_GOT_EPSILON; }
00356 MsgGotEpsilon(float time){
00357 type = NLC_GOT_EPSILON;
00358 *((float*)data) = time;
00359 }
00360 };
00361
00362 struct MsgChat : public Message {
00363 char *getString(){ return data; }
00364 void setString(char *str){ strncpy(data,str,64); }
00365 MsgChat(char *str){
00366 type = NLC_CHAT;
00367 strncpy(data,str,64);
00368 }
00369 };
00370
00371 struct MsgUfo : public Message {
00372 int targetRemote(){ return *data; }
00373 MsgUfo(int targetLocal){
00374 type = NLC_UFO;
00375 *data = targetLocal;
00376 }
00377 MsgUfo(){
00378 type = NLC_UFO;
00379 }
00380 };
00381
00382 struct MsgPhotonHit : public Message {
00383 float remoteVehicleImpact(){ return *((float*)data); }
00384 float localVehicleImpact(){ return *((float*)(data+4)); }
00385 void combine(MsgPhotonHit &msg){
00386 *((float*)data) += *((float*)msg.data);
00387 *((float*)(data+4)) += *((float*)(msg.data+4));
00388 }
00389 MsgPhotonHit(float localImpact, float remoteImpact){
00390 type = NLC_PHOTON_HIT;
00391 *((float*)(data)) = localImpact;
00392 *((float*)(data+4)) = remoteImpact;
00393 }
00394 MsgPhotonHit(){
00395 type = NLC_PHOTON_HIT;
00396 }
00397 };
00398
00399 struct MsgGameType : public Message {
00400 int deathMatch(){ return *data; }
00401 MsgGameType(int deathMatch){
00402 type = NLC_GAMETYPE;
00403 *data = deathMatch;
00404 }
00405 MsgGameType(){
00406 type = NLC_GAMETYPE;
00407 }
00408 };
00409
00410 struct MsgConnect : public Message {
00411 int isBot(){ return data[0]; }
00412 char *getName(){ return data+1; }
00413 MsgConnect(){
00414 type = NLM_CONNECT;
00415 data[0] = config.netbot_mode?1:0;
00416 if(config.userName) strncpy(data+1,config.userName,16);
00417 else data[1] = 0;
00418 }
00419 };
00420
00421 struct MsgAccept : public Message {
00422 int isBot(){ return data[0]; }
00423 char *getName(){ return data+1; }
00424 MsgAccept(){
00425 type = NLM_ACCEPT;
00426 data[0] = config.netbot_mode?1:0;
00427 if(config.userName) strncpy(data+1,config.userName,16);
00428 else data[1] = 0;
00429 }
00430 };
00431
00433
00435
00436 struct Packet {
00437 int magic;
00438 int packetVersion;
00439 int connection_id;
00440 int acknowledge;
00441 #ifdef NLTEST_ENABLE
00442 int timeStamp;
00443 #endif
00444 Message msg;
00445 int msgNumber;
00446 StateStream stream;
00447
00448 Packet(){
00449 magic = NETLINK_MAGIC;
00450 packetVersion = NL_PACKET_VERSION;
00451 acknowledge = 0;
00452 msg.type = 0;
00453 }
00454
00455 Packet(Message m){
00456 magic = NETLINK_MAGIC;
00457 packetVersion = NL_PACKET_VERSION;
00458 acknowledge = 0;
00459 msg = m;
00460 }
00461 };
00462
00463 struct TPacket {
00464 NetLinkAddr dest;
00465 Packet packet;
00466 TPacket(NetLinkAddr d, Packet p){
00467 dest = d;
00468 packet = p;
00469 }
00470 };
00471
00472
00474
00476
00477 class NetLink : public Overlay {
00478 int sockfd;
00479 NetLinkAddr localAddr;
00480 NetLinkAddr remoteAddr;
00481
00482 char remoteName[16];
00483 int remoteIsBot;
00484
00485 int state;
00486 int connection_id;
00487 int connectInitiator;
00488 char errorMsg[256];
00489
00490 int rs_inGame, ls_inGame;
00491
00492
00493 Vehicle *vehicle;
00494 int streamPos;
00495 int photonCount;
00496 PhotonDef photonList[STATE_MAX_PHOTONS];
00497
00498
00499 State rs_last, rs_current, rs_next, rs_tmp;
00500 u_int rs_count;
00501 int rs_delta_time;
00502 int remoteStreamPos;
00503
00504 int msgNumber, remoteMsgNumber, retryMsgNumber;
00505 list<Message> msgRecvQueue;
00506 deque<Message> msgSendQueue;
00507 deque<Message> pendSendAckQueue;
00508 deque<int> pendRecvAckQueue;
00509 deque<TPacket> sendQueue;
00510 #ifdef NLTEST_ENABLE
00511 list<TPacket> inetModelQueue;
00512 #endif
00513
00514
00515 u_int lastTime;
00516 u_int pollTimer, streamTimer, retryTimer;
00517 u_int ti_poll, ti_stream, ti_retry, ti_uc_retry;
00518 int retryCount, maxRetries;
00519
00520 int lastDeltaTime;
00521
00522
00523 u_int displayTime;
00524 u_int flashTimer;
00525 int displayMsgTimer;
00526 int displayFlash;
00527 char displayMessage[80];
00528 int dismsg_disconnect, dismsg_reject, dismsg_error, dismsg_timeout, dismsg_abort;
00529 int dismsg_packet_error, dismsg_version_error, dismsg_connect_fail, dismsg_invalid_ip;
00530 int dismsg_gametype;
00531 int enableDisplay;
00532
00533 public:
00534 void update();
00535 void send(Packet packet, NetLinkAddr addr);
00536 void send(int type, NetLinkAddr addr);
00537 void connect(const char *);
00538 void connect(NetLinkAddr);
00539 void connectAccept();
00540 void connectReject();
00541 void disconnect();
00542 int hasConnectRequest(){ return state==NLSTATE_RCON; }
00543 int isConnected(){ return state==NLSTATE_CONNECTED; }
00544 int isActive(){ return state!=NLSTATE_INACTIVE; }
00545 int isIdle(){ return state==NLSTATE_IDLE; }
00546 int isInitiator(){ return connectInitiator; }
00547 int remoteInGame(){ return state==NLSTATE_CONNECTED && rs_inGame; }
00548 const char *getRemoteName(){ return remoteName[0] ? remoteName : 0; }
00549 int isRemoteBot(){ return remoteIsBot; }
00550 const char *getDisplayMessage(){ return displayMessage; }
00551 void gameStateEnd(){ rs_inGame = 0; ls_inGame = 0; }
00552 void gameStateBegin(){ ls_inGame = 1; }
00553 void setDisplayState(int s){ enableDisplay = s; }
00554 int resolve(){ return connectInitiator; }
00555 void stream(Vehicle *v){ vehicle = v; }
00556 State *getRemoteState();
00557 void sendMsg(Message);
00558 int getMsg(Message&);
00559 int getMsg(Message&,int);
00560 void clearMessages(int);
00561 void sendPhoton(v3f x, v3f P, float lifeTimer);
00562 int init();
00563 void draw();
00564
00565 NetLink(){
00566 state = NLSTATE_INACTIVE;
00567
00568 lastTime = 0;
00569 streamTimer = 0;
00570 ti_poll = 10;
00571 ti_stream = 100;
00572 ti_retry = 3000;
00573 ti_uc_retry = 3000;
00574
00575 maxRetries = 5;
00576 retryTimer = 0;
00577
00578 displayTime = lastTime;
00579 displayFlash = 0;
00580
00581 vehicle = 0;
00582 rs_count = 0;
00583
00584 displayMessage[0] = 0;
00585 dismsg_disconnect = 0; dismsg_reject = 0; dismsg_error = 0; dismsg_timeout = 0;
00586 dismsg_packet_error = 0; dismsg_version_error = 0; dismsg_connect_fail = 0;
00587 dismsg_gametype = 0;
00588 enableDisplay = 1;
00589 }
00590
00591 friend class NetLinkStat;
00592 };
00593
00594 extern NetLink netLink;
00595 extern NetLinkStat netLinkStat;
00596
00597 #endif
00598