#include #include #include #include #include #include #include #include #include #include using namespace std; static long long getnow () { struct timeval tv; gettimeofday (&tv,NULL); return tv.tv_sec *(long long)1000000 + tv.tv_usec; } class C_INFO: public ARRAY_OBJ{ public: bool is_ctl; bool is_client; int talkto; }; class C_BLK{ public: int target_tick; int talkto; int linelen; char *line; C_BLK(int _target_tick, int _talkto, const char *_line, int _linelen) { target_tick = _target_tick; talkto = _talkto; linelen = _linelen; line = NULL; if (linelen >= 0){ line = (char*)malloc(_linelen); memcpy (line,_line,_linelen); } } ~C_BLK() { free (line); } C_BLK(const C_BLK &c) { target_tick = c.target_tick; talkto = c.talkto; linelen = c.linelen; line = NULL; if (linelen >= 0){ line = (char*)malloc (c.linelen); memcpy (line,c.line,c.linelen); } } C_BLK &operator =(const C_BLK &c) { target_tick = c.target_tick; talkto = c.talkto; linelen = c.linelen; line = NULL; if (linelen >= 0){ line = (char*)malloc (c.linelen); memcpy (line,c.line,c.linelen); } return *this; } }; int main (int argc, char *argv[]) { glocal int ret = -1; glocal const char *host = NULL; glocal const char *dport = NULL; glocal const char *lport = "8200"; glocal int nbtick = 10; glocal.ret = (argc,argv); setarg ('h',"host","host to connect",glocal.host,true); setarg ('l',"listen","Listen on this port",glocal.lport,false); setarg ('p',"port","port to connect",glocal.dport,true); setarg ('n',"nbtick","nbtick X 10ms",glocal.nbtick,false); { glocal int tick = 0; glocal vector blks; glocal long long lastnow = getnow(); glocal int lasttick = 0; (glocal.lport,10); C_INFO *inf = new C_INFO; inf->is_ctl = false; inf->is_client = true; inf->talkto = cmdsock_connect (glocal.host ,glocal.dport,10,1); if (inf->talkto == -1){ endclient = true; }else{ C_INFO *inf2 = new C_INFO; inf2->talkto = no; inf2->is_ctl = false; inf2->is_client = false; inject (inf->talkto,inf2); debug_printf ("newclient %d -> %d\n",no,inf->talkto); } info.data = inf; settcpnodelay(true); C_INFO *inf = (C_INFO*)info.data; debug_printf ("endclient %d -> %d\n",no,inf->talkto); // On enleve toutes references a ce handle // On transmet tout ce qui est en attente pour le destinataire // et on le ferme for (vector::iterator it=glocal.blks.begin(); it != glocal.blks.end(); it++){ if (it->talkto == no){ it->talkto = -1; }else if (it->talkto == inf->talkto){ sendto (it->talkto,it->line,it->linelen); it->talkto = -1; } } closeclient (inf->talkto); C_INFO *inf = (C_INFO*)info.data; if (inf->is_ctl){ if ((glocal.tick % 10000)==0){ long long now = getnow(); double rate=(glocal.tick-glocal.lasttick)/(double)(now-glocal.lastnow)*1000000; debug_printf ("tick %d %lfticks/s\n",glocal.tick,rate); glocal.lastnow = now; glocal.lasttick = glocal.tick; } glocal.tick++; int delto = 0; for (vector::iterator it=glocal.blks.begin(); it != glocal.blks.end(); it++){ if (it->target_tick <= glocal.tick){ if (it->talkto != -1){ if (it->linelen == -1){ closeclient (it->talkto); }else{ //debug_printf ("Send %d [%d]\n",it->talkto,it->linelen); sendto (it->talkto,it->line,it->linelen); } } delto++; } } if (delto > 0){ glocal.blks.erase (glocal.blks.begin() ,glocal.blks.begin() + delto); } }else{ //debug_printf ("Rec %d -> %d [%d]\n",no,inf->talkto,info.linelen); glocal.blks.push_back(C_BLK(glocal.tick+glocal.nbtick ,inf->talkto,line,info.linelen)); } s.setrawmode (true); int tb[2]; if (pipe(tb)==-1){ tlmp_error ("Set pipe (%s)\n",strerror(errno)); }else{ pid_t pid = fork(); if (pid == (pid_t)0){ close (tb[0]); while (1){ usleep(100); write (tb[1]," ",1); } _exit (1); }else if (pid == (pid_t)-1){ tlmp_error ("Can't fork (%s)\n",strerror(errno)); }else{ C_INFO *inf = new C_INFO; inf->is_ctl = true; s.inject (tb[0],inf); close (tb[1]); s.loop(); } } } return 0; return glocal.ret; }