static CURLcode http2_disconnect(struct connectdata *conn, bool dead_connection) { struct HTTP *http = conn->data->req.protop; struct http_conn *c = &conn->proto.httpc; (void)dead_connection; DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); nghttp2_session_del(c->h2); Curl_safefree(c->inbuf); if(http) { Curl_add_buffer_free(http->header_recvbuf); http->header_recvbuf = NULL; /* clear the pointer */ for(; http->push_headers_used > 0; --http->push_headers_used) { free(http->push_headers[http->push_headers_used - 1]); } free(http->push_headers); http->push_headers = NULL; } DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); return CURLE_OK; }
void h2_session_destroy(h2_session *session) { AP_DEBUG_ASSERT(session); if (session->mplx) { h2_mplx_release_and_join(session->mplx, session->iowait); session->mplx = NULL; } if (session->streams) { if (h2_stream_set_size(session->streams)) { ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c, "h2_session(%ld): destroy, %d streams open", session->id, (int)h2_stream_set_size(session->streams)); } h2_stream_set_destroy(session->streams); session->streams = NULL; } if (session->ngh2) { nghttp2_session_del(session->ngh2); session->ngh2 = NULL; } h2_conn_io_destroy(&session->io); if (session->iowait) { apr_thread_cond_destroy(session->iowait); session->iowait = NULL; } if (session->pool) { apr_pool_destroy(session->pool); } }
static void cleanup_session(h2session *h2sess) { session *sess = CONTAINER(h2sess, session, S); nghttp2_session_del(sess->S.h2sess); event_free(sess->pingtimer); bufferevent_free(sess->S.bev); free(sess); }
static CURLcode http2_disconnect(struct connectdata *conn, bool dead_connection) { struct http_conn *c = &conn->proto.httpc; (void)dead_connection; DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n")); nghttp2_session_del(c->h2); Curl_safefree(c->inbuf); Curl_hash_destroy(&c->streamsh); DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n")); return CURLE_OK; }
static void delete_http2_session_data(http2_session_data *session_data) { http2_stream_data *stream_data; SSL *ssl = bufferevent_openssl_get_ssl(session_data->bev); fprintf(stderr, "%s disconnected\n", session_data->client_addr); if (ssl) { SSL_shutdown(ssl); } bufferevent_free(session_data->bev); nghttp2_session_del(session_data->session); for (stream_data = session_data->root.next; stream_data;) { http2_stream_data *next = stream_data->next; delete_http2_stream_data(stream_data); stream_data = next; } free(session_data->client_addr); free(session_data); }
static void delete_http2_session_data(http2_session_data *session_data) { SSL *ssl = bufferevent_openssl_get_ssl(session_data->bev); if (ssl) { SSL_shutdown(ssl); } bufferevent_free(session_data->bev); session_data->bev = NULL; evdns_base_free(session_data->dnsbase, 1); session_data->dnsbase = NULL; nghttp2_session_del(session_data->session); session_data->session = NULL; if (session_data->stream_data) { delete_http2_stream_data(session_data->stream_data); session_data->stream_data = NULL; } free(session_data); }
static CURLcode http2_disconnect(struct connectdata *conn, bool dead_connection) { struct http_conn *httpc = &conn->proto.httpc; (void)dead_connection; infof(conn->data, "HTTP/2 DISCONNECT starts now\n"); nghttp2_session_del(httpc->h2); Curl_safefree(httpc->header_recvbuf->buffer); Curl_safefree(httpc->header_recvbuf); Curl_safefree(httpc->inbuf); infof(conn->data, "HTTP/2 DISCONNECT done\n"); return CURLE_OK; }
static void run_nghttp2_session_send_server(void) { nghttp2_session *session; nghttp2_session_callbacks *callbacks; int rv; const uint8_t *txdata; ssize_t txdatalen; const uint8_t origin[] = "nghttp2.org"; const uint8_t altsvc_field_value[] = "h2=\":443\""; rv = nghttp2_session_callbacks_new(&callbacks); if (rv != 0) { return; } rv = nghttp2_session_server_new3(&session, callbacks, NULL, NULL, nghttp2_mem_fm()); nghttp2_session_callbacks_del(callbacks); if (rv != 0) { return; } rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin, sizeof(origin) - 1, altsvc_field_value, sizeof(altsvc_field_value) - 1); if (rv != 0) { goto fail; } txdatalen = nghttp2_session_mem_send(session, &txdata); if (txdatalen < 0) { goto fail; } fail: nghttp2_session_del(session); }
int nghttp2client_connect(httpclient *pclient, char *url, int port, http2_ssl_custom_conf_t *ssl_config, const struct URI *uri) { struct Connection connection; nghttp2_session_callbacks *callbacks; int rv; int ret = 0; struct Request req; request_init(&req, uri); if (0 == (ret = nghttp2s_client_conn(pclient, url, port, ssl_config))) { pclient->remote_port = HTTPS_PORT; nghttp2_socket.fd = pclient->fd.fd; } else { printf("https_client_conn failed %d\r\n", ret); /* Resource cleanup */ mbedtls_ssl_close_notify( &(pclient->ssl) ); mbedtls_net_free( &pclient->fd ); mbedtls_x509_crt_free( &(ssl_config->verify_source.cacertl) ); mbedtls_ssl_free( &(pclient->ssl) ); mbedtls_ssl_config_free( &(ssl_config->conf) ); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); request_free(&req); return ret; } //set_tcp_nodelay(nghttp2_socket.fd); connection.ssl = &(pclient->ssl); rv = nghttp2_session_callbacks_new(&callbacks); if (rv != 0) { printf("nghttp2_session_callbacks_new1 %d", rv); } setup_nghttp2_callbacks(callbacks); rv = nghttp2_session_client_new(&connection.session, callbacks, &connection); nghttp2_session_callbacks_del(callbacks); if (rv != 0) { printf("nghttp2_session_client_new2 %d", rv); } nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0); /* Submit the HTTP request to the outbound queue. */ submit_request(&connection, &req); /* Event loop */ while (1) { int read_flag = 0; int write_flag = 0; write_flag = nghttp2_session_want_write(connection.session); if (write_flag) { int rv = nghttp2_session_send(connection.session); printf("nghttp2_session_send %d\r\n", rv); if (rv < 0) { write_flag = 0; //break; } } read_flag = nghttp2_session_want_read(connection.session); if (read_flag) { int rv = nghttp2_session_recv(connection.session); printf("nghttp2_session_recv %d\r\n", rv); if (rv < 0) { read_flag = 0; //break; } } printf("write_flag = %d, read_flag = %d\r\n", write_flag, read_flag); if ((read_flag == 0) && (write_flag == 0)) { printf("No active stream!\r\n"); break; } } /* Resource cleanup */ nghttp2_session_del(connection.session); mbedtls_ssl_close_notify( &(pclient->ssl) ); mbedtls_net_free( &pclient->fd ); mbedtls_x509_crt_free( &(ssl_config->verify_source.cacertl) ); mbedtls_ssl_free( &(pclient->ssl) ); mbedtls_ssl_config_free( &(ssl_config->conf) ); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); request_free(&req); return 0; }
void h2_session_destroy(h2_session *session) { assert(session); if (session->streams) { if (h2_stream_set_size(session->streams)) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, "h2_session(%ld): destroy, %ld streams open", session->id, h2_stream_set_size(session->streams)); /* destroy all sessions, join all existing tasks */ h2_stream_set_iter(session->streams, close_active_iter, session); ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, "h2_session(%ld): destroy, %ld streams remain", session->id, h2_stream_set_size(session->streams)); } h2_stream_set_destroy(session->streams); session->streams = NULL; } if (session->zombies) { if (h2_stream_set_size(session->zombies)) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, "h2_session(%ld): destroy, %ld zombie streams", session->id, h2_stream_set_size(session->zombies)); /* destroy all zombies, join all existing tasks */ h2_stream_set_iter(session->zombies, close_zombie_iter, session); ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, "h2_session(%ld): destroy, %ld zombies remain", session->id, h2_stream_set_size(session->zombies)); } h2_stream_set_destroy(session->zombies); session->zombies = NULL; } if (session->ngh2) { nghttp2_session_del(session->ngh2); session->ngh2 = NULL; } if (session->mplx) { h2_mplx_destroy(session->mplx); session->mplx = NULL; } h2_conn_io_destroy(&session->io); if (session->iowait) { apr_thread_cond_destroy(session->iowait); session->iowait = NULL; } apr_allocator_t *allocator = session->allocator; if (session->alock) { if (allocator) { apr_allocator_mutex_set(allocator, session->alock); } apr_thread_mutex_destroy(session->alock); session->alock = NULL; } if (session->pool) { apr_pool_destroy(session->pool); } if (allocator) { apr_allocator_destroy(allocator); } }
/* * Fetches the resource denoted by |uri|. */ static void fetch_uri(const struct URI *uri) { nghttp2_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]; request_init(&req, uri); /* Establish connection and setup SSL */ fd = connect_to(req.host, req.port); if (fd == -1) { die("Could not open file descriptor"); } 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); 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] SSL/TLS handshake completed\n"); rv = nghttp2_session_callbacks_new(&callbacks); if (rv != 0) { diec("nghttp2_session_callbacks_new", rv); } setup_nghttp2_callbacks(callbacks); rv = nghttp2_session_client_new(&connection.session, callbacks, &connection); nghttp2_session_callbacks_del(callbacks); if (rv != 0) { diec("nghttp2_session_client_new", rv); } rv = nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0); if (rv != 0) { diec("nghttp2_submit_settings", rv); } /* Submit the HTTP request to the outbound queue. */ submit_request(&connection, &req); pollfds[0].fd = fd; ctl_poll(pollfds, &connection); /* Event loop */ while (nghttp2_session_want_read(connection.session) || nghttp2_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 */ nghttp2_session_del(connection.session); SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ssl_ctx); shutdown(fd, SHUT_WR); close(fd); request_free(&req); }
static void run_nghttp2_session_recv(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; nghttp2_hd_deflater deflater; nghttp2_frame frame; nghttp2_bufs bufs; nghttp2_nv nv[] = {MAKE_NV(":authority", "example.org"), MAKE_NV(":scheme", "https")}; nghttp2_settings_entry iv[2]; my_user_data ud; data_feed df; int rv; nghttp2_nv *nva; size_t nvlen; rv = frame_pack_bufs_init(&bufs); if (rv != 0) { return; } memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.recv_callback = data_feed_recv_callback; ud.df = &df; nghttp2_failmalloc_pause(); nvlen = ARRLEN(nv); nghttp2_nv_array_copy(&nva, nv, nvlen, nghttp2_mem_fm()); nghttp2_hd_deflate_init(&deflater, nghttp2_mem_fm()); nghttp2_session_server_new3(&session, &callbacks, &ud, NULL, nghttp2_mem_fm()); nghttp2_failmalloc_unpause(); /* HEADERS */ nghttp2_failmalloc_pause(); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen); nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); nghttp2_frame_headers_free(&frame.headers, nghttp2_mem_fm()); data_feed_init(&df, &bufs); nghttp2_bufs_reset(&bufs); nghttp2_failmalloc_unpause(); rv = nghttp2_session_recv(session); if (rv != 0) { goto fail; } /* PING */ nghttp2_failmalloc_pause(); nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL); nghttp2_frame_pack_ping(&bufs, &frame.ping); nghttp2_frame_ping_free(&frame.ping); data_feed_init(&df, &bufs); nghttp2_bufs_reset(&bufs); nghttp2_failmalloc_unpause(); rv = nghttp2_session_recv(session); if (rv != 0) { goto fail; } /* RST_STREAM */ nghttp2_failmalloc_pause(); nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR); nghttp2_frame_pack_rst_stream(&bufs, &frame.rst_stream); nghttp2_frame_rst_stream_free(&frame.rst_stream); nghttp2_bufs_reset(&bufs); nghttp2_failmalloc_unpause(); rv = nghttp2_session_recv(session); if (rv != 0) { goto fail; } /* SETTINGS */ nghttp2_failmalloc_pause(); iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; iv[0].value = 4096; iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[1].value = 100; nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, nghttp2_frame_iv_copy(iv, 2, nghttp2_mem_fm()), 2); nghttp2_frame_pack_settings(&bufs, &frame.settings); nghttp2_frame_settings_free(&frame.settings, nghttp2_mem_fm()); nghttp2_bufs_reset(&bufs); nghttp2_failmalloc_unpause(); rv = nghttp2_session_recv(session); if (rv != 0) { goto fail; } fail: nghttp2_bufs_free(&bufs); nghttp2_session_del(session); nghttp2_hd_deflate_free(&deflater); }
static void run_nghttp2_session_send(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; nghttp2_nv nv[] = {MAKE_NV(":host", "example.org"), MAKE_NV(":scheme", "https")}; nghttp2_data_provider data_prd; nghttp2_settings_entry iv[2]; my_user_data ud; int rv; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 64 * 1024; iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; iv[0].value = 4096; iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[1].value = 100; rv = nghttp2_session_client_new3(&session, &callbacks, &ud, NULL, nghttp2_mem_fm()); if (rv != 0) { goto client_new_fail; } rv = nghttp2_submit_request(session, NULL, nv, ARRLEN(nv), &data_prd, NULL); if (rv < 0) { goto fail; } rv = nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, nv, ARRLEN(nv), NULL); if (rv < 0) { goto fail; } rv = nghttp2_session_send(session); if (rv != 0) { goto fail; } /* The HEADERS submitted by the previous nghttp2_submit_headers will have stream ID 3. Send HEADERS to that stream. */ rv = nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, NULL, nv, ARRLEN(nv), NULL); if (rv != 0) { goto fail; } rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 3, &data_prd); if (rv != 0) { goto fail; } rv = nghttp2_session_send(session); if (rv != 0) { goto fail; } rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 3, NGHTTP2_CANCEL); if (rv != 0) { goto fail; } rv = nghttp2_session_send(session); if (rv != 0) { goto fail; } /* Sending against half-closed stream */ rv = nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, NULL, nv, ARRLEN(nv), NULL); if (rv != 0) { goto fail; } rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 3, &data_prd); if (rv != 0) { goto fail; } rv = nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL); if (rv != 0) { goto fail; } rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2); if (rv != 0) { goto fail; } rv = nghttp2_session_send(session); if (rv != 0) { goto fail; } rv = nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 100, NGHTTP2_NO_ERROR, NULL, 0); if (rv != 0) { goto fail; } rv = nghttp2_session_send(session); if (rv != 0) { goto fail; } fail: nghttp2_session_del(session); client_new_fail:; }