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,