void* comm_recv_thread_start( void* data ) {
  recv_thread_t* my_info = reinterpret_cast<recv_thread_t*>(data);
  char   incoming_buf[1500];
  msg_t* incoming;

  // Receive loop
  // Communication hasn't been stopped
  while ( my_info->state == T_STATE_ACTIVE ) {
    int bytes = ::recv( my_info->sockfd, incoming_buf, sizeof(incoming_buf), 0 );
    if ( bytes != sizeof(msg_t) ) {
      cout << "DIDNOT RECEIVE ENTIRE MESSAGE" << endl;
    }

    // Normal receive
    if ( bytes > 0 ) {
      incoming = reinterpret_cast<msg_t*>(incoming_buf);
      comm_recv_q.push( *incoming );
    }

    // Connection closed
    else if ( bytes <= 0 ) {
      cout << "comm_recv_thread_start Terminating receive thread" << endl;
      comm_close_connection( incoming->send_ID );
      my_info->state = T_STATE_STOP;
      break;
    }
  }

  ::close( my_info->sockfd );

  return NULL;
}
int comm_stop() {
  comm_tcp_recv_threads.mutex.lock();

  // Mark all threads STOP
  comm_tcp_listen_thread.state = T_STATE_STOP;
  comm_udp_recv_thread.state = T_STATE_STOP;
  comm_recv_parse_thread.state = T_STATE_STOP;
  comm_send_thread.state = T_STATE_STOP;
  for ( list<recv_thread_t>::iterator it = comm_tcp_recv_threads.thread_list.begin();
        it != comm_tcp_recv_threads.thread_list.end();
        it++ ) {
    it->state = T_STATE_STOP;
  }

  // Close sockets threads are working with.
  // This gets the receiver threads and the listener thread off the blocking
  // accept() and recv() calls
  ::close( comm_tcp_listen_thread.sockfd );
  ::close( comm_udp_recv_thread.sockfd );
  for ( contact_list_t::iterator it = comm_contacts.begin();
        it != comm_contacts.end();
        it++ ) {
    comm_close_connection( it->second );
  }
  for ( list<recv_thread_t>::iterator it = comm_tcp_recv_threads.thread_list.begin();
        it != comm_tcp_recv_threads.thread_list.end();
        it++ ) {
    ::close( it->sockfd );
  }
  
  comm_tcp_recv_threads.mutex.unlock();

  // Push an execution STOP message into the send and recv queues
  // This gets the receiver parser thread and the sending thread off the blocked
  // wait_and_pop() calls
  // msg_t terminate = create_msg( MSG_T_FINAL, 0, 0, 0, "" );
  msg_t terminate;
  terminate.header = MSG_T_HALT;
  comm_recv_q.push( terminate );
  comm_send_q.push( terminate );

  return 0;
}
void* comm_tcp_recv_thread_fun( void* data ) {
  list<recv_thread_t>::iterator my_info;
  char      incoming_buf[512];
  msg_t*    incoming;

  wait_ms_duration( 100 );

  // Locate this recv thread's info in the list
  bool found = false;
  do {
    comm_tcp_recv_threads.mutex.lock();

    for ( my_info = comm_tcp_recv_threads.thread_list.begin();
          my_info != comm_tcp_recv_threads.thread_list.end();
          my_info++ ) {
      if ( pthread_equal( my_info->id, pthread_self() ) ) {
        found = true;
        break;
      }
    }

    comm_tcp_recv_threads.mutex.unlock();
  } while ( !found );

  // Receive loop
  // Communication hasn't been stopped
  while ( my_info->state == T_STATE_ACTIVE ) {
    int bytes = ::recv( my_info->sockfd, incoming_buf, sizeof(incoming_buf), 0 );
    if ( bytes != sizeof(msg_t) ) {
      cout << "comm_tcp_recv_thread_fun DID NOT RECEIVE ENTIRE MESSAGE" << endl;
    }

    // Normal receive
    if ( bytes > 0 ) {
      incoming = reinterpret_cast<msg_t*>(incoming_buf);
      comm_recv_q.push( *incoming );
    }

    // Connection closed from remote end
    else {
      cout << "comm_tcp_recv_thread_fun Terminating receive thread" << endl;
      ::close( my_info->sockfd );
      comm_close_connection( comm_contacts[incoming->send_id] );
      my_info->state = T_STATE_STOP;
    }
  }

  // Remove this thread from the recv_thread_ids
  comm_tcp_recv_threads.mutex.lock();
  comm_tcp_recv_threads.thread_list.erase( my_info );
  comm_tcp_recv_threads.mutex.unlock();

  return NULL;
}
int comm_stop() {
  // Mark all threads STOP
  comm_listen_thread_id.state = T_STATE_STOP;
  comm_recv_parse_thread_id.state = T_STATE_STOP;
  comm_send_thread_id.state = T_STATE_STOP;
  for ( unsigned int i = 0; i < comm_recv_thread_ids.size(); i++ ) {
    comm_recv_thread_ids[i].state = T_STATE_STOP;
  }

  // Close sockets threads are working with.
  // This gets the receiver threads and the listener thread off the blocking
  // accept() and recv() calls
  ::close( comm_listen_thread_id.sockfd );
  for ( unsigned int i = 0; i < comm_recv_thread_ids.size(); i++ ) {
    ::close( comm_recv_thread_ids[i].sockfd );
  }
  for ( contact_list_t::iterator it = comm_contacts.begin();
        it != comm_contacts.end();
        it++ ) {
    comm_close_connection( it->first );     
  }

  // Push an execution STOP message into the send and recv queues
  // This gets the receiver parser thread and the sending thread off the blocked
  // wait_and_pop() calls
  msg_t terminate;
  terminate.msg_type = MSG_T_TERMINATE;
  comm_recv_q.push( terminate );
  comm_send_q.push( terminate );

  // Join all threads
  pthread_join( comm_listen_thread_id.id, NULL );
  pthread_join( comm_recv_parse_thread_id.id, NULL );
  pthread_join( comm_send_thread_id.id, NULL );
  for ( unsigned int i = 0; i < comm_recv_thread_ids.size(); i++ ) {
    pthread_join( comm_recv_thread_ids[i].id, NULL );
  }

  return 0;
}
	void thread_recv() {
		while (connected.load()) {
			spmsg_t msg = std::make_shared<msg_t>(sizeof(uint32_t));

			if (!_do_recv(msg->data(), sizeof(uint32_t)))
				return;
			
			uint32_t msg_len = *(uint32_t*)msg->data();
			msg->resize(msg_len + sizeof(uint32_t));
			*(uint32_t*)msg->data() = msg_len;
			
			if (!_do_recv(msg->data() + sizeof(uint32_t), msg_len))
				return;
			
			recv_queue.push(std::move(msg));
		}
	}
