text: #ifndef _UDP_PROTOCOL_C
  #define _UDP_PROTOCOL_C
  #endif
  
  #include "udp_protocol.h"
  
  #if defined(__WIN32__) || defined(WIN32)
  char *strsep(char **stringp, const char *delim) 
  {
    char *start = *stringp;
    char *p = NULL;
    p = (start != NULL) ? strpbrk(start, delim) : NULL;
    if (p == NULL)  
      {
        *stringp = NULL;
      } 
    else 
      {
        *p = '\0';
        *stringp = p + 1;
      }
    return start;
  }
  
  const char *inet_ntop(int af, const void *src, char *dst, int len){
    struct sockaddr_in srcaddr;
    memset(&srcaddr, 0, sizeof(struct sockaddr_in));
    memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
    srcaddr.sin_family = af;
    if (WSAAddressToString((struct sockaddr*) &srcaddr, sizeof(struct sockaddr_in), 0, dst, (LPDWORD) &len) != 0) {
      DWORD rv = WSAGetLastError();
      printf("WSAAddressToString() : %d\n",rv);
      return NULL;
    }
    return dst;
  }
  #endif
  
  int connect_session(connection_data *connection, char *server_ip, uint16_t server_port, uint16_t client_port) 
  {
    handshake_packet syn_packet, *received_packet = NULL;
    struct sockaddr_in server, client;
    socklen_t client_len;
    int i = 0, return_value = 0;
    char *ptr = NULL;
    char *client_ip = malloc(sizeof(char) * 16);
    uint32_t sock_fd = 0;
  
    srand(time(NULL));
    net_init();
  
  #ifdef _DEBUG_
    printf("Before creating socket.\n");
  #endif
  
    if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
      {
        perror("socket() failed");
        return -1;
      }
  #ifdef _DEBUG_
    printf("After creating socket.\n");
    printf("Creating sockaddr_in to find out client ip\n");
  #endif
  
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(server_ip);
    server.sin_port = htons(server_port);
  #ifdef _DEBUG_
    printf("Using a connected UDP socket to find out client ip\n");
  #endif
  
    if (connect(sock_fd, (struct sockaddr *)&server, sizeof(server)) < 0) 
      {
        perror("connect() failed (in trying to find out client ip)");
        return -1;
      }
  
    client_len = sizeof(client);
  #ifdef _DEBUG_
    printf("Using getsockname() to get local IP the socket bound to\n");
  #endif
  
    if (getsockname(sock_fd, (struct sockaddr *)&client, &client_len) < 0) 
      {
        perror("getsockname() failed when trying to find out client ip");
        return -1;
      }
  #ifdef _DEBUG_
    printf("Fetching the IP address from client sockaddr struct\n");
  #endif
  
    if (inet_ntop(AF_INET, &client.sin_addr, client_ip, 16) < 0)
      {
        perror("inet_ntop() failed to get client ip");
        return -1;
      }
  
    CLOSE(sock_fd);
  #ifdef _DEBUG_
    printf("Client ip in buffer: %s\n", client_ip);
    printf("Before creating socket.\n");
  #endif
  
    if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
      {
        perror("socket() failed");
        return -1;
      }
  #ifdef _DEBUG_
    printf("After creating socket.\n");
    printf("Preparing SYN packet.\n");
  #endif
  
    syn_packet.proto_id = "herp";
    syn_packet.packet_type = HANDSHAKE;
    syn_packet.client_ip = client_ip;
    syn_packet.client_port = client_port;
    syn_packet.client_id = rand();
    syn_packet.flags = SYN;
    syn_packet.trailer = "derp";
  
  #ifdef _DEBUG_
    printf("Converting to string.\n");
  #endif
    ptr = packet_to_string(&syn_packet, HANDSHAKE);
  #ifdef _DEBUG_
    printf("Setting up listening socket.\n");
  #endif
  
    connection = create_connection_data(client_ip, client_port, syn_packet.client_id, sock_fd, connection);
  
  #ifdef _DEBUG_
    printf("Binding socket.\n");
  #endif
  
    if (bind(connection->sock_fd, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) 
      {
        perror("Bind() failed");
        CLOSE(connection->sock_fd);
        return -1;
      }
  #ifdef _DEBUG_
    printf("Creating connection_data.\n");
  #endif
  
    connection = create_connection_data(server_ip, server_port, syn_packet.client_id, connection->sock_fd, connection);
    connection->client_ip = client_ip;
    connection->client_port = client_port;
  
    for(i = 0; i < 3; i++) 
      {
  #ifdef _DEBUG_
        printf("Try %d\n", i+1);
        printf("Struct data: %d %d %d socket: %d client_id: %d\n", connection->destination->sin_family, connection->destination->sin_port, connection->destination->sin_addr.s_addr, connection->sock_fd, connection->client_id);
  #endif
  
        if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) 
  	{
  	  perror("sendto() failed");
  	  CLOSE(connection->sock_fd);
  	  return -1;
  	}
  
  #ifdef _DEBUG_
        printf("Entering listening mode.\n");
  #endif
  
        ptr = listen_socket(connection, 5, 0);
  
  #ifdef _DEBUG_
        if (ptr != NULL)
  	printf("Received string: %s\n", ptr);
  #endif
        if (ptr != NULL) {
  
  	if (atoi(&ptr[5]) == HANDSHAKE) 
  	  {
  #ifdef _DEBUG_
  	    printf("It is a handshake packet outside recv_data!\n");
  #endif
  	    received_packet = (handshake_packet *)string_to_packet(ptr, HANDSHAKE);
  #ifdef _DEBUG_
  	    printf("ptr size %d\n", strlen(ptr));
  #endif
  	    if (!is_packet(received_packet, HANDSHAKE) && !strncmp(connection->client_ip, received_packet->client_ip, strlen(connection->client_ip)) && (received_packet->flags == ACK)) 
  	      {
  #ifdef _DEBUG_
  		printf("ACK packet received: %p.\n", connection);
  #endif
  		connection->client_id = received_packet->client_id;
  		free(client_ip);
  		return 0;
  	      }
  	  } 
  	else 
  	  {
  #ifdef _DEBUG_
  	    printf("Is not a packet :(\n");
  #endif
  	    break;
  	  }
        }
      } 
  
    fprintf(stderr, "No server responded with a ACK, stopping connection attempts...\n");
    free(client_ip);
    return 1;
  }
  int accept_session (connection_data *connection, uint16_t port, int client_id) 
  {
    handshake_packet ack_packet, *received_packet = NULL;
    static int first_time = 1;
    static uint16_t sock_fd;
    char *ptr = NULL;
  
    if (first_time) 
      {
  #ifdef _DEBUG_
        printf("Inside a first_time only\n");
  #endif
        net_init();
  #ifdef _DEBUG_
        printf("Before creating socket.\n");
  #endif
  
        if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 
  	{
  	  perror("socket() failed");
  	  return -1;
  	}
  #ifdef _DEBUG_
        printf("After creating socket.\n");
  #endif
      }
  
    connection = create_connection_data("0.0.0.0", port, 0, sock_fd, connection);
  
    if (first_time) 
      {
  #ifdef _DEBUG_
        printf("Setting up listening socket.\n");
        printf("Binding socket.\n");
  #endif
        if (bind(sock_fd, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) 
  	{
  	  perror("Bind() failed");
  	  CLOSE(sock_fd);
  	  return -1;
  	}
        first_time = 0;
      }
  
    while(1) 
      {
  #ifdef _DEBUG_
        printf("Listening for SYN packet.\n");
        printf("connection->sock_fd: %d\n", connection->sock_fd);
  #endif
        ptr = listen_socket(connection, 60, 0);
  #ifdef _DEBUG_
        printf("Received string: %s\n", ptr);
  #endif
        if (ptr != NULL) {
  
          if (atoi(&ptr[5]) == HANDSHAKE) 
            {
  #ifdef _DEBUG_
              printf("Converting from string to packet.\n");
  #endif
              received_packet = (handshake_packet *)string_to_packet(ptr, HANDSHAKE);
  #ifdef _DEBUG_
              printf("ptr size %d\n", strlen(ptr));
              printf("It is a handshake packet outside recv_data!\n");
              printf("Content: %s %u %s %u %u %s\n", received_packet->proto_id, received_packet->packet_type, received_packet->client_ip, received_packet->client_port, received_packet->flags, received_packet->trailer);
  #endif
  
              if (!is_packet(received_packet, HANDSHAKE) && received_packet->flags == SYN) 
                {
  #ifdef _DEBUG_
                  printf("SYN Packet received.\n");
  #endif
                  break;
                }
              else if (!is_packet(received_packet, HANDSHAKE) && received_packet->flags == RST) 
                {
                  connection_termination(connection, SERVER);
                  return 1;
                }
            }
        }
      }
  #ifdef _DEBUG_
    printf("Preparing ACK packet.\n");
  #endif
  
    ack_packet.proto_id = "herp";
    ack_packet.packet_type = HANDSHAKE;
    ack_packet.client_ip = received_packet->client_ip;
    ack_packet.client_port = received_packet->client_port;
    ack_packet.client_id = client_id;
    ack_packet.flags = ACK;
    ack_packet.trailer = "derp";
  #ifdef _DEBUG_
    printf("Creating connection_data struct.\n");
  #endif
  
    connection = create_connection_data(received_packet->client_ip, received_packet->client_port, client_id, connection->sock_fd, connection);
  #ifdef _DEBUG_
    printf("Converting packet_to_string.\n");
  #endif
  
    ptr = packet_to_string(&ack_packet, HANDSHAKE);
  
  #ifdef _DEBUG_
    printf("Sending ACK packet.\n");
  #endif
  
    if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) 
      {
        perror("sendto() failed");
        CLOSE(connection->sock_fd);
        return -1;
      }
  #ifdef _DEBUG_
    printf("pointer address %p\n", connection);
  #endif
    free(received_packet);
    free(ptr);
    return 0;
  }
  
  int end_session(connection_data *connection) 
  {
    handshake_packet rst_packet, *received_packet = NULL;
    char *ptr = NULL;
    int i;
  
    rst_packet.proto_id = "herp";
    rst_packet.packet_type = HANDSHAKE;
    rst_packet.client_ip = connection->client_ip;
    rst_packet.client_port = connection->client_port;
    rst_packet.client_id = connection->client_id;
    rst_packet.flags = RST;
    rst_packet.trailer = "derp";
  
    ptr = packet_to_string(&rst_packet, HANDSHAKE);
  
    if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) 
      {
        perror("sendto() failed");
        CLOSE(connection->sock_fd);
        return -1;
      }
  
    for (i = 0; i < 2; i++)
      {
  #ifdef _DEBUG_
        printf("Listening for ACK packet from termination.\n");
  #endif
  
        ptr = listen_socket(connection, 3, 0);
  
  #ifdef _DEBUG_
        if (ptr != NULL) {
  	printf("ptr size %d\n", strlen(ptr));
  	printf("packet type: %d ptr: %s\n", atoi(&ptr[5]), ptr);
        }
  #endif
        if (ptr != NULL) {
  
          if (atoi(&ptr[5]) == HANDSHAKE) 
            {
  #ifdef _DEBUG_
              printf("Converting from string to packet.\n");
  #endif
              received_packet = (handshake_packet *)string_to_packet (ptr, HANDSHAKE);
  #ifdef _DEBUG_
              printf("It is a handshake packet outside recv_data()!\n");
  #endif
  
              if (!is_packet(received_packet, HANDSHAKE) && (received_packet->flags == ACK)) 
                {
  #ifdef _DEBUG_
                  printf("ACK Packet received.\n");
  #endif
                  connection_termination(connection, CLIENT);
                  break;
                } 
            }
        }
      }
  
    free(received_packet);
    return 0;  
  }
  
  char *packet_to_string(void *packet, uint32_t type) 
  {
    char *ptr = NULL;
    handshake_packet *hs_ptr = NULL;
    data_packet *data_ptr = NULL;
  
  #ifdef _DEBUG_
    printf("Inside packet_to_string.\n");
  #endif
    switch(type) 
      {
      case HANDSHAKE:
  #ifdef _DEBUG_
        printf("Inside handshake case.\n");
  #endif
        ptr = malloc(sizeof(char) * 64);
        hs_ptr = (handshake_packet *)packet;
        snprintf(ptr, 64, "%s %u %s %u %u %u %s", hs_ptr->proto_id, hs_ptr->packet_type, hs_ptr->client_ip, hs_ptr->client_port, hs_ptr->client_id, hs_ptr->flags, hs_ptr->trailer);
  #ifdef _DEBUG_
        printf("%s %u %s %u %u %u %s\n", hs_ptr->proto_id, hs_ptr->packet_type, hs_ptr->client_ip, hs_ptr->client_port, hs_ptr->client_id, hs_ptr->flags, hs_ptr->trailer, ptr);
  #endif
        break;
      case DATA:
  #ifdef _DEBUG_
        printf("Inside data case.\n");
  #endif
        ptr = malloc(sizeof(char) * 1500);
        data_ptr = (data_packet *)packet;
        snprintf(ptr, 1500, "%s %u %u %u %s %s", data_ptr->proto_id, data_ptr->packet_type, data_ptr->seq_nr, data_ptr->client_id, (char *)data_ptr->data, data_ptr->trailer);
  #ifdef _DEBUG_
        printf("%s %u %u %u %s %s\n%s\n", data_ptr->proto_id, data_ptr->packet_type, data_ptr->seq_nr, data_ptr->client_id, (char *)data_ptr->data, data_ptr->trailer, ptr);
  #endif
        break;
      }
  
    return ptr;
  }
  char *listen_socket (connection_data *connection, int timeout_sec, int timeout_usec) 
  {
    char *ptr = malloc(sizeof(char) * 1500);
    socklen_t socklen = sizeof(struct sockaddr);
    struct timeval timeout;
    fd_set listen_set;
    int return_value;
  
    FD_ZERO(&listen_set);
    timeout.tv_sec = timeout_sec;
    timeout.tv_usec = timeout_usec;
    FD_SET(connection->sock_fd, &listen_set);
  
  #ifdef _DEBUG_
    printf("Before recvfrom() in listen socket.\n");
  #endif
  
    if (FD_ISSET(connection->sock_fd, &listen_set))
      {
        return_value = select(connection->sock_fd+1, &listen_set, NULL, NULL, &timeout);
  #ifdef _DEBUG_
        printf("Return_value: %d\n", return_value);
  #endif
      } 
    else 
      {
        fprintf(stderr, "FD_SET was never called on the socket %d, quitting\n", connection->sock_fd);
        return NULL;
      }
    if (return_value == -1) 
      {
        perror("Select() failed");
        CLOSE(connection->sock_fd);
        return NULL;
      } 
    else if (return_value) 
      {
        if (recvfrom(connection->sock_fd, ptr, 1500, 0, (struct sockaddr *)connection->destination, &socklen) < 0) 
  	{
  	  perror ("recvfrom() failed");
  	  return NULL;
  	}
      } 
    else 
      {
        printf("Nothing happened... booooring... >:(\n");
        return NULL;
      }
  #ifdef _DEBUG_
    printf("After recvfrom().\n");
  #endif
  
    return ptr;
  }
  
  void *string_to_packet(char *string, uint32_t type) 
  {
    handshake_packet *hs_ptr = NULL;
    data_packet *data_ptr = NULL;
    void *ptr = NULL;
    int i;
  #ifdef _DEBUG_
    printf("Inside string_to_packet.\n");
  #endif
    switch(type) 
      {
      case HANDSHAKE:
  #ifdef _DEBUG_
        printf("Inside handshake case %s.\n", string);
  #endif
        hs_ptr = malloc(sizeof(handshake_packet));
        for(i = 0; i < 7; i++) 
  	{
  	  switch(i) 
  	    {
  	    case 0:
  	      hs_ptr->proto_id = strsep(&string, " "); break;
  	    case 1:
  	      hs_ptr->packet_type = atoi(strsep(&string, " ")); break;
  	    case 2:
  	      hs_ptr->client_ip = strsep(&string, " "); break;
  	    case 3:
  	      hs_ptr->client_port = atoi(strsep(&string, " ")); break;
  	    case 4:
  	      hs_ptr->client_id = atoi(strsep(&string, " ")); break;
  	    case 5:
  	      hs_ptr->flags = atoi(strsep(&string, " ")); break;
  	    case 6:
  	      hs_ptr->trailer = strsep(&string, " "); break;
  	    }
  	}
  #ifdef _DEBUG_
        printf("Packet: %s %u %u %s\n", hs_ptr->proto_id, hs_ptr->client_id, hs_ptr->flags, hs_ptr->trailer);
  #endif
        ptr = (void *)hs_ptr;
        break;
  
      case DATA:
  #ifdef _DEBUG_
        printf("Inside data case %s.\n", string);
  #endif
        data_ptr = malloc(sizeof(data_packet));
  
        for(i = 0; i < 6; i++) 
  	{
  	  switch(i) 
  	    {
  	    case 0:
  	      data_ptr->proto_id = strsep(&string, " "); break;
  	    case 1:
  	      data_ptr->packet_type = atoi(strsep(&string, " ")); break;
  	    case 2:
  	      data_ptr->seq_nr = atoi(strsep(&string, " ")); break;
  	    case 3:
  	      data_ptr->client_id = atoi(strsep(&string, " ")); break;
  	    case 4:
  	      data_ptr->data = (void *)strsep(&string, " "); break;
  	    case 5:
  	      data_ptr->trailer = strsep(&string, " "); break;
  	    }
  	}
  
        ptr = (void *)data_ptr;
        break;
      }
  
    return ptr;
  }
  
  connection_data *create_connection_data(char *ip, uint16_t port, uint32_t client_id, uint32_t sock_fd, connection_data *connection) 
  {
    int i;
  #ifdef _DEBUG_
    printf("before malloc in create connection data\n");
  #endif
    struct sockaddr_in *destination = malloc(sizeof(struct sockaddr_in));
  #ifdef _DEBUG_
    printf("pointer: %p\n", connection);
  #endif
  
    destination->sin_addr.s_addr = inet_addr(ip);
    destination->sin_port = htons(port);
    destination->sin_family = AF_INET;
  #ifdef _DEBUG_
    printf("Before assigning to connection_data struct.\n");
    printf("Struct data: %d %d %d\n", destination->sin_family, destination->sin_port, destination->sin_addr.s_addr);
  #endif
    connection->destination = destination;
  #ifdef _DEBUG_
    printf("Struct data: %d %d %d\n", connection->destination->sin_family, connection->destination->sin_port, connection->destination->sin_addr.s_addr);
  #endif
    connection->sock_fd = sock_fd;
    connection->client_id = client_id;
    connection->client_ip = ip;
    connection->client_port = port;
  
    for (i = 0; i < 6; i++)
      {
        connection->last_seen_pkt[i] = 0;
      }
  #ifdef _DEBUG_
    printf("After assigning to connection_data struct.\n");
  #endif
  
    return connection;
  }
  
  int net_init(void)
  {
  #if defined(__WIN32__) || defined(WIN32)
    WORD version_wanted = MAKEWORD(1,1);
    WSADATA wsa_data;
    if (WSAStartup(version_wanted, &wsa_data) != 0) 
      {
  #ifdef _DEBUG_
        printf("WSAStartup() failed: %d\n", WSAGetLastError());
  #endif
        return -1;
      } 
    else 
      {
        return 0;
      }
  #else
    return 0;
  #endif
  }
  
  int net_cleanup(void) 
  {
  #if defined(__WIN32__) || defined(WIN32)
  
    if ( WSACleanup() == SOCKET_ERROR ) 
      {
        if ( WSAGetLastError() == WSAEINPROGRESS ) 
  	{
  	  WSACancelBlockingCall();
  	  WSACleanup();
  	  return 0;
  	}
      }
    return 0;
  #else
    return 0;
  #endif
  }
  
  int send_data (connection_data *connection, char *data) 
  {
    data_packet d_packet;
    char *ptr = NULL;
    static uint32_t sequence_nr;
  
    d_packet.proto_id = "herp";
    d_packet.packet_type = DATA;
    d_packet.seq_nr = sequence_nr;
  #ifdef _DEBUG_
    printf("Client_id: %d, %d last_seen_pkt[%d] = %d\n", connection->client_id, connection->client_id-1, connection->client_id-1, connection->last_seen_pkt[connection->client_id-1]);
  #endif
    d_packet.client_id = connection->client_id;
    d_packet.data = (void *)data;
    d_packet.trailer = "derp";
  
    ptr = packet_to_string(&d_packet, DATA);
  
    if (sendto(connection->sock_fd, ptr, strlen(ptr)+1, 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) <0) 
      {
        perror ("sendto (func send_data) failed!");
        return -1;
      }
  
    free(ptr);
    sequence_nr++;
    return 0;
  }
  
  void *recv_data (connection_data *connection, int timer) 
  {
    char *ptr = NULL, *data = NULL;
    data_packet *data_ptr = NULL;
    handshake_packet *hs_ptr = NULL;
    fd_set listen_set;
    int result, client_index;
  
  #ifdef _DEBUG_
    printf("Listen socket in recv-data\n");
  #endif
    ptr = listen_socket(connection, timer, 0);
  #ifdef _DEBUG_
    if (ptr != NULL)
      printf("ptr in recv_data is: %s\n and ptr[5] is: %c\n", ptr, ptr[5]);
  #endif
  
    if (ptr != NULL) 
      {
        switch(atoi(&ptr[5])) 
  	{
  	case HANDSHAKE:
  	  hs_ptr = string_to_packet(ptr, HANDSHAKE);
  
  	  if (!is_packet(hs_ptr, HANDSHAKE) && (connection->client_id == 7 || connection->client_id == hs_ptr->client_id)) 
  	    {
  #ifdef _DEBUG_
  	      printf("It is a handshake packet!\n");
  #endif
  	      if (hs_ptr->flags != RST) {
  		free(hs_ptr);
  		return NULL;
  	      } else {
  		connection_termination(connection, SERVER);
  		free(hs_ptr);
  		return "Terminated";
  	      }
  	    } 
  	  else 
  	    {
  #ifdef _DEBUG_
  	      printf("Is not a packet :(\n");
  #endif
  	      return NULL;
  	    }
  	  break;
  	case DATA:
  	  data_ptr = string_to_packet(ptr, DATA);
  
  	  if (!is_packet(data_ptr, DATA)) 
  	    {
  #ifdef _DEBUG_
  	      printf("Data packet received, containing data: %s\n", (char *)data_ptr->data);
  #endif
  	      client_index = data_ptr->client_id-1;
  #ifdef _DEBUG_
  	      printf("Client_index: %d\n", client_index);
  	      printf("Last_seen_pkt[%d] = %d data_ptr->seq_nr = %d\n", client_index, connection->last_seen_pkt[client_index], data_ptr->seq_nr);
  #endif
  	      if (data_ptr->seq_nr > connection->last_seen_pkt[client_index])
  		{
  #ifdef _DEBUG_
  		  printf("Data packet is newer than last seen, using...\n");
  #endif
  		  connection->last_seen_pkt[client_index] = data_ptr->seq_nr;
  		  data = strdup(data_ptr->data);
  		  free(data_ptr);
  #ifdef _DEBUG_
  		  printf("Last_seen_pkt[%d] = %d\n", client_index, connection->last_seen_pkt[client_index]);
  #endif
  		  return data;
  		}
  	      else 
  		{
  #ifdef _DEBUG_
  		  printf("Packet out of order, dumping...\n");
  #endif
  		  return NULL;
  		}
  	    } 
  	  else 
  	    {
  	      return NULL;
  	    }
  	default:
  	  return NULL;
  	}
      } 
    else
      {
        return NULL;
      }
  } 
  
  int is_packet(void *packet_ptr, uint32_t type) 
  {
    handshake_packet *hs_ptr = NULL;
    data_packet *data_ptr = NULL;
  
  #ifdef _DEBUG_
    printf("In is_packet, before switch: %d\n", type);
  #endif
  
    switch(type) 
      {
      case HANDSHAKE:
  #ifdef _DEBUG_
        printf("is handshake?\n");
  #endif
        hs_ptr = (handshake_packet *)packet_ptr;
  
        if (!strncmp("herp", hs_ptr->proto_id, 4) && !strncmp("derp", hs_ptr->trailer, 4)) 
  	{
  #ifdef _DEBUG_
  	  printf("Is a handshake!\n");
  #endif
  	  return 0;
  	} 
        else 
  	{
  #ifdef _DEBUG_
  	  printf("Is not a handshake :(\n");
  #endif
  	  return 1;
  	}
        break;
      case DATA:
  #ifdef _DEBUG_
        printf("is data?\n");
  #endif
        data_ptr = (data_packet *)packet_ptr;
  
        if (!strncmp("herp", data_ptr->proto_id, 4) && !strncmp("derp", data_ptr->trailer, 4)) 
  	{
  #ifdef _DEBUG_
  	  printf("Is a data\n");
  #endif
  	  return 0;
  	} 
        else 
  	{
  #ifdef _DEBUG_
  	  printf("Is not a data :(\n");
  #endif
  	  return 1;
  	}
      }
  }
  
  int connection_termination(connection_data *connection, uint8_t side) 
  {
    handshake_packet *rst_ack_packet = NULL;
    char *ptr = NULL;
    int i;
  
  #ifdef _DEBUG_
    printf("Terminating connection.\n");
  #endif
    switch(side) 
      {
      case SERVER:
  #ifdef _DEBUG_
        printf("Preparing ACK packet for termination.\n");
  #endif
        rst_ack_packet = malloc(sizeof(handshake_packet));
        rst_ack_packet->proto_id = "herp";
        rst_ack_packet->packet_type = HANDSHAKE;
        rst_ack_packet->client_ip = connection->client_ip;
        rst_ack_packet->client_port = connection->client_port;
        rst_ack_packet->client_id = connection->client_id;
        rst_ack_packet->flags = ACK;
        rst_ack_packet->trailer = "derp";
  #ifdef _DEBUG_
        printf("Converting to string.\n");
  #endif
  
        ptr = packet_to_string(rst_ack_packet, HANDSHAKE);
  
  #ifdef _DEBUG_
        printf("Sending ACK for termination.\n");
  #endif
        for(i = 0; i < 2; i++) {
          if (sendto(connection->sock_fd, ptr, strlen(ptr), 0, (struct sockaddr *)connection->destination, sizeof(struct sockaddr)) < 0) 
            {
              perror("sendto() failed in ACK for termination");
              CLOSE(connection->sock_fd);
              return -1;
            }
        }
        free(ptr);
        free(rst_ack_packet);
        break;
      case CLIENT:
  #ifdef _DEBUG_
        printf("Closing socket.\n");
  #endif
        CLOSE(connection->sock_fd);
  #ifdef _DEBUG_
        printf("Freeing connection_data.\n");
  #endif
        free(connection->destination);
        free(connection);
        break;
      }
    net_cleanup();
    return 0;
  }
  