Example #1
0
/* @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);
}
Example #2
0
//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);
    }
}
Example #3
0
int get_seqno(uint8_t* packet)
{
  uint8_t seqno[4] = {0};
  memmove(seqno, packet + 8, 4);
  return binary2int(seqno, 4);
}
Example #4
0
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);
}
Example #5
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;

  }
}