void rel_read (rel_t *s) { if (send_check(s)) { packet_t out_pkt; int count = conn_input(s->c, out_pkt.data, READ_SIZE); if (count == 0) { // no input return; } else { if (count == -1) { // EOF count = 0; s->SEND_EOF = true; } // send out_pkt.cksum = 0; out_pkt.len = htons(count + 12); out_pkt.ackno = htonl(1); out_pkt.seqno = htonl(s->LSS+1); out_pkt.cksum = cksum(&out_pkt, count+12); conn_sendpkt(s->c, &out_pkt, count+12); addPktToSWindow(s, out_pkt); } } }
int send_ack (rel_t *r) { packet_t ackPacket; ackPacket.cksum = 0; ackPacket.len = htons(8); ackPacket.ackno = htonl(r->LSR+1); ackPacket.cksum = cksum(&ackPacket, 8); return conn_sendpkt(r->c, &ackPacket, 8); }
void sendRead(rel_t *s){ if (s && s->inputEOF == 0) { int size = s->recvWindows; if(size > s->cwndSize){ size = s->cwndSize; } size = (size > 9) ? 9 : size; while (sizeOfQueue(s->senderBuff) < size) { packetQueue* tempPack = new_packet(); int dataIn = conn_input(s->c, tempPack->packet->data, 1000); if (dataIn == 0) { break; } if(dataIn > 0){ tempPack->packet->cksum = 0; tempPack->packet->len = htons((16 + dataIn)); tempPack->packet->seqno = htonl(s->seqOut); s->seqOut++; tempPack->packet->rwnd = htonl(s->recvWindows - sizeOfQueue(s->receiverBuff)); tempPack->packet->ackno = htonl(s->seqIn); tempPack->packet->cksum = cksum(tempPack->packet, (16 + dataIn)); addToQueue(&(s->senderBuff), tempPack); conn_sendpkt(s->c, tempPack->packet, (16 + dataIn)); } else{ s->inputEOF = 1; s->seqLast = s->seqOut; dataIn = 0; tempPack->packet->cksum = 0; tempPack->packet->len = htons((16 + dataIn)); tempPack->packet->seqno = htonl(s->seqOut); s->seqOut++; tempPack->packet->rwnd = htonl(s->recvWindows - sizeOfQueue(s->receiverBuff)); tempPack->packet->ackno = htonl(s->seqIn); tempPack->packet->cksum = cksum(tempPack->packet, (16 + dataIn)); addToQueue(&(s->senderBuff), tempPack); conn_sendpkt(s->c, tempPack->packet, (16 + dataIn)); } } return; } rel_destroy (s); return; }
/* * Method to resend ack packets when they were dropped. */ void retransmit_ack(rel_t *r, int ackVal) { packet_t *ackPacket = malloc(sizeof (struct packet)); ackPacket->len = ACK_PACKET_HEADER; ackPacket->ackno = ackVal; int ackLength = ackPacket->len; preparePacketForSending(ackPacket); ackPacket->cksum = 0; ackPacket->cksum = cksum(ackPacket, ackLength); conn_sendpkt(r->c, ackPacket, ackPacket->len); }
void rel_read (rel_t *s) { int numPacketsInWindow = s->LAST_PACKET_SENT - s->LAST_PACKET_ACKED; fprintf(stderr, "REL_READ -- lastpacketsent: %d, lastacked: %d\n", s->LAST_PACKET_SENT, s->LAST_PACKET_ACKED); if (numPacketsInWindow == 0 && s->eofSent == 1 && s->eofRecv == 1) { rel_destroy(s); return; } if (numPacketsInWindow >= s->windowSize || s->eofSent) { // don't send, window's full, waiting for acks return; } // can send packet char payloadBuffer[MAX_PAYLOAD_SIZE]; int bytesReceived = conn_input(s->c, payloadBuffer, MAX_PAYLOAD_SIZE); if (bytesReceived == 0) { return; // no data is available at the moment, just return } else if (bytesReceived == -1) { // eof or error s->eofSent = 1; bytesReceived = 0; // Why do we need to create and send a packet here? // packet_t *packet = createDataPacket(s, payloadBuffer, bytesReceived); // conn_sendpkt(s->c, packet, HEADER_SIZE + bytesReceived); // free(packet); // return; } // TODO: Need to handle overflow bytes here as well packet_t *packet = createDataPacket(s, payloadBuffer, bytesReceived); s->LAST_PACKET_SENT++; fprintf(stderr, "Sent sequence number: %d\n", ntohl(packet->seqno)); conn_sendpkt(s->c, packet, HEADER_SIZE + bytesReceived); // Save packet until it's acked/in case it needs to be retransmitted int slot = s->LAST_PACKET_SENT - s->LAST_PACKET_ACKED - 1; // fprintf(stderr, "Slot: %d\n", slot); memcpy(s->sentPackets[slot]->packet, packet, HEADER_SIZE + bytesReceived); s->sentPackets[slot]->sentTime = getCurrentTime(); s->sentPackets[slot]->acked = 1; fprintf(stderr, "%s\n", "====================SENDING PACKET================"); // fprintf(stderr, "Packet data: %s\n", packet->data); free(packet); }
void ack(rel_t *r, uint32_t ackno) { struct ack_packet* tempAck = (struct ack_packet*) malloc(sizeof(struct ack_packet)); memset(tempAck, 0, sizeof(struct ack_packet)); tempAck->ackno = htonl(ackno); tempAck->rwnd = htonl(r->recvWindows - sizeOfQueue(r->receiverBuff)); //fprintf(stderr, "ack rwnd: %d\n", r->recvWindows - sizeOfQueue(r->receiverBuff)); tempAck->len = htons(sizeof(struct ack_packet)); tempAck->cksum = cksum((void *)tempAck, sizeof(struct ack_packet)); conn_sendpkt(r->c, (packet_t *)tempAck, sizeof(struct ack_packet)); free(tempAck); return; }
void rel_timer () { /* Retransmit any packets that need to be retransmitted */ // check timeout // check acks...3 of same? congestion control /* Retransmit any packets that need to be retransmitted */ rel_t *r = rel_list; uint32_t curTime = getCurrentTime(); if (r->LAST_ACK_COUNT >= 3) { r->slowStart = 0; r->windowSize /= 2; int j; for (j = 0; j < r->LAST_PACKET_SENT - r->LAST_PACKET_ACKED; j++) { wrapper *curPacketNode = r->sentPackets[j]; if (ntohl(curPacketNode->packet->seqno) == r->LAST_ACK_RECVD) { curPacketNode->sentTime = curTime; conn_sendpkt(r->c, curPacketNode->packet, ntohs(curPacketNode->packet->len)); return; } } } int numPacketsInWindow = r->LAST_PACKET_SENT - r->LAST_PACKET_ACKED; int i; for (i = 0; i < numPacketsInWindow; i++) { wrapper *curPacketNode = r->sentPackets[i]; // uint32_t timediff = curTime - curPacketNode->sentTime; if (curTime - curPacketNode->sentTime > r->timeout) { // fprintf(stderr, "Retransmitted packet w/ sequence number: %d\n", ntohl(curPacketNode->packet->seqno)); // retransmit package conn_sendpkt(r->c, curPacketNode->packet, ntohs(curPacketNode->packet->len)); } } }
void rel_output (rel_t *r) { // printf("rel_output\n"); int numPacketsInWindow = r->LAST_PACKET_SENT - r->LAST_PACKET_ACKED; int i; // fprintf(stderr, "lastpacksent: %d, lackPackacked: %d\n", r->LAST_PACKET_SENT, r->LAST_PACKET_ACKED); for (i = 0; i < r->windowSize; i++) { // fprintf(stderr, "Recvpacket of %d has ack %d\n", i, r->recvPackets[i]->acked); if(r->recvPackets[i]->acked == 0) { break; } packet_t *pkt = r->recvPackets[i]->packet; uint16_t packet_len = ntohs(pkt->len); size_t len = conn_bufspace(r->c); // fprintf(stderr, "Packet len: %d\n", (int) packet_len); if(len >= packet_len - HEADER_SIZE) { if(packet_len == HEADER_SIZE) { r->eofRecv = 1; } // fprintf(stderr, "Outputting packet %d from recvPackets \n", i); conn_output(r->c, pkt->data, packet_len - HEADER_SIZE); r->recvPackets[i]->acked = 0; } else { break; } } // fprintf(stderr, "value of i: %d\n", i); // fprintf(stderr, "Next Packet Expected Before: %d\n", r->NEXT_PACKET_EXPECTED ); r->NEXT_PACKET_EXPECTED += i; struct ack_packet *ack = createAckPacket(r, r->NEXT_PACKET_EXPECTED); // fprintf(stderr, "Next Packet Expected: %d\n", r->NEXT_PACKET_EXPECTED); conn_sendpkt(r->c, (packet_t *)ack, ACK_PACKET_SIZE); free(ack); // fprintf(stderr, "reloutput -- numPackets: %d, eofRecv: %d, eofSend: %d\n", numPacketsInWindow, r->eofRecv, r->eofSent); if(numPacketsInWindow == 0 && r->eofRecv == 1 && r->eofSent == 1) { rel_destroy(r); return; } shiftRecvPacketList(r); }
void retransmit(rel_t *rel) { packetQueue* current = rel->senderBuff; while(current){ if(!(current->packet)){ break; } conn_sendpkt(rel->c, current->packet, ntohs(current->packet->len)); current = current->next; } current = rel->senderBuff; if (sizeOfQueue(current)> 0) { if(current){ rel->ssthresh = rel->ssthresh / 2; rel->cwndSize = 3; } } }
void rel_send_ack (rel_t *r, int ackno) { assert(r); assert(ackno >= r->ackno); /* Acks cannot regress */ r->ackno = ackno; /* Build the ack packet */ packet_t ack_packet; ack_packet.ackno = htonl(ackno); ack_packet.len = htons(8); ack_packet.cksum = 0; ack_packet.cksum = cksum(&ack_packet, 8); /* Send it off */ conn_sendpkt (r->c, &ack_packet, 8); }
void recvRead (rel_t *s){ if (s->inputEOF != 1) { s->seqLast = s->seqOut; packetQueue *eofpacket = new_packet(); memset(eofpacket, 0, sizeof(packetQueue)); eofpacket->packet->len = htons(16); eofpacket->packet->seqno = htonl(s->seqOut); s->seqOut = s->seqOut + 1; eofpacket->packet->rwnd = htonl(s->recvWindows - sizeOfQueue(s->receiverBuff)); eofpacket->packet->ackno = htonl(s->seqIn); uint16_t checksum = cksum(eofpacket->packet, 16); eofpacket->packet->cksum = checksum; conn_sendpkt(s->c, eofpacket->packet, 16); addToQueue(&(s->senderBuff), eofpacket); s->inputEOF = 1; return; } return; }
void send_data_pkt(rel_t *s, int data_size) { //update sender state when a new data packet is sent s->sender.last_frame_sent++; s->sender.packet.len = data_size + DATA_PACKET_HEADER; s->sender.packet.seqno = s->sender.last_frame_sent; s->sender.packet.ackno = s->sender.packet.seqno + 1; //ackno should always be 1 higher than seqno //fprintf(stderr, "seqno: %i, buffer position: %i\n", s->sender.packet.seqno, s->sender.buffer_position); //alert the user when user has exceeded sender's window size if (s->sender.packet.seqno > s->windowSize + s->sender.buffer_position || s->sender.packet.seqno == s->windowSize + s->sender.buffer_position) { // fprintf(stderr, "**** You have exceeded the sender's window size. Packet will not be sent. **** \n"); s->sender.last_frame_sent--; return; } int positionInArray = s->sender.packet.seqno; int length = s->sender.packet.len; preparePacketForSending(&(s->sender.packet)); s->sender.packet.cksum = 0; s->sender.packet.cksum = cksum(&s->sender.packet, length); //prepare a copy of the packet along with other state to store in sender buffer packet_t *sendingPacketCopy = malloc(sizeof s->sender.packet); memcpy(sendingPacketCopy, &s->sender.packet, sizeof s->sender.packet); struct WindowBuffer *packetBuffer = malloc(sizeof(struct WindowBuffer)); packetBuffer->isFull = 1; packetBuffer->ptr = sendingPacketCopy; packetBuffer->timeStamp = timestamp; //place the WindowBuffer in the buffer array s->senderWindowBuffer[positionInArray] = *packetBuffer; //send the packet over network conn_sendpkt(s->c, &s->sender.packet, s->sender.packet.len); memset(&s->sender.packet, 0, sizeof(&s->sender.packet)); }
void rel_timer () { //fprintf(stderr, "%s\n", "REL_TIMER"); /* Retransmit any packets that need to be retransmitted */ rel_t *r = rel_list; uint32_t curTime = getCurrentTime(); while (r != NULL) { int numPacketsInWindow = r->LAST_PACKET_SENT - r->LAST_PACKET_ACKED; int i; for (i = 0; i < numPacketsInWindow; i++) { wrapper *curPacketNode = r->sentPackets[i]; // uint32_t timediff = curTime - curPacketNode->sentTime; if (curTime - curPacketNode->sentTime > r->timeout) { fprintf(stderr, "Retransmitted packet w/ sequence number: %d\n", ntohl(curPacketNode->packet->seqno)); // retransmit package conn_sendpkt(r->c, curPacketNode->packet, ntohs(curPacketNode->packet->len)); } } r = r->next; } }
void rel_recvpkt (rel_t *r, packet_t *pkt, size_t n) { uint16_t len = ntohs(pkt->len); uint32_t ackno = ntohl(pkt->ackno); int verified = verifyChecksum(r, pkt, n); if (!verified || (len != n)) { // Drop packets with bad length fprintf(stderr, "Packet w/ sequence number %d dropped\n", ntohl(pkt->seqno)); return; } if (len == ACK_PACKET_SIZE) { // Received packet is an ack packet fprintf(stderr, "Received ack number: %d\n", ackno); if (ackno <= r->LAST_PACKET_ACKED + 1) { // Drop duplicate acks fprintf(stderr, "Duplicate ack: %d received\n", ackno); return; } //if (ackno == r->LAST_PACKET_SENT + 1) { // REMOVE THIS AFTER WE FIX ACK SENDING!!!! shiftSentPacketList(r, ackno); r->LAST_PACKET_ACKED = ackno - 1; rel_read(r); //} } else { // data packet fprintf(stderr, "%s\n", "======================RECEIVED DATA PACKET========================="); uint32_t seqno = ntohl(pkt->seqno); // fprintf(stderr, "Received data: %s\n", pkt->data); // if (seqno > r->NEXT_PACKET_EXPECTED) { // // Ghetto fix // return; // } if (seqno < r->NEXT_PACKET_EXPECTED) { // duplicate packet fprintf(stderr, "Received duplicate packet w/ sequence number: %d\n", seqno); struct ack_packet *ack = createAckPacket(r, r->NEXT_PACKET_EXPECTED); conn_sendpkt(r->c, (packet_t *)ack, ACK_PACKET_SIZE); free(ack); return; } if (seqno - r->NEXT_PACKET_EXPECTED > r->windowSize) { // Packet outside window return; } fprintf(stderr, "Received sequence number: %d\n", seqno); int slot = seqno - r->NEXT_PACKET_EXPECTED; fprintf(stderr, "RecvPacket slot number: %d\n", slot); memcpy(r->recvPackets[slot]->packet, pkt, sizeof(packet_t)); r->recvPackets[slot]->sentTime = getCurrentTime(); r->recvPackets[slot]->acked = 1; rel_output(r); // if (seqno == r->NEXT_PACKET_EXPECTED) { // struct ack_packet *ack = createAckPacket(r, r->NEXT_PACKET_EXPECTED + 1); // conn_sendpkt(r->c, (packet_t *)ack, ACK_PACKET_SIZE); // conn_output(r->c, pkt->data, len - HEADER_SIZE); // // rel_output(r); // r->NEXT_PACKET_EXPECTED++; // free(ack); // } } }
/* * Method to resend data packets when they were dropped. * This method is called in rel_timer(). */ void retransmit_data(rel_t *s, int seqno) { struct WindowBuffer *packet = &s->senderWindowBuffer[seqno]; conn_sendpkt(s->c, packet->ptr, packet->ptr->len); }
int resend_pkt (rel_t *s, int index) { return conn_sendpkt(s->c, &(s->sendWindow[index]), ntohs(s->sendWindow[index].len)); }
void rel_recvpkt (rel_t *r, packet_t *pkt, size_t n) { // printf("rel_recvpkt\n"); uint16_t len = ntohs(pkt->len); uint32_t ackno = ntohl(pkt->ackno); int verified = verifyChecksum(r, pkt, n); if (!verified || (len != n)) { // Drop packets with bad length // fprintf(stderr, "Packet w/ sequence number %d dropped\n", ntohl(pkt->seqno)); return; } if (len == ACK_PACKET_SIZE) { // Received packet is an ack packet // fprintf(stderr, "Received ack number: %d\n", ackno); // fprintf(stderr, "%s\n", "======================RECEIVED ACK PACKET========================="); if (ackno <= r->LAST_PACKET_ACKED + 1) { // Drop duplicate acks // fprintf(stderr, "Duplicate ack: %d received\n", ackno); return; } if (ackno == r->LAST_ACK_RECVD) { r->LAST_ACK_COUNT++; } else { r->LAST_ACK_RECVD = ackno; r->LAST_ACK_COUNT = 1; } if (r->slowStart) { // fprintf(stderr, "window size: %d\n", r->windowSize); if (r->windowSize * 2 > r->ssThresh) { // START AIMD // return; } else { r->windowSize = r->windowSize * 2; } // fprintf(stderr, "success? %d\n", r->windowSize); } else { if (r->windowSize + 1 == r->ssThresh) { } else { r->windowSize = r->windowSize + 1; } } shiftSentPacketList(r, ackno); r->LAST_PACKET_ACKED = ackno - 1; rel_read(r); } else { // data packet // fprintf(stderr, "%s\n", "======================RECEIVED DATA PACKET========================="); uint32_t seqno = ntohl(pkt->seqno); // fprintf(stderr, "Received Data: %s\n", pkt->data); // fprintf(stderr, "Received data: %s\n", pkt->data); // if (seqno > r->NEXT_PACKET_EXPECTED) { // // Ghetto fix // return; // } if (seqno < r->NEXT_PACKET_EXPECTED) { // duplicate packet // fprintf(stderr, "Received duplicate packet w/ sequence number: %d\n", seqno); struct ack_packet *ack = createAckPacket(r, r->NEXT_PACKET_EXPECTED); conn_sendpkt(r->c, (packet_t *)ack, ACK_PACKET_SIZE); free(ack); return; } if (seqno - r->NEXT_PACKET_EXPECTED > r->windowSize) { // Packet outside window return; } // fprintf(stderr, "Received sequence number: %d\n", seqno); int slot = seqno - r->NEXT_PACKET_EXPECTED; // fprintf(stderr, "RecvPacket slot number: %d\n", slot); memcpy(r->recvPackets[slot]->packet, pkt, sizeof(packet_t)); r->recvPackets[slot]->sentTime = getCurrentTime(); r->recvPackets[slot]->acked = 1; rel_output(r); // if (seqno == r->NEXT_PACKET_EXPECTED) { // struct ack_packet *ack = createAckPacket(r, r->NEXT_PACKET_EXPECTED + 1); // conn_sendpkt(r->c, (packet_t *)ack, ACK_PACKET_SIZE); // conn_output(r->c, pkt->data, len - HEADER_SIZE); // // rel_output(r); // r->NEXT_PACKET_EXPECTED++; // free(ack); // } } }
/* If the reliable program is running in the receiver mode (see c.sender_receiver in rlib.c, you can get its value in rel_create), this receiver should send an EOF to the sender when rel_read is first called. After this first call, the function rel_read can simply return for later calls. Note that this EOF will wait in the receiver's sending window. When timeout happens, the receiver have to retransmit this EOF as well until an ACK is received. If the reliable is running in the sender mode, the rel_read's behavior is the same as that is described above in 3a. */ void rel_read (rel_t *s) { // printf("rel_read\n"); if(s->c->sender_receiver == RECEIVER) { // if already sent eof to the sender/not first call // return; if(s->eofSent == 1) { // fprintf(stderr, "%s\n", "EOF already sent in rel_read"); // s->eofSent = 0; return; } else { // first call // set eofSent to 1 s->eofSent = 1; // send eof char payloadBuffer[MAX_PAYLOAD_SIZE]; int bytesReceived = 0; packet_t *packet = createDataPacket(s, payloadBuffer, bytesReceived); conn_sendpkt(s->c, packet, HEADER_SIZE + bytesReceived); free(packet); // printf("Sending EOF to sender in rel_read\n"); } //if already sent EOF to the sender // return; //else // send EOF to the sender } else //run in the sender mode { //same logic as lab 1 int numPacketsInWindow = s->LAST_PACKET_SENT - s->LAST_PACKET_ACKED; // fprintf(stderr, "REL_READ -- lastpacketsent: %d, lastacked: %d\n", s->LAST_PACKET_SENT, s->LAST_PACKET_ACKED); // fprintf(stderr, "relread -- numPackets: %d, eofRecv: %d, eofSend: %d\n", numPacketsInWindow, s->eofRecv, s->eofSent); if (numPacketsInWindow == 0 && s->eofSent == 1 && s->eofRecv == 1) { rel_destroy(s); return; } if (numPacketsInWindow >= s->windowSize || s->eofSent) { // don't send, window's full, waiting for acks return; } // can send packet char payloadBuffer[MAX_PAYLOAD_SIZE]; memset(payloadBuffer, 0, MAX_PAYLOAD_SIZE); int bytesReceived = conn_input(s->c, payloadBuffer, MAX_PAYLOAD_SIZE); // fprintf(stderr, "Bytes received: %d\n", bytesReceived ); if (bytesReceived == 0) { return; // no data is available at the moment, just return } else if (bytesReceived == -1) { // eof or error s->eofSent = 1; bytesReceived = 0; // Why do we need to create and send a packet here? // packet_t *packet = createDataPacket(s, payloadBuffer, bytesReceived); // conn_sendpkt(s->c, packet, HEADER_SIZE + bytesReceived); // free(packet); // return; } // TODO: Need to handle overflow bytes here as well packet_t *packet = createDataPacket(s, payloadBuffer, bytesReceived); s->LAST_PACKET_SENT++; // fprintf(stderr, "Sent sequence number: %d\n", ntohl(packet->seqno)); // fprintf(stderr, "PACKET INFO: %s\n", packet->data); // fprintf(stderr, "PACKET INFO: %s\n", strdup(payloadBuffer)); // fprintf(stderr, "String Compare Value: %d\n", strcmp(packet->data, "")); conn_sendpkt(s->c, packet, HEADER_SIZE + bytesReceived); // Save packet until it's acked/in case it needs to be retransmitted int slot = s->LAST_PACKET_SENT - s->LAST_PACKET_ACKED - 1; // fprintf(stderr, "Slot: %d\n", slot); memcpy(s->sentPackets[slot]->packet, packet, HEADER_SIZE + bytesReceived); s->sentPackets[slot]->sentTime = getCurrentTime(); s->sentPackets[slot]->acked = 1; // fprintf(stderr, "%s\n", "====================SENDING PACKET================"); // fprintf(stderr, "Packet data: %s\n", packet->data); free(packet); } }