/* send packets until window is maxed out */ void sendWindow(chunkEle* cep, int sock){ // no acks yet, send single packet window if( cep->lastAcked == NULL ){ void* packet = cep->packetList.headp->data; unsigned int bufSize = ((packetHead *)packet)->packLen; spiffy_sendto(sock, packet, bufSize, 0, (struct sockaddr *) &cep->fromThisPeer->cli_addr, sizeof(cep->fromThisPeer->cli_addr)); //sendto(sock, packet, bufSize, 0, (struct sockaddr *) &cep->fromThisPeer->cli_addr, sizeof(cep->fromThisPeer->cli_addr)); cep->lastSent = cep->packetList.headp; return; } //while window isn't exhausted while( ( ((packetHead*)cep->lastSent->data)->seqNum - ((packetHead*)cep->lastAcked->data)->seqNum ) < cep->packetList.length - 1 ){ cep->lastSent = cep->lastSent->prevp; void* packet = cep->lastSent->data; unsigned int bufSize = ((packetHead *)packet)->packLen; spiffy_sendto(sock, packet, bufSize, 0, (struct sockaddr *) &cep->fromThisPeer->cli_addr, sizeof(cep->fromThisPeer->cli_addr)); //sendto(sock, packet, bufSize, 0, (struct sockaddr *) &cep->fromThisPeer->cli_addr, sizeof(cep->fromThisPeer->cli_addr)); } return; }
void sendback_response(int sock, char **haschunk_list, int size, struct sockaddr_in from) { int num_chunks, head; packet *p; p = packet_factory(IHAVE); dprintf(STDOUT_FILENO, "Response payload has: \n"); for (num_chunks = 0; num_chunks < size; num_chunks++) { head = 4 + num_chunks * BT_CHUNKS_SIZE; strncpy(p->payload + head, haschunk_list[num_chunks], BT_CHUNKS_SIZE); dprintf(STDOUT_FILENO, "%s\n", haschunk_list[num_chunks]); } p->packet_length = 20 + num_chunks * BT_CHUNKS_SIZE; p->payload[0] = num_chunks; p->payload[1] = '\0'; p->payload[2] = '\0'; p->payload[3] = '\0'; spiffy_sendto(sock, p, p->packet_length, 0, (struct sockaddr *) &from, sizeof(from)); free(p); }
void sendData(struct sockaddr_in from, bt_config_t *config) { packet *p; FILE *fp; if ((fp = fopen("example/C.tar", "rb")) == NULL ) return; p = packet_factory(DATA); p->packet_length = 16 + BT_FULL_DATASIZE; p->sequence_num = ++lastSent[nodeInMap]; // look for the correct position to read the data to packet long int offset = BT_CHUNK_SIZE * BT_FULL_DATASIZE * jobs[nodeInMap] + BT_FULL_DATASIZE * (p->sequence_num - 1); fseek(fp, offset, SEEK_SET); fread(p->payload, 1, BT_FULL_DATASIZE, fp); fclose(fp); spiffy_sendto(config->sock, p, p->packet_length, 0, (struct sockaddr *) &from, sizeof(from)); TTL[nodeInMap][p->sequence_num - 1] = 0; dprintf(STDOUT_FILENO, "sending data: %d\n", p->sequence_num); free(p); }
// send one packet void send_packet(struct packet packet, int socket, struct sockaddr* dst_addr){ char buffer[MAX_PACKET_SIZE]; memcpy(buffer, packet.header, 16); memcpy(buffer+16, packet.payload, MAX_PAYLOAD_SIZE); unsigned short packet_length = ntohs(*(unsigned short*)(packet.header+6)); spiffy_sendto(socket, buffer, packet_length, 0, dst_addr, sizeof(*dst_addr)); }
void process_get(char *chunkfile, char *outputfile) { parseChunkFile(chunkfile, &chunkList); printChunkList(chunkList); strcpy(outputFilePath,outputfile); if((outputFile = fopen(outputfile, "w")) == NULL){ fprintf(stderr,"Error opening %s\n",outputfile); exit(1); } int i; int j; /* needed if too many chunks for one packet */ for(i = 0; i < chunkList.length; i += MAXCHUNKS){ void* whohasp = whohasCons(&chunkList, i); unsigned int bufSize = ((packetHead *)whohasp)->packLen; node* itr = peerList.headp; for(j = 0; j < peerList.length; j++){ peerEle* thisPeer = (peerEle*)itr->data; if( thisPeer->id != myId ){ printf("Send packet to peer %d @ %s:%d\n", thisPeer->id, inet_ntoa(thisPeer->cli_addr.sin_addr) ,ntohs(thisPeer->cli_addr.sin_port)); spiffy_sendto(sock, whohasp, bufSize, 0, (struct sockaddr *) &thisPeer->cli_addr, sizeof(thisPeer->cli_addr)); //sendto(sock, whohasp, bufSize, 0, (struct sockaddr *) &thisPeer->cli_addr, sizeof(thisPeer->cli_addr)); } itr = itr->nextp; } } printf("PROCESS GET SKELETON CODE CALLED. Fill me in! (%s, %s)\n", chunkfile, outputfile); }
void broadcast_query(char **chunk_list, bt_config_t *config) { packet *p; int num_chunks, head; bt_peer_t *node; p = (packet *) malloc(sizeof(packet)); dprintf(STDOUT_FILENO, "Sending packet payload has:\n"); p = packet_factory(WHOHAS); for (num_chunks = 0; num_chunks < BT_MAX_NUM_CHUNKS; num_chunks++) { if (chunk_list[num_chunks] == NULL ) break; head = 4 + num_chunks * BT_CHUNKS_SIZE; strncpy(p->payload + head, chunk_list[num_chunks], BT_CHUNKS_SIZE); dprintf(STDOUT_FILENO, "%s\n", chunk_list[num_chunks]); } p->packet_length = 20 + num_chunks * BT_CHUNKS_SIZE; p->payload[0] = num_chunks; p->payload[1] = '\0'; p->payload[2] = '\0'; p->payload[3] = '\0'; for (node = config->peers; node != NULL ; node = node->next) if (node->id != config->identity) spiffy_sendto(config->sock, p, p->packet_length, 0, (struct sockaddr *) &node->addr, sizeof(node->addr)); }
void flushQueue(int sock, queue *sendQueue) { int i = 0; int retVal = -1; int count = sendQueue->size; int noLoss = 0; Packet *pkt = dequeue(sendQueue); if(pkt == NULL) { return; } peerList_t *list = peerInfo.peerList; while(count > 0) { if(pkt->dest != NULL) { // IHAVE retVal = spiffy_sendto(sock, pkt->payload, getPacketSize(pkt), 0, (struct sockaddr *) (pkt->dest), sizeof(*(pkt->dest))); } else { // WHOHAS for(i = 0; i < peerInfo.numPeer; i++) { if(list[i].isMe == 0) { retVal = spiffy_sendto(sock, pkt->payload, getPacketSize(pkt), 0, (struct sockaddr *) & (list[i].addr), sizeof(list[i].addr)); if(retVal == -1) { enqueue(sendQueue, pkt); noLoss = 1; } } } } if(noLoss == 0) { fprintf(stderr,"spiffy_sendto() returned -1. This is broken!"); } freePacket(pkt); pkt = dequeue(sendQueue); count--; } }
void sendGetSW(int sock, struct sockaddr_in from) { packet *p; // check if the target chunkHash has been transferred by other peers // allow concurrent download while (queue_contains(peers[nodeInMap]->chunkHash) == EXIT_FAILURE) { if (peers[nodeInMap]->next == NULL ) { if (queue_empty() == EXIT_SUCCESS) { dprintf(STDOUT_FILENO, "JOB is done\n"); numDataMisses[nodeInMap] = -1; } return; } linkNode *temp = peers[nodeInMap]; peers[nodeInMap] = peers[nodeInMap]->next; free(temp); } if (peers[nodeInMap]->chunkHash == NULL ) { dprintf(STDOUT_FILENO, "sending chunk equals zero\n"); return; } p = packet_factory(GET); p->packet_length = 20 + BT_CHUNKS_SIZE; p->ack_num = 0; p->payload[0] = 1; p->payload[1] = '\0'; p->payload[2] = '\0'; p->payload[3] = '\0'; strncpy(p->payload + 4, peers[nodeInMap]->chunkHash, BT_CHUNKS_SIZE); spiffy_sendto(sock, p, p->packet_length, 0, (struct sockaddr *) &from, sizeof(from)); jobs[nodeInMap] = getChunkId(peers[nodeInMap]->chunkHash, chunkf); dprintf(STDOUT_FILENO, "Requesting chunk ID: %d from %d\n", jobs[nodeInMap], nodeInMap); nextExpected[nodeInMap] = 1; GETTTL[nodeInMap] = 0; free(p); // chunk is transferring, remove it from work queue so that // other peers won't transfer this again queue_remove(getChunkHash(jobs[nodeInMap], chunkf)); }
void flushUpload(int sock) { int i = 0; Packet *pkt; connUp *pool = uploadPool; for(i = 0; i < peerInfo.numPeer; i++) { int peerID = peerInfo.peerList[i].peerID; Packet *ack = peek(pool[peerID].ackWaitQueue); if(ack != NULL) { struct timeval curTime; gettimeofday(&curTime, NULL); long dt = diffTimeval(&curTime, &(ack->timestamp)); if(dt > DATA_TIMEOUT_SEC) { pool[peerID].timeoutCount++; fprintf(stderr,"Timeout while waiting ACK %d\n", getPacketSeq(ack)); if(pool[peerID].timeoutCount == 3) { fprintf(stderr,"Receiver ID %d timed out 3 times. Closing connection!\n", peerID); numConnUp--; cleanUpConnUp(&(pool[peerID])); continue; } fprintf(stderr,"Data timed out. Resizing window.\n"); shrinkWindow(&(pool[peerID].sw.ctrl)); mergeAtFront(pool[peerID].ackWaitQueue, pool[peerID].dataQueue); } } pkt = peek(pool[peerID].dataQueue); while(pkt != NULL && (getPacketSeq(pkt) <= pool[peerID].sw.lastPacketAvailable)) { peerList_t *p = &(peerInfo.peerList[i]); int retVal = spiffy_sendto(sock, pkt->payload, getPacketSize(pkt), 0, (struct sockaddr *) & (p->addr), sizeof(p->addr)); setPacketTime(pkt); fprintf(stderr,"Sent data %d. last available %d\n", getPacketSeq(pkt), pool[peerID].sw.lastPacketAvailable); if(retVal == -1) { // If spiffy_sendto doesn't f*****g work (AND IT DOESN'T!) fprintf(stderr,"spiffy_sendto() returned -1.\n"); enqueue(pool[peerID].dataQueue, dequeue(pool[peerID].dataQueue)); } else { dequeue(pool[peerID].dataQueue); pool[peerID].sw.lastPacketSent = getPacketSeq(pkt); enqueue(pool[peerID].ackWaitQueue, pkt); pkt = peek(pool[peerID].dataQueue); } } } }
int send_packet(int peer, data_packet_t * packet){ static char buf[BT_MAX_PKT_SIZE]; memcpy(buf + sizeof(header_t), packet->data, packet->header.packet_len); packet->header.packet_len += sizeof(header_t); memcpy(buf, (const char *)&packet->header, sizeof(header_t)); bt_peer_t * pinfo = bt_peer_info(&config, peer); if(pinfo == NULL) return -1; spiffy_sendto(config.sock_fd, buf, packet->header.packet_len, 0, (struct sockaddr *) &pinfo->addr, sizeof(pinfo->addr)); return 0; }
/* description: send a packet using sendto */ void send_packet(int socket, char* data, size_t packet_len, int flag, struct sockaddr *dest_addr, socklen_t addr_len) { /* simulate packet loss */ if (((double)rand() / (double)RAND_MAX) < PACKET_LOSS_RATIO) return; int has_send = 0, ret; while (has_send < packet_len){ ret = spiffy_sendto(socket, data + has_send, packet_len - has_send, 0, dest_addr, addr_len); if (ret < 0) { perror("send packet error"); exit(-1); } else has_send += ret; } }
/* Broadcast WHOHAS request to all node except myself */ void broadcast(data_packet_t *packet, bt_config_t *config){ bt_peer_t *node; short my_id = config->identity; node = config->peers; while(node!=NULL){ // Don't send request to itself if(node->id == my_id){ node = node->next; continue; } // Send request int p = spiffy_sendto(sock, packet, ntohs(packet->header.packet_len), 0, (struct sockaddr *) &node->addr, sizeof(struct sockaddr)); // Iterate to next node if( p < 0 ){ // printf("Can not broadcast\n"); } node = node->next; } //printf("Ending broadcast\n"); return; }
void sendAfterLastAcked(chunkEle* cep){ node* cur; if(cep->lastSent == NULL) return; //last acked is head if nothing acked yet if(cep->lastAcked == NULL) cur = cep->packetList.headp; else cur = cep->lastAcked->prevp; do{ void* packet = cur->data; unsigned int bufSize = ((packetHead *)packet)->packLen; //printf("***Timeout, retrans packet %d\n to peer %d***\n", ((packetHead* )packet)->seqNum, cep->fromThisPeer->id ); spiffy_sendto(sock, packet, bufSize, 0, (struct sockaddr *) &cep->fromThisPeer->cli_addr, sizeof(cep->fromThisPeer->cli_addr)); //sendto(sock, ihavep, bufSize, 0, (struct sockaddr *) &from, fromlen); cur = cur->prevp; }while(cur != cep->lastSent->prevp); return; }
void processData(packet *incomingPacket, bt_config_t *config, int sock, struct sockaddr_in from) { FILE * outfile; packet *p; outfile = fopen(outf, "r+b"); // look for the correct position to insert the packet data long int offset = BT_CHUNK_SIZE * BT_FULL_DATASIZE * jobs[nodeInMap] + BT_FULL_DATASIZE * (incomingPacket->sequence_num - 1); fseek(outfile, offset, SEEK_SET); fwrite(incomingPacket->payload, sizeof(char), BT_FULL_DATASIZE, outfile); fclose(outfile); p = packet_factory(ACK); p->packet_length = 16; p->ack_num = incomingPacket->sequence_num; spiffy_sendto(sock, p, p->packet_length, 0, (struct sockaddr *) &from, sizeof(from)); dprintf(STDOUT_FILENO, "sending ACK num: %d back to %d\n", p->ack_num, nodeInMap); free(p); }
int send_packet(int peer_id, int type, int seq, int ack, char* body, int body_len) { DPRINTF(DEBUG_SOCKETS, "send packet to peer:%d type:%d seq:%d ack:%d body_len:%d\n", peer_id, type, seq, ack, body_len); struct io_peer *peer = NULL; HASH_FIND(hh_id, peers_id, &peer_id, sizeof(int), peer); if (peer == NULL) { fprintf(stderr, "Unknown peer id %d\n", peer_id); return -1; } char data[sizeof(struct packet_header) + body_len]; struct packet_header *header = (struct packet_header *) data; header->magic = PACKET_MAGIC; header->version = PACKET_VERSION; header->header_len = sizeof(struct packet_header); header->total_len = (uint16_t) (header->header_len + body_len); header->type = (unsigned int) type; header->seq = (unsigned int) seq; header->ack = (unsigned int) ack; if (header->type == PACKET_ACK) { --header->ack; } packet_hton(header); if (body && body_len) { memcpy(data + sizeof(struct packet_header), body, (size_t) body_len); } int ret = spiffy_sendto(peer_sockfd, data, sizeof(data), MSG_NOSIGNAL, (const struct sockaddr *) &peer->addr, sizeof(struct sockaddr_in)); if (ret == -1) { DEBUG_PERROR("Cannot send packet\n"); } return ret; }
void peer_run(bt_config_t *config) { struct sockaddr_in myaddr; fd_set readfds; struct user_iobuf *userbuf; struct timeval tv; tv.tv_sec = 3; tv.tv_usec = 0; if ((userbuf = create_userbuf()) == NULL) { perror("peer_run could not allocate userbuf"); exit(-1); } if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1) { perror("peer_run could not create socket"); exit(-1); } bzero(&myaddr, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = htonl(INADDR_ANY); myaddr.sin_port = htons(config->myport); if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) { perror("peer_run could not bind socket"); exit(-1); } spiffy_init(config->identity, (struct sockaddr *)&myaddr, sizeof(myaddr)); while (1) { int nfds; FD_SET(STDIN_FILENO, &readfds); FD_SET(sock, &readfds); nfds = select(sock+1, &readfds, NULL, NULL, &tv); if (nfds > 0) { if (FD_ISSET(sock, &readfds)) { process_inbound_udp(sock); } if (FD_ISSET(STDIN_FILENO, &readfds)) { process_user_input(STDIN_FILENO, userbuf, handle_user_input, "Currently unused"); } } /* loop all the chunks to check if the node for this chunk fails */ data_packet_list_t *potential_whohas = re_generateWhohas(config); if( NULL != potential_whohas){ printf("=======================\n"); printf("re_generateWhohas again\n"); printf("=======================\n"); potential_whohas = reverseList(potential_whohas); data_packet_list_t *p; for( p = potential_whohas; p != NULL; p = p->next){ data_packet_t *who = p->packet; broadcast(who, config); } } /* loop all the data packet send and check if packet timeout*/ packet_tracker_t *head; for( head = p_tracker ; head != NULL ;head = head->next ){ if( -1 == timer_expired(head) ){ /* retransmit*/ data_packet_t *packet = head->packet; /* ignore dummy head */ if( head->seq == -441) continue; printf("DEBUG timer out seq = %d \n", head->seq); packet->header.seq_num = htonl(head->seq); int p = spiffy_sendto(sock, packet, ntohs(packet->header.packet_len), 0, (struct sockaddr *)head->from, sizeof(struct sockaddr)); if( p < 0){ printf("Timeout resend error = %d\n", p); } /* reduce the ssthresh */ process_packet_loss( head->packet->header.ack_num ); /* reset timer */ head->send_time = time(NULL); } } } }
void process_inbound_udp(int sock, bt_config_t *config) { struct sockaddr_in from; socklen_t fromlen; char **chunk_list; char **haschunk_list; packet incomingPacket; bt_peer_t *curPeer; packet *p; int i; rttRecord *tempRtt; fromlen = sizeof(from); spiffy_recvfrom(sock, &incomingPacket, sizeof(incomingPacket), 0, (struct sockaddr *) &from, &fromlen); // check the node where the packet comes from depending on ip and port for (curPeer = config->peers; curPeer != NULL ; curPeer = curPeer->next) if (strcmp(inet_ntoa(curPeer->addr.sin_addr), inet_ntoa(from.sin_addr)) == 0 && ntohs(curPeer->addr.sin_port) == ntohs(from.sin_port)) nodeInMap = curPeer->id; switch (incomingPacket.type) { case WHOHAS: // sender dprintf(STDOUT_FILENO, "WHOHAS received\n"); chunk_list = retrieve_chunk_list(&incomingPacket); haschunk_list = has_chunks(config, &incomingPacket, chunk_list); if (haschunk_list[0] != NULL ) sendback_response(sock, haschunk_list, incomingPacket.payload[0], from); free_chunks(chunk_list, incomingPacket.payload[0]); free_chunks(haschunk_list, incomingPacket.payload[0]); break; case IHAVE: // requester dprintf(STDOUT_FILENO, "IHAVE received\n"); chunk_list = retrieve_chunk_list(&incomingPacket); allocate_peer_chunks(chunk_list, incomingPacket.payload[0]); sendGetSW(sock, from); free_chunks(chunk_list, incomingPacket.payload[0]); break; case GET: // sender dprintf(STDOUT_FILENO, "GET received\n"); chunk_list = retrieve_chunk_list(&incomingPacket); jobs[nodeInMap] = getChunkId(chunk_list[0], config->has_chunk_file); // send a window to requester //congestion control started windowSize[nodeInMap] = 1; congestionState[nodeInMap] = 0; ssthresh[nodeInMap] = 64; lastSent[nodeInMap] = 0; for (i = 0; i < windowSize[nodeInMap]; i++) sendData(from, config); recordWindowSize(config); free_chunks(chunk_list, incomingPacket.payload[0]); break; case DATA: // requester dprintf(STDOUT_FILENO, "DATA received %d from %d\n", incomingPacket.sequence_num, nodeInMap); GETTTL[nodeInMap] = -1; // if sequence_num < expected, ignore as they might be channel-queued packets // if sequence_num > expected, something is lost or in wrong order if (incomingPacket.sequence_num > nextExpected[nodeInMap] && numMismatches < 3) { p = packet_factory(ACK); p->packet_length = 16; p->ack_num = nextExpected[nodeInMap] - 1; spiffy_sendto(sock, p, p->packet_length, 0, (struct sockaddr *) &from, sizeof(from)); numMismatches++; numDataMisses[nodeInMap] = 0; } else if (incomingPacket.sequence_num == nextExpected[nodeInMap]) { numDataMisses[nodeInMap] = 0; numMismatches = 0; processData(&incomingPacket, config, sock, from); nextExpected[nodeInMap] = incomingPacket.sequence_num + 1; if (incomingPacket.sequence_num == BT_CHUNK_SIZE && peers[nodeInMap]->next != NULL ) { dprintf(STDOUT_FILENO, "Got %s\n", peers[nodeInMap]->chunkHash); linkNode *temp = peers[nodeInMap]; //cp1 peers[nodeInMap] = peers[nodeInMap]->next; free(temp); sendGetSW(sock, from); } else if (incomingPacket.sequence_num == BT_CHUNK_SIZE && peers[nodeInMap]->next == NULL ) { dprintf(STDOUT_FILENO, "JOB is done\n"); numDataMisses[nodeInMap] = -1; } } break; case ACK: dprintf(STDOUT_FILENO, "ACK received %d\n", incomingPacket.ack_num); // sender if (lastACKed[nodeInMap] == incomingPacket.ack_num) dup_ack[nodeInMap]++; // similarly, smaller received ack can be channel queued, ignore else if (incomingPacket.ack_num != lastACKed[nodeInMap] + 1) return; // duplicate acked else dup_ack[nodeInMap] = 0; // clear DATA TTL TTL[nodeInMap][incomingPacket.ack_num - 1] = -1; // retransmit if (dup_ack[nodeInMap] == 3) //loss { dprintf(STDOUT_FILENO, "dup retransmitting\n"); congestionControlRetransmit(config); //change windowSize lastSent[nodeInMap] = lastACKed[nodeInMap]; sendData(from, config); dup_ack[nodeInMap] = 0; } else //normal { congestionControlNormal(&incomingPacket, config); lastACKed[nodeInMap] = incomingPacket.ack_num; // ok... task finished if (incomingPacket.ack_num == BT_CHUNK_SIZE) { jobs[nodeInMap] = -1; lastACKed[nodeInMap] = 0; lastSent[nodeInMap] = 0; windowSize[nodeInMap] = 0; congestionState[nodeInMap] = -1; ssthresh[nodeInMap] = 64; resetCCRTT(); dprintf(STDOUT_FILENO, "JOB is done\n"); numDataMisses[nodeInMap] = -1; } else { for (i = lastSent[nodeInMap]; i < lastACKed[nodeInMap] + windowSize[nodeInMap] && i < BT_CHUNK_SIZE; i++) sendData(from, config); if (congestionState[nodeInMap] == CA) //test the RTT timer { if (headRTT != NULL ) { for (tempRtt = headRTT; tempRtt->next != NULL ; tempRtt = tempRtt->next) ; tempRtt->next = (rttRecord *) malloc(sizeof(rttRecord)); tempRtt->next->seq = lastSent[nodeInMap]; tempRtt->next->next = NULL; } else { headRTT = (rttRecord *) malloc(sizeof(rttRecord)); headRTT->seq = lastSent[nodeInMap]; headRTT->next = NULL; } } } } break; case DENIED: dprintf(STDOUT_FILENO, "DENIED received\n"); break; default: perror("Unknown Command: Ignored...\n"); break; } }
void flushDownload(int sock) { int i = 0; int idx; uint8_t *hash; Packet *pkt; connDown *pool = downloadPool; for(i = 0; i < peerInfo.numPeer; i++) { int peerID = peerInfo.peerList[i].peerID; Packet *ack = peek(pool[peerID].ackSendQueue); while(ack != NULL) { peerList_t *p = &(peerInfo.peerList[i]); fprintf(stderr,"Sending ACK %d\n", getPacketAck(ack)); int retVal = spiffy_sendto(sock, ack->payload, getPacketSize(ack), 0, (struct sockaddr *) & (p->addr), sizeof(p->addr)); fprintf(stderr,"Sent ACK %d\n", getPacketAck(ack)); if(retVal == -1) { // spiffy_sendto() does not work!! fprintf(stderr,"spiffy_sendto() returned -1.\n"); enqueue(pool[peerID].ackSendQueue, dequeue(pool[peerID].ackSendQueue)); } else { dequeue(pool[peerID].ackSendQueue); freePacket(ack); ack = dequeue(pool[peerID].ackSendQueue); } } switch(pool[peerID].state) { case 0: // Ready pkt = dequeue(pool[peerID].getQueue); while(pkt != NULL) { hash = getPacketHash(pkt, 0); printHash(hash); idx = searchHash(hash, &getChunk, 0); if(idx == -1) { // Someone else is sending or has sent this chunk freePacket(pkt); pkt = dequeue(pool[peerID].getQueue); } else if(numConnDown < maxConn){ getChunk.list[idx].fetchState = 2; if(downloadPool[peerID].connected == 1) fprintf(stderr,"NOT SUPPOSED TO BE CONNECTEED! \n\n\n\n\n\n"); downloadPool[peerID].connected = 1; numConnDown++; break; } else { // Cannot allow more download connections fprintf(stderr,"->No more download connection allowed!\n"); pool[peerID].state = 2; break; } } if(pool[peerID].state == 2) break; if(pkt != NULL) { fprintf(stderr,"Sending a GET\n"); peerList_t *p = &(peerInfo.peerList[i]); hash = pkt->payload + 16; char buf[50]; bzero(buf, 50); binary2hex(hash, 20, buf); fprintf(stderr,"GET hash:%s\n", buf); pool[peerID].curChunkID = searchHash(hash, &getChunk, -1); int retVal = spiffy_sendto(sock, pkt->payload, getPacketSize(pkt), 0, (struct sockaddr *) & (p->addr), sizeof(p->addr)); if(retVal == -1) { // Spiffy is broken! fprintf(stderr,"spiffy_snetto() returned -1.\n"); newPacketWHOHAS(nonCongestQueue); freePacket(pkt); cleanUpConnDown(&(pool[peerID])); numConnDown--; return; } setPacketTime(pkt); enqueue(pool[peerID].timeoutQueue, pkt); pool[peerID].state = 1; } break; case 1: { // Downloading pkt = peek(pool[peerID].timeoutQueue); struct timeval curTime; gettimeofday(&curTime, NULL); long dt = diffTimeval(&curTime, &(pkt->timestamp)); if(dt > GET_TIMEOUT_SEC) { pool[peerID].timeoutCount++; fprintf(stderr,"GET request timed out %d times!\n", pool[peerID].timeoutCount); setPacketTime(pkt); if(pool[peerID].timeoutCount == 3) { getChunk.list[pool[peerID].curChunkID].fetchState = 0; pool[peerID].state = 0; newPacketWHOHAS(nonCongestQueue); freePacket(pkt); cleanUpConnDown(&(pool[peerID])); numConnDown--; } } break; } case 2: { break; } default: break; } } }
void process_inbound_udp(int sock) { printf("\n"); // DEBUG #define BUFLEN 1500 struct sockaddr_in from; socklen_t fromlen; char buf[BUFLEN]; fromlen = sizeof(from); spiffy_recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &from, &fromlen); /* printf("PROCESS_INBOUND_UDP SKELETON -- replace!\n" "Incoming message from %s:%d\n%s\n\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port), buf); */ /* first generate the incoming packet */ data_packet_t *recv_packet = build_packet_from_buf(buf); //recv_packet->header.ack_num = ntohl(recv_packet->header.ack_num); //recv_packet->header.seq_num = ntohl(recv_packet->header.seq_num); /* next parse this packet and build the response packet*/ bt_peer_t *node; short target_id = -1; node = config.peers; while(node!=NULL){ if( from.sin_family == node->addr.sin_family && from.sin_port == node->addr.sin_port && from.sin_addr.s_addr == node->addr.sin_addr.s_addr) { target_id = node->id; break; } node = node->next; } if( target_id == -1){ printf("Can not locate id %d, %d, %d\n",from.sin_family, from.sin_port, from.sin_addr.s_addr ); return; } data_packet_list_t *response_list = handle_packet(recv_packet, &config, (int)target_id, p_tracker); /* NEW: add parameter socket address from the one who send the packet */ //data_packet_list_t *response_list = handle_packet(packet, &config, sock, p_tracker); /* finally call spiffy_sendto() to send back the packet*/ if( NULL == response_list ){ /* can not generate a response or no data avaiable */ return; } else{ data_packet_list_t *head; response_list = reverseList(response_list); for( head = response_list; head != NULL; head = head->next ){ data_packet_t *packet = head->packet; if( packet->header.packet_type == 3 ){ printf("DEBUG : SEND DATA SEQ = %d\n", packet->header.seq_num); } if( packet->header.packet_type == 4 ){ printf("DEBUG : SEND ACK ACK = %d\n", packet->header.ack_num); } /* check timer if already send and within timeout , then dont send */ packet_tracker_t *head; int find = 0; for( head = p_tracker ; head != NULL ;head = head->next ){ if( head->packet->header.seq_num == packet->header.seq_num && head->packet->header.ack_num == packet->header.ack_num){ if( -1 == timer_expired(head) ){ find = 1; } } } if( find == 0){ if( packet->header.packet_type == 3){ p_tracker = create_timer(p_tracker, packet, (int)target_id, &from); } packet_tracker_t * p = p_tracker; while( p != NULL){ printf("(%d,%d) - ",p->seq, p->sock); p = p->next; } printf("\n"); int r = rand(); if( r % 20 < -5 &&( packet->header.packet_type == 3 || packet->header.packet_type == 4)){ /* use a random number to simulate the packet loss , currently it is 100% deliver */ printf("RANDOM DISCARD THIS PACKET\n"); continue; } else{ packet->header.ack_num = ntohl(packet->header.ack_num); packet->header.seq_num = ntohl(packet->header.seq_num); int ret = spiffy_sendto(sock, packet, ntohs(packet->header.packet_len), 0, (struct sockaddr *) &from, sizeof(struct sockaddr)); if( ret <= 0 ) printf("Inbound_udp send to sock %d ret = %d", sock, ret); } } else if( find == 1){ if( packet->header.packet_type != 3){ int ret = spiffy_sendto(sock, packet, ntohs(packet->header.packet_len), 0, (struct sockaddr *) &from, sizeof(struct sockaddr)); if( ret <= 0 ) printf("Inbound_udp send to sock %d ret = %d", sock, ret); } printf("Not timeout dont send this packet or not find"); } } } }
void process_inbound_udp(int sock) { #define BUFLEN 1500 struct sockaddr_in from; socklen_t fromlen; char buf[BUFLEN]; fromlen = sizeof(from); spiffy_recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &from, &fromlen); //recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &from, &fromlen); packetHead* pHead = (packetHead* )buf; peerEle* peer = resolvePeer(from, peerList); switch(pHead->type){ case WHOHAS:{ printf("Recieve WHOHAS request\n"); void* ihavep = ihaveCons(buf, &haschunkList); if( ihavep!= NULL){ unsigned int bufSize = ((packetHead *)ihavep)->packLen; spiffy_sendto(sock, ihavep, bufSize, 0, (struct sockaddr *) &from, fromlen); //sendto(sock, ihavep, bufSize, 0, (struct sockaddr *) &from, fromlen); time(&start); } break; } case IHAVE:{ printf("Receieve IHAVE request\n"); printf("packet length is %u\n", pHead->packLen); char tmp[sizeofHash]; memcpy(tmp, (buf+20), sizeofHash); printf("chunk hash: %s\n", tmp); peerEle* thisPeer = resolvePeer(from, peerList); time_t finish; time(&finish); if( thisPeer == NULL ){ printf("RESOLVE FAILED\n"); } thisPeer->rtt = difftime(finish, start); AddResponses(thisPeer, buf, &chunkList, sock); printChunkList(chunkList); break; } case GET:{ printf("Receive GET Request\n"); printf("packet length is %u\n", pHead->packLen); //check for free connections printf("maxcon:%d id: %d numout: %d\n",maxCon,mePeer->id,mePeer->numOut); if(mePeer->numOut == maxCon){ chunkEle* dcp = lookupChunkHash((buf+20),&haschunkList); void* deniedp = deniedCons(dcp->chunkId); spiffy_sendto(sock, deniedp, headerSize, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); //sendto(sock, deniedp, headerSize, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); break; } chunkEle* thisWindow = buildNewWindow(&windowSets, &haschunkList, peer, masterDataFilePath, buf); // send first element, no need to clean or fill sendWindow(thisWindow, sock); mePeer->numOut++;//increase num break; } case DATA:{ unsigned int bufSize = ((packetHead *)buf)->packLen; void* newBuf = malloc(bufSize); memcpy(newBuf,buf,bufSize); chunkEle* cep = resolveChunk(peer, chunkList); getRetryTimer = 0; // reject packets from finished chunk if(cep && (cep->chunkId != ((packetHead*)buf)->ackNum)){ printf("Wrong chunk!\n"); break; } orderedAdd(cep,newBuf); printf("Receive data packet %d, with size %d \n", ((packetHead *)buf)->seqNum, ((packetHead *)buf)->packLen - headerSize); findMex(cep); printPacketList(cep->packetList); void* packet = ackCons(cep->nextExpectedSeq - 1); printf("Send Ack %d\n", cep->nextExpectedSeq - 1); spiffy_sendto(sock, packet, headerSize, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); //sendto(sock, packet, headerSize, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); printf("bytes read for hash %s : %d\n",cep->chunkHash, cep->bytesRead); //check if finish receiving the whole chunk if(cep->bytesRead == chunkSize ){ if ( cep->fromThisPeer->inUse == 1){ printf("Sucessfully receive the chunk %s\n", cep->chunkHash); chunkList.finished ++; cep->fromThisPeer->inUse = 0; cep->inProgress = 0; mePeer->numOut--; } printf("FINISHED %d\n", chunkList.finished); if(chunkList.finished == chunkList.length){ printf("Finish receiving the whole file\n"); // merge the chunks and write to the corresponding output file buildOuputFile(outputFile, &chunkList); fclose(outputFile); printf("GOT %s\n",outputFilePath); }else{ // try to send rest of pending get requests // they are deferred to make sure no concurrent downloading from the same peer sendPendingGetRequest(&chunkList, sock); } } break; } case ACK:{ chunkEle* cep = resolveChunk(peer, windowSets); if ( cep->inProgress == 0){ break; } //check which wether SLOWSTART or CONGAVOID if(cep->mode == SLOWSTART){ cep->windowSize++; printf("####in slow start\n"); } else printf("@@@@in cong avoid rtt: %f\n",cep->fromThisPeer->rtt); //check if enough to enter cong avoid if(cep->windowSize == cep->ssthresh) cep->mode = CONGAVOID; //check for no ack in rtt if((cep->mode == CONGAVOID) && (cep->haveACK == 0)){ cep->windowSize++; printf("IIIIincreasing in cong avoid\n"); } //set ack cep->haveACK = 1; printf("Receive Ack %d\n", *(int*)(buf+12)); if( (cep->lastAcked) && ((packetHead* )(cep->lastAcked->data))->seqNum == ((packetHead* )(buf))->ackNum ){ cep->lastAckedCount ++; printf("Incrementing last ack counter for %d to %d\n", ((packetHead* )(buf))->ackNum,cep->lastAckedCount); if( cep->lastAckedCount == 3 ){ //cut ssthresh in half and set window 1 cep->ssthresh = halve(cep->windowSize); cep->windowSize = 1; cep->mode = SLOWSTART; //reset this ones time time(&cep->afterLastAckedTime); //try retrasmit cep->lastAckedCount = 0; node* retry = cep->lastAcked->prevp; printf("Retramsmit packet %d\n", ((packetHead* )retry->data)->seqNum); spiffy_sendto(sock, retry->data, ((packetHead* )retry->data)->packLen, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); break; } }else{ cep->lastAcked = resolveLastPacketAcked( ((packetHead*)buf)->ackNum, cep); cleanList(cep); time(&cep->afterLastAckedTime); } //check if finish sending the whole chunk if( cep->bytesRead == chunkSize ){ printf("Successfully send the chunk %s\n", cep->chunkHash); if(cep->lastAcked == cep->lastSent){ // some clear below printf("All sent packets have been acked\n"); cep->inProgress = 0; mePeer->numOut--; }else{ printf("lastAcked:%d, lastSent:%d\n",((packetHead*)cep->lastAcked->data)->seqNum, ((packetHead*)cep->lastSent->data)->seqNum ); } }else{ cleanList(cep); fillWindow(cep); sendWindow(cep, sock); } printPacketList(cep->packetList); printf("window: %d, ssthresh: %d, mode: %d\n",cep->windowSize, cep->ssthresh, cep->mode); break; } case DENIED:{ printf("Received a denied ack!\n"); chunkEle* cep = resolveChunk(peer, chunkList); //fclose(outputFile); time(&getRetryTimer); cep->fromThisPeer->inUse = 0; break; } } printf("PROCESS_INBOUND_UDP SKELETON -- replace!\n" "Incoming message from %s:%d\n%s\n\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port), buf); }
void process_get(char *chunkfile, char *outputfile) { printf("PROCESS GET SKELETON CODE CALLED. Fill me in! (%s, %s)\n", chunkfile, outputfile); char *sendBuf = (char*) malloc(BUFLEN); unsigned short packet_length = ntohs(*(unsigned short*)(sendBuf+6)); FILE *f = fopen(chunkfile, "r"); char line[255]; char chunk_count = 0; unsigned int id; uint8_t hash[SHA1_HASH_SIZE*2+1]; uint8_t binary_hash[SHA1_HASH_SIZE]; struct bt_peer_s* peer; struct sockaddr* dst_addr; // printf("len:%d, %s\n", packet_length, sendBuf); while (fgets(line, 255, f) != NULL) { if (line[0] == '#'){ continue; } sscanf(line, "%d %s", &id, hash); hex2binary((char*)hash, SHA1_HASH_SIZE*2, binary_hash); memcpy(sendBuf + 20 + 20 * chunk_count, (char*)binary_hash, sizeof(binary_hash)); chunk_count++; if(chunk_count >= 74 ) { //reached the maximum size of a packet printf("WHOHAS packet has 74 chunks\n"); fill_header(sendBuf, WHOHAS, 1500, 0, 0); *(sendBuf + 16) = chunk_count; peer = config.peers; while(peer!=NULL) { if(peer->id==config.identity){ peer = peer->next; } else{ dst_addr = (struct sockaddr*)&peer->addr; spiffy_sendto(sock, sendBuf, 1500, 0, dst_addr, sizeof(*dst_addr)); peer = peer->next; } } memset(sendBuf, 0, BUFLEN); chunk_count = 0; } } fclose(f); *(sendBuf + 16) = chunk_count; // printf("chunk_count:%d, %s\n", sendBuf[16], sendBuf); peer = config.peers; while(peer!=NULL) { if(peer->id==config.identity){ peer = peer->next; } else{ dst_addr = (struct sockaddr*)&peer->addr; spiffy_sendto(sock, sendBuf, packet_length, 0, dst_addr, sizeof(*dst_addr)); peer = peer->next; } } free(sendBuf); }