void reliablyTransfer(char* hostname, unsigned short int hostUDPport, char* filename, unsigned long long int bytesToTransfer) { //printf("%s %hu %s %llu\n",hostname ,hostUDPport,filename,bytesToTransfer); /* make a udp socket. reach the host and the destination port. waiting for receive ack. if ok, send part 2. otherwise nack send last part again. */ int socket_fd; //data struct addrinfo * dest; log_init(&data_to_send); if( (socket_fd = socket_init(hostname, hostUDPport, &dest)) < 0){ return; } if( (Convert_File_To_List(&data_to_send , filename, bytesToTransfer)) < 0){ return; } a = data_to_send.head;/////// int rv = 1; //rv = slow_start(socket_fd, dest, &data_to_send); ack_r = calloc(total,sizeof(int));/// while(data_to_send.head != NULL){ //printf("timeout or dup or other?\n"); switch(rv){ case -1:{ free(ack_r); freeaddrinfo(servinfo); return; } case 1:{ rv = slow_start(socket_fd, dest, &data_to_send); break; } //rv = slow_start(socket_fd, dest, &data_to_send); //case 2: // rv = slow_start(socket_fd, dest, &data_to_send); // break; case 2:{ //rv = slow_start(socket_fd, dest, &data_to_send); rv = congestion_avoidance(socket_fd, dest, &data_to_send); break; } //default: // break;//rv = slow_start(socket_fd, dest, &data_to_send); } } free(ack_r); freeaddrinfo(servinfo); /* after part 1, add the function of trafic control which includes increase window size and decrease window size. */ }
void process_filename_request(){ int n; n = recvfrom(socket_d,filename,20,0,(struct sockaddr *)&client,&length); if( n < 0 ){ perror("Didn't get the filename!"); exit(0); }else{ printf("Reading the file:%s",filename); } int i; fp = fopen(filename,"r"); if( fp == NULL ){ perror("File does not exist!"); } slow_start(); }
void * rcvMessage(void * arg) { // receive message in chat from thread int sock = (int)arg; // client socket variable int seq_tmp = 0, data_tmp = 0; // sequence number, data_size variable timeout.tv_sec = 5; timeout.tv_usec = 0; FILE *fp; // file transfer pointer variable int i = 0, j = 0, cnt = 0; // normal variable(i = recv, j = for loop, cnt = acknowledge size while(1) { if((i = recv(sock, rcv_buf, sizeof(rcv_buf), 0)) > 0) { // recv message(i = 1024) rcv_buf[i] = '\0'; // last message buffer, close array fflush(stdout); // if buffer value exist, print it if(cnt > 0) { if(ack[cnt-1] > rwnd_size) { // if rwnd is full, don't receive message sprintf(snd_buf, "oversize"); send(sock, snd_buf, strlen(snd_buf), 0); continue; } } pthread_mutex_lock(&mutx); // rcvCnt is public variable in stack. so using lock&unlock rcvCnt += 1; pthread_mutex_unlock(&mutx); if(!strncmp(rcv_buf, "file", 4)) { // if recv message is 'file' printf("\n## Client wants file transport...\n"); i = recv(sock, rcv_buf, sizeof(rcv_buf), 0); // one more receive message rcv_buf[i] = '\0'; fflush(stdout); if((fp = fopen(rcv_buf, "r")) == NULL) { // and second message check printf("## File Not Found!!\n"); sprintf(snd_buf, "failed"); send(sock, snd_buf, strlen(snd_buf), 0); fp = NULL; continue; } else { // if second message is correct file name, printf("## File Found!! Transporting ...\n"); while(!feof(fp)) { fgets(rcv_buf,1024,fp); if(feof(fp)) break; strcat(file_buffer,rcv_buf); // file open and read each sentence, and append it 'file_buffer' } fclose(fp); sprintf(snd_buf, "success"); send(sock, snd_buf, strlen(snd_buf), 0); // signal "file transfer success" sleep(3); send(sock, file_buffer, strlen(file_buffer), 0); // give to client file content sleep(3); printf("\n## Server >> File IO is finish. New client waiting...\n"); printf("#####################################################\n"); fp = NULL; continue; } } else if(!strncmp(rcv_buf, "flowStart", 9)) { // if client message is 'flowStart' pthread_mutex_lock(&mutx); rcvCnt -= 1; // it isn't seq-data & ack relation, so rcvCnt value - 1 pthread_mutex_unlock(&mutx); printf("\n## Client wants flow control...\n"); i = recv(sock, rcv_buf, sizeof(rcv_buf), 0); // recv client size rcv_buf[i] = '\0'; fflush(stdout); printf("## server's size is 102, client's size is %s.\n## starting flow control !!\n", rcv_buf); sleep(1); flow_start(rcv_buf, (void *)sock); } else if(!strncmp(rcv_buf, "cgstStart", 9)) { // if client message is 'cgstStart' printf("\n## Client wants congestion control...\n"); while(1) { i = slow_start((void *)sock); // slow start !! if(i != 0) { // i variable is number when cwnd >= ssthresh, break printf("\n## Slow Start Finished. Congestion Avoid Start..\n"); while(1) { cgst_avoid((void *)sock); if(cgst_cnt >= 3) // in cgst_avoid method, cgst_cnt value + 1 when 1/10 MSS * 10 times run break; } printf("\n## Congestion Avoid Finished. Recovery Start...\n"); pthread_mutex_lock(&mutx); rcvCnt -= 1; cgst_cnt = 0; pthread_mutex_unlock(&mutx); while(1) { recovery((void *)sock); // fast recovery run!! if(cgst_cnt >= 3) break; } } i = 0; if(cgst_cnt >= 3) break; } } else if(!strncmp(rcv_buf, "quit", 4)) { // if receive message 'quit' pthread_mutex_lock(&mutx); clnt_number--; pthread_mutex_unlock(&mutx); printf("\n%s", rcv_buf); close(sock); // client socket closed } else { j = MSS; // give enough size to j value for(i = 0; i < strlen(rcv_buf); i++) { // client send (abcdefasdcasd sequence number = XX data size = XX) if(!isdigit(rcv_buf[i]) && rcv_buf[i] == '=') { // if not digit and correct = signal for(j = i+1; j < strlen(rcv_buf); j++) { // give next to = size to j value if(!isdigit(rcv_buf[j]) && rcv_buf[j] == '=') { i = j+1; // secondly correct = signal, give next to = size to i value, break break; } else if(isdigit(rcv_buf[j])) { // after first = signal, sequence number save to seq_tmp variable seq_tmp *= 10; seq_tmp += (rcv_buf[j] - '0'); } } } if(isdigit(rcv_buf[i]) && i > j) { // after second = signal, data size save to data_tmp variable data_tmp *= 10; data_tmp += (rcv_buf[i] - '0'); } } pthread_mutex_lock(&mutx); ack[cnt] = seq_tmp + data_tmp; // acknowledge save(ack is public variable in stack) rwnd_tmp[cnt] = data_tmp; // for increase rwnd threshold pthread_mutex_unlock(&mutx); cnt++; seq_tmp = 0; data_tmp = 0; printf("\n%s", rcv_buf); } } } }
void listen_for_ack(){ int recv_check; //getting back the header int sequence_no; char temp_seqno[4]; int acknow_no; char temp_ackno[4]; char FLAG[1]; char recv_data[1400]; int recv_data_length; char temp_datalen[4]; tv.tv_sec = 2; tv.tv_usec = 0; setsockopt(socket_d,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)); printf("\nListening for ACK's"); while((recv_check = recvfrom(socket_d,recv_buffer,200,0,(struct sockaddr *)&client,&length)) > 0){ strcpy(temp_seqno,strtok(recv_buffer,":")); strcpy(temp_ackno,strtok(NULL,":")); acknow_no = atoi(temp_ackno); ack_recv_array[k] = acknow_no; printf("\nACK RECEIVED ARRAY:%d",ack_recv_array[k]); k++; printf("\n--------------"); printf("\nACKNOWLEDGMENT"); printf("\n%d",acknow_no); //printf("\n%d\n%d:K:",acknow_no,k); strcpy(temp_datalen,strtok(NULL,":")); strcpy(FLAG,strtok(NULL,":")); printf("\nFLAG"); printf("%s",FLAG); memset(recv_buffer,0,200); }//end of while k=0; //once you get an ack traverse the expected ACK NUMBER ARRAY to see if it is present int j; int m; int p; //check if you have received the expected ACK's // if NO then retransmit and call listen_for_ack again /** for(j=0; j<4; j++){ p = expected_ack_array[j]; if( ack_recv_array[j] == p){ printf("j:%d",j); printf("Do i come here!"); expected_ack_array[j] = '\0'; ack_recv_array[j] = '\0'; } } for(m=0;m<4;m++){ if(expected_ack_array[m] != '\0'){ p = expected_ack_array[m]; printf("RETRANSMITTING!"); retransmit_flag = true; retransmit(p); } } printf("RETRANSMITTING ENDS!"); if(retransmit_flag){ listen_for_ack(); } else{**/ //go back to slow_start if you have received all the ACK's slow_start(); }