Author: rhuijben Date: Wed Nov 18 18:28:40 2015 New Revision: 1715033 URL: http://svn.apache.org/viewvc?rev=1715033&view=rev Log: Use a few recently added bucket features to simplify the ssltunnel creation code. Store the unencrypted streams in the regular locations to allow reusing the write code.
* outgoing.c (serf__conn_update_pollset): Use pump state directly instead of cached value. (serf__connection_pre_cleanup): Remove ssltunnel handling. (prepare_conn_streams): Remove output arguments. (serf__connection_flush): Simplify. (write_to_connection, read_from_connection): Simplify. * serf_private.h (serf__connection_state_t): Remove unnecessary closed state. (serf_connection_t): Remove ssltunnel. * ssltunnel.c Modified: serf/trunk/outgoing.c serf/trunk/serf_private.h serf/trunk/ssltunnel.c Modified: serf/trunk/outgoing.c URL: http://svn.apache.org/viewvc/serf/trunk/outgoing.c?rev=1715033&r1=1715032&r2=1715033&view=diff ============================================================================== --- serf/trunk/outgoing.c (original) +++ serf/trunk/outgoing.c Wed Nov 18 18:28:40 2015 @@ -152,7 +152,7 @@ apr_status_t serf__conn_update_pollset(s from the aggregate to requests that are done. */ data_waiting = serf_pump__data_pending(&conn->pump) - && (conn->state != SERF_CONN_CLOSING); + && !conn->pump.done_writing; if (data_waiting) { desc.reqevents |= APR_POLLOUT; @@ -229,11 +229,6 @@ void serf__connection_pre_cleanup(serf_c serf_pump__done(&conn->pump); - if (conn->ssltunnel_ostream != NULL) { - serf_bucket_destroy(conn->ssltunnel_ostream); - conn->ssltunnel_ostream = NULL; - } - /* Tell all written request that they are free to destroy themselves */ rq = conn->written_reqs; while (rq != NULL) { @@ -313,9 +308,7 @@ static apr_status_t do_conn_setup(serf_c [en/de]cryption. */ -static apr_status_t prepare_conn_streams(serf_connection_t *conn, - serf_bucket_t **ostreamt, - serf_bucket_t **ostreamh) +static apr_status_t prepare_conn_streams(serf_connection_t *conn) { apr_status_t status; @@ -330,28 +323,6 @@ static apr_status_t prepare_conn_streams return status; } } - *ostreamt = conn->pump.ostream_tail; - *ostreamh = conn->pump.ostream_head; - } else if (conn->state == SERF_CONN_SETUP_SSLTUNNEL) { - - /* SSL tunnel needed and not set up yet, get a direct unencrypted - stream for this socket */ - if (conn->pump.stream == NULL) { - conn->pump.stream = - serf_context_bucket_socket_create(conn->ctx, - conn->skt, - conn->allocator); - } - - /* Don't create the ostream bucket chain including the ssl_encrypt - bucket yet. This ensure the CONNECT request is sent unencrypted - to the proxy. */ - *ostreamt = *ostreamh = conn->ssltunnel_ostream; - } else { - /* SERF_CONN_CLOSING or SERF_CONN_INIT */ - - *ostreamt = conn->pump.ostream_tail; - *ostreamh = conn->pump.ostream_head; } return APR_SUCCESS; @@ -637,30 +608,7 @@ static apr_status_t reset_connection(ser apr_status_t serf__connection_flush(serf_connection_t *conn, bool fetch_new) { - apr_status_t status; - serf_bucket_t *tmp_bkt = NULL; - - if (fetch_new) { - serf_bucket_t *ostreamh, *ostreamt; - - status = prepare_conn_streams(conn, &ostreamt, &ostreamh); - if (status) - return status; - - tmp_bkt = conn->pump.ostream_head; - conn->pump.ostream_head = ostreamh; - } - - status = serf_pump__write(&conn->pump, fetch_new); - - if (fetch_new) { - conn->pump.ostream_head = tmp_bkt; - } - - if (conn->pump.done_writing) - conn->state = SERF_CONN_CLOSING; - - return status; + return serf_pump__write(&conn->pump, fetch_new); } /* Implements serf_bucket_event_callback_t and is called (potentially @@ -750,8 +698,6 @@ static apr_status_t write_to_connection( serf_request_t *request; apr_status_t status; apr_status_t read_status; - serf_bucket_t *ostreamt; - serf_bucket_t *ostreamh; /* If we have unwritten data in iovecs, then write what we can directly. */ @@ -805,7 +751,7 @@ static apr_status_t write_to_connection( return APR_SUCCESS; } - status = prepare_conn_streams(conn, &ostreamt, &ostreamh); + status = prepare_conn_streams(conn); if (status) { return status; } @@ -831,7 +777,8 @@ static apr_status_t write_to_connection( request_writing_done, request_writing_finished, conn->allocator); - serf_bucket_aggregate_append(ostreamt, event_bucket); + serf_bucket_aggregate_append(conn->pump.ostream_tail, + event_bucket); } /* If we got some data, then deliver it. */ @@ -902,12 +849,10 @@ static apr_status_t read_from_connection /* Invoke response handlers until we have no more work. */ while (1) { - serf_bucket_t *dummy1, *dummy2; - apr_pool_clear(tmppool); /* Only interested in the input stream here. */ - status = prepare_conn_streams(conn, &dummy1, &dummy2); + status = prepare_conn_streams(conn); if (status) { goto error; } Modified: serf/trunk/serf_private.h URL: http://svn.apache.org/viewvc/serf/trunk/serf_private.h?rev=1715033&r1=1715032&r2=1715033&view=diff ============================================================================== --- serf/trunk/serf_private.h (original) +++ serf/trunk/serf_private.h Wed Nov 18 18:28:40 2015 @@ -460,8 +460,6 @@ typedef enum { SERF_CONN_INIT, /* no socket created yet */ SERF_CONN_SETUP_SSLTUNNEL, /* ssl tunnel being setup, no requests sent */ SERF_CONN_CONNECTED, /* conn is ready to send requests */ - SERF_CONN_CLOSING /* conn is closing, no more requests, - start a new socket */ } serf__connection_state_t; struct serf_connection_t { @@ -502,9 +500,6 @@ struct serf_connection_t { serf_response_handler_t async_handler; void *async_handler_baton; - /* Aggregate bucket used to send the CONNECT request. */ - serf_bucket_t *ssltunnel_ostream; - /* The list of requests that are written but no response has been received yet. */ serf_request_t *written_reqs; Modified: serf/trunk/ssltunnel.c URL: http://svn.apache.org/viewvc/serf/trunk/ssltunnel.c?rev=1715033&r1=1715032&r2=1715033&view=diff ============================================================================== --- serf/trunk/ssltunnel.c (original) +++ serf/trunk/ssltunnel.c Wed Nov 18 18:28:40 2015 @@ -105,14 +105,26 @@ static apr_status_t handle_response(serf serf_bucket_t *hdrs; const char *val; - conn->state = SERF_CONN_CONNECTED; + /* Body is supposed to be empty. */ apr_pool_destroy(ctx->pool); - serf_bucket_destroy(conn->ssltunnel_ostream); - conn->ssltunnel_ostream = NULL; + + /* If there was outgoing data waiting, we can't use it + any more. It's lifetime is limited by ostream_head + ... (There shouldn't be any, as we disabled pipelining) */ + conn->pump.vec_len = 0; + + conn->state = SERF_CONN_CONNECTED; + + /* Destroy the unencrypted head */ + serf_bucket_destroy(conn->pump.ostream_head); + conn->pump.ostream_head = NULL; + /* And the unencrypted stream */ serf_bucket_destroy(conn->pump.stream); conn->pump.stream = NULL; + + /* New ones will be created in the normal setup code */ ctx = NULL; serf__log(LOGLVL_INFO, LOGCOMP_CONN, __FILE__, conn->config, @@ -170,11 +182,18 @@ static apr_status_t setup_request(serf_r return APR_SUCCESS; } -static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket) +apr_status_t ssltunnel_ostream_destroyed(void *baton, + apr_uint64_t bytes_read) { serf_connection_t *conn = baton; - conn->pump.hit_eof = true; - return APR_EAGAIN; + + if (conn->state == SERF_CONN_SETUP_SSLTUNNEL) { + /* Connection is destroyed while not connected. + Destroy tail to avoid leaking memory */ + serf_bucket_destroy(conn->pump.ostream_tail); + conn->pump.ostream_tail = NULL; + } + return APR_SUCCESS; } /* SSL tunnel is needed, push a CONNECT request on the connection. */ @@ -182,7 +201,7 @@ apr_status_t serf__ssltunnel_connect(ser { req_ctx_t *ctx; apr_pool_t *ssltunnel_pool; - serf_bucket_t *ssltunnel_ostream; + serf_bucket_t *stream, *ostream; apr_pool_create(&ssltunnel_pool, conn->pool); @@ -191,10 +210,29 @@ apr_status_t serf__ssltunnel_connect(ser ctx->uri = apr_psprintf(ctx->pool, "%s:%d", conn->host_info.hostname, conn->host_info.port); - ssltunnel_ostream = serf_bucket_aggregate_create(conn->allocator); - serf_bucket_aggregate_hold_open(ssltunnel_ostream, detect_eof, conn); + /* We want to setup a plain http request to be sent before the + actual streams are connected... */ + serf_pump__prepare_setup(&conn->pump); + + /* Ok, we now have a head and a tail bucket. The tail has pump + events attached to it so we don't want to destroy that one + later. Let's create a barrier around it and manage the lifetime + ourself. */ + + ostream = serf_bucket_barrier_create(conn->pump.ostream_tail, + conn->allocator); + + ostream = serf__bucket_event_create(ostream, + conn, NULL, NULL, + ssltunnel_ostream_destroyed, + conn->allocator); + + stream = serf_context_bucket_socket_create(conn->ctx, + conn->skt, + conn->allocator); + + serf_pump__complete_setup(&conn->pump, stream, ostream); - conn->ssltunnel_ostream = ssltunnel_ostream; serf__ssltunnel_request_create(conn, setup_request,