ssize_t dg_send_recv(int fd, const void *outbuff, size_t outbytes, void *inbuff, size_t inbytes, const SA *destaddr, socklen_t destlen) { ssize_t n; struct iovec iovsend[2], iovrecv[2]; if (rttinit == 0) { rtt_init(&rttinfo); /* first time we're called */ rttinit = 1; rtt_d_flags = 1; } sendhdr.seq++; msgsend.msg_name = destaddr; msgsend.msg_namelen = destlen; msgsend.msg_iov = iovsend; msgsend.msg_iovlen = 2; iovsend[0].iov_base = &sendhdr; iovsend[0].iov_len = sizeof(struct hdr); iovsend[1].iov_base = outbuff; iovsend[1].iov_len = outbytes; msgrecv.msg_name = NULL; msgrecv.msg_namelen = 0; msgrecv.msg_iov = iovrecv; msgrecv.msg_iovlen = 2; iovrecv[0].iov_base = &recvhdr; iovrecv[0].iov_len = sizeof(struct hdr); iovrecv[1].iov_base = inbuff; iovrecv[1].iov_len = inbytes; Signal(SIGALRM, sig_alrm); rtt_newpack(&rttinfo); /* initialize for this packet */ sendagain: sendhdr.ts = rtt_ts(&rttinfo); Sendmsg(fd, &msgsend, 0); alarm(rtt_start(&rttinfo)); /* calc timeout value & start timer */ if (sigsetjmp(jmpbuf, 1) != 0) { if (rtt_timeout(&rttinfo) < 0) { err_msg("dg_send_recv: no response from server, giving up"); rtt_init = 0; /* reinit in case we're called again */ errno = ETIMEDOUT; return -1; } goto sendagain; } do { n = Recvmsg(fd, &msgrecv, 0); } while (n < sizeof(struct hdr) || recvhdr.seq != sendhdr.seq); alarm(0); /* stop SIGALRM timer. */ /* calculate & store new RTT estimator value. */ rtt_stop(&rttinfo, rtt_ts(&rttinfo) - recvhdr.ts); return (n - sizeof(struct hdr)); /* return size of received datagram. */ }
ssize_t dg_send_recv(int fd, const void *outbuff, size_t outbytes, void *inbuff, size_t inbytes, const SA *destaddr, socklen_t destlen) { ssize_t n; struct iovec iovsend[2], iovrecv[2]; if (rttinit == 0) { rtt_init(&rttinfo); /* first time we're called */ rttinit = 1; rtt_d_flag = 1; } sendhdr.seq++; msgsend.msg_name = destaddr; msgsend.msg_namelen = destlen; msgsend.msg_iov = iovsend; msgsend.msg_iovlen = 2; iovsend[0].iov_base = &sendhdr; iovsend[0].iov_len = sizeof(struct hdr); iovsend[1].iov_base = outbuff; iovsend[1].iov_len = outbytes; msgrecv.msg_name = NULL; msgrecv.msg_namelen = 0; msgrecv.msg_iov = iovrecv; msgrecv.msg_iovlen = 2; iovrecv[0].iov_base = &recvhdr; iovrecv[0].iov_len = sizeof(struct hdr); iovrecv[1].iov_base = inbuff; iovrecv[1].iov_len = inbytes; /* end dgsendrecv1 */ /* include dgsendrecv2 */ if (signal(SIGALRM, sig_alrm) == SIG_ERR) { perror("signal error"); exit(1); } rtt_newpack(&rttinfo); /* initialize for this packet */ sendagain: #ifdef RTT_DEBUG fprintf(stderr, "send %4d: ", sendhdr.seq); #endif sendhdr.ts = rtt_ts(&rttinfo); int nbytes = 0; /* must first figure out what return value should be */ int i; for (i = 0; i < msgsend.msg_iovlen; i++) nbytes += msgsend.msg_iov[i].iov_len; if (sendmsg(fd, &msgsend, 0) != nbytes) { perror("sendmsg error"); exit(1); } alarm(rtt_start(&rttinfo)); /* calc timeout value & start timer */ #ifdef RTT_DEBUG rtt_debug(&rttinfo); #endif if (sigsetjmp(jmpbuf, 1) != 0) { if (rtt_timeout(&rttinfo) < 0) { fprintf(stderr, "dg_send_recv: no response from server, giving up\n"); rttinit = 0; /* reinit in case we're called again */ errno = ETIMEDOUT; return(-1); } #ifdef RTT_DEBUG fprintf(stderr, "dg_send_recv: timeout, retransmitting\n"); #endif goto sendagain; } do { if ((n = recvmsg(fd, &msgrecv, 0)) < 0) { perror("recvmsg error"); exit(1); } #ifdef RTT_DEBUG fprintf(stderr, "recv %4d\n", recvhdr.seq); #endif } while (n < sizeof(struct hdr) || recvhdr.seq != sendhdr.seq); alarm(0); /* stop SIGALRM timer */ /* 4calculate & store new RTT estimator values */ rtt_stop(&rttinfo, rtt_ts(&rttinfo) - recvhdr.ts); return(n - sizeof(struct hdr)); /* return size of received datagram */ }
/* RETURNS ACK_NO */ int dg_recieve_ack( int fd ) { ssize_t n; struct iovec iovrecv[2]; char IPClient[20]; memset( &msgrecv, '\0', sizeof(msgrecv) ); memset( &recvhdr, '\0', sizeof(recvhdr) ); msgrecv.msg_name = NULL; msgrecv.msg_namelen = 0; msgrecv.msg_iov = iovrecv; msgrecv.msg_iovlen = 2; iovrecv[0].iov_base = &recvhdr; iovrecv[0].iov_len = sizeof(struct hdr); if( n = Recvmsg( fd, &msgrecv, 0) < 0 ) { printf("Error in RecvMsg!!\n"); printf("Error no : %d\n", errno ); exit(0); } if( recvhdr.ack_no == -3 ) { printf("Recieved a FIN-ACK from client..\n"); // struct itimerval value, ovalue, pvalue; // value.it_interval.tv_sec = 0; /* Zero seconds */ // value.it_interval.tv_usec = 0; /* Two hundred milliseconds */ // value.it_value.tv_sec = 0; /* Zero seconds */ // value.it_value.tv_usec = 0; /* Five hundred milliseconds */ // setitimer( ITIMER_REAL, &value, &ovalue ); return -3; } /* If we recieved the right packet ACKNOWLEDGEMENT, that is one which na was pointing to, we calculate RTT */ if( na == (recvhdr.ack_no - 1) ) { rtt_stop(&rttinfo, rtt_ts(&rttinfo) - recvhdr.ts); rtt_newpack( &rttinfo ); printf("Recieved an ACK-%d from client..\n", recvhdr.ack_no ); } printf( "Updating the reciever advertisement global variable with %d..\n", recvhdr.recv_window_advertisement ); recv_advertisement = recvhdr.recv_window_advertisement; update_na( recvhdr.ack_no ); current_ack = recvhdr.ack_no; if( prev_ack == current_ack ) { /* We got 3 DUP's */ dup_ack++; } else { dup_ack = 0; } /* swap fpr next ACK */ prev_ack = current_ack; return recvhdr.ack_no; }
static int su_serv_send_recv_act(su_serv_t *psvr, SA *destaddr, socklen_t destlen, const void *outbuff, int outbytes, void *inbuff, int inbytes, int retransmit) { int n; struct iovec iovsend[2]= {{0}}; struct msghdr msgsend = {0}; /* assumed init to 0 */ suhdr_t *r, sendhdr = {0}; /* protocol header */ int ret, waitsec; struct list *node = 0; frames_t *packet = 0; pthread_mutex_lock(&psvr->mutex); pthread_mutex_lock(&psvr->lock); if (retransmit == 0) { psvr->seq++; psvr->retransmission = 1; } else { if (psvr->retransmission == 0) { pthread_mutex_unlock(&psvr->mutex); pthread_mutex_unlock(&psvr->lock); errno = ETIMEDOUT; return -1; } psvr->retransmission --; } if (psvr->rttinit == 0) { rtt_init(&psvr->rttinfo, psvr->retry); /* first time we're called */ psvr->rttinit = 1; } sendhdr.act = SU_SYN; sendhdr.type = SU_RELIABLE; sendhdr.sid = psvr->sid; sendhdr.seq = psvr->seq; msgsend.msg_name = (void*)destaddr; msgsend.msg_namelen = destlen; msgsend.msg_iov = iovsend; msgsend.msg_iovlen = 2; iovsend[0].iov_base = (void*)&sendhdr; iovsend[0].iov_len = sizeof(suhdr_t); iovsend[1].iov_base = (void*)outbuff; iovsend[1].iov_len = outbytes; struct timespec abstime = {0}; suhdr_t *precvhdr; rtt_newpack(&psvr->rttinfo); /* initialize for this packet */ psvr->ackwaitnum ++; sendagain: sendhdr.ts = rtt_ts(&psvr->rttinfo); if (sendmsg(psvr->fd, &msgsend, 0) < 0) { ERR_RET("sendmsg error"); goto error_ret; } waitsec = rtt_start(&psvr->rttinfo); /* calc timeout value & start timer */ #ifdef SU_DEBUG_RTT fprintf(stderr, ColorRed "send seq %4d: " ColorEnd, sendhdr.seq); rtt_debug(&psvr->rttinfo); #endif /* set timed wait time-point */ maketimeout_seconds(&abstime, waitsec); #ifdef SU_DEBUG_TIMEVERBOSE struct timeval now; gettimeofday(&now, 0); log_msg( ColorBlue "pthread_cond_timedwait : %u.%u time expire" ColorEnd, abstime.tv_sec, abstime.tv_nsec); log_msg( ColorBlue "pthread_cond_timedwait : %d.%d now time" ColorEnd, now.tv_sec, now.tv_usec*1000); #endif timedwaitagain: ret = pthread_cond_timedwait(&psvr->ackcond, &psvr->lock, &abstime); if (ret == 0) { #ifdef SU_DEBUG_TIMEVERBOSE struct timeval now; gettimeofday(&now, 0); log_msg(ColorBlue "pthread_cond_timedwait : %d.%d ack cond interrupt" ColorEnd, now.tv_sec, now.tv_usec*1000); #endif node = psvr->ackrecvls.next; for (; node != &psvr->ackrecvls; node = node->next) { packet = container_of(node, frames_t, node); r = &packet->recvhdr; if (su_cmp_ack_SU_RELIABLE(&sendhdr, r)) { break; } } if ( node == &psvr->ackrecvls ) { /* Be careful of the lock, locked -> timedwait -> unlock */ #ifdef SU_DEBUG_LIST log_msg("serv %x no found seq %d ack, timed wait again", psvr, sendhdr.seq); #endif goto timedwaitagain; } /* Find response packet node */ list_remove(&packet->node); n = packet->len; precvhdr = &packet->recvhdr; #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST log_msg("serv %x finded ack " ColorRed "%p" ColorEnd " seq %d datagram len %d", psvr, packet, r->seq, packet->len); #endif #ifdef SU_DEBUG_RTT fprintf(stderr, ColorRed "recv seq %4d \n" ColorEnd, precvhdr->seq); #endif // SU_RELIABLE received response, copy to user buffer memcpy(inbuff, packet->data, n > inbytes ? inbytes : n); } else if (ret == EINTR) { log_msg("pthread_cond_timedwait system EINTR"); goto timedwaitagain; } else if (ret == ETIMEDOUT) { #ifdef SU_DEBUG_TIMEVERBOSE struct timeval now; gettimeofday(&now, 0); log_msg(ColorBlue "pthread_cond_timedwait : %u.%u ETIMEOUT have expired" ColorEnd, now.tv_sec, now.tv_usec*1000); #endif if (rtt_timeout(&psvr->rttinfo) < 0) { #ifdef SU_DEBUG_RTT err_msg(ColorYel "no response from server, giving up" ColorEnd); #endif psvr->rttinit = 0; /* reinit in case we're called again */ errno = ETIMEDOUT; goto error_ret; } #ifdef SU_DEBUG_RTT err_msg(ColorRed " seq %4d timeout, retransmitting %d" ColorEnd, sendhdr.seq, ++retransmit); #endif goto sendagain; } else { errno = ret; ERR_RET(" su_serv_send_recv_act unknown error[%d]", ret); goto error_ret; } /* calculate & store new RTT estimator values */ rtt_stop(&psvr->rttinfo, rtt_ts(&psvr->rttinfo) - precvhdr->ts); if (--psvr->ackwaitnum == 0) { su_serv_list_empty(psvr, &psvr->ackrecvls); } pthread_mutex_unlock(&psvr->mutex); pthread_mutex_unlock(&psvr->lock); #ifdef SU_DEBUG_LIST log_msg("serv %x free node " ColorRed "%p"ColorEnd" seq %d", psvr, packet, sendhdr.seq); #endif free(packet); return(n); /* return size of received datagram */ error_ret: if (--psvr->ackwaitnum == 0) { su_serv_list_empty(psvr, &psvr->ackrecvls); } pthread_mutex_unlock(&psvr->mutex); pthread_mutex_unlock(&psvr->lock); return(-1); }
int sendFileContents(int sockfd,int totalblocks, int windowsize){ //printf("%d\n", totalblocks); int first_unacknowledged_pos = 0; int pos_sent = -1; int prev_ack = 0; struct dgram recv_packet; int dups = 0; int recv_ack = -1; int retransmit = 0; int rtt_measured_packet = 0; uint32_t ts; int starttimer = 1; int hasBeenRtransmitted = 0; int slow_start = 1; Signal(SIGALRM, sig_alrm); if (rttinit == 0) { rtt_init(&rttinfo); /* first time we're called */ rttinit = 1; rtt_d_flag = 1; } while(1){ retransmitpack: if(retransmit){ printf("RETRANSMIT PACKET: %d\n", first_unacknowledged_pos); hasBeenRtransmitted = 1; slow_start = 1; Sendto(sockfd, (void *)&fileContent[first_unacknowledged_pos], sizeof(struct dgram), 0, NULL, NULL); retransmit = 0; } if (sigsetjmp(jmpbuf, 1) != 0) { //rtt_debug(&rttinfo); if (rtt_timeout(&rttinfo) < 0) { err_msg("no response from client, giving up"); rttinit = 0; errno = ETIMEDOUT; return(-1); } retransmit = 1; goto retransmitpack; } int sent_packets = 0; while( (0 < slow_start) && (pos_sent < totalblocks-1) && (pos_sent + 1 < first_unacknowledged_pos + windowsize)){ if(starttimer){ rtt_newpack(&rttinfo); alarm(rtt_start(&rttinfo)); ts = rtt_ts(&rttinfo); starttimer = 0; rtt_measured_packet = fileContent[pos_sent+1].seqNum; hasBeenRtransmitted = 0; } Sendto(sockfd, (void *)&fileContent[pos_sent+1], sizeof(struct dgram), 0, NULL, NULL); printf("SEND PACKET: %d\n", pos_sent+1); pos_sent++; slow_start--; } if(Recvfrom(sockfd, &recv_packet, sizeof(struct dgram), 0, NULL, NULL) < 0){ err_msg("Receive error from client"); return -1; } else{ //rtt_debug(&rttinfo); windowsize = recv_packet.windowsize; if(recv_packet.ack == recv_ack){ dups++; } else { dups = 0; } recv_ack = recv_packet.ack; printf("RECEIVED ACK: %d\n", recv_ack); if(dups == 0){ alarm(0); if(!hasBeenRtransmitted && recv_ack > rtt_measured_packet) rtt_stop(&rttinfo, rtt_ts(&rttinfo) - ts); starttimer = 1; slow_start += 2*(recv_ack - prev_ack); } prev_ack = recv_ack; first_unacknowledged_pos = recv_packet.ack; retransmit = 0; if(dups >= MAXDUPS){ // retransmit first unack pos retransmit = 1; goto retransmitpack; } } if( first_unacknowledged_pos > 0 && fileContent[first_unacknowledged_pos-1].eof){ printf("SUCCESS: SENT ENTIRE FILE\n"); break; } } return totalblocks; }
ssize_t dg_send_recv(int fd, const void *outbuff, size_t outbytes, void *inbuff, size_t inbytes, const SA *destaddr, socklen_t destlen) { ssize_t n; struct iovec iovsend[2], iovrecv[2]; fd_set rset; int nsel, maxfdp1; struct timeval tv; if (rttinit == 0) { rtt_init(&rttinfo); /* first time we're called */ rttinit = 1; rtt_d_flag = 1; } sendhdr.seq++; msgsend.msg_name = destaddr; msgsend.msg_namelen = destlen; msgsend.msg_iov = iovsend; msgsend.msg_iovlen = 2; iovsend[0].iov_base = &sendhdr; iovsend[0].iov_len = sizeof(struct hdr); iovsend[1].iov_base = outbuff; iovsend[1].iov_len = outbytes; msgrecv.msg_name = NULL; msgrecv.msg_namelen = 0; msgrecv.msg_iov = iovrecv; msgrecv.msg_iovlen = 2; iovrecv[0].iov_base = &recvhdr; iovrecv[0].iov_len = sizeof(struct hdr); iovrecv[1].iov_base = inbuff; iovrecv[1].iov_len = inbytes; rtt_newpack(&rttinfo); /* initialize for this packet */ sendagain: #ifdef RTT_DEBUG fprintf(stderr, "send %4d: ", sendhdr.seq); #endif sendhdr.ts = rtt_ts(&rttinfo); Sendmsg(fd, &msgsend, 0); alarm(rtt_start(&rttinfo)); /* calc timeout value & start timer */ #ifdef RTT_DEBUG rtt_debug(&rttinfo); #endif tv.tv_sec = rtt_start(&rttinfo); tv.tv_usec = 0; maxfdp1 = fd + 1; again: FD_ZERO(&rset); FD_SET(fd, &rset); nsel = select(maxfdp1, &rset, NULL, NULL, &tv); if ((nsel == -1) || (errno == EINTR)) goto again; else if (nsel == -1) err_msg("select error"); else if (nsel == 0) { if (rtt_timeout(&rttinfo) < 0) { err_msg("dg_send_recv: no response from server, giving up"); rttinit = 0; /* reinit in case we're called again */ errno = ETIMEDOUT; return(-1); } #ifdef RTT_DEBUG err_msg("dg_send_recv: timeout, retransmitting"); #endif goto sendagain; } if (FD_ISSET(fd, &rset)) { do { n = Recvmsg(fd, &msgrecv, 0); #ifdef RTT_DEBUG fprintf(stderr, "recv %4d\n", recvhdr.seq); #endif } while (n < sizeof(struct hdr) || recvhdr.seq != sendhdr.seq); } /* 4calculate & store new RTT estimator values */ rtt_stop(&rttinfo, rtt_ts(&rttinfo) - recvhdr.ts); return(n - sizeof(struct hdr)); /* return size of received datagram */ }
void child(int index, struct sockaddr_in* ptr_connaddr, struct datagram* ptr_conn_gram) { struct datagram recv_gram; struct datagram send_gram; struct datagram* sendbuf; uint32_t* sendtv; char *tmp; int sockfd; int nready; int i; fd_set rset, allset; int maxfdp1 = 0; struct sockaddr_in servaddr, cliaddr; int local = 0; int on = 1; int len; //int filepos = -1; int filesize = 0; int servsockclosed = 0; int recv_seq; int last_ack; int last_ack_times; int recv_ack; int send_seq; int send_flag; int seq = 2568; int newport = 0; int recv_lock = 0; int eof = 0; int send_exist = 0; int buf_to_send = 0; int ssth = 0; float congestion_size = 1; int max_size = 0; uint32_t ts; FILE* file; char* payload; char* filename; struct rtt_info rttinfo; rtt_init(&rttinfo); for (i=0;i<count;i++) { if (i != index) { Close(sockfds[i]); continue; } } // todo: file not exist // todo: pipeline payload = get_payload_ptr(ptr_conn_gram); recv_windowsize = *(int*)payload; filename = payload+sizeof(int); printf("Client [%s:%d] request %s\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port), filename); file = fopen(filename, "r"); if (!file) { printf("File not exist: %s\n", filename); Close(sockfd); return; } fseek(file, 0, SEEK_END); filesize = ftell(file); fseek(file, 0, SEEK_SET); local = is_local(addrs[index], ptr_connaddr, 0); sockfd = Socket(AF_INET, SOCK_DGRAM, 0); Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = ((struct sockaddr_in*)addrs[index]->ifi_addr)->sin_addr.s_addr; servaddr.sin_port = 0; Bind(sockfd, (SA *) &servaddr, sizeof(servaddr)); len = sizeof(servaddr); getsockname(sockfd, (SA *) &servaddr, &len); if (local == 0) { printf("Client [%s:%d] is not LOCAL\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port)); } else if (local == 1) { printf("Client [%s:%d] is LOCAL\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port)); } else if (local == 2) { printf("Client [%s:%d] is LOOPBACK\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port)); } if (local) Setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE, &on, sizeof(on)); //Connect(sockfd, (SA*)ptr_connaddr, sizeof(struct sockaddr_in)); // init // todo: fail sendbuf = (struct datagram*)malloc(windowsize*sizeof(struct datagram)); memset(sendbuf, 0, windowsize*sizeof(struct datagram)); sendtv = (uint32_t*)malloc(windowsize*sizeof(uint32_t)); memset(sendtv, 0, windowsize*sizeof(uint32_t)); send_exist = 0; last_ack = 0; last_ack_times = 0; newport = (int)ntohs(servaddr.sin_port); printf("New port for client [%s:%d] is %d\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port), newport); get_header(ptr_conn_gram, 0, &recv_seq, 0, &ts); make_datagram(&sendbuf[0], SYN | ACK, seq, recv_seq+1, ts, (char*)&newport, sizeof(newport)); sendtv[0] = rtt_ts(&rttinfo) + rtt_start(&rttinfo); send_to(sockfd, &sendbuf[0], ptr_connaddr, sizeof(struct sockaddr_in)); send_exist++; FD_ZERO(&allset); FD_ZERO(&rset); FD_SET(sockfd, &allset); maxfdp1 = sockfd+1; for(;;) { rset = allset; // handle timeout // todo: rtt, recv_lock ts = rtt_start(&rttinfo); struct timeval tv; tv.tv_sec = ts/1000; tv.tv_usec = (ts % 1000)*1000; nready = select(maxfdp1, &rset, NULL, NULL, &tv); if (nready < 0) { if (errno == EINTR) continue; /* back to for() */ else err_sys("select error"); } else if (nready == 0) { // timeout if (recv_lock) { ts = rtt_ts(&rttinfo); make_datagram(&send_gram, ACK, 0, 0, ts, NULL, 0); send_to(sockfd, &send_gram, ptr_connaddr, sizeof(*ptr_connaddr)); continue; } // resend for (i=0;i<windowsize;i++) { if (0 == sendtv[i]) continue; ts = rtt_ts(&rttinfo); if (ts >= sendtv[i]) { set_ts(&sendbuf[i], ts); send_to(sockfd, &sendbuf[i], ptr_connaddr, sizeof(*ptr_connaddr)); sendtv[i] = ts + rtt_start(&rttinfo); } } if (rtt_timeout(&rttinfo) < 0) { if (!servsockclosed) { Close(sockfds[index]); servsockclosed = 1; } Close(sockfd); fclose(file); printf("Too many timeouts for Client [%s:%d]\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port)); return; } ssth = (int)congestion_size/2; if (ssth < 1) ssth = 1; congestion_size = 1; printf("Timeout slow start\n"); continue; } if (FD_ISSET(sockfd, &rset)) { len = sizeof(cliaddr); recv_from(sockfd, &recv_gram, &cliaddr, &len); get_header(&recv_gram, 0, 0, &recv_ack, &ts); rtt_stop(&rttinfo, rtt_ts(&rttinfo)-ts); payload = get_payload_ptr(&recv_gram); recv_lock = (*(int*)payload == 0)?1:0; if (!servsockclosed) { Close(sockfds[index]); servsockclosed = 1; } for (i=0;i<windowsize;i++) { get_header(&sendbuf[i], &send_flag, &send_seq, 0, 0); if (!send_flag) continue; if (send_seq < recv_ack) { set_flag(&sendbuf[i], 0); sendtv[i] = 0; send_exist--; } } if ((recv_ack > seq) && eof) { Close(sockfd); fclose(file); printf("Client [%s:%d] end\n", inet_ntoa(ptr_connaddr->sin_addr), ntohs(ptr_connaddr->sin_port)); return; } if (last_ack == recv_ack) { last_ack_times++; } else { last_ack = recv_ack; last_ack_times=1; } if (last_ack_times >= 3) { last_ack = 0; for (i=0;i<windowsize;i++) { get_header(&sendbuf[i], &send_flag, &send_seq, 0, 0); if (!send_flag) continue; if (send_seq == recv_ack) break; } ts = rtt_ts(&rttinfo); set_ts(&sendbuf[i], ts); send_to(sockfd, &sendbuf[i], ptr_connaddr, sizeof(*ptr_connaddr)); // todo: congestion printf("Fast recvory\n"); congestion_size = ssth; if (congestion_size <= 0) congestion_size = 1; continue; } // todo: congestion max_size = windowsize; if (recv_windowsize < max_size) max_size = recv_windowsize; if (congestion_size < ssth) { congestion_size++; if (congestion_size >= ssth) { printf("Reach slow start threshold\n"); } } else { congestion_size += (max_size > 0)? 1.0/max_size:1.0; } if (congestion_size < max_size) max_size = (int)congestion_size; if (eof || recv_lock) { buf_to_send = 0; } else if (send_exist < max_size) { buf_to_send = max_size - send_exist; } else if (send_exist >= max_size) { buf_to_send = 0; } //printf("buf_to_send %d\n", buf_to_send); for (;buf_to_send > 0;buf_to_send--) { for (i=0;i<windowsize;i++) { get_header(&sendbuf[i], &send_flag, &send_seq, 0, 0); if (!send_flag) break; } seq++; ts = rtt_ts(&rttinfo); make_datagram(&sendbuf[i], DAT, seq, 0, ts, NULL, 0); payload = get_payload_ptr(&sendbuf[i]); //len = fread(payload+4, BUFFER_SIZE-HEADER_SIZE-4, 1, file); len = fread(payload+4, 1, BUFFER_SIZE-HEADER_SIZE-4, file); *(int*)payload = len; //printf("f %d %s\n", len, payload+4); if (ftell(file) >= filesize) { eof = 1; set_fin_flag(&sendbuf[i]); } sendtv[i] = ts + rtt_start(&rttinfo); send_to(sockfd, &sendbuf[i], ptr_connaddr, sizeof(*ptr_connaddr)); send_exist++; if (eof) break; } } } }
ssize_t jxclient_sendrecv(struct jxclient* cli, const struct sockaddr* servaddr, jxsocklen_t addrlen, mflag_t mflag) { char outbuf[MAX_MSG_LEN]; ssize_t recvbytes; jxsocklen_t sendlen; struct jxmsg_header* bufheader = NULL; if (s_rttinit == 0) { rtt_init(&s_rttinfo); s_rttinit = 1; #ifdef _DEBUG rtt_d_flag = 1; #endif } if (s_mutex_inited == 0) { s_sendrecv_init(); } bufheader = (struct jxmsg_header*)outbuf; bufheader->mflag = mflag; bufheader->header.seq = ++s_sendhdr.seq; rtt_newpack(&s_rttinfo); sendlen = sizeof(bufheader->addr); jxsock_getsockname(cli->hsock_sendrecv, &bufheader->addr, &sendlen); bufheader->addrlen = (uint8_t)sendlen; bufheader->numbytes = htonl(cli->len_senddata); if (jxmemcpy( outbuf + sizeof(struct jxmsg_header), sizeof(outbuf) - sizeof(struct jxmsg_header), cli->sendbuf, cli->len_senddata) != 0) { return 1; } s_recv_stat = RECV_RESEND; while (RECV_RESEND == s_recv_stat) { bufheader->header.ts = s_sendhdr.ts = rtt_ts(&s_rttinfo); if (SOCKET_ERROR == sendto( cli->hsock_sendrecv, outbuf, sizeof(struct jxmsg_header) + cli->len_senddata, 0, servaddr, (jxsocklen_t)addrlen)) { fprintf(stderr, "%s sendto() fail, error code: %d.\n", cli->prompt, jxsock_get_last_error()); return -2; } if (!JX_MFLAG_WAIT_RECV(mflag)) { return 0; } s_reset_recvtimer(); if ((recvbytes = s_recvmsg(cli->hsock_sendrecv, cli->recvbuf, sizeof(cli->recvbuf))) == -3) { return -3; } } if (s_recv_stat == RECV_TIMEOUT) { s_rttinit = 0; return -1; } rtt_stop(&s_rttinfo, rtt_ts(&s_rttinfo) - ((struct jxmsg_header*)cli->recvbuf)->header.ts); jxmsg_copyaddr((struct jxmsg_header*)cli->recvbuf, servaddr, addrlen); return recvbytes - sizeof(struct jxmsg_header); }