int do_communicate (const struct sockaddr_in *sock_addr_p, socklen_t addrlen, enum comm_complexity how)
{
  int result = 0;
  char *buf;
  static const size_t buf_size = 10 * 1024;

  buf = malloc (buf_size + 1); /* Extra byte for null-termination */
  if (NULL == buf)
  {
    result = 99;
    fprintf (stderr, "Error allocating memory for buffer.\n");
  }
  else
  {
    SYS_socket clnt_s;
    if (!sock_addr_p)
      return 99;
    clnt_s = socket (AF_INET, SOCK_STREAM, 0);
    if (SYS_INVALID_SOCKET == clnt_s)
    {
      fprintf (stderr, "Can't create socket: %u\n",
               (unsigned)SYS_sock_errno);
      result = 99;
    }
    else
    {
      char *str_addr;
      printf ("\nTrying communication sequence with server_part %s.\n", str_complexity (how));
      str_addr = inet_ntoa (sock_addr_p->sin_addr);
      if (!str_addr)
        str_addr = "server_part";

      printf ("Connecting to %s...\n", str_addr);
      if (connect (clnt_s, (const struct sockaddr*)sock_addr_p, addrlen) < 0)
      {
        fprintf (stderr, "Failed to connect: %u\n",
                 (unsigned)SYS_sock_errno);
        result = 99;
      }
      else
      {
        static const char data1[] = "FIRST PING\n";
        printf ("Connected. Sending \"FIRST PING\".\n");
        if (!send_str (clnt_s, data1, sizeof (data1) - 1))
        {
          result = 1;
          fprintf (stderr, "Error sending data.\n");
        }
        else
        {
          char *rcv_ptr;
          char *processed_ptr;
          const char *nl_ptr;

          rcv_ptr = buf;
          processed_ptr = buf;
          printf ("Sent. Waiting for receive \"FIRST PONG\".\n");
          nl_ptr = recv_line (clnt_s, &rcv_ptr, buf_size - (rcv_ptr - buf));
          if (!nl_ptr)
          {
            result = 1;
            fprintf (stderr, "Error receiving \"FIRST PONG\".\n");
          }
          else
          {
            rcv_ptr[0] = 0; /* Null-terminate for safety */
            printf ("Received: %*.*s\n", (int)(nl_ptr - processed_ptr), (int)(nl_ptr - processed_ptr), processed_ptr);
            if (!cmp_to_lower (processed_ptr, nl_ptr - processed_ptr, "first pong"))
            {
              result = 1;
              fprintf (stderr, "Expected marker not found in received data.\n");
            }
            else
            {
              static const char data2[] = "SECOND PING\n";
              processed_ptr = rcv_ptr;
              printf ("Sending \"SECOND PING\".\n");
              if (!send_str (clnt_s, data2, sizeof (data2) - 1))
              {
                result = 1;
                fprintf (stderr, "Error sending data.\n");
              }
              else
              {
                printf ("Sent.\n");
                if (how == COMM_DELAY || how == COMM_DELAY_ADD_DATA)
                {
                  printf ("Idling for delayed response receive...\n");
                  local_sleep (1500);
                }
                if (how == COMM_ADD_DATA || how == COMM_DELAY_ADD_DATA ||
                    how == COMM_ADD_DATA_TCPNDL || how == COMM_ADD_DATA_DELAY)
                {
                  static const char data_ign[] = "Additional data to be ignored.\n";
                  int on_val, off_val;

                  on_val = 1;
                  off_val = 0;
                  if (how == COMM_ADD_DATA_TCPNDL &&
                      0 != setsockopt (clnt_s, IPPROTO_TCP, TCP_NODELAY, (void*)&on_val, sizeof (on_val)))
                  {
                    result = 99;
                    fprintf(stderr,"Can't set TCP_ONDELAY option: %d.\n",
                            (unsigned)SYS_sock_errno);
                  }
                  printf ("Sending additional ignorable data.\n");
                  if (!send_str (clnt_s, data_ign, sizeof (data_ign) - 1))
                  {
                    printf ("Sending data failed.\n");
                  }
                  else
                  {
                    printf ("Sent.\n");
                  }
                }
                if (how == COMM_ADD_DATA_DELAY)
                {
                  printf ("Idling after additional sending for delayed response receive...\n");
                  local_sleep (1500);
                }
                printf ("Waiting for \"SECOND PONG\".\n");
                SYS_reset_sock_errno ();
                nl_ptr = recv_line (clnt_s, &rcv_ptr, buf_size - (rcv_ptr - buf));
                if (!nl_ptr)
                {
                  int err = SYS_sock_errno;
                  result = 1;
                  fprintf (stderr, "Error receiving \"SECOND PONG\".\n");
                  if (SYS_ECONNABORTED == err || SYS_ECONNRESET == err)
                    fprintf (stderr, "Looks like any received data was lost in system on this host after this system detected that connection was closed by remote side.\n");
                }
                else
                {
                  rcv_ptr[0] = 0; /* Null-terminate for safety */
                  printf ("Received: %*.*s\n", (int)(nl_ptr - processed_ptr), (int)(nl_ptr - processed_ptr), processed_ptr);
                  if (!cmp_to_lower (processed_ptr, nl_ptr - processed_ptr, "second pong"))
                  {
                    result = 1;
                    fprintf (stderr, "Expected marker not found in received data.\n");
                  }
                  else
                  {
                    printf ("Sequence completed.\n");
                  }
                }
              }
            }
          }
        }
      }
    }

    printf ("Closing connection.\n");
    SYS_socket_close_ (clnt_s);
  }

  if (result)
    fprintf (stderr, "Completed with some error.\n");
  else
    printf ("Completed without errors.\n");

  return result;
}
int
main (int argc, char *const *argv)
{
  int i;
  time_t start_t, end_t;
  int result = 0;
  MHD_THRD_RTRN_TYPE_ (MHD_THRD_CALL_SPEC_ *test_func)(void* data);
#ifdef MHD_WINSOCK_SOCKETS
  WORD ver_req;
  WSADATA wsa_data;
  int err;
#endif /* MHD_WINSOCK_SOCKETS */
  bool test_poll;

  test_poll = has_in_name(argv[0], "_poll");
  if (!test_poll)
    test_func = &select_thread;
  else
    {
#ifndef HAVE_POLL
      return 77;
#else  /* ! HAVE_POLL */
      test_func = &poll_thread;
#endif /* ! HAVE_POLL */
    }

#ifdef MHD_WINSOCK_SOCKETS
  ver_req = MAKEWORD(2, 2);

  err = WSAStartup(ver_req, &wsa_data);
  if (err != 0 || MAKEWORD(2, 2) != wsa_data.wVersion)
    {
      printf("WSAStartup() failed\n");
      WSACleanup();
      return 99;
    }
#endif /* MHD_WINSOCK_SOCKETS */

  /* try several times to ensure that accidental incoming connection
   * didn't interfere with test results
   */
  for (i = 0; i < 5 && result == 0; i++)
    {
      MHD_thread_handle_ sel_thrd;
      /* fprintf(stdout, "Creating, binding and listening socket...\n"); */
      MHD_socket listen_socket = start_socket_listen (AF_INET);
      if (MHD_INVALID_SOCKET == listen_socket)
        return 99;

      check_err = !0;
      /* fprintf (stdout, "Starting select() thread...\n"); */
#if defined(MHD_USE_POSIX_THREADS)
      if (0 != pthread_create (&sel_thrd, NULL, test_func, &listen_socket))
        {
          MHD_socket_close_chk_ (listen_socket);
          fprintf (stderr, "Can't start thread\n");
          return 99;
        }
#elif defined(MHD_USE_W32_THREADS)
      sel_thrd = (HANDLE)_beginthreadex (NULL, 0, test_func, &listen_socket, 0, NULL);
      if (0 == (sel_thrd))
        {
          MHD_socket_close_chk_ (listen_socket);
          fprintf (stderr, "Can't start select() thread\n");
          return 99;
        }
#else
#error No threading lib available
#endif
      /* fprintf (stdout, "Waiting...\n"); */
      local_sleep(1); /* make sure that select() is started */

      /* fprintf (stdout, "Shutting down socket...\n"); */
      start_t = time (NULL);
      shutdown (listen_socket, SHUT_RDWR);

      /* fprintf (stdout, "Waiting for thread to finish...\n"); */
      if (!MHD_join_thread_(sel_thrd))
        {
          MHD_socket_close_chk_(listen_socket);
          fprintf (stderr, "Can't join select() thread\n");
          return 99;
        }
      if (check_err)
        {
          MHD_socket_close_chk_(listen_socket);
          fprintf (stderr, "Error in waiting thread\n");
          return 99;
        }
      end_t = time (NULL);
      /* fprintf (stdout, "Thread finished.\n"); */
      MHD_socket_close_chk_(listen_socket);

      if (start_t == (time_t)-1 || end_t == (time_t)-1)
        {
          MHD_socket_close_chk_(listen_socket);
          fprintf (stderr, "Can't get current time\n");
          return 99;
        }
      if (end_t - start_t > 3)
        result++;
    }

#ifdef MHD_WINSOCK_SOCKETS
  WSACleanup();
#endif /* MHD_WINSOCK_SOCKETS */

  return result;
}