#include #include #include #include #include #include #include #include #include #include #include #include static volatile int nbdead; static int debug=0; static void fctchild (int) { // write (1,"dead\n",5); nbdead++; } static void play_gettoken(SSTRING &token, const char *server, const char *page) { SSTRING *token; const char *page; glocal.token = &token; glocal.page = page; if (debug > 9) fprintf (stderr,"gettoken start server=%s page=%s\n",server,page); (server,"80",10); sendf ("GET %s HTTP/1.0\r\n\r\n",glocal.page); if (debug > 9) fprintf (stderr,"gettoken init\n"); // if (debug) fprintf (stderr,"gettoken line: %s\n",line); const char *pt = strstr(line,"token="); if (pt != NULL){ SSTRING tmp(pt+6); tmp.strip_end(); pt = tmp.get(); int len = strlen(pt); if (*pt == '"'){ pt++; len--; char *end = strchr(pt,'"'); if (end != NULL){ len--; } } glocal.token->setfrom (pt,len); // fprintf (stderr,"token= :%s:\n",glocal.token->get()); end = true; } if (debug > 9) fprintf (stderr,"gettoken end\n"); } typedef long long TIMEUSEC; static TIMEUSEC getnow() { struct timeval ti; gettimeofday(&ti,NULL); return ((long long)ti.tv_sec * 1000000) + ti.tv_usec; } static bool fusion = false; static int play_readpacket(FILE *fin, TIMEUSEC &ti, char buf[]) { int ret = 0; char line[100]; size_t bytes=0; int nbfusion=0; while (1){ struct timeval tmp; off_t pos = ftell(fin); if (fgets(line,sizeof(line)-1,fin)!=NULL && sscanf(line+3,"%08lx.%08lx:%u",&tmp.tv_sec,&tmp.tv_usec,&bytes)==3){ TIMEUSEC newti = ((long long)tmp.tv_sec * 1000000) + tmp.tv_usec; if (ret == 0 || (fusion && newti - 1000000 < ti)){ //if (ret > 0) fprintf (stderr,"Fusionne %d\n",nbfusion++); if (fread(buf+ret,1,bytes,fin)==bytes){ ret += bytes; buf[ret] = '\0'; ti = newti; }else{ fprintf (stderr,"short record\n"); break; } }else{ fseek (fin,pos,SEEK_SET); break; } }else{ break; } } return ret; } /* Extract the CONTENT feature of an HTTP META REFRESH statement */ static void uni_getcontent (const char *line, SSTRING &val) { line = strstr(line,"CONTENT="); if (line != NULL){ line+=8; if (line[0] == '"'){ line++; const char *end = line; while (*end != '\0' && *end != '"') end++; val.setfrom (line,(int)(end-line)); } } } static void play_doreport ( const char *line, const char *server, const char *port, const char *oldtoken, const char *newtoken) { if (server == NULL){ printf ("Pas de serveur défini: Rapport annulé: %s\n",line); }else{ if (debug > 2) fprintf (stderr,"sleeping 5\n"); sleep(5) ; // if (fork()==0){ int iter; SSTRING tmp; printf("Report: %s\n", line) ; glocal.tmp.setfrom(line); if (oldtoken != NULL && 0){ const char *pt = strstr(line,oldtoken); if (pt != NULL){ glocal.tmp.setfrom (line,(int)(pt-line)); glocal.tmp.append (newtoken); glocal.tmp.append (pt+strlen(oldtoken)); } } glocal.iter = 1000; // Nous devons redemander la page // plusieurs fois jusqu'a ce que nous // ayons le rapport glocal bool pdf = false; while (glocal.iter > 0){ glocal bool silent = false; glocal int delay = 5; glocal int size = 0; (server,port,10); SSTRING buf; buf.setfromf ("GET %s HTTP/1.1\r\n" "Accept: */*\r\n" "Accept-Language: en-us\r\n" "Accept-Encoding: gzip, deflate\r\n" "User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)\r\n" "Host: %s:%s\r\n" "Connection: Keep-Alive\r\n" "\r\n" ,glocal.tmp.get(),info.host,info.port); send (buf.get()); if (debug) fputs (buf.get(),stderr); glocal.size += info.linelen; if (line[0] < ' ') glocal.silent = true; if (!glocal.silent && debug) fprintf (stderr,"RAP: %s\n",line); if (glocal.silent && !glocal.pdf && debug) fprintf (stderr,"RAP: %s\n",line); if (strstr(line,"500 Internal")!=NULL){ printf ("Erreur rapport annulé: %s\n",line) ; _exit (0); } if (strstr(line,"REFRESH")!=NULL){ if (debug) fprintf (stderr,"REFRESH: %s\n",line); SSTRING content; uni_getcontent (line,content); glocal.delay = content.getval(); const char *url = content.strstr("URL"); if (debug > 9) fprintf (stderr,"REFRESH2: %d :%s:\n",glocal.delay,url); if (url != NULL){ end = true; glocal.tmp.setfrom (url+4); // bug glocal.iter = 2; glocal.pdf = true ; } } fprintf (stderr,"timeout play_doreport\n"); end = true; glocal.iter = 0; glocal.iter--; if (debug) fprintf (stderr,"size=%d\n",glocal.size); if (glocal.iter > 0 && glocal.delay > 0) sleep(glocal.delay); } // _exit (0); //} } } static void play_send ( _F_tcpconnect *c, const char *buf, int len, const char *oldtoken, const char *newtoken, int nbsend) { char newbuf[len+100]; if (oldtoken != NULL && oldtoken[0] != '\0'){ const char *pt = strstr(buf,oldtoken); if (pt != NULL){ memcpy (newbuf,buf,len); memcpy (newbuf+(pt-buf),newtoken,strlen(newtoken)); buf = newbuf; } } if (debug){ printf ("Send[%d]: ",nbsend); fwrite (buf,1,len,stdout); } c->send (buf,len); } static void getdate(char date[20]) { time_t ti = time(NULL); struct tm *t = localtime(&ti); sprintf (date,"%04d/%02d/%02d %02d:%02d:%02d" ,t->tm_year+1900,t->tm_mon+1,t->tm_mday ,t->tm_hour,t->tm_min,t->tm_sec); } static void play_oneclient ( const char *file, const char *server, const char *port, const char *tokenserv, const char *tokenpage, const char *reportserv, const char *reportport, int endfd, // Sends a byte on this handle when done bool burst, const char *log, int waittime, bool xml) // Produit un rapport xml { glocal const char *file = file; glocal FILE *fin = fopen (file,"r"); glocal const char *reportserv = reportserv; glocal const char *reportport = reportport; glocal bool burst = burst; if (glocal.fin == NULL){ fprintf (stderr,"Can't open file %s (%s)\n",file,strerror(errno)); }else if (fork()==0){ sleep(waittime); usleep (getpid()); glocal int len = 0; glocal char buf[1000000]; glocal SSTRING token; glocal SSTRING oldtoken; glocal TIMEUSEC next; // Next time we must send something glocal TIMEUSEC last; glocal TIMEUSEC lastsend; // Last time we sent something glocal TIMEUSEC duration = 0; glocal int nbsend = 0; glocal int nbreceive = 0; glocal int receive = 0; glocal bool recu = false; if (tokenserv != NULL) play_gettoken(glocal.token,tokenserv,tokenpage); (server,port,30); TIMEUSEC start; glocal.len = play_readpacket(glocal.fin,start,glocal.buf); if (glocal.len > 0 && strncmp(glocal.buf,"TOKEN=",6)==0 && glocal.token.is_empty()){ glocal.len = play_readpacket (glocal.fin,start,glocal.buf); } if (glocal.len <= 0){ end = true; }else{ if (glocal.token.is_filled() && strncmp(glocal.buf,"TOKEN=",6)==0){ strip_end (glocal.buf); glocal.oldtoken.setfrom(glocal.buf+6); strcat (glocal.buf,"\r\n"); printf ("Nouveau token remplacé\n"); play_send (this,glocal.buf,glocal.len,glocal.oldtoken.get() ,glocal.token.get(),glocal.nbsend); }else{ if (debug){ printf ("Send : "); fwrite (glocal.buf,1,glocal.len,stdout); } send (glocal.buf,glocal.len); } glocal.len = play_readpacket(glocal.fin,glocal.last,glocal.buf); TIMEUSEC now = getnow(); glocal.next = glocal.last - start + now; glocal.lastsend = now; if (debug) fprintf (stderr,"now %Ld %Ld %Ld\n",now,glocal.next, glocal.next - now); glocal.nbsend++; } fprintf (stderr,"play_oneclient: fail %s (errno=%s)\n",glocal.file,strerror(errno)); TIMEUSEC now = getnow(); if (debug > 2) fprintf (stderr,"REP %Ld %Ld %Ld\n",glocal.lastsend,now,now-glocal.lastsend); glocal.duration += (now-glocal.lastsend); glocal.nbreceive++; glocal.receive += info.linelen; if (debug > 2) fprintf (stderr,"oneline len %d: %s\n",info.linelen,line); if (0 && strstr(line,"REPORT_SRV_URL")!=NULL){ char *pt = str_skipword(line); pt = str_skipword(pt); SSTRING tmp; str_extract (pt,tmp); play_doreport (tmp.get(),glocal.reportserv,glocal.reportport ,glocal.oldtoken.get(),glocal.token.get()); } glocal.recu = true; if (glocal.len > 0 && (glocal.burst || now >= glocal.next)){ glocal.nbsend++; play_send (this,glocal.buf,glocal.len,glocal.oldtoken.get() ,glocal.token.get(),glocal.nbsend); TIMEUSEC ti; glocal.len = play_readpacket(glocal.fin,ti,glocal.buf); TIMEUSEC attend = ti - glocal.last; glocal.next = attend + now; glocal.last = ti; glocal.recu = false; } glocal.lastsend = now; if (glocal.len <= 0){ set_timeout (30); }else if (glocal.burst && 0){ set_timeout (5); }else{ TIMEUSEC delay = glocal.next - now; set_timeout (delay/1000000,delay%1000000); } TIMEUSEC now = getnow(); fprintf (stderr,"time_out %Ld %Ld len=%d\n",now,glocal.next,glocal.len); if (glocal.len <= 0){ end = true; }else if (!glocal.recu){ fprintf (stderr,"attend plus\n"); glocal.next = now + 4000000; glocal.recu = true; }else if (glocal.burst || now >= glocal.next){ glocal.nbsend++; play_send (this,glocal.buf,glocal.len,glocal.oldtoken.get() ,glocal.token.get(),glocal.nbsend); TIMEUSEC ti; glocal.len = play_readpacket(glocal.fin,ti,glocal.buf); TIMEUSEC attend = ti - glocal.last; glocal.next = attend + now; glocal.last = ti; glocal.lastsend = now; glocal.recu = false; } if (glocal.len <= 0){ set_timeout (30); }else{ TIMEUSEC delay = glocal.next - now; set_timeout (delay/1000000,delay%1000000); } write (endfd,".",1); if (log != NULL){ (log,true); char date[20]; getdate(date); fprintf (fout,"%s %Ld %d %d %d %s\n",glocal.file,glocal.duration ,glocal.nbsend,glocal.nbreceive,glocal.receive ,date); return 0; } if (xml){ printf ("\n" ,glocal.file ,glocal.nbsend,glocal.nbreceive ,glocal.duration ,glocal.receive); }else{ char date[20]; getdate(date); printf ("Duration: %Ld %d %d %d %s\n",glocal.duration,glocal.nbsend ,glocal.nbreceive,glocal.receive,date); fflush (stdout); } _exit (0); }else{ fclose (glocal.fin); } } int main (int argc, char *argv[]) { int nbclients; int delay; const char *server; const char *port; const char *tokenserv; const char *tokenpage; const char *reportserv; const char *reportport; bool loop; bool burst; const char *log; bool xml; glocal.nbclients = 1; glocal.delay = 10; glocal.port = NULL; glocal.server = NULL; glocal.tokenserv = NULL; glocal.tokenpage = "/crweb/cgi-bin/crweb.cgi"; glocal.reportserv = NULL; glocal.reportport = NULL; glocal.loop = false; glocal.burst = false; glocal.log = NULL; glocal.xml = false; int ret = (argc, argv); setproginfo ("uniplayback",PACKAGE_REV ,"uniplayback [ options ] in-files ...\n"); setarg ('n',"nbclients","Nombre de client simultané",glocal.nbclients,false); setarg ('d',"delay","Delai entre le démarage des clients",glocal.delay,false); setarg ('f',"fusion","Fusionne les paquets consécutifs",fusion,false); setarg ('D',"debug","Debug",debug,false); setarg ('l',"loop","Répétition de la séquence, sans arrêt",glocal.loop,false); setarg ('s',"server","Nom ou IP du serveur applicatif",glocal.server,true); setarg ('t',"tokenserv","Nom ou IP du serveur de token",glocal.tokenserv,false); setarg ('P',"tokenpage","Page web fournissant le token",glocal.tokenpage,false); setarg ('r',"reportserv","Nom ou IP du serveur de rapport",glocal.reportserv,false); setarg ('p',"port","Port TCP du serveur applicatif",glocal.port,true); setarg ('o',"reportport","Port TCP du serveur de rapport",glocal.reportport,false); setarg ('b',"burst","Envoie les requêtes sans délai",glocal.burst,false); setarg ('L',"log","Ajoute des statistics au journal",glocal.log,false); setarg ('x',"xml","Produit un rapport xml pour chaque session",glocal.xml,false); int ret = -1; if (glocal.server == NULL){ fprintf (stderr,"Server not specified\n\n"); usage(); }else if (glocal.port == NULL){ fprintf (stderr,"Port not specified\n\n"); usage(); }else{ if (glocal.log != NULL && !file_exist(glocal.log)){ (glocal.log,true); char date[20]; getdate(date); fprintf (fout,"test Temps-reponse(us) nbsend nbreceive sizereceive date\n"); return 0; } ret = 0; int nofile = 0; int nbwaitdead = 0; signal (SIGCHLD,fctchild); int tbfd[2]; if (pipe(tbfd)==-1){ fprintf (stderr,"Can't setup control pipe (%s)\n" ,strerror(errno)); }else{ int nbrunning = 0; int sofar = 0; int maxsession = argc > glocal.nbclients ? argc : glocal.nbclients; while (1){ if (debug) fprintf (stderr,"nbrunning %d,sofar %d\n",nbrunning,sofar); while (nbrunning < glocal.nbclients && (glocal.loop || sofar < maxsession)){ int delay = 0; if (sofar < glocal.nbclients){ delay = glocal.delay*(nbrunning%10); } play_oneclient (argv[nofile],glocal.server,glocal.port ,glocal.tokenserv,glocal.tokenpage ,glocal.reportserv ,glocal.reportport,tbfd[1] ,glocal.burst,glocal.log ,delay ,glocal.xml); nofile = (nofile+1)%argc; nbrunning++; sofar++; } // sleep(glocal.delay); fd_set in; FD_ZERO (&in); FD_SET (tbfd[0],&in); struct timeval tmout; tmout.tv_sec = 1; tmout.tv_usec = 0; if (select(tbfd[0]+1,&in,NULL,NULL,&tmout)>0){ char buf[glocal.nbclients]; int len = read(tbfd[0],buf,glocal.nbclients); if (debug) fprintf (stderr,"Process ending: %d\n",len); if (len > 0){ nbrunning -= len; if (nbrunning <= 0 && !glocal.loop && sofar >= maxsession) break; } } while(nbwaitdead < nbdead){ int status; wait(&status); nbwaitdead++; } } close (tbfd[0]); close (tbfd[1]); } } return ret; return ret; }