示例#1
0
int srt_client_disconnect(int sockfd) {
	seg_t s;
	memset(&s, 0, sizeof(seg_t));
	s.header.src_port = tcb_table[sockfd]->client_portNum;
	s.header.dest_port = tcb_table[sockfd]->svr_portNum;
	s.header.length = 0;
	s.header.type = FIN;
	if (-1 == snp_sendseg(connection, &s)) {
		printf("%s TCB[%d] First Try: Sending FIN Failure!\n", output, sockfd);
	}
	else {
		printf("%s TCB[%d] First Try: Sending FIN Success!\n", output, sockfd);
	}
	printf("%s TCB[%d] State (CONNECTED) ==> (FINWAIT)\n", output, sockfd);
	tcb_table[sockfd]->state = FINWAIT;
	int retry = 0;
	int p = 0;
	do {
		struct timespec tm;
		tm.tv_sec = 0;
		tm.tv_nsec = FIN_TIMEOUT;
		nanosleep(&tm, NULL);
		if (CLOSED == tcb_table[sockfd]->state) {
			p = 1;
		}
		else if (++retry > FIN_MAX_RETRY) {
			printf("%s TCB[%d] Exceeded Retry Limit!\n", output, sockfd);
			tcb_table[sockfd]->state = CLOSED;
			p = -1;
		}
		else  {
			if (-1 == snp_sendseg(connection, &s)) {
				printf("%s TCB[%d] Retry [%d]: Sending FIN Failure!\n", output, sockfd, retry);
			}
			else {
				printf("%s TCB[%d] Retry [%d]: Sending FIN Success!\n", output, sockfd, retry);
			}
		}
	} while (p == 0);

	//clear send buffer
	pthread_mutex_lock(tcb_table[sockfd]->bufMutex);
	segBuf_t *cur = tcb_table[sockfd]->sendBufHead;
	while (NULL != cur) {
		segBuf_t *temp = cur;
		cur = cur->next;
		free(temp);
	}
	pthread_mutex_unlock(tcb_table[sockfd]->bufMutex);

	return p;
}
示例#2
0
// This function is used to connect to the server. It takes the socket ID and the 
// server's port number as input parameters. The socket ID is used to find the TCB entry.  
// This function sets up the TCB's server port number and a SYN segment to send to
// the server using snp_sendseg(). After the SYN segment is sent, a timer is started. 
// If no SYNACK is received after SYNSEG_TIMEOUT timeout, then the SYN is 
// retransmitted. If SYNACK is received, return 1. Otherwise, if the number of SYNs 
// sent > SYN_MAX_RETRY,  transition to CLOSED state and return -1.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
int srt_client_connect(int sockfd, unsigned int server_port)
{
	printf("srt_client_connect\n");
	if(sockfd < 0 || sockfd > MAX_TRANSPORT_CONNECTIONS || clients[sockfd] == NULL)
	{
		printf("Error in srt_client_connect sockfd = %d max clients supported = %d\n", sockfd, MAX_TRANSPORT_CONNECTIONS);
		return -1;
	}
	client_tcb_t *client = clients[sockfd];
	seg_t segment;
	bzero(&segment,sizeof(segment));
	segment.header.src_port = client->client_portNum;
	segment.header.dest_port = client->svr_portNum = server_port;
	segment.header.type = SYN;
	segment.header.seq_num = 0;
	segment.header.length = 0;
	int trialNum = 0 ;
	//  first trial
	if(snp_sendseg(mainTcpSockId,&segment) < 0){ // error check for sendseg when there is TCP socket error
		printf("Error in sending message in TCP layer = %d \n", mainTcpSockId);
		return -1;
	}
	long start_time = current_time_millis(); // timer started
	trialNum++; // increment trial num
	client->state = SYNSENT ;
	while(client->state == SYNSENT){
		wait_for_some_time(LOOP_WAITING_TIME);
		long now = current_time_millis();
		long diff = now - start_time ;
		if((diff ) > SYN_TIMEOUT_MS){
			printf("TIMEOUT in connect %d for trial num = %d \n", sockfd, trialNum);
			if(trialNum < SYN_MAX_RETRY){
				printf("resending segment \n");
				if(snp_sendseg(mainTcpSockId,&segment) < 0){ // error check for sendseg when there is TCP socket error
					printf("ERROR in sending message sockfd = %d \n", sockfd);
					return -1;
				}
				start_time = (long)time(NULL); // reset timer
				trialNum++;
			}else{
				printf("MAX TRIAL reached in connect segment of sock fd %d\n" ,sockfd);
				client->state = CLOSED;
				return -1;
			}
		}	
	}
 	printf("srt_client_connect ends \n");
 	fflush(stdout);
  return 1; // returning success it can be rechecked with state = CONNECTED
}
示例#3
0
void send_unsent_segments(client_tcb_t *client){
	pthread_mutex_lock(client->bufMutex);
	printf("send_unsent_segments starts \n");
	while(client->sendBufunSent!=NULL && client->unAck_segNum < GBN_WINDOW){
		// 1. send the segment
		// 2. check if it was succesfull
		// 3. update the sent time 
		// 4. start the timeout thread if required which means client->unAck_segNum should be zero 
		// 5. switch to next segment
		if(snp_sendseg(mainTcpSockId,(seg_t*)client->sendBufunSent)){
			printf("DATA PACKET SENT sequence number %d sent to server \n",client->sendBufunSent->seg.header.seq_num);
			client->sendBufunSent->sentTime = current_time_millis();
			client->sendBufunSent = client->sendBufunSent->next;
			if(client->unAck_segNum == 0) { // check 
				printf("TIMEOUT thread create called\n");
				pthread_t timeout_thread;
				pthread_create(&timeout_thread,NULL,sendBuf_timer, (void*)client);
			}
			client->unAck_segNum++;
			printf("UNACKED count = %d \n", client->unAck_segNum);
		}else{
			printf("ERROR (send_unsent_segments) in snp_sendseg exiting TCP error \n");
			exit(-1);
		}
	}
	pthread_mutex_unlock(client->bufMutex);
	printf("send_unsent_segments ends \n");
	fflush(stdout);
}
示例#4
0
// This thread continuously polls send buffer to trigger timeout events
// It should always be running when the send buffer is not empty
// If the current time -  first sent-but-unAcked segment's sent time > DATA_TIMEOUT, a timeout event occurs
// When timeout, resend all sent-but-unAcked segments
// When the send buffer is empty, this thread terminates
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void* sendBuf_timer(void* arg)
{
	int i = *(int *) arg;
	while (1) {
		struct timespec tm;
		tm.tv_sec = 0;
		tm.tv_nsec = SENDBUF_POLLING_INTERVAL;
		nanosleep(&tm, NULL);
	
		pthread_mutex_lock(tcb_table[i]->bufMutex);
		if (NULL == tcb_table[i]->sendBufHead) {
			pthread_mutex_unlock(tcb_table[i]->bufMutex);
			printf("%s TCB[%d] sendBuf_timer thread killed...\n", output, i);
			return NULL;
		}
		if (clock() - tcb_table[i]->sendBufHead->sentTime > DATA_TIMEOUT) {
			segBuf_t *cur = tcb_table[i]->sendBufHead;
			int T = tcb_table[i]->unAck_segNum;
			printf("%s TCB[%d] Resend Buffer %d...\n", output, i, cur->seg.header.seq_num);
			while (T-- > 0) {
				snp_sendseg(connection, &(cur->seg));
				cur->sentTime = clock();
				cur = cur->next;
			}
		}
		pthread_mutex_unlock(tcb_table[i]->bufMutex);
	}
	return NULL;
}
示例#5
0
//sendN send from first unsent to GBN_WINDOW or TAIL
void sendN(int i) {
	while (NULL != tcb_table[i]->sendBufunSent && tcb_table[i]->unAck_segNum < GBN_WINDOW) {
		snp_sendseg(connection, &(tcb_table[i]->sendBufunSent->seg));
		printf("%s TCB[%d] Send Buffer %d!\n", output, i, tcb_table[i]->sendBufunSent->seg.header.seq_num);
		tcb_table[i]->sendBufunSent->sentTime = clock();
		tcb_table[i]->sendBufunSent = tcb_table[i]->sendBufunSent->next;
		tcb_table[i]->unAck_segNum++;
	}
}
示例#6
0
int srt_client_connect(int sockfd, unsigned int server_port) {
	tcb_table[sockfd]->svr_portNum = server_port;
	seg_t s;
	memset(&s, 0, sizeof(seg_t));
	s.header.src_port = tcb_table[sockfd]->client_portNum;
	s.header.dest_port = tcb_table[sockfd]->svr_portNum;
	s.header.length = 0;
	s.header.type = SYN;
	if (-1 == snp_sendseg(connection, &s)) {
		printf("%s TCB[%d] First Try: Sending SYN Failure!\n", output, sockfd);
	}
	else {
		printf("%s TCB[%d] First Try: Sending SYN Success!\n", output, sockfd);
	}
	printf("%s TCB[%d] State (CLOSED) ==> (SYNSENT)\n", output, sockfd);
	tcb_table[sockfd]->state = SYNSENT;
	int retry = 0;
	int p = 0;
	do {
		struct timespec tm;
		tm.tv_sec = 0;
		tm.tv_nsec = SYN_TIMEOUT;
		nanosleep(&tm, NULL);
		if (CONNECTED == tcb_table[sockfd]->state) {
			p = 1;
		}
		else if (++retry > SYN_MAX_RETRY) {
			printf("%s TCB[%d] Exceeded Retry Limit!\n", output, sockfd);
			tcb_table[sockfd]->state = CLOSED;
			p = -1;
		}
		else  {
			if (-1 == snp_sendseg(connection, &s)) {
				printf("%s TCB[%d] Retry [%d]: Sending SYN Failure!\n", output, sockfd, retry);
			}
			else {
				printf("%s TCB[%d] Retry [%d]: Sending SYN Success!\n", output, sockfd, retry);
			}
		}
	} while (p == 0);
	
	return p;
}
示例#7
0
void handle_timeout_resend(client_tcb_t *client){
	printf("handle_timeout_resend starts\n");
	int unack_count = 0 ;
	segBuf_t *head = client->sendBufHead;
	pthread_mutex_lock(client->bufMutex);
	while(head && unack_count < client->unAck_segNum){
		if(snp_sendseg(mainTcpSockId,(seg_t*)head)){
			printf("DATA PACKET RESENT sequence number %d sent to server total UNACKED =  %d \n",head->seg.header.seq_num, client->unAck_segNum );
			head->sentTime = current_time_millis();
			head = head->next;
			unack_count++;
		}else{
			printf("ERROR (handle_timeout_resend) in snp_sendseg exiting TCP error \n");
			exit(-1);
		}
	}
	pthread_mutex_unlock(client->bufMutex);
	printf("handle_timeout_resend ends\n");
}
示例#8
0
文件: srt_server.c 项目: alonbee/Net
// This is a thread  started by srt_server_init(). It handles all the incoming 
// segments from the client. The design of seghanlder is an infinite loop that calls snp_recvseg(). If
// snp_recvseg() fails then the overlay connection is closed and the thread is terminated. Depending
// on the state of the connection when a segment is received  (based on the incoming segment) various
// actions are taken. See the client FSM for more details.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
void* seghandler(void* arg)
{
  seg_t* seg = (seg_t*) malloc(sizeof(seg_t));
  seg_t* ack = (seg_t*) malloc(sizeof(seg_t));
  // memset(&seg, 0, sizeof(seg));
  svr_tcb_t* tp = (svr_tcb_t*) malloc(sizeof(svr_tcb_t));

  while (1) {
    // Find the right server
    tp = NULL;
    if (snp_recvseg(tcp_socknum,seg) != 1) {
        printf("Can't receive data in server, ready to close\n");
      	close(tcp_socknum);
        pthread_exit(NULL);
    }

    // Get socketfd by port
    int sockfd = -1;
    for (int i = 0; i < MAX_TRANSPORT_CONNECTIONS; ++i)
      {
        if (svr_tcb_table[i] != NULL && svr_tcb_table[i] -> svr_portNum == seg->header.dest_port) {
          // Get the right tcb based on dest port
            sockfd = i; /*get socket number in srt for client port*/
            // tp -> client_port = seg.header.src_port;
            tp = svr_tcb_table[i];
          }
        }

      printf("Server sockfd =%d,Received seg header type =%d\n",sockfd,seg->header.type);

      if (!tp){
      printf("Server: Can't get server_tcp for the seg\n");
      continue;
        }

      printf("seghandler sockfd=%d , state=%d \n", sockfd, tp->state);
    switch(tp->state) {
      case CLOSED:
          printf("Server: sockfd=%d received seg in CLOSED\n", sockfd);
        break;
      case LISTENING: {
        if(seg->header.type == SYN) {
          pthread_mutex_lock(tp -> bufMutex);
          tp->client_portNum = seg->header.src_port;
          tp->state=CONNECTED;
          printf("Server:sockfd = %d Got SYN from client\n", sockfd);
          
          // Set tcb expect_seqNum
          tp -> expect_seqNum = seg->header.seq_num;
          pthread_mutex_unlock(tp -> bufMutex);

          // memset(&ack,0, sizeof(ack));
          // Received SYN and send SYNACK back
          ack->header.type = SYNACK;
          ack->header.src_port = tp -> svr_portNum;
          ack->header.dest_port = tp -> client_portNum;
          ack->header.length = 0;
          snp_sendseg(tcp_socknum, ack);
          printf("Server:sockfd = %d Sent SYNACK to client\n", sockfd);
        }
        else
          printf("Server: Listening received SYN\n");
        break;
   	 }
      case CONNECTED: 
      {
        switch (seg->header.type) {
          printf("Server: tp %d: receive %d\n", sockfd, seg->header.type);
          case SYN:
          {
            // Received SYN and send SYNACK back
            // seg_t ack;
            // memset(&ack,0, sizeof(ack));
            pthread_mutex_lock(tp -> bufMutex);
          	tp -> expect_seqNum = seg->header.seq_num;
            pthread_mutex_unlock(tp -> bufMutex);

            ack->header.type = SYNACK;
            ack->header.src_port = tp -> svr_portNum;
            ack->header.dest_port = tp -> client_portNum;
            ack->header.length = 0;
            snp_sendseg(tcp_socknum, ack);
            break;            
          }
          case DATA: {
          	// tp -> expect_seqNum will be updated if right; Otherwise, same old expect_seqNum
          	if (seg -> header.seq_num == tp -> expect_seqNum){
          		// Update tp -> expect_seqNum and store data in tp -> recvBuf 
          		restore_data(tp, seg);
          	}
          		// Send ack back anayway
          		ack->header.type = DATAACK;
            	ack->header.src_port = tp -> svr_portNum;
            	ack->header.dest_port = tp -> client_portNum;
            	ack->header.length = 0;
            	ack->header.ack_num = tp -> expect_seqNum;  // Send the new expect_seqNum(added by data length) if the expect_seqNum is right 
            	snp_sendseg(tcp_socknum, ack);
         
          	break;
          }
          case FIN:
          {
            time_t timer = time(NULL);
            printf("Server: tp %d: receive FIN %s", sockfd, ctime(&timer));

            // send FINACK
            // seg_t ack;
            // memset(&ack,0, sizeof(ack));
            ack->header.type = FINACK;
            ack->header.src_port = tp -> svr_portNum;
            ack->header.dest_port = tp -> client_portNum;
            ack->header.length = 0;
            snp_sendseg(tcp_socknum, ack);

            tp->state = CLOSEWAIT;

            // start a thread for CLOSE_WAIT_TIMEOUT; If time expires, Set tp state as CLOSED  
            pthread_t closetimer;
            pthread_create(&closetimer,NULL,closewait, (void*)tp);
            break;                    
          }
          default:
            break;
          }
        break;
      }
      case CLOSEWAIT:
        // receive FIN
        if (seg->header.type == FIN) {

          // send FINACK
          // seg_t ack;
          // memset(&ack,0, sizeof(ack));
          ack->header.type = FINACK;
          ack->header.src_port = tp -> svr_portNum;
          ack->header.dest_port = tp -> client_portNum;
          ack->header.length = 0;
          snp_sendseg(tcp_socknum, ack);
          printf("Server: sent FINACK in closewait\n");
          }
        else {
          printf("Server: Received not fin in CLOSEWAIT\n");
        }
        break;
      default:
        printf("Server: sockfd= %d: wrong state\n", sockfd);
        break;
    }
  }
}
示例#9
0
// This is a thread  started by srt_server_init(). It handles all the incoming 
// segments from the client. The design of seghanlder is an infinite loop that calls snp_recvseg(). If
// snp_recvseg() fails then the overlay connection is closed and the thread is terminated. Depending
// on the state of the connection when a segment is received  (based on the incoming segment) various
// actions are taken. See the client FSM for more details.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
void* seghandler(void* arg)
{
  	seg_t *segPtr = malloc(sizeof(seg_t));
	MALLOC_CHECK(segPtr);
	memset(segPtr, 0, sizeof(seg_t));

	char *segTypeStrings[] = {"SYN", "SYNACK", "FIN", "FINACK", "DATA", "DATAACK"};
	char *states[] = {"Unknown", "CLOSED", "LISTENING", "CONNECTED", "CLOSEWAIT"};
	int src_nodeID;

	while (snp_recvseg(overlay_conn_fd, &src_nodeID, segPtr) > 0) {

		if(!segPtr)
			break;

		//get the right server_tcb_t index
		unsigned int destPort = segPtr->header.dest_port;
		int idx = 0;
		while (idx < MAX_TRANSPORT_CONNECTIONS) {
			if (server_TCB_Table[idx] != NULL) {
				if (server_TCB_Table[idx]->svr_portNum == destPort){
					break;
				}
			}
			idx++;
		}

		if (idx < MAX_TRANSPORT_CONNECTIONS){
			svr_tcb_t *currentTCB = server_TCB_Table[idx];
			printf("\nReceived %s in state %s. client: %u, server: %u.\n", 
				segTypeStrings[segPtr->header.type], states[currentTCB->state], segPtr->header.src_port, segPtr->header.dest_port);

			switch(currentTCB->state) {
				case CLOSED:
				  //printf("State is CLOSED.\n");
				  printf("Doing nothing.\n");
				  break;

				case LISTENING:
				  //printf("State is LISTENING.\n");
				  if (segPtr->header.type == SYN){
				  	printf("Changing state to CONNECTED. client_portNum: %u, expect_seqNum: %u. Sending SYNACK.\n",
				  		 segPtr->header.src_port, segPtr->header.seq_num);
				  	currentTCB->state = CONNECTED;
				  	currentTCB->client_portNum = segPtr->header.src_port;
					currentTCB->expect_seqNum = segPtr->header.seq_num;
					currentTCB->client_nodeID = src_nodeID; //new
				  	
				  	//create SYNACK seg_t
					seg_t* synSegPtr = malloc(sizeof(seg_t));
					MALLOC_CHECK(synSegPtr);
					memset(synSegPtr, 0, sizeof(seg_t));
					synSegPtr->header.src_port = currentTCB->svr_portNum;
					synSegPtr->header.dest_port = currentTCB->client_portNum;
					synSegPtr->header.type = SYNACK;

					//send SYNACK seg_t
					if (snp_sendseg(overlay_conn_fd, currentTCB->client_nodeID, synSegPtr) < 0) {
						printf("Error sending SYNACK seg_t.\n");
					}
					free(synSegPtr);
				  } else {
				  	printf("Doing nothing.\n");
				  }
				  break;

				case CONNECTED:
				  //printf("State is CONNECTED.\n");
				  if (segPtr->header.type == SYN  && currentTCB->client_portNum == segPtr->header.src_port && currentTCB->client_nodeID == src_nodeID){
				  	printf("Sending SYNACK.\n");

				  	//create SYNACK seg_t
					seg_t* synSegPtr = malloc(sizeof(seg_t));
					MALLOC_CHECK(synSegPtr);
					memset(synSegPtr, 0, sizeof(seg_t));
					synSegPtr->header.src_port = currentTCB->svr_portNum;
					synSegPtr->header.dest_port = currentTCB->client_portNum;
					synSegPtr->header.type = SYNACK;

					//send SYNACK seg_t
					if (snp_sendseg(overlay_conn_fd, currentTCB->client_nodeID, synSegPtr) < 0) {
						printf("Error sending SYNACK seg_t.\n");
					}
					free(synSegPtr);
				  } else if (segPtr->header.type == FIN  && currentTCB->client_portNum == segPtr->header.src_port && currentTCB->client_nodeID == src_nodeID) {

				  	printf("Changing state to CLOSEWAIT and sending FINACK.\n");
				  	currentTCB->state = CLOSEWAIT;
				  	pthread_t closeWaitThread;
				    if (pthread_create(&closeWaitThread, NULL, closeWaitTimer, currentTCB)){
				    	printf("Error creating closeWaitTimer thread.\n");
				    }

				  	//create FINACK seg_t
					seg_t *finSegPtr = malloc(sizeof(seg_t));
					MALLOC_CHECK(finSegPtr);
					memset(finSegPtr, 0, sizeof(seg_t));
					finSegPtr->header.src_port = currentTCB->svr_portNum;
					finSegPtr->header.dest_port = currentTCB->client_portNum;
					finSegPtr->header.type = FINACK;

					//send FINACK seg_t
					if (snp_sendseg(overlay_conn_fd, currentTCB->client_nodeID, finSegPtr) < 0) {
						printf("Error sending FINACK seg_t.\n");
					}
					free(finSegPtr);

				  } else if (segPtr->header.type == DATA  && currentTCB->client_portNum == segPtr->header.src_port && currentTCB->client_nodeID == src_nodeID) {

					  	//create DATAACK seg_t
						seg_t *dataSegPtr = malloc(sizeof(seg_t));
						MALLOC_CHECK(dataSegPtr);
						memset(dataSegPtr, 0, sizeof(seg_t));
						dataSegPtr->header.src_port = currentTCB->svr_portNum;
						dataSegPtr->header.dest_port = currentTCB->client_portNum;
						dataSegPtr->header.type = DATAACK;

						//if the seq_nums match, add to buffer and increment relevant variables
						pthread_mutex_lock(currentTCB->bufMutex);
						if (segPtr->header.seq_num == currentTCB->expect_seqNum) {
							//put received data in recv buffer if it can fit
							if (segPtr->header.length + currentTCB->usedBufLen < RECEIVE_BUF_SIZE) {
								printf("Seq_nums match (%u)! Adding to buffer.\n", segPtr->header.seq_num);
								memcpy(currentTCB->recvBuf, segPtr->data, segPtr->header.length);
								currentTCB->recvBuf += segPtr->header.length;
								currentTCB->usedBufLen += segPtr->header.length;
								currentTCB->expect_seqNum += segPtr->header.length;
							} else {
								printf("Seq_nums match but recv Buf is too full. Dropping data and sending DATAACK.\n");
							}
						} else {
							printf("Out of order packet (%u).\n", segPtr->header.seq_num);
						}
						dataSegPtr->header.seq_num = currentTCB->expect_seqNum;
						pthread_mutex_unlock(currentTCB->bufMutex);

						//send DATAACK seg_t
						printf("Sending DATAACK with expect_seqNum %u.\n", dataSegPtr->header.seq_num);
						if (snp_sendseg(overlay_conn_fd, currentTCB->client_nodeID, dataSegPtr) < 0) {
							printf("Error sending DATAACK seg_t.\n");
						}
						free(dataSegPtr);
				  } else {
				  	printf("Doing nothing.\n");
				  }
				  break;

				case CLOSEWAIT:
				  //printf("State is CLOSEWAIT.\n");
				  if (segPtr->header.type == FIN  && currentTCB->client_portNum == segPtr->header.src_port && currentTCB->client_nodeID == src_nodeID){

				  	printf("Sending FINACK.\n");
				  	//create FINACK seg_t
					seg_t* synSegPtr = malloc(sizeof(seg_t));
					MALLOC_CHECK(synSegPtr);
					memset(synSegPtr, 0, sizeof(seg_t));
					synSegPtr->header.src_port = currentTCB->svr_portNum;
					synSegPtr->header.dest_port = currentTCB->client_portNum;
					synSegPtr->header.type = FINACK;

					//send FINACK seg_t
					if (snp_sendseg(overlay_conn_fd, currentTCB->client_nodeID, synSegPtr) < 0) {
						printf("Error sending FINACK seg_t.\n");
					}
					free(synSegPtr);

				  } else {
				  	printf("Doing nothing.\n");
				  }
				  break;

				default:
				  printf("Unknown state.\n");
				  break;
			}
		} else {
			printf("Couldn't find the server_tcb the client was trying to reach.\n");
		}

		memset(segPtr, 0, sizeof(seg_t));
	
	}

	printf("seghandler is closing the overlay connection.\n");
	close(overlay_conn_fd);
	free(segPtr);
	pthread_exit(NULL);
}
示例#10
0
// This is a thread  started by srt_server_init(). It handles all the incoming 
// segments from the client. The design of seghandler is an infinite loop that calls snp_recvseg(). If
// snp_recvseg() fails then the overlay connection is closed and the thread is terminated. Depending
// on the state of the connection when a segment is received  (based on the incoming segment) various
// actions are taken. See the client FSM for more details.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
void* seghandler(void* arg)
{

	/* seg_t struct to receive messages from client */

	seg_t* segPtr = calloc (1, sizeof(seg_t));

	if (NULL == segPtr) {

		free(segPtr);
		fprintf(stderr, "Failed to allocate memory for segment\n");
		exit(1);
	} 

	/* Infinite loop that receives segments */

	int src_nodeID;

	while (1) {
	
		/* For timing from CLOSEWAIT to CLOSED for server-client connection, loop through all connections */

		/* If Timer has already been started, then check for timeout */

		// int j;

		// for (j = 0; j < MAX_TRANSPORT_CONNECTIONS; j++) {

		// 	svr_tcb_t* sTp = svrConnList[j];

		// 	if ((NULL != sTp) && (sTp->timeSetBool) && (CLOSED != sTp->state)) { /* Don't want to track time if client connection already closed */

		// 		gettimeofday(&(sTp->t2), NULL); // keep checking the time

		// 		/* compute the elapsed time in milliseconds */
		// 	    sTp->elapsedTime = (sTp->t2.tv_sec - sTp->t1.tv_sec) * 1000.0;      // sec to ms
		// 	    sTp->elapsedTime += (sTp->t2.tv_usec - sTp->t1.tv_usec) / 1000.0;   // us to ms


		// 		//fprintf(stdout, "\nElapsed time: %lf\n", sTp->elapsedTime);
			
				
		// 		/* CLOSE after CLOSEWAIT period */
		// 		if (sTp->elapsedTime > (CLOSEWAIT_TIMEOUT * 1000.0)) {

		// 			fprintf(stdout, "\nNow closing server port %d after CLOSEWAIT_TIME: %f MS\n", sTp->svr_portNum, sTp->elapsedTime);

		// 			/* set state of that server port to CLOSED */

		// 			sTp->state = CLOSED;
		// 		}
		// 	}
		// }

		if (0 > snp_recvseg(svrSockGlobal, &src_nodeID, segPtr)) { /* Receive failed */
			;
		}

		/* Packet received */

		else {

			/* check the packet for bit errors */

			if (0 < checkchecksum(segPtr)) { // If the packet is valid

				/* Determine the serverPort it's meant for */

				int svrPort = segPtr->header.dest_port;
				int clientPort = segPtr->header.src_port;

				/* Determine what entry in the TCB table that serverPort corresponds to */

				int i;

				svr_tcb_t *tp;
				
				for (i = 0; i < MAX_TRANSPORT_CONNECTIONS; i++) {

					if ((NULL != svrConnList[i]) && (svrPort == svrConnList[i]->svr_portNum)) {

						tp = svrConnList[i];
						tp->client_portNum = clientPort;
						break;
					}
				}

				if (NULL == tp) {
					fprintf(stderr, "Bad packet, found no matching port number on server side\n");
					exit(1);
				}

				/* Switch on the type of packet */

				switch(segPtr->header.type) {

					case SYN: /* Update server state and send a SYNACK */

						fprintf(stdout, "Server at server port: %d received SYN from client NodeID: %d at port: %d\n", svrPort, src_nodeID, clientPort);

						if ((LISTENING == tp->state) || (CONNECTED == tp->state)) {

							tp->state = CONNECTED;

							tp->client_nodeID = src_nodeID;

							/* Set tp->expect_seqNum using the sequence number in the received SYN segment */

							tp->expect_seqNum = segPtr->header.seq_num;

							/* Setup a SYNACK segment and send the segment to the server */

							seg_t* segSYNACK = calloc (1, sizeof(seg_t));

							if (NULL == segSYNACK) {

								free(segSYNACK);
								fprintf(stderr, "Failed to allocate memory for SYNACK segment\n");
								exit(1);
							} 

							segSYNACK->header.type = SYNACK;

							segSYNACK->header.src_port = svrPort;

							segSYNACK->header.dest_port = clientPort;

							/* Generate a checksum and add to PacketHeader */

							unsigned short int crcSumSYNACK = checksum(segSYNACK);

							segSYNACK->header.checksum = crcSumSYNACK;

							if (0 > snp_sendseg(svrSockGlobal, tp->client_nodeID, segSYNACK)) {
								fprintf(stderr, "Overlay send failed\n");
								exit(1);
							}

							free(segSYNACK);
						}

						break;

					case FIN: /* Stay at CLOSEWAIT and keep sending FINACKs */

						/* If currently CONNECTED or in CLOSEWAIT, stay/transition to CLOSEWAIT, and send FINACK */

						fprintf(stdout, "\nServer at server port: %d received FIN from client NodeID: %d at port: %d\n", svrPort, src_nodeID, clientPort);

						if ((CONNECTED == tp->state) || (CLOSEWAIT == tp->state)) {

							/* If originally CONNECTED, then start timer for this server-client port connection */

							if (CONNECTED == tp->state) {

/*								gettimeofday(&(tp->t1), NULL);
								tp->timeSetBool = 1; // indicate that timer has been started*/

								pthread_t segMain;

								int segRC = pthread_create(&segMain, NULL, serverTimer, tp); /* Params: fourth param is arg to function */

								if (segRC) {
								    fprintf(stderr, "pthread_create failed for server, rc=%d\n", segRC);
								    exit(segRC);
								}

								else {
									fprintf(stdout, "Starting timer for CLOSE_WAIT for server port: %d\n", svrPort);
								}
							}

							tp->state = CLOSEWAIT;

							/* Setup a FINACK segment and send the segment to the server */

							seg_t* segFINACK = calloc (1, sizeof(seg_t));

							if (NULL == segFINACK) {

								free(segFINACK);
								fprintf(stderr, "Failed to allocate memory for FINACK segment\n");
								exit(1);
							} 

							segFINACK->header.type = FINACK;

							segFINACK->header.src_port = svrPort;

							segFINACK->header.dest_port = clientPort;

							/* Generate a checksum and add to PacketHeader */

							unsigned short int crcSumFINACK = checksum(segFINACK);

							segFINACK->header.checksum = crcSumFINACK;

							if (0 > snp_sendseg(svrSockGlobal, tp->client_nodeID, segFINACK)) {
								fprintf(stderr, "Overlay send failed\n");
								exit(1);
							}

							free(segFINACK);
						}

						break;


					case DATA:

						fprintf(stdout, "Server at server port: %d received DATA from client NodeID: %d at port: %d\n", svrPort, src_nodeID, clientPort);

						if (CONNECTED == tp->state) {

							/* If the sequence number of the segment matches server tcb's expected sequence number */

							if (tp->expect_seqNum == segPtr->header.seq_num) {

								pthread_mutex_lock(tp->bufMutex);

								/* If receive buffer can still accommodate for received DATA segment */

								if ((tp->usedBufLen + segPtr->header.length) < RECEIVE_BUF_SIZE) {

									/* Store the received data into the receive buffer */

									char * receiveBuffer = tp->recvBuf;

									unsigned int usedBufferLen = tp->usedBufLen;

									memcpy(receiveBuffer + usedBufferLen, segPtr->data, segPtr->header.length);

									/* Increment usedBufLen and expect_seqNum by data size of received DATA segment */

									tp->expect_seqNum += segPtr->header.length;

									tp->usedBufLen += segPtr->header.length;

								}

								else { /* Simply discard received DATA segment */

									fprintf(stdout, "Receive buffer storage exceeded!!!\n");
								}

								pthread_mutex_unlock(tp->bufMutex);

							}

							/* Send DATAACK back to client w/ updated expect_seqNum or old expect_seqNum */
							
							seg_t* segDATAACK = calloc (1, sizeof(seg_t));

							if (NULL == segDATAACK) {

								free(segDATAACK);
								fprintf(stderr, "Failed to allocate memory for DATAACK segment\n");
								exit(1);
							} 

							segDATAACK->header.type = DATAACK;

							segDATAACK->header.src_port = svrPort;

							segDATAACK->header.dest_port = clientPort;

							segDATAACK->header.ack_num = tp->expect_seqNum;

							/* Generate a checksum and add to Packet Header */

							unsigned short int crcSumDATAACK = checksum(segDATAACK);

							segDATAACK->header.checksum = crcSumDATAACK;

							if (0 > snp_sendseg(svrSockGlobal, tp->client_nodeID, segDATAACK)) {
								fprintf(stderr, "Overlay send failed\n");
								exit(1);
							}

							free(segDATAACK);
						}

						else {

							fprintf(stdout, "BAD RECEIVING STATE, NOT CONNECTED\n");
						}

						break;
				}

				free(segPtr);

				/* Allocate memory for new segPtr to receive a segment from a client */

				segPtr = calloc (1, sizeof(seg_t));

				if (NULL == segPtr) {

					free(segPtr);
					fprintf(stderr, "Failed to allocate memory for segment\n");
					exit(1);
				}
			}

			else {

				/* Packet contains a bit error, so free it and drop the packet */

				fprintf(stdout, "Packet bit corruption detected!\n");

				free (segPtr);

				segPtr = calloc (1, sizeof(seg_t));

				if (NULL == segPtr) {
					free(segPtr);
					fprintf(stderr, "Failed to allocate memory for segment\n");
					exit(1);
				}
			}
		}
	}

  	return 0;
}