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;
}
示例#2
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;
}
示例#3
0
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;
}
示例#4
0
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;

  }
}
示例#5
0
/* 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;
}
示例#6
0
/* 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;
}