/* * 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); }
//static void fetch_uri(const struct URI *uri) static void * fetch_uri(void * arg) { 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; struct URI *uri = (struct URI *)arg; // typecast void * back to proper type request_init(&req, uri); setup_spdylay_callbacks(&callbacks); /* Establish connection and setup SSL */ fd = connect_to(req.host, req.port); 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); 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); close(fd); request_free(&req); }
/* * 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; }