void spdy_free_connection(struct SPDY_Connection * connection) { struct Proxy *proxy; struct Proxy *proxy_next; if(NULL != connection) { for(proxy = connection->proxies_head; NULL != proxy; proxy=proxy_next) { proxy_next = proxy->next; DLL_remove(connection->proxies_head, connection->proxies_tail, proxy); proxy->spdy_active = false; proxy->spdy_error = true; PRINT_INFO2("spdy_free_connection for id %i", proxy->id); if(!proxy->http_active) { free_proxy(proxy); } } spdylay_session_del(connection->session); SSL_free(connection->ssl); free(connection->host); free(connection); //connection->session = NULL; } }
/* * 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); 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); }
static void run_spdylay_session_recv(void) { spdylay_session *session; spdylay_session_callbacks callbacks; spdylay_zlib deflater; spdylay_frame frame; uint8_t *buf = NULL, *nvbuf = NULL; size_t buflen = 0, nvbuflen = 0; ssize_t framelen; const char *nv[] = { ":host", "example.org", ":scheme", "https", NULL }; spdylay_settings_entry iv[2]; spdylay_mem_chunk proof; spdylay_mem_chunk *certs; size_t ncerts; my_user_data ud; data_feed df; int rv; memset(&callbacks, 0, sizeof(spdylay_session_callbacks)); callbacks.recv_callback = data_feed_recv_callback; ud.df = &df; spdylay_failmalloc_pause(); spdylay_zlib_deflate_hd_init(&deflater, SPDYLAY_PROTO_SPDY3); spdylay_session_server_new(&session, SPDYLAY_PROTO_SPDY3, &callbacks, &ud); spdylay_failmalloc_unpause(); /* SYN_STREAM */ spdylay_failmalloc_pause(); spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_PROTO_SPDY3, SPDYLAY_CTRL_FLAG_FIN, 1, 0, 2, spdylay_frame_nv_copy(nv)); framelen = spdylay_frame_pack_syn_stream(&buf, &buflen, &nvbuf, &nvbuflen, &frame.syn_stream, &deflater); spdylay_frame_syn_stream_free(&frame.syn_stream); data_feed_init(&df, buf, framelen); spdylay_failmalloc_unpause(); rv = spdylay_session_recv(session); if(rv != 0) { goto fail; } /* PING */ spdylay_failmalloc_pause(); spdylay_frame_ping_init(&frame.ping, SPDYLAY_PROTO_SPDY3, 1); framelen = spdylay_frame_pack_ping(&buf, &buflen, &frame.ping); spdylay_frame_ping_free(&frame.ping); data_feed_init(&df, buf, framelen); spdylay_failmalloc_unpause(); rv = spdylay_session_recv(session); if(rv != 0) { goto fail; } /* RST_STREAM */ spdylay_failmalloc_pause(); spdylay_frame_rst_stream_init(&frame.rst_stream, SPDYLAY_PROTO_SPDY3, 1, SPDYLAY_PROTOCOL_ERROR); framelen = spdylay_frame_pack_rst_stream(&buf, &buflen, &frame.rst_stream); spdylay_frame_rst_stream_free(&frame.rst_stream); spdylay_failmalloc_unpause(); rv = spdylay_session_recv(session); if(rv != 0) { goto fail; } /* SETTINGS */ spdylay_failmalloc_pause(); iv[0].settings_id = SPDYLAY_SETTINGS_UPLOAD_BANDWIDTH; iv[0].flags = SPDYLAY_ID_FLAG_SETTINGS_PERSIST_VALUE; iv[0].value = 256; iv[1].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS; iv[1].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE; iv[1].value = 100; spdylay_frame_settings_init(&frame.settings, SPDYLAY_PROTO_SPDY3, SPDYLAY_FLAG_SETTINGS_CLEAR_SETTINGS, spdylay_frame_iv_copy(iv, 2), 2); framelen = spdylay_frame_pack_settings(&buf, &buflen, &frame.settings); spdylay_frame_settings_free(&frame.settings); spdylay_failmalloc_unpause(); rv = spdylay_session_recv(session); if(rv != 0) { goto fail; } /* CREDENTIAL */ spdylay_failmalloc_pause(); proof.data = (uint8_t*)strcopy("PROOF"); proof.length = strlen("PROOF"); ncerts = 2; certs = malloc(sizeof(spdylay_mem_chunk)*ncerts); certs[0].data = (uint8_t*)strcopy("CERT0"); certs[0].length = strlen("CERT0"); certs[1].data = (uint8_t*)strcopy("CERT1"); certs[1].length = strlen("CERT1"); spdylay_frame_credential_init(&frame.credential, SPDYLAY_PROTO_SPDY3, 1, &proof, certs, ncerts); framelen = spdylay_frame_pack_credential(&buf, &buflen, &frame.credential); spdylay_frame_credential_free(&frame.credential); spdylay_failmalloc_unpause(); rv = spdylay_session_recv(session); if(rv != 0) { goto fail; } fail: free(buf); free(nvbuf); spdylay_session_del(session); spdylay_zlib_deflate_free(&deflater); }
static void run_spdylay_session_send(void) { spdylay_session *session; spdylay_session_callbacks callbacks; const char *nv[] = { ":host", "example.org", ":scheme", "https", NULL }; spdylay_data_provider data_prd; spdylay_settings_entry iv[2]; my_user_data ud; int rv; memset(&callbacks, 0, sizeof(spdylay_session_callbacks)); callbacks.send_callback = null_send_callback; callbacks.get_credential_ncerts = get_credential_ncerts; callbacks.get_credential_cert = get_credential_cert; callbacks.get_credential_proof = get_credential_proof; data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 64*1024; iv[0].settings_id = SPDYLAY_SETTINGS_UPLOAD_BANDWIDTH; iv[0].flags = SPDYLAY_ID_FLAG_SETTINGS_PERSIST_VALUE; iv[0].value = 256; iv[1].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS; iv[1].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE; iv[1].value = 100; rv = spdylay_session_client_new(&session, SPDYLAY_PROTO_SPDY3, &callbacks, &ud); if(rv != 0) { goto client_new_fail; } rv = spdylay_submit_request(session, 3, nv, &data_prd, NULL); if(rv != 0) { goto fail; } rv = spdylay_submit_syn_stream(session, SPDYLAY_CTRL_FLAG_NONE, 0, 3, nv, NULL); if(rv != 0) { goto fail; } rv = spdylay_session_send(session); if(rv != 0) { goto fail; } /* The SYN_STREAM submitted by the previous spdylay_submit_syn_stream will have stream ID 3. Send HEADERS to that stream. */ rv = spdylay_submit_headers(session, SPDYLAY_CTRL_FLAG_NONE, 3, nv); if(rv != 0) { goto fail; } rv = spdylay_submit_data(session, 3, SPDYLAY_DATA_FLAG_FIN, &data_prd); if(rv != 0) { goto fail; } rv = spdylay_session_send(session); if(rv != 0) { goto fail; } rv = spdylay_submit_rst_stream(session, 3, SPDYLAY_CANCEL); if(rv != 0) { goto fail; } rv = spdylay_session_send(session); if(rv != 0) { goto fail; } /* Sending against half-closed stream */ rv = spdylay_submit_headers(session, SPDYLAY_CTRL_FLAG_NONE, 3, nv); if(rv != 0) { goto fail; } rv = spdylay_submit_data(session, 3, SPDYLAY_DATA_FLAG_FIN, &data_prd); if(rv != 0) { goto fail; } rv = spdylay_submit_ping(session); if(rv != 0) { goto fail; } rv = spdylay_submit_settings(session, SPDYLAY_FLAG_SETTINGS_NONE, iv, 2); if(rv != 0) { goto fail; } rv = spdylay_session_send(session); if(rv != 0) { goto fail; } rv = spdylay_submit_goaway(session, SPDYLAY_GOAWAY_OK); if(rv != 0) { goto fail; } rv = spdylay_session_send(session); if(rv != 0) { goto fail; } fail: spdylay_session_del(session); client_new_fail: ; }
/* * 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); }