void* comm_udp_recv_thread_fun( void* data ) {
  int newfd = -1, error = 0;
  struct sockaddr remote_addr;
  socklen_t sin_size = sizeof(remote_addr);
  char      incoming_buf[512];
  msg_t*    incoming;

  comm_udp_recv_thread.sockfd = comm_bind_once( comm_port, SOCK_DGRAM ); 
  if ( comm_udp_recv_thread.sockfd < 0 ) {
    cout << "comm_udp_recv_thread_fun Couldn't bind to port " << comm_port << endl;
    return NULL;
  }

  // Recvfrom loop
  // Communication hasn't been stopped
  while ( comm_udp_recv_thread.state == T_STATE_ACTIVE ) {
    int bytes = ::recvfrom( comm_udp_recv_thread.sockfd, incoming_buf, sizeof(incoming_buf), 0,
                            &remote_addr, &sin_size );
    if ( bytes != sizeof(msg_t) ) {
      cout << "comm_udp_recv_thread_fun DID NOT RECEIVE ENTIRE MESSAGE" << endl;
    }

    // Normal receive
    if ( bytes > 0 ) {
      incoming = reinterpret_cast<msg_t*>(incoming_buf);
      comm_recv_q.push( *incoming );
    }

    // Connection closed from remote end
    else {
      cout << "comm_udp_recv_thread_fun Terminating receive thread" << endl;
      ::close( comm_udp_recv_thread.sockfd );
      comm_udp_recv_thread.state = T_STATE_STOP;
    }
  }

  return NULL;
}
// Server interaction functions
int comm_send( msg_t msg ) {
  msg.send_ID = NODE_INFO.id;
  comm_send_q.push( msg );

  return 0;
}
	bool send(spmsg_t msg_) {
		send_queue.push(std::move(msg_));
		return true;
	}