int main() { int *input_array1, *input_array2, *output_array,i = 0, j = 0, d = 0; for (i = 0; i < 10; i++) { head1 = NULL, head2 = NULL; input_array1 = allocate(testcase[i].input1, testcase[i].length1); input_array2 = allocate(testcase[i].input2, testcase[i].length2); if (testcase[i].length1>testcase[i].length2) output_array = allocate(testcase[i].output, testcase[i].length1); else output_array = allocate(testcase[i].output, testcase[i].length2); for (j = 0; j < testcase[i].length1; j++) { create_ll(&head1, input_array1[j]); } for (j = 0; j<testcase[i].length2; j++) { create_ll(&head2, input_array2[j]); } head1 = add_2LL(head1, head2); if (testcase[i].length1>testcase[i].length2) d = compare(output_array, testcase[i].length1, head1); else d = compare(output_array, testcase[i].length2, head1); if (d == 1) printf("\nPASSED"); else printf("\nFAILED"); } return 0; }
int main(void) { int returndata = EXIT_FAILURE; linkedlist *sample_data = NULL; sample_data = create_ll(); if(sample_data != NULL) { linkedlistnode node; display_ll_element(sample_data); /* (null) */ node.element = 1; add_ll_element_forward(sample_data, node); display_ll_element(sample_data); /* 1 */ node.element = 2; add_ll_element_forward(sample_data, node); display_ll_element(sample_data); /* 2 1 */ node.element = 4; add_ll_element_backward(sample_data, node); display_ll_element(sample_data); /* 2 1 4 */ node.element = 5; add_ll_element_backward(sample_data, node); display_ll_element(sample_data); /* 2 1 4 5 */ node.element = 6; add_ll_element(sample_data, 3, node); display_ll_element(sample_data); /* 2 1 4 6 5 */ node.element = 7; add_ll_element(sample_data, 2, node); display_ll_element(sample_data); /* 2 1 7 4 6 5 */ remove_ll_element(sample_data, 4); display_ll_element(sample_data); /* 2 1 7 4 5 */ remove_ll_element(sample_data, 0); display_ll_element(sample_data); /* 1 7 4 5 */ delete_ll(sample_data); returndata = EXIT_SUCCESS; } return returndata; }
ll* gen_ACK(int ackNum, int copies){ byte_buf *tempRequest = create_bytebuf(PACKET_LENGTH); mmemclear(tempRequest); ll* myLL = create_ll(); uint8_t magicNumber[2]; uint8_t versionNumber[1] = {VERSION_NUMBER}; uint8_t packetType[1] = {ACK_TYPE}; uint8_t headerLength[2]; uint8_t totalPacketLength[2]; uint8_t sequenceNumber[4] = {0,0,0,0}; uint8_t ackNumber[4]; bzero(magicNumber, 2); bzero(headerLength, 2); bzero(totalPacketLength, 2); bzero(ackNumber, 4); dec2hex2binary(MAGIC_NUMBER, 4, magicNumber); dec2hex2binary(HEADER, 4, headerLength); dec2hex2binary(HEADER, 4, totalPacketLength); dec2hex2binary(ackNum, 8, ackNumber); mmemcat(tempRequest, magicNumber, 2); mmemcat(tempRequest, versionNumber, 1); mmemcat(tempRequest, packetType, 1); mmemcat(tempRequest, headerLength, 2); mmemcat(tempRequest, totalPacketLength, 2); mmemcat(tempRequest, sequenceNumber, 4); mmemcat(tempRequest, ackNumber, 4); while(copies){ add_node(myLL, tempRequest->buf, HEADER + DATA_LENGTH, 0); copies--; } return myLL; }
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; } }
/* Generates a WHOHAS/IHAVE/GET request (more than one if necessary). Each * packet has its own header. Which request is generated depends on the * packetCode argument. * Arguments: * 1. list: Pre-processed linked list. The head contains the number of * chunks and a first node, which corresponds to the first chunk. * 2. packetCode: 0 for WHOHAS, 1 for IHAVE, 2 for GET (the real GET). */ ll* gen_WHOIGET(ll *list, int packetCode){ int numHashes = list->count; int numPacket = (numHashes / MAX_NUM_HASH) + 1; int packCounter = 0; int tempNumHashes; ll *myLL = create_ll(); node *temp = list->first; byte_buf *tempRequest = create_bytebuf(PACKET_LENGTH); mmemclear(tempRequest); /* if(packetCode == 2){ ASSERT(numHashes == 1); } */ uint8_t magicNumber[2]; uint8_t versionNumber[1] = {VERSION_NUMBER}; uint8_t packetType[1] = {packetCode}; uint8_t headerLength[2]; uint8_t totalPacketLength[2]; uint8_t sequenceNumber[4] = {0,0,0,0}; uint8_t ackNumber[4] = {0,0,0,0}; uint8_t padding[3] = {0,0,0}; uint8_t numberHashes[1]; while(packCounter < numPacket){ if(numPacket == packCounter + 1){ tempNumHashes = numHashes; } else { tempNumHashes = MAX_NUM_HASH; } bzero(magicNumber, 2); bzero(headerLength, 2); bzero(totalPacketLength, 2); bzero(numberHashes, 1); mmemclear(tempRequest); dec2hex2binary(MAGIC_NUMBER, 4, magicNumber); dec2hex2binary(HEADER, 4, headerLength); if(packetCode != 2){ dec2hex2binary(HEADER + CHUNK * tempNumHashes + 4, 4, totalPacketLength); } else { dec2hex2binary(HEADER + CHUNK * tempNumHashes, 4, totalPacketLength); } dec2hex2binary(tempNumHashes, 2, numberHashes); mmemcat(tempRequest, magicNumber, 2); mmemcat(tempRequest, versionNumber, 1); mmemcat(tempRequest, packetType, 1); mmemcat(tempRequest, headerLength, 2); mmemcat(tempRequest, totalPacketLength, 2); mmemcat(tempRequest, sequenceNumber, 4); mmemcat(tempRequest, ackNumber, 4); if(packetCode != 2){ mmemcat(tempRequest, numberHashes, 1); mmemcat(tempRequest, padding, 3); } while(temp != NULL){ mmemcat(tempRequest, temp->data, CHUNK); // No temp = temp->next; } if(packetCode != 2) add_node(myLL, tempRequest->buf, HEADER + CHUNK * tempNumHashes + 4, 0); else add_node(myLL, tempRequest->buf, HEADER + CHUNK * tempNumHashes, 2); packCounter++; numHashes -= MAX_NUM_HASH; } return myLL; }
/* Generates a complete set of DATA packets for an entire chunk. * Arguments: * 1. Requests: Array of uint8_ts. Must have space for at least 512 spots. * 2. chunkHash: The required chunk to send. */ ll* gen_DATA(uint8_t *chunkHash) { byte_buf *tempRequest = create_bytebuf(PACKET_LENGTH); mmemclear(tempRequest); int id; uint8_t buf[CHUNK_SIZE]; uint8_t tempBuf[DATA_LENGTH]; bzero(buf, CHUNK_SIZE); chunk_table *lookup; ll *myLL = create_ll(); HASH_FIND(hh, has_chunks, chunkHash, 20, lookup); if(lookup == NULL){ //Error! } else { id = (int)lookup->id; } FILE *fp = fopen(master_data_file, "r"); if(!(fseek(fp, id * CHUNK_SIZE, SEEK_SET))){ //Error! } if(fread((char *)buf, CHUNK_SIZE, 1, fp) == 0){ //BROKEN? //Short count! } int numPacket = 512; int packCounter = 0; int bufPos = 0; int seqNumber = 1; uint8_t magicNumber[2]; uint8_t versionNumber[1] = {VERSION_NUMBER}; uint8_t packetType[1] = {DATA_TYPE}; uint8_t headerLength[2]; uint8_t totalPacketLength[2]; uint8_t sequenceNumber[4]; uint8_t ackNumber[4] = {0,0,0,0}; while(packCounter < numPacket){ bzero(magicNumber, 2); bzero(headerLength, 2); bzero(totalPacketLength, 2); bzero(sequenceNumber, 4); bzero(tempBuf, DATA_LENGTH); memcpy(tempBuf, buf + bufPos, DATA_LENGTH); dec2hex2binary(MAGIC_NUMBER, 4, magicNumber); dec2hex2binary(HEADER, 4, headerLength); dec2hex2binary(HEADER + DATA_LENGTH, 4, totalPacketLength); dec2hex2binary(seqNumber, 8, sequenceNumber); mmemclear(tempRequest); mmemcat(tempRequest, magicNumber, 2); mmemcat(tempRequest, versionNumber, 1); mmemcat(tempRequest, packetType, 1); mmemcat(tempRequest, headerLength, 2); mmemcat(tempRequest, totalPacketLength, 2); mmemcat(tempRequest, sequenceNumber, 4); mmemcat(tempRequest, ackNumber, 4); mmemcat(tempRequest, tempBuf, DATA_LENGTH); add_node(myLL, tempRequest->buf, HEADER + DATA_LENGTH, 1); packCounter++; seqNumber++; bufPos += DATA_LENGTH; } return myLL; }