/* @brief Parses a given, complete packet. * @param packet: The actual packet to be parsed. * @param myPack: A struct that will contain information about the packet. */ void parse_packet(uint8_t *packet, packet_info* myPack){ byte_buf *tempRequest = create_bytebuf(PACKET_LENGTH); mmemclear(tempRequest); memcpy(tempRequest->buf, packet, PACKET_LENGTH); mmemmove(myPack->magicNumber, tempRequest, 2); mmemmove(myPack->versionNumber, tempRequest, 1); /* if(magicNumber != 15441 && versionNumber != 1){ //Drop the packet } */ mmemmove(myPack->packetType, tempRequest, 1); mmemmove(myPack->headerLength, tempRequest, 2); mmemmove(myPack->totalPacketLength, tempRequest, 2); mmemmove(myPack->sequenceNumber, tempRequest, 4); mmemmove(myPack->ackNumber, tempRequest, 4); int packetType = binary2int(myPack->packetType, 1); if(packetType == 0 || packetType == 1){ mmemmove(myPack->numberHashes, tempRequest, 1); mmemmove(myPack->padding, tempRequest, 3); } int headerLength = binary2int(myPack->headerLength, 2); int totalPacketLength = binary2int(myPack->totalPacketLength, 2); mmemmove(myPack->body, tempRequest, totalPacketLength - headerLength); delete_bytebuf(tempRequest); }
//Convierte a bin, un vector de binarios representando muchas variables, en un vector de enteros. // Cada variable tiene asignado tantos bits como dice paso void utils::vectorBinary2Int(std::vector<bool> &bin, std::vector<int> &res, unsigned int paso) { //Calculamos la cantidad de variables que tiene bin unsigned int cantidad_variables = bin.size()/paso; //Recorremos por cada variable for (unsigned int i = 0 ; i < cantidad_variables; i++) { //vector copia std::vector<bool> convertir; //Le asignamos el rango que estamos interesados convertir.assign(bin.begin()+paso*i, bin.begin()+paso*(i+1)); //lo convertimos a entero int valor = binary2int(convertir,false); //Lo agregamos al vector res.push_back(valor); } }
int get_seqno(uint8_t* packet) { uint8_t seqno[4] = {0}; memmove(seqno, packet + 8, 4); return binary2int(seqno, 4); }
void print_packet(uint8_t* packet, int i) { packet_info myPack = {0}; byte_buf *tempRequest = create_bytebuf(PACKET_LENGTH); mmemclear(tempRequest); memcpy(tempRequest->buf, packet, PACKET_LENGTH); mmemmove(myPack.magicNumber, tempRequest, 2); mmemmove(myPack.versionNumber, tempRequest, 1); mmemmove(myPack.packetType, tempRequest, 1); mmemmove(myPack.headerLength, tempRequest, 2); mmemmove(myPack.totalPacketLength, tempRequest, 2); mmemmove(myPack.sequenceNumber, tempRequest, 4); mmemmove(myPack.ackNumber, tempRequest, 4); int type = binary2int(myPack.packetType, 1); int hlen = binary2int(myPack.headerLength, 2); int plen = binary2int(myPack.totalPacketLength, 2); if(type == 0 || type == 1){ mmemmove(myPack.numberHashes, tempRequest, 1); mmemmove(myPack.padding, tempRequest, 3); } mmemmove(myPack.body, tempRequest, plen - hlen); int numh = binary2int(myPack.numberHashes, 1); char typestr[10]; switch (type) { case 0: sprintf(typestr, "WHOHAS"); break; case 1: sprintf(typestr, "IHAVE"); break; case 2: sprintf(typestr, "GET"); break; case 3: sprintf(typestr, "DATA"); break; case 4: sprintf(typestr, "ACK"); break; case 5: sprintf(typestr, "DENIED"); break; default: sprintf(typestr, "DEFAULT"); break; } printf("\n###############################\n"); if(i == SEND) printf("Sending packet with contents:\n"); if(i == RECV) printf("Receiving packet with contents:\n"); printf("Magic Number: %d\n", binary2int(myPack.magicNumber, 2)); printf("Version Number: %d\n", binary2int(myPack.versionNumber, 1)); printf("Packet Type : %s\n", typestr); printf("Header Len : %d\n", hlen); printf("Packet Len : %d\n", plen); printf("Seq No : %d\n", binary2int(myPack.sequenceNumber , 4)); printf("Ack No : %d\n", binary2int(myPack.ackNumber , 4)); printf("Hash No : %d\n", numh); char hash[45] = {0}; for(int i = 0; i < numh; i++) { binary2hex(myPack.body + 20 * i, 20, hash); printf("Hash %d: %s \n", i, hash); bzero(hash, 45); } if(type == 2) // GET { binary2hex(myPack.body, 20, hash); printf("Hash %d: %s \n", i, hash); bzero(hash, 45); } printf("###############################\n\n"); delete_bytebuf(tempRequest); }
void parse_data(packet_info* packetinfo, peer* p) { ll* tmplist = create_ll(); chunk_table* find = NULL; uint8_t n = packetinfo->numberHashes[0]; uint8_t tempChunk[CHUNK]; bzero(tempChunk, CHUNK); unsigned int seqNumber; unsigned int ackNumber; int headerLength; int totalPacketLength; int delno; switch (packetinfo->packetType[0]) { case 0: /* // IF WHOHAS extract chunk; check if chunk exists in has_chunks create linked list of request chunks that we have call gen_WHOIGET with IHAVE and pass in the linked list should return a linked list of packets to send use sendto to send the packets */ for (uint8_t i = 0; i < n; i++){ HASH_FIND(hh, has_chunks, packetinfo->body + CHUNK * i, CHUNK, find); if(find) add_node(tmplist, packetinfo->body + CHUNK * i, CHUNK, 0); } p->tosend = append(gen_WHOIGET(tmplist, 1), p->tosend); remove_ll(tmplist); break; case 1: /* // IF IHAVE extract chunk; add chunk to the hash table 'p->has_chunks'; Lookup chunk in 'get_chunks'; if that chunk has not yet been requested, change the whohas field to identify this peer. I'll send a GET to him later. I'll put in a timer to retransmit the GET after 5 seconds. } */ for (uint8_t i = 0; i < n; i++) { find = calloc(1, sizeof(chunk_table)); memmove(find->chunk, packetinfo->body + CHUNK * i, CHUNK); find->id = 0; HASH_ADD(hh, p->has_chunks, chunk, CHUNK, find); } break; case 2: /* IF GET extract the chunk; check if we have it; If we don't, deny him. eheheh. if we do, send it. */ /* Free previous chunk state */ del_all_nodes(p->tosend); p->LPAcked = 0; p->LPSent = 0; p->LPAvail = p->LPAcked + p->window; n = 1; for(uint8_t i = 0; i < n; i++) { HASH_FIND(hh, has_chunks, packetinfo->body + CHUNK * i, CHUNK, find); if(find) { memcpy(tempChunk, packetinfo->body + CHUNK * i, CHUNK); p->tosend = append(p->tosend, gen_DATA(tempChunk)); bzero(tempChunk, CHUNK); } else { //Generate a denial message. } } break; /* // IF DATA Gonna have to do some flow control logic here; extract the data and store it in a 512KB buffer. How are we gonna know we recevied the entire chunk of data? ANS: use a goddamn bytebuf. when pos = 512KB, we hit gold. Perform a checksum afterwards, if badhash, send GET again, else write the data into a file using fseek and all. */ case 3: //If seq Number != Last Acked + 1, DUPACK //Else, copy data into bytebuf //Check, complete? If yes, gotcha = True // Perform checksum. If passes, good, else, send GET again //Send ACK seqNumber, update Last acked. /* Ignore DATA packets from peers whom we haven't requested data from */ if(!p->busy) break; seqNumber = (unsigned int) binary2int(packetinfo->sequenceNumber, 4); headerLength = binary2int(packetinfo->headerLength, 2); totalPacketLength = binary2int(packetinfo->totalPacketLength, 2); /* Check if we received a packet we got before */ if (seqNumber <= p->LPRecv && p->LPRecv > 0) { p->tosend = append(gen_ACK(p->LPRecv, 1), p->tosend); break; } /* Check if we received an out of order packet */ if(seqNumber > p->LPRecv + 1 && p->LPRecv > 0) { p->tosend = append(gen_ACK(p->LPRecv, 3), p->tosend); break; } /* We received the next expected packet */ else { HASH_FIND(hh, get_chunks, p->chunk, HASH_SIZE, find); // if(find == NULL) // Badstuff mmemcat(find->data, packetinfo->body, totalPacketLength - headerLength); p->LPRecv = seqNumber; if(find->data->pos == CHUNK_SIZE) { //Complete Chunk! find->gotcha = 1; find->requested = 1; p->busy = 0; p->LPRecv = 0; // Reset state. /* Copying is to ensure consistency within the Hash Table lib */ chunk_table* copy = duptable(find); HASH_ADD(hh, has_chunks, chunk, CHUNK, copy); // Check sum here, resend if necessary // Save to file; save2file(find); finished++; } //Send ACK p->tosend = append(gen_ACK(seqNumber, 1), p->tosend); if(find->data->pos == CHUNK_SIZE) sliding_send(p, sock); // Send 512th ACK immediately. } break; case 4: //First, check if this is a DUPACK (use p->LPAcked) //If yes, increment dupack counter. // If counter == 3, send approp. packet. Set counter to 0. //If not, delete packet from node and send next one. //Increment p->LPAcked, p->LPAvail //Sliding window stuff. ackNumber = (unsigned int) binary2int(packetinfo->ackNumber, 4); if(p->LPAcked == ackNumber) { p->dupCounter++; if(p->dupCounter >= 3) { /* Begin fast retransmit */ p->dupCounter = 0; /* Lengthen time since start */ p->start_time.tv_sec = 0; p->start_time.tv_nsec = 0; } } else { p->dupCounter = 0; delno = ackNumber - p->LPAcked; for (int i = 0; i < delno; i++) { delete_node(p->tosend); } if(p->window < p->ssthresh) { //slow start p->window++; } else { //Congestion avoidance p->rttcnt++; if(p->rttcnt >= p->window){ p->window++; p->rttcnt = 0; } } gen_graph(p); if(!p->ttl) computeRTT(p); //Karn Partridge p->LPAcked = ackNumber; p->LPAvail = p->LPAcked + p->window; } if(p->LPAcked == 512) // We send 512 packets of a 1000 bytes each. { // Reset the sliding window state for this peer. p->LPAcked = 0; p->LPSent = 0; p->LPAvail = p->LPAcked + p->window; } break; case 5: // Leave this for now... break; } }