예제 #1
0
static int
test_tls_session_time_out (gnutls_session_t session)
{
  int ret;
  MHD_socket sd;
  struct sockaddr_in sa;

  sd = socket (AF_INET, SOCK_STREAM, 0);
  if (sd == -1)
    {
      fprintf (stderr, "Failed to create socket: %s\n", strerror (errno));
      return -1;
    }

  memset (&sa, '\0', sizeof (struct sockaddr_in));
  sa.sin_family = AF_INET;
  sa.sin_port = htons (DEAMON_TEST_PORT);
  sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) sd);

  ret = connect (sd, (struct sockaddr *) &sa, sizeof (struct sockaddr_in));

  if (ret < 0)
    {
      fprintf (stderr, "Error: %s\n", MHD_E_FAILED_TO_CONNECT);
      MHD_socket_close_ (sd);
      return -1;
    }

  ret = gnutls_handshake (session);
  if (ret < 0)
    {
      fprintf (stderr, "Handshake failed\n");
      MHD_socket_close_ (sd);
      return -1;
    }

  sleep (TIME_OUT + 1);

  /* check that server has closed the connection */
  /* TODO better RST trigger */
  if (send (sd, "", 1, 0) == 0)
    {
      fprintf (stderr, "Connection failed to time-out\n");
      MHD_socket_close_ (sd);
      return -1;
    }

  MHD_socket_close_ (sd);
  return 0;
}
예제 #2
0
/*
 * Connects to the host |host| and port |port|.  This function returns
 * the file descriptor of the client socket.
 */
static int connect_to(const char *host, uint16_t port)
{
  struct addrinfo hints;
  int fd = -1;
  int rv;
  char service[NI_MAXSERV];
  struct addrinfo *res, *rp;
  snprintf(service, sizeof(service), "%u", port);
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  rv = getaddrinfo(host, service, &hints, &res);
  if(rv != 0) {
    dief("getaddrinfo", gai_strerror(rv));
  }
  for(rp = res; rp; rp = rp->ai_next) {
    fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
    if(fd == -1) {
      continue;
    }
    while((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 &&
          errno == EINTR);
    if(rv == 0) {
      break;
    }
    MHD_socket_close_(fd);
    fd = -1;
    dief("connect", strerror(errno));
  }
  freeaddrinfo(res);
  return fd;
}
예제 #3
0
static void *
ServeOneRequest(void *param)
{
    struct MHD_Daemon *d;
    fd_set rs;
    fd_set ws;
    fd_set es;
    MHD_socket fd, max;
    time_t start;
    struct timeval tv;
    int done = 0;

    fd = (MHD_socket) (intptr_t) param;

    d = MHD_start_daemon (MHD_USE_DEBUG,
                          1082, NULL, NULL, &ahc_echo, "GET",
                          MHD_OPTION_LISTEN_SOCKET, fd,
                          MHD_OPTION_NOTIFY_COMPLETED, &request_completed, &done,
                          MHD_OPTION_END);
    if (d == NULL)
        return "MHD_start_daemon() failed";

    start = time (NULL);
    while ((time (NULL) - start < 5) && done == 0)
    {
        max = 0;
        FD_ZERO (&rs);
        FD_ZERO (&ws);
        FD_ZERO (&es);
        if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
        {
            MHD_stop_daemon (d);
            MHD_socket_close_(fd);
            return "MHD_get_fdset() failed";
        }
        tv.tv_sec = 0;
        tv.tv_usec = 1000;
        MHD_SYS_select_ (max + 1, &rs, &ws, &es, &tv);
        MHD_run (d);
    }
    MHD_stop_daemon (d);
    MHD_socket_close_(fd);
    return NULL;
}
예제 #4
0
파일: test_get.c 프로젝트: Chris112/sep
static int
testStopRace (int poll_flag)
{
    struct sockaddr_in sin;
    MHD_socket fd;
    struct MHD_Daemon *d;
    
    d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG | poll_flag,
                         1081, NULL, NULL, &ahc_echo, "GET",
                         MHD_OPTION_CONNECTION_TIMEOUT, 5, MHD_OPTION_END);
    if (d == NULL)
       return 16;
    
    fd = socket (PF_INET, SOCK_STREAM, 0);
    if (fd == MHD_INVALID_SOCKET)
    {
       fprintf(stderr, "socket error\n");
       return 256;
    }
    
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(1081);
    sin.sin_addr.s_addr = htonl(0x7f000001);
    
    if (connect (fd, (struct sockaddr *)(&sin), sizeof(sin)) < 0)
    {
       fprintf(stderr, "connect error\n");
       MHD_socket_close_ (fd);
       return 512;
    }
    
    /*  printf("Waiting\n"); */
    /* Let the thread get going. */
    usleep(500000);
    
    /* printf("Stopping daemon\n"); */
    MHD_stop_daemon (d);
 
    MHD_socket_close_ (fd);
    
    /* printf("good\n"); */
    return 0;
}
예제 #5
0
/**
 * Close socket and release allocated resourced
 * @param s the socket to close
 * @return zero on succeed, -1 otherwise
 */
static int wr_close(wr_socket s)
{
  int ret = (MHD_socket_close_(s->fd)) ? 0 : -1;
#ifdef HTTPS_SUPPORT
  if (wr_tls == s->t)
    {
      gnutls_deinit (s->tls_s);
      gnutls_certificate_free_credentials (s->tls_crd);
    }
#endif /* HTTPS_SUPPORT */
  free(s);
  return ret;
}
예제 #6
0
/**
 * Create wr_socket with TLS TCP underlying socket
 * @return created socket on success, WR_BAD otherwise
 */
static wr_socket wr_create_tls_sckt(void)
{
#ifdef HTTPS_SUPPORT
  wr_socket s = (wr_socket)malloc(sizeof(struct wr_socket_strc));
  if (WR_BAD == s)
    return WR_BAD;
  s->t = wr_tls;
  s->tls_connected = 0;
  s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (MHD_INVALID_SOCKET != s->fd)
    {
      if (GNUTLS_E_SUCCESS == gnutls_init (&(s->tls_s), GNUTLS_CLIENT))
        {
          if (GNUTLS_E_SUCCESS == gnutls_set_default_priority (s->tls_s))
            {
              if (GNUTLS_E_SUCCESS == gnutls_certificate_allocate_credentials (&(s->tls_crd)))
                {
                  if (GNUTLS_E_SUCCESS == gnutls_credentials_set (s->tls_s, GNUTLS_CRD_CERTIFICATE, s->tls_crd))
                    {
#if GNUTLS_VERSION_NUMBER+0 >= 0x030109
                      gnutls_transport_set_int (s->tls_s, (int)(s->fd));
#else  /* GnuTLS before 3.1.9 */
                      gnutls_transport_set_ptr (s->tls_s, (gnutls_transport_ptr_t)(intptr_t)(s->fd));
#endif /* GnuTLS before 3.1.9 */
                      return s;
                    }
                  gnutls_certificate_free_credentials (s->tls_crd);
                }
            }
          gnutls_deinit (s->tls_s);
        }
      (void)MHD_socket_close_ (s->fd);
    }
  free(s);
#endif /* HTTPS_SUPPORT */
  return WR_BAD;
}
예제 #7
0
/**
 * Test daemon response to TLS client hello requests containing extensions
 *
 * @param session
 * @param exten_t - the type of extension being appended to client hello request
 * @param ext_count - the number of consecutive extension replicas inserted into request
 * @param ext_length - the length of each appended extension
 * @return 0 on successful test completion, -1 otherwise
 */
static int
test_hello_extension (gnutls_session_t session, extensions_t exten_t,
                      int ext_count, int ext_length)
{
  int i, ret = 0, pos = 0;
  MHD_socket sd;
  int exten_data_len, ciphersuite_len, datalen;
  struct sockaddr_in sa;
  char url[255];
  opaque *data = NULL;
  uint8_t session_id_len = 0;
  opaque rnd[TLS_RANDOM_SIZE];
  opaque extdata[MAX_EXT_DATA_LENGTH];

  /* single, null compression */
  unsigned char comp[] = { 0x01, 0x00 };
  struct CBC cbc;

  sd = -1;
  memset (&cbc, 0, sizeof (struct CBC));
  if (NULL == (cbc.buf = malloc (sizeof (char) * 256)))
    {
      fprintf (stderr, MHD_E_MEM);
      ret = -1;
      goto cleanup;
    }
  cbc.size = 256;

  sd = socket (AF_INET, SOCK_STREAM, 0);
  if (sd == -1)
    {
      fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
      free (cbc.buf);
      return -1;
    }
  memset (&sa, '\0', sizeof (struct sockaddr_in));
  sa.sin_family = AF_INET;
  sa.sin_port = htons (DEAMON_TEST_PORT);
  sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

  enum MHD_GNUTLS_Protocol hver;

  /* init hash functions */
  session->internals.handshake_mac_handle_md5 =
    MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
  session->internals.handshake_mac_handle_sha =
    MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);

  /* version = 2 , random = [4 for unix time + 28 for random bytes] */
  datalen = 2 /* version */ + TLS_RANDOM_SIZE + (session_id_len + 1);

  data = MHD_gnutls_malloc (datalen);
  if (data == NULL)
      {
	 free (cbc.buf);
	 return -1;
      }
  hver = MHD_gtls_version_max (session);
  data[pos++] = MHD_gtls_version_get_major (hver);
  data[pos++] = MHD_gtls_version_get_minor (hver);

  /* Set the version we advertise as maximum (RSA uses it). */
  set_adv_version (session, MHD_gtls_version_get_major (hver),
                   MHD_gtls_version_get_minor (hver));

  session->security_parameters.version = hver;
  session->security_parameters.timestamp = time (NULL);

  /* generate session client random */
  memset (session->security_parameters.client_random, 0, TLS_RANDOM_SIZE);
  gnutls_write_uint32 (time (NULL), rnd);
  if (GC_OK != MHD_gc_nonce ((char *) &rnd[4], TLS_RANDOM_SIZE - 4)) abort ();
  memcpy (session->security_parameters.client_random, rnd, TLS_RANDOM_SIZE);
  memcpy (&data[pos], rnd, TLS_RANDOM_SIZE);
  pos += TLS_RANDOM_SIZE;

  /* Copy the Session ID       */
  data[pos++] = session_id_len;

  /*
   * len = ciphersuite data + 2 bytes ciphersuite length \
   *       1 byte compression length + 1 byte compression data + \
   * 2 bytes extension length, extensions data
   */
  ciphersuite_len = MHD__gnutls_copy_ciphersuites (session, extdata,
                                                   sizeof (extdata));
  exten_data_len = ext_count * (2 + 2 + ext_length);
  datalen += ciphersuite_len + 2 + 2 + exten_data_len;
  data = MHD_gtls_realloc_fast (data, datalen);
  memcpy (&data[pos], extdata, sizeof (ciphersuite_len));
  pos += ciphersuite_len;

  /* set compression */
  memcpy (&data[pos], comp, sizeof (comp));
  pos += 2;

  /* set extensions length = 2 type bytes + 2 length bytes + extension length */
  gnutls_write_uint16 (exten_data_len, &data[pos]);
  pos += 2;
  for (i = 0; i < ext_count; ++i)
    {
      /* write extension type */
      gnutls_write_uint16 (exten_t, &data[pos]);
      pos += 2;
      gnutls_write_uint16 (ext_length, &data[pos]);
      pos += 2;
      /* we might want to generate random data here */
      memset (&data[pos], 0, ext_length);
      pos += ext_length;
    }

  if (connect (sd, &sa, sizeof (struct sockaddr_in)) < 0)
    {
      fprintf (stderr, "%s\n", MHD_E_FAILED_TO_CONNECT);
      ret = -1;
      goto cleanup;
    }

  gnutls_transport_set_ptr (session, (MHD_gnutls_transport_ptr_t) (long) sd);

  if (gen_test_file_url (url, DEAMON_TEST_PORT))
    {
      ret = -1;
      goto cleanup;
    }

  /* this should crash the server */
  ret = gnutls_send_handshake (session, data, datalen,
			       GNUTLS_HANDSHAKE_CLIENT_HELLO);

  /* advance to STATE2 */
  session->internals.handshake_state = STATE2;
  ret = gnutls_handshake (session);
  ret = gnutls_bye (session, GNUTLS_SHUT_WR);

  gnutls_free (data);

  /* make sure daemon is still functioning */
  if (CURLE_OK != send_curl_req (url, &cbc, "AES128-SHA",
                                 MHD_GNUTLS_PROTOCOL_TLS1_2))
    {
      ret = -1;
      goto cleanup;
    }

cleanup:
  if (-1 != sd)
    MHD_socket_close_ (sd);
  gnutls_free (cbc.buf);
  return ret;
}
예제 #8
0
static int
testExternalGet ()
{
  struct MHD_Daemon *d;
  CURL *c;
  char buf[2048];
  struct CBC cbc;
  CURLM *multi;
  CURLMcode mret;
  fd_set rs;
  fd_set ws;
  fd_set es;
  MHD_socket maxsock;
#ifdef MHD_WINSOCK_SOCKETS
  int maxposixs; /* Max socket number unused on W32 */
#else  /* MHD_POSIX_SOCKETS */
#define maxposixs maxsock
#endif /* MHD_POSIX_SOCKETS */
  int running;
  struct CURLMsg *msg;
  time_t start;
  struct timeval tv;
  int i;
  MHD_socket fd;

  multi = NULL;
  cbc.buf = buf;
  cbc.size = 2048;
  cbc.pos = 0;
  d = MHD_start_daemon (MHD_USE_DEBUG,
                        11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
  if (d == NULL)
    return 256;
  c = setupCURL(&cbc);

  multi = curl_multi_init ();
  if (multi == NULL)
    {
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 512;
    }
  mret = curl_multi_add_handle (multi, c);
  if (mret != CURLM_OK)
    {
      curl_multi_cleanup (multi);
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 1024;
    }

  for (i = 0; i < 2; i++) {
    start = time (NULL);
    while ((time (NULL) - start < 5) && (multi != NULL))
      {
        maxsock = MHD_INVALID_SOCKET;
        maxposixs = -1;
        FD_ZERO (&rs);
        FD_ZERO (&ws);
        FD_ZERO (&es);
        curl_multi_perform (multi, &running);
        mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
        if (mret != CURLM_OK)
          {
            curl_multi_remove_handle (multi, c);
            curl_multi_cleanup (multi);
            curl_easy_cleanup (c);
            MHD_stop_daemon (d);
            return 2048;
          }
        if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock))
          {
            curl_multi_remove_handle (multi, c);
            curl_multi_cleanup (multi);
            curl_easy_cleanup (c);
            MHD_stop_daemon (d);
            return 4096;
          }
        tv.tv_sec = 0;
        tv.tv_usec = 1000;
        select (maxposixs + 1, &rs, &ws, &es, &tv);
        curl_multi_perform (multi, &running);
        if (running == 0)
          {
            msg = curl_multi_info_read (multi, &running);
            if (msg == NULL)
              break;
            if (msg->msg == CURLMSG_DONE)
              {
                if (i == 0 && msg->data.result != CURLE_OK)
                  printf ("%s failed at %s:%d: `%s'\n",
                          "curl_multi_perform",
                          __FILE__,
                          __LINE__, curl_easy_strerror (msg->data.result));
                else if (i == 1 && msg->data.result == CURLE_OK)
                  printf ("%s should have failed at %s:%d\n",
                          "curl_multi_perform",
                          __FILE__,
                          __LINE__);
                curl_multi_remove_handle (multi, c);
                curl_multi_cleanup (multi);
                curl_easy_cleanup (c);
                c = NULL;
                multi = NULL;
              }
          }
        MHD_run (d);
      }

      if (i == 0) {
        /* quiesce the daemon on the 1st iteration, so the 2nd should fail */
        fd = MHD_quiesce_daemon(d);
        if (MHD_INVALID_SOCKET == fd)
          {
            fprintf (stderr,
                     "MHD_quiesce_daemon failed.\n");
            curl_multi_remove_handle (multi, c);
            curl_multi_cleanup (multi);
            curl_easy_cleanup (c);
            MHD_stop_daemon (d);
            return 2;
          }
        c = setupCURL (&cbc);
        multi = curl_multi_init ();
        mret = curl_multi_add_handle (multi, c);
        if (mret != CURLM_OK)
        {
          curl_multi_remove_handle (multi, c);
          curl_multi_cleanup (multi);
          curl_easy_cleanup (c);
          MHD_stop_daemon (d);
          return 32768;
        }
      }
    }
  if (multi != NULL)
    {
      curl_multi_remove_handle (multi, c);
      curl_easy_cleanup (c);
      curl_multi_cleanup (multi);
    }
  MHD_stop_daemon (d);
  MHD_socket_close_ (fd);
  if (cbc.pos != strlen ("/hello_world"))
    return 8192;
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    return 16384;
  return 0;
}
예제 #9
0
static int
testGet (int type, int pool_count, int poll_flag)
{
  struct MHD_Daemon *d;
  CURL *c;
  char buf[2048];
  struct CBC cbc;
  CURLcode errornum;
  MHD_socket fd;
  pthread_t thrd;
  const char *thrdRet;

  cbc.buf = buf;
  cbc.size = 2048;
  cbc.pos = 0;
  if (pool_count > 0) {
    d = MHD_start_daemon (type | MHD_USE_DEBUG | MHD_USE_PIPE_FOR_SHUTDOWN | poll_flag,
                          11080, NULL, NULL, &ahc_echo, "GET",
                          MHD_OPTION_THREAD_POOL_SIZE, pool_count, MHD_OPTION_END);

  } else {
    d = MHD_start_daemon (type | MHD_USE_DEBUG | MHD_USE_PIPE_FOR_SHUTDOWN | poll_flag,
                          11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
  }
  if (d == NULL)
    return 1;

  c = setupCURL(&cbc);

  if (CURLE_OK != (errornum = curl_easy_perform (c)))
    {
      fprintf (stderr,
               "curl_easy_perform failed: `%s'\n",
               curl_easy_strerror (errornum));
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 2;
    }

  if (cbc.pos != strlen ("/hello_world")) {
    curl_easy_cleanup (c);
    MHD_stop_daemon (d);
    return 4;
  }
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) {
    curl_easy_cleanup (c);
    MHD_stop_daemon (d);
    return 8;
  }

  fd = MHD_quiesce_daemon (d);
  if (MHD_INVALID_SOCKET == fd)
    {
      fprintf (stderr,
               "MHD_quiesce_daemon failed.\n");
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 2;
    }
  if (0 != pthread_create(&thrd, NULL, &ServeOneRequest, (void*)(intptr_t) fd))
    {
      fprintf (stderr, "pthread_create failed\n");
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 16;
    }

  cbc.pos = 0;
  if (CURLE_OK != (errornum = curl_easy_perform (c)))
    {
      fprintf (stderr,
               "curl_easy_perform failed: `%s'\n",
               curl_easy_strerror (errornum));
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 2;
    }

  if (0 != pthread_join(thrd, (void**)&thrdRet))
    {
      fprintf (stderr, "pthread_join failed\n");
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 16;
    }
  if (NULL != thrdRet)
    {
      fprintf (stderr, "ServeOneRequest() error: %s\n", thrdRet);
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      return 16;
    }

  if (cbc.pos != strlen ("/hello_world"))
    {
      fprintf(stderr, "%s\n", cbc.buf);
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      MHD_socket_close_(fd);
      return 4;
    }
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
    {
      fprintf(stderr, "%s\n", cbc.buf);
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      MHD_socket_close_(fd);
      return 8;
    }

  /* at this point, the forked server quit, and the new
   * server has quiesced, so new requests should fail
   */
  if (CURLE_OK == (errornum = curl_easy_perform (c)))
    {
      fprintf (stderr, "curl_easy_perform should fail\n");
      curl_easy_cleanup (c);
      MHD_stop_daemon (d);
      MHD_socket_close_(fd);
      return 2;
    }
  curl_easy_cleanup (c);
  MHD_stop_daemon (d);
  MHD_socket_close_(fd);

  return 0;
}
예제 #10
0
/**
 * Create a listen socket, with noninheritable flag if possible.
 *
 * @param use_ipv6 if set to non-zero IPv6 is used
 * @return created socket or MHD_INVALID_SOCKET in case of errors
 */
MHD_socket
MHD_socket_create_listen_ (int use_ipv6)
{
  int domain;
  MHD_socket fd;
  int cloexec_set;
#if defined(OSX) && defined(SOL_SOCKET) && defined(SO_NOSIGPIPE)
  static const int on_val = 1;
#endif

#ifdef HAVE_INET6
  domain = (use_ipv6) ? PF_INET6 : PF_INET;
#else  /* ! HAVE_INET6 */
  if (use_ipv6)
    return MHD_INVALID_SOCKET;
  domain = PF_INET;
#endif /* ! HAVE_INET6 */

#if defined(MHD_POSIX_SOCKETS) && defined(SOCK_CLOEXEC)
  fd = socket (domain,
               SOCK_STREAM | SOCK_CLOEXEC,
               0);
  cloexec_set = !0;
#elif defined(MHD_WINSOCK_SOCKETS) && defined (WSA_FLAG_NO_HANDLE_INHERIT)
  fd = WSASocketW (domain,
                   SOCK_STREAM,
                   0,
                   NULL,
                   0,
                   WSA_FLAG_NO_HANDLE_INHERIT);
  cloexec_set = !0;
#else  /* !SOCK_CLOEXEC */
  fd = MHD_INVALID_SOCKET;
#endif /* !SOCK_CLOEXEC */
  if (MHD_INVALID_SOCKET == fd)
    {
      fd = socket (domain,
                   SOCK_STREAM,
                   0);
      cloexec_set = 0;
    }
  if (MHD_INVALID_SOCKET == fd)
    return MHD_INVALID_SOCKET;
#if defined(OSX) && defined(SOL_SOCKET) && defined(SO_NOSIGPIPE)
  if(0 != setsockopt(fd,
                     SOL_SOCKET,
                     SO_NOSIGPIPE,
                     &on_val,
                     sizeof (on_val)))
    {
      int err = MHD_socket_get_error_ ();
      MHD_socket_close_ (fd);
      MHD_socket_fset_error_ (err);
      return MHD_INVALID_SOCKET;
    }
#endif
  if (! cloexec_set)
    (void) MHD_socket_noninheritable_ (fd);

  return fd;
}
예제 #11
0
/*
 * Fetches the resource denoted by |uri|.
 */
static void fetch_uri(const struct URI *uri)
{
  spdylay_session_callbacks callbacks;
  int fd;
  struct Request req;
  struct Connection connection;
  int rv;
  nfds_t npollfds = 1;
  struct pollfd pollfds[1];
  uint16_t spdy_proto_version = 3;

  request_init(&req, uri);

  setup_spdylay_callbacks(&callbacks);

  /* Establish connection and setup SSL */
  fd = connect_to(req.host, req.port);
  if (-1 == fd)
    abort ();

  connection.fd = fd;
  connection.want_io = IO_NONE;

  /* Here make file descriptor non-block */
  make_non_block(fd);
  set_tcp_nodelay(fd);

  printf("[INFO] SPDY protocol version = %d\n", spdy_proto_version);
  rv = spdylay_session_client_new(&connection.session, spdy_proto_version,
                                  &callbacks, &connection);
  if(rv != 0) {
    diec("spdylay_session_client_new", rv);
  }

  /* Submit the HTTP request to the outbound queue. */
  submit_request(&connection, &req);

  pollfds[0].fd = fd;
  ctl_poll(pollfds, &connection);

  /* Event loop */
  while(spdylay_session_want_read(connection.session) ||
        spdylay_session_want_write(connection.session)) {
    int nfds = poll(pollfds, npollfds, -1);
    if(nfds == -1) {
      dief("poll", strerror(errno));
    }
    if(pollfds[0].revents & (POLLIN | POLLOUT)) {
      exec_io(&connection);
    }
    if((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
      die("Connection error");
    }
    ctl_poll(pollfds, &connection);
  }

  /* Resource cleanup */
  spdylay_session_del(connection.session);
  shutdown(fd, SHUT_WR);
  MHD_socket_close_(fd);
  request_free(&req);
}
예제 #12
0
/*
 * Fetches the resource denoted by |uri|.
 */
static void
fetch_uri(const struct URI *uri)
{
    spdylay_session_callbacks callbacks;
    int fd;
    SSL_CTX *ssl_ctx;
    SSL *ssl;
    struct Request req;
    struct Connection connection;
    int rv;
    nfds_t npollfds = 1;
    struct pollfd pollfds[1];
    uint16_t spdy_proto_version;

    request_init(&req, uri);

    setup_spdylay_callbacks(&callbacks);

    /* Establish connection and setup SSL */
    fd = connect_to(req.host, req.port);
    if (-1 == fd)
        abort ();
    ssl_ctx = SSL_CTX_new(SSLv23_client_method());
    if(ssl_ctx == NULL) {
        dief("SSL_CTX_new", ERR_error_string(ERR_get_error(), NULL));
    }
    init_ssl_ctx(ssl_ctx, &spdy_proto_version);
    ssl = SSL_new(ssl_ctx);
    if(ssl == NULL) {
        dief("SSL_new", ERR_error_string(ERR_get_error(), NULL));
    }
    /* To simplify the program, we perform SSL/TLS handshake in blocking
       I/O. */
    ssl_handshake(ssl, fd);

    connection.ssl = ssl;
    connection.want_io = IO_NONE;

    /* Here make file descriptor non-block */
    make_non_block(fd);
    set_tcp_nodelay(fd);

    spdylay_printf("[INFO] SPDY protocol version = %d\n", spdy_proto_version);
    rv = spdylay_session_client_new(&connection.session, spdy_proto_version,
                                    &callbacks, &connection);
    if(rv != 0) {
        diec("spdylay_session_client_new", rv);
    }

    /* Submit the HTTP request to the outbound queue. */
    submit_request(&connection, &req);

    pollfds[0].fd = fd;
    ctl_poll(pollfds, &connection);

    /* Event loop */
    while(spdylay_session_want_read(connection.session) ||
            spdylay_session_want_write(connection.session)) {
        int nfds = poll(pollfds, npollfds, -1);
        if(nfds == -1) {
            dief("poll", strerror(errno));
        }
        if(pollfds[0].revents & (POLLIN | POLLOUT)) {
            exec_io(&connection);
        }
        if((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
            die("Connection error");
        }
        ctl_poll(pollfds, &connection);
    }

    /* Resource cleanup */
    spdylay_session_del(connection.session);
    SSL_shutdown(ssl);
    SSL_free(ssl);
    SSL_CTX_free(ssl_ctx);
    shutdown(fd, SHUT_WR);
    MHD_socket_close_ (fd);
    request_free(&req);
}
예제 #13
0
/*
 * Fetches the resource denoted by |uri|.
 */
struct SPDY_Connection *
spdy_connect(const struct URI *uri,
             uint16_t port,
             bool is_tls)
{
  spdylay_session_callbacks callbacks;
  int fd;
  SSL *ssl=NULL;
  struct SPDY_Connection * connection = NULL;
  int rv;

  spdy_setup_spdylay_callbacks(&callbacks);

  /* Establish connection and setup SSL */
  PRINT_INFO2("connecting to %s:%i", uri->host, port);
  fd = spdy_socket_connect_to(uri->host, port);
  if(fd == -1)
  {
    PRINT_INFO("Could not open file descriptor");
    return NULL;
  }

  if(is_tls)
  {
    ssl = SSL_new(glob_opt.ssl_ctx);
    if(ssl == NULL) {
      spdy_dief("SSL_new", ERR_error_string(ERR_get_error(), NULL));
    }

    //TODO non-blocking
    /* To simplify the program, we perform SSL/TLS handshake in blocking
       I/O. */
    glob_opt.spdy_proto_version = 0;
    rv = spdy_ssl_handshake(ssl, fd);
    if(rv <= 0 || (glob_opt.spdy_proto_version != 3 && glob_opt.spdy_proto_version != 2))
    {
      PRINT_INFO("Closing SSL");
      //no spdy on the other side
      goto free_and_fail;
    }
  }
  else
  {
    glob_opt.spdy_proto_version = 3;
  }

  if(NULL == (connection = au_malloc(sizeof(struct SPDY_Connection))))
    goto free_and_fail;

  connection->is_tls = is_tls;
  connection->ssl = ssl;
  connection->want_io = IO_NONE;
  if(NULL == (connection->host = strdup(uri->host)))
    goto free_and_fail;

  /* Here make file descriptor non-block */
  spdy_socket_make_non_block(fd);
  spdy_socket_set_tcp_nodelay(fd);

  PRINT_INFO2("[INFO] SPDY protocol version = %d\n", glob_opt.spdy_proto_version);
  rv = spdylay_session_client_new(&(connection->session), glob_opt.spdy_proto_version,
                                  &callbacks, connection);
  if(rv != 0) {
    spdy_diec("spdylay_session_client_new", rv);
  }

  connection->fd = fd;

	return connection;

	//for GOTO
	free_and_fail:
  if(NULL != connection)
  {
    free(connection->host);
    free(connection);
  }

  if(is_tls)
    SSL_shutdown(ssl);

  MHD_socket_close_ (fd);

  if(is_tls)
    SSL_free(ssl);

  return NULL;
}