Main Page | Modules | Namespace List | Class Hierarchy | Compound List | File List | Compound Members | File Members

netlink.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * $Id: netlink.h,v 1.10 2003/07/16 11:42:15 schou Exp $
00003  * Author: Jakob Schou Jensen <schou@sourceforge.net>
00004  * Licence: GPL
00005  *
00006  * Description: Netlink handles communication between rover applications over
00007  *              network.
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 // NetLink meta messages
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 // Netlink connected state messages
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 // NetLink states
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 // NetLink test defines
00085 //#define NLTEST_ENABLE 1
00086 #define NLTEST_PACKET_DELAY 100
00087 #define NLTEST_PACKET_DVAR 10
00088 #define NLTEST_DROP_INTERVAL 1000000
00089 
00091 // NetLinkStat
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   // Delta time arrays
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 // NetLinkAddr
00130 
00131 #ifdef ADSO_WINDOWS
00132 struct sockaddr_un { // this is a dummy definition, unix sockets will not work in windows
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       /*if(inet_aton(addr_str,&iaddr.sin_addr)) valid = 1; // the right way
00249       else valid = 0;*/
00250       iaddr.sin_addr.s_addr = inet_addr(addr_str); // the windows way
00251       if(iaddr.sin_addr.s_addr == INADDR_NONE) valid = 0;
00252     }
00253   }
00254 };
00255 
00257 // State
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     /*rb.mass = b->rb.mass;
00281       rb.Ibodyinv = b->rb.Ibodyinv;*/
00282     
00283     massPos = (1.0-w)*a->massPos + w*b->massPos;
00284     R = a->R*(1.0-w) + b->R*w;
00285     /*rb.P = (1.0-w)*a->rb.P + w*b->rb.P;
00286     rb.L = (1.0-w)*a->rb.L + w*b->rb.L;
00287     
00288     rb.Iinv = a->rb.Iinv*(1.0-w) + b->rb.Iinv*w;
00289     rb.vel = (1.0-w)*a->rb.vel + w*b->rb.vel;
00290     rb.omega = (1.0-w)*a->rb.omega + w*b->rb.omega;
00291     rb.force = (1.0-w)*a->rb.force + w*b->rb.force;
00292     rb.torque = (1.0-w)*a->rb.torque + w*b->rb.torque;*/
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 // Message
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 // Packet
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 // NetLink
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   // State stream
00493   Vehicle *vehicle;
00494   int streamPos;
00495   int photonCount;
00496   PhotonDef photonList[STATE_MAX_PHOTONS];
00497 
00498   // Remote state
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; // messages that has been sent but need acknowledge
00508   deque<int> pendRecvAckQueue; // message numbers that needs to be acknowledged
00509   deque<TPacket> sendQueue;
00510 #ifdef NLTEST_ENABLE
00511   list<TPacket> inetModelQueue;
00512 #endif
00513 
00514   // net access timing
00515   u_int lastTime;
00516   u_int pollTimer, streamTimer, retryTimer;
00517   u_int ti_poll, ti_stream, ti_retry, ti_uc_retry;  // timer interval
00518   int retryCount, maxRetries;
00519 
00520   int lastDeltaTime;
00521 
00522   // display timing
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 

Generated on Mon Jul 21 10:44:47 2003 for Rover by doxygen 1.3.2