static TANG_MSG * request(int sock, const TANG_MSG *req, const char *file, int line) { TANG_MSG *msg = NULL; pkt_t pkt = {}; int r = 0; test((r = pkt_encode((const ASN1_VALUE *) req, &TANG_MSG_it, &pkt)) == 0); test((r = send(sock, pkt.data, pkt.size, 0)) == pkt.size); test((pkt.size = recv(sock, pkt.data, sizeof(pkt.data), 0)) > 0); test(msg = d2i_TANG_MSG(NULL, &(const unsigned char *) { pkt.data }, pkt.size)); return msg; }
void getFile(const int sfd, char *filename, int out){ //Ouverture fichier pour ecriture int fichier; if(out) fichier= fileno(stdin); else{ fichier= open(filename, O_WRONLY|O_CREAT|O_APPEND|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if(fichier==-1){ fprintf(stderr, "%s coudn't be opened.\n", filename); return; } } //Initialisations fd_set readfds,writefds; fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) | O_NONBLOCK); char *buffer; struct timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; pkt_t **stock; stock= malloc(sizeof(pkt_t)*WINSIZE); if(stock==NULL){ fprintf(stderr, "window allocation\n"); if(out!=1) close(fichier); return; } int k; for(k=0; k<=WINSIZE; k++) stock[k]= pkt_new(); uint8_t seq= 0, win= (uint8_t) WINSIZE-1; int ack= 0, err= 0, gotEof= 0; ssize_t bytes_read= 0; pkt_t *acquis; struct timeval rtt; struct timezone zone; while(1){ int ret= 0; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_SET(sfd, &readfds); FD_SET(sfd, &writefds); if((ret=select(sfd+1,&readfds,&writefds,NULL,&timeout))<0){ fprintf(stderr, "select()\n"); if(out!=1) close(fichier); return; } double tmp= getRtt(rtt); if(gotEof && win==WINSIZE-1 && tmp>MAXRTT) return; acquis= pkt_new(); //Socket vers fichier if(FD_ISSET(sfd,&readfds) && win>=0){ //Paquet recu buffer= malloc(sizeof(char)*BUFSIZE); if(buffer==NULL){ fprintf(stderr, "buffer allocation\n"); } bytes_read= read(sfd, (void *) buffer, BUFSIZE); if(bytes_read==0){ //Fin. si buffer encore rempli, attend d'avoir tout recu if(win==WINSIZE-1) return; gotEof= 1; } else if(bytes_read<0){ fprintf(stderr, "read(socket)\n"); } else{ pkt_t *paquet= pkt_new(); pkt_status_code state= pkt_decode(buffer, bytes_read, paquet); if(state!=PKT_OK){ //normalement decode contient le header si != E_NOHEADER fprintf(stderr, "corrupted packet\n"); if(bytes_read<=4 && state!=E_NOHEADER){ //Congestion //pkt_copy(acquis, paquet); acquis= paquet; acquis->type= PTYPE_NACK; acquis->window= win; ack= 2; } else //n'envoie rien pkt_del(paquet); } else{ if(paquet->length==0) gotEof= 1; if(paquet->seqnum==seq){ //bon paquet recu err= write(fichier, (void *) paquet->payload, paquet->length); if(err==-1){ fprintf(stderr, "write(fichier)\n"); return; } seq++; pkt_del(paquet); } else{ //stocke le paquet en attendant le bon stock[paquet->seqnum%WINSIZE]= paquet; win--; } ack= 1; } } free(buffer); } // vider le buffer contenant les paquets recus et ecrire le contenu dans un fichier SI le paquet a le bon numero de sequence int j, nomiss= 1; for(j=seq%WINSIZE; j<WINSIZE && nomiss; j= (j+1)%WINSIZE){ if(stock[j]->payload!=NULL){ err= write(fichier, (void *) stock[j]->payload, stock[j]->length); if(err==-1){ fprintf(stderr, "write(fichier)\n"); return; } fprintf(stderr, "\tn°%d ecrit.\n", stock[j]->seqnum); pkt_del(stock[j]); stock[j]= pkt_new(); seq++; win++; } else nomiss= 0; } //Confirmation vers Socket if(FD_ISSET(sfd,&writefds) && ack>0){ //Envoi acquis if(ack){ //acquis cumulatif acquis->type= PTYPE_ACK; acquis->window= win; acquis->seqnum= seq; } char *p; p= malloc(bytes_read*sizeof(char)); pkt_encode(acquis, p, (size_t *) &bytes_read); write(sfd, (void *) p, bytes_read); pkt_del(acquis); if(gotEof && win==WINSIZE-1) //dernier acquis à envoyer gettimeofday(&rtt,&zone); } ack= 0; waitFor(0); } if(out) close(fichier); return; }