in src/outgoing.c [473:585]
static apr_status_t reset_connection(serf_connection_t *conn,
int requeue_requests)
{
serf_context_t *ctx = conn->ctx;
apr_status_t status;
serf_request_t *old_reqs;
serf__log(LOGLVL_DEBUG, LOGCOMP_CONN, __FILE__, conn->config,
"reset connection 0x%p\n", conn);
conn->probable_keepalive_limit = conn->completed_responses;
conn->completed_requests = 0;
conn->completed_responses = 0;
/* Clear the unwritten_reqs queue, so the application can requeue cancelled
requests on it for the new socket. */
old_reqs = conn->unwritten_reqs;
conn->unwritten_reqs = NULL;
conn->unwritten_reqs_tail = NULL;
serf__connection_pre_cleanup(conn);
if (conn->protocol_baton && conn->perform_pre_teardown)
conn->perform_pre_teardown(conn);
/* First, cancel all written requests for which we haven't received a
response yet. Inform the application that the request is cancelled,
so it can requeue them if needed. */
while (conn->written_reqs) {
serf__cancel_request(conn->written_reqs, &conn->written_reqs,
requeue_requests);
}
conn->written_reqs_tail = NULL;
/* Handle all outstanding unwritten requests.
TODO: what about a partially written request? */
while (old_reqs) {
/* If we haven't started to write the connection, bring it over
* unchanged to our new socket.
* Do not copy a CONNECT request to the new connection, the ssl tunnel
* setup code will create a new CONNECT request already.
*/
if (requeue_requests && (old_reqs->writing == SERF_WRITING_NONE) &&
!old_reqs->ssltunnel) {
serf_request_t *req = old_reqs;
old_reqs = old_reqs->next;
req->next = NULL;
serf__link_requests(&conn->unwritten_reqs,
&conn->unwritten_reqs_tail,
req);
}
else {
/* We don't want to requeue the request or this request was partially
written. Inform the application that the request is cancelled. */
serf__cancel_request(old_reqs, &old_reqs, requeue_requests);
}
}
/* Requests queue has been prepared for a new socket, close the old one. */
if (conn->skt != NULL) {
remove_connection(ctx, conn);
status = clean_skt(conn);
if (conn->closed != NULL) {
handle_conn_closed(conn, status);
}
}
if (conn->pump.stream != NULL) {
serf_bucket_destroy(conn->pump.stream);
conn->pump.stream = NULL;
}
/* Don't try to resume any writes */
conn->pump.vec_len = 0;
serf_io__set_pollset_dirty(&conn->io);
conn->state = SERF_CONN_INIT;
conn->pump.hit_eof = 0;
conn->connect_time = 0;
conn->latency = -1;
conn->pump.stop_writing = false;
conn->write_now = false;
/* conn->pipelining */
conn->framing_type = SERF_CONNECTION_FRAMING_TYPE_HTTP1;
if (conn->protocol_baton) {
conn->perform_teardown(conn);
conn->protocol_baton = NULL;
}
conn->perform_read = read_from_connection;
conn->perform_write = write_to_connection;
conn->perform_hangup = hangup_connection;
conn->perform_teardown = NULL;
conn->perform_pre_teardown = NULL;
conn->perform_cancel_request = NULL;
conn->perform_prioritize_request = NULL;
conn->status = APR_SUCCESS;
/* Let our context know that we've 'reset' the socket already. */
conn->seen_in_pollset |= APR_POLLHUP;
/* Recalculate the current list length */
conn->nr_of_written_reqs = 0;
conn->nr_of_unwritten_reqs = serf__req_list_length(conn->unwritten_reqs);
/* Found the connection. Closed it. All done. */
return APR_SUCCESS;
}