static void timeoutFunction(Connection *conn) { SgmBuffElem *curr = NULL; DBGPRINT(RUSP_DEBUG, "RETRANSMISSION"); if (pthread_rwlock_rdlock(&(conn->sndsgmbuff.rwlock)) > 0) ERREXIT("Cannot acquire read-lock."); curr = conn->sndsgmbuff.head; while (curr) { if (testSgmBuffElemAttributes(curr, RUSP_NACK, getTimeoutValue(&(conn->timeout)))) { updateSgmBuffElemAttributes(curr, 1, getTimeoutValue(&(conn->timeout))); sendSegment(conn, curr->segment); } curr = curr->next; } if (pthread_rwlock_unlock(&(conn->sndsgmbuff.rwlock)) > 0) ERREXIT("Cannot release read-write lock."); DBGPRINT(RUSP_DEBUG, "END OF RETRANSMISSION"); }
static void sendCACK(Connection *conn, const uint32_t ackn) { Segment acksgm; acksgm = createSegment(RUSP_CACK, 0, getWindowNext(&(conn->sndwnd)), ackn, NULL); sendSegment(conn, acksgm); }
static void *senderLoop(void *arg) { Connection *conn = (Connection *) arg; char payload[RUSP_PLDS]; size_t plds; pthread_cleanup_push(cleanupFunction, &(conn->sndusrbuff.mtx)); while (1) { plds = waitLookMaxStrBuff(&(conn->sndusrbuff), payload, RUSP_PLDS); Segment sgm = createSegment((conn->sndusrbuff.size == plds) ? RUSP_PSH : RUSP_NUL, plds, getWindowNext(&(conn->sndwnd)), 0, payload); waitWindowSpace(&(conn->sndwnd), plds); addSgmBuff(&(conn->sndsgmbuff), sgm, RUSP_NACK); sendSegment(conn, sgm); slideWindowNext(&(conn->sndwnd), sgm.hdr.plds); DBGPRINT(RUSP_DEBUG, "SND (NXT): base:%u nxt:%u end:%u SNDUSRBUFF:%zu SNDSGMBUFF:%ld", getWindowBase(&(conn->sndwnd)), getWindowNext(&(conn->sndwnd)), getWindowEnd(&(conn->sndwnd)), getStrBuffSize(&(conn->sndusrbuff)), getSgmBuffSize(&(conn->sndsgmbuff))); popStrBuff(&(conn->sndusrbuff), plds); } pthread_cleanup_pop(1); return NULL; }
void Transportlag::senderTransport(std::string enTekst) { senderBuffer.clear(); numberOfSequences = enTekst.size() / 80; if (enTekst.size() % 80 != 0) { numberOfSequences++; } senderBuffer = { "00000000" }; //Her laves probing headeren senderBuffer[0] += "001"; senderBuffer[0] += intToString(numberOfSequences); for (size_t i = 1; i <= numberOfSequences; i++) //Der laves headeren til hvert segment { senderBuffer.push_back(intToString(i)); if (i<numberOfSequences) { senderBuffer[i] += "000"; } else { senderBuffer[i] += "100"; } for (size_t k = 0; k < 80; k++) { if (enTekst.size() == k + 80 * i - 80) //Hvis et segment er mindre end 80 byte, { //så der ikke mere at sende i det segment break; } senderBuffer[i] += enTekst[k+80*i-80]; } } //----------------------------------------------- for (size_t i = 0; i < senderBuffer.size(); i++) { std::cout << senderBuffer[i] << std::endl; sendSegment(senderBuffer[i]); //std::string somestuff = waitForACK(); } //----------------------------------------------- }
void activeClose(Connection *conn) { Segment fin; cancelThread(conn->sender); joinThread(conn->sender); fin = createSegment(RUSP_FIN, 0, getWindowNext(&(conn->sndwnd)), 0, NULL); addSgmBuff(&(conn->sndsgmbuff), fin, RUSP_NACK); setConnectionState(conn, RUSP_FINWT1); sendSegment(conn, fin); slideWindowNext(&(conn->sndwnd), 1); DBGPRINT(RUSP_DEBUG, "SND (NXT): base:%u nxt:%u end:%u SNDUSRBUFF:%zu SNDSGMBUFF:%ld", getWindowBase(&(conn->sndwnd)), getWindowNext(&(conn->sndwnd)), getWindowEnd(&(conn->sndwnd)), getStrBuffSize(&(conn->sndusrbuff)), getSgmBuffSize(&(conn->sndsgmbuff))); joinThread(conn->receiver); }
/* Send all unsent segments from buffer to remote destination */ void sendFromSendBuffer (TCP_buffer* bufptr, int sock, struct sockaddr_in dest, struct sockaddr_in timer, int mode, TCP_buffer* ptr){ /* Traverse the buffer and send valid segments that have not been * sent before. A segment is valid if its seqno is within current * send window. */ TCP_buffer* p = bufptr; struct timeval tim; double t1; int time = 0; if (mode == SEND_ONE){ p = ptr; if (isWithinWindow (sendWindow, p->ts.hdr.seq + p->len) && (p->txCount > 0)){ /*if (fork() == 0){*/ printf("Sending data...\n"); /* Sending segment to destination */ sendSegment (&(p->ts), p->len, sock, dest); /* Set timeout value using exponential backoff */ /*time = (int)(RTO * pow(2.0, (double)p->txCount)); */ time = RTO; /* Sending request to timer process to add new entry */ sendTimerAddRequest (sock, timer, &(p->ts), time); printf("Retransmitted segment seq = %d\n",p->ts.hdr.seq); /* Updating number of tries and time of last transmission*/ p->txCount = p->txCount + 1; gettimeofday(&tim, NULL); p->lastTxTime = tim.tv_sec + (tim.tv_usec/1000000.0); /* printf("lastTime = %.2f\n",p->lastTxTime); */ } else { printf("RT segment not in window seq = %d txcount = %d\n",p->ts.hdr.seq, p->txCount); /* exit(1); */ } return; } while (p != NULL){ if (isWithinWindow (sendWindow, p->ts.hdr.seq + p->len) && (p->txCount == 0)){ printf("Sending data...\n"); /* Sending segment to destination */ sendSegment (&(p->ts), p->len, sock, dest); /* Sending request to timer process to add new entry */ sendTimerAddRequest (sock, timer, &(p->ts), time); /* * printf("Sent segment seq = %d\n",p->ts.hdr.seq); */ /* Updating number of tries */ p->txCount = p->txCount + 1; gettimeofday(&tim, NULL); p->lastTxTime = tim.tv_sec + (tim.tv_usec/1000000.0); /* printf("lastTime = %.2f\n",p->lastTxTime); */ } else { /* printf("segment not in window (%d,%d)seq = %d txcount = %d\n",sendWindow.low, sendWindow.high,p->ts.hdr.seq, p->txCount); */ } p = p->next; } }
int main (){ int sock_main, sock_timer; struct sockaddr_in main, timer; char buf[TCP_SEGMENT_SIZE]; char hostname[128]; gethostname (hostname, sizeof(hostname)); hp = gethostbyname(hostname); sock_main = socket (AF_INET, SOCK_DGRAM, 0); if (sock_main < 0){ perror("opening UDP socket for main use"); exit(1); } bzero ((char*)&main, sizeof (main)); main.sin_family = AF_INET; main.sin_port = TCPD_PORT; bcopy((void *)hp->h_addr_list[0], (void *)&main.sin_addr, hp->h_length); if (bind(sock_main, (struct sockaddr *)&main, sizeof(main)) < 0){ perror("getting socket name of main TCPD port"); exit(2); } printf("TCPD MAIN SOCKET : PORT = %d ADDR = %d\n",main.sin_port,main.sin_addr.s_addr); bzero((char*)&timer, sizeof(timer)); timer.sin_family = AF_INET; timer.sin_port = TIMER_PORT; bcopy((void *)hp->h_addr_list[0], (void *)&timer.sin_addr, hp->h_length); /* TODO : Initialize send and receive windows */ sendWindow.low = 100; sendWindow.high = sendWindow.low + WINDOW_SIZE * TCP_MSS; recvWindow.low = 100; recvWindow.high = recvWindow.low + WINDOW_SIZE * TCP_MSS; while (1){ int type = 0; void *ptr = NULL; int send_bytes = 0; int sock = 0; int rlen = 0; int i = 0; TCP_segment ts; TCP_segment ts_recv; TCP_segment* tsp; struct sockaddr_in name; /* printf("Inside child process to receive data\n"); */ printf("\n\n"); /* Initialize buffer to all zeroes */ bzero(buf, TCP_MSS); /* Receive data from UDP port */ rlen = recvSegment((TCP_segment *)&ts, sock_main, main); /* Get segment type (LOCAL, REMOTE or TIMER) */ type = getSegmentType (ts); /* printf("Segment Type = %d len = %d\n",type,rlen); */ /* Segment received from local application process */ if (type == LOCAL_SEGMENT) { printf("Received local segment len = %d\n",rlen); printf("sBufCount = %d\n",sBufCount); printf("Send window : (%d, %d)\n",sendWindow.low, sendWindow.high); /* Receiving destination address when a CONNECT is called*/ if (ts.hdr.seq == DEST_INFO) { memcpy ((void*)&dest, (void*)&(ts.data), sizeof(struct sockaddr_in)); printf("Received destination info from app\n"); continue; } /* Receiving source address when a BIND is called*/ else if (ts.hdr.seq == SRC_INFO) { memcpy ((void*)&src, (void*)&(ts.data), sizeof(struct sockaddr_in)); printf("Received source info from app port = %d\n",src.sin_port); continue; } /* memcpy((void*)&buf[0], (void*)&ts.data, rlen-TCP_HEADER_SIZE); for (i = 0; i < rlen-TCP_HEADER_SIZE; ++i) printf("%d", buf[i]); printf("Recv bytes = %d\n",rlen-TCP_HEADER_SIZE); */ if (sBufCount == BUFFER_SIZE) continue; /* sBufCount++; */ /* Construct TCP segment with received data */ ts = constructSegment((void*)&ts.data, rlen-TCP_HEADER_SIZE); /* Sequence number gets incremented by * 1 for each byte sent */ nextSeq = nextSeq + rlen-TCP_HEADER_SIZE; /* Add segment to send buffer */ /* TODO: Revisit buffer overflow logic here */ memcpy((void*)&buf, (void*) &ts.data, rlen); /* for (i = 0; i < rlen; ++i) printf("%c"); printf("\n"); */ sBufPtr = addToBuffer (sBufPtr, &sBufCount, ts, rlen); /* Send from send buffer */ sendFromSendBuffer (sBufPtr, sock_main, dest, timer, SEND_ALL, NULL); } /* Segment received from remote process */ else if (type == REMOTE_SEGMENT) { printf("Received remote segment len = %d\n",rlen); printf("Recv window : (%d, %d)\n",recvWindow.low, recvWindow.high); /* TODO : Checksum here */ /* printf("seq = %d crc = %d len = %d\n",ts.hdr.seq,ts.hdr.sum, rlen); memcpy((void*)&buf[0], (void*)&ts, rlen); for (i = 0; i < TCP_HEADER_SIZE; ++i) printf("%d",buf[i]); printf("\n"); */ /* Check if segment has valid checksum */ if (!isValidChecksum(&ts, rlen)){ printf("Checksum FAILURE\n"); continue; } printf("Checksum SUCCESS\n"); /* Check if ACK flag is set */ if (isACK(&ts)){ /* TODO :Handle ACK for already ACKed segments here */ printf("Received ACK no = %d\n", ts.hdr.ack); /* Remove ACKed segment from buffer */ sBufPtr = removeFromSendBuffer(sBufPtr, sock_main, timer, ts.hdr.ack); /* Maintain ACK Count and compute RTO */ ackCount += 1; computeRTO (); continue; } /* Check if segment has valid checksum */ /* if (!isValidChecksum(&ts, rlen)){ printf("Checksum FAILURE"); continue; } printf("Checksum SUCCESS\n"); */ /* Process received segment and return ptr to data*/ ptr = processSegment((TCP_segment *)&ts, rlen); setACKFlag(&ts); /* TODO : How ACK set?*/ ts.hdr.ack = ts.hdr.seq + rlen-TCP_HEADER_SIZE; if (isWithinWindow(recvWindow, ts.hdr.seq+rlen-TCP_HEADER_SIZE)|| (ts.hdr.seq < recvWindow.low)){ int seq = ts.hdr.seq; printf("Sending ACK for seq = %d\n",ts.hdr.seq); ts.hdr.seq = nextSeq; ts.hdr.urp = 0; ts.hdr.sum = 0; memcpy((void*)&buf, (void*)&ts, TCP_HEADER_SIZE); ts.hdr.sum = computeChecksum(&buf[0], TCP_HEADER_SIZE, &(ts.hdr.sum)); /* printf("Checksum for ACK seq : %d crc : %d len : %d\n",ts.hdr.seq, ts.hdr.sum, TCP_HEADER_SIZE); for (i = 0; i < TCP_HEADER_SIZE; ++i) printf("%d",buf[i]); printf("\n"); */ /*ts.hdr.urp = REMOTE_SEGMENT;*/ /* for (i = 0; i < TCP_HEADER_SIZE; ++i) printf("%d",buf[i]); printf("\n"); */ /* Sending ACK to remote process */ sendSegment(&ts, TCP_HEADER_SIZE, sock_main, replyaddr); nextSeq = nextSeq + TCP_HEADER_SIZE; ts.hdr.seq = seq; } /*printf("Sent ACK for seq = %d to dest = %d\n",ts.hdr.seq, replyaddr.sin_addr.s_addr); */ if (!isWithinWindow(recvWindow, ts.hdr.seq+rlen-TCP_HEADER_SIZE) || nextExpectedSeq > ts.hdr.seq){ printf("Not within recv window seq = %d\n",ts.hdr.seq); continue; } printf("rBufCount = %d\n",rBufCount); /* if (rBufPtr != NULL) printf("RB : headseq = %d nes = %d\n",rBufPtr->ts.hdr.seq, nextExpectedSeq); if (rBufPtr != NULL && rBufPtr->ts.hdr.seq < nextExpectedSeq){ printf("EXITING.......... \n"); exit(1); } */ /* if (nextExpectedSeq < recvWindow.low){ printf("EXITING..\n"); exit(1); } */ if (rBufCount == BUFFER_SIZE) continue; /*rBufCount++; */ /* TODO: Temporary hack to avoid recv buffer */ /*sendData(&ts, rlen, sock_main, src); continue; */ /* Add segment to receive buffer */ rBufPtr = addToBuffer (rBufPtr, &rBufCount, ts, rlen); if (rBufPtr == NULL){ printf("rbufptr = NULL post adding\n"); continue; } /* Update receive window */ updateWindow(&recvWindow, ts.hdr.seq, rlen-TCP_HEADER_SIZE); /* Send data to local process */ rBufPtr = sendFromRecvBuffer(rBufPtr, sock_main, src); } else if (type == TIMER_SEGMENT){ TCP_buffer* ptr = NULL; printf("Received timer segment len = %d\n",rlen); memcpy((void*)&ptr, (void*)&(ts.data), sizeof(ptr)); /* Update RTO on timeout. Message from timer * implies timeout. */ computeRTO(); /* Retransmit segment to remote process */ sendFromSendBuffer (sBufPtr, sock_main, dest, timer, SEND_ONE, ptr); } } return 0; }