in src/outgoing.c [672:768]
static apr_status_t write_to_connection(serf_connection_t *conn)
{
/* Keep reading and sending until we run out of stuff to read, or
* writing would block.
*/
while (1) {
serf_request_t *request;
apr_status_t status;
apr_status_t read_status;
/* If we have unwritten data in iovecs, then write what we can
directly. */
status = serf__connection_flush(conn, FALSE);
if (APR_STATUS_IS_EAGAIN(status))
return APR_SUCCESS;
else if (status)
return status;
/* If we're setting up an ssl tunnel, we can't send real requests
as yet, as they need to be encrypted and our encrypt buckets
aren't created yet as we still need to read the unencrypted
response of the CONNECT request. */
if (conn->state == SERF_CONN_SETUP_SSLTUNNEL
&& REQS_IN_PROGRESS(conn) > 0)
{
/* But flush out SSL data when necessary! */
status = serf__connection_flush(conn, TRUE);
if (APR_STATUS_IS_EAGAIN(status))
return APR_SUCCESS;
return status;
}
/* We try to limit the number of in-flight requests so that we
don't have to repeat too many if the connection drops.
This check matches that in serf__conn_update_pollset()
*/
if ((conn->probable_keepalive_limit &&
conn->completed_requests > conn->probable_keepalive_limit) ||
(conn->max_outstanding_requests &&
REQS_IN_PROGRESS(conn) >= conn->max_outstanding_requests)) {
serf_io__set_pollset_dirty(&conn->io);
/* backoff for now. */
return APR_SUCCESS;
}
/* We may need to move forward to a request which has something
* to write.
*/
if (!request_or_data_pending(&request, conn)) {
/* No more requests (with data) are registered with the
* connection, and no data is pending on the outgoing stream.
* Let's update the pollset so that we don't try to write to this
* socket again.
*/
serf_io__set_pollset_dirty(&conn->io);
return APR_SUCCESS;
}
if (request && request->writing == SERF_WRITING_NONE) {
serf_bucket_t *event_bucket;
if (request->req_bkt == NULL) {
read_status = serf__setup_request(request);
if (read_status) {
/* Something bad happened. Propagate any errors. */
return read_status;
}
}
request->writing = SERF_WRITING_STARTED;
/* And now add an event bucket to keep track of when the request
has been completely written */
event_bucket = serf__bucket_event_create(request->req_bkt,
request,
NULL,
request_writing_done,
request_writing_finished,
conn->allocator);
serf_pump__add_output(&conn->pump, event_bucket, false);
}
/* If we got some data, then deliver it. */
/* ### what to do if we got no data?? is that a problem? */
status = serf__connection_flush(conn, TRUE);
if (APR_STATUS_IS_EAGAIN(status))
return APR_SUCCESS;
else if (status)
return status;
}
/* NOTREACHED */
}