1 /* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <apr_pools.h>
18 #include <apr_version.h>
19 #include <apr_portable.h>
22 #include "serf_bucket_util.h"
24 #include "serf_private.h"
26 /* cleanup for sockets */
27 static apr_status_t clean_skt(void *data)
29 serf_connection_t *conn = data;
30 apr_status_t status = APR_SUCCESS;
33 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt, "cleanup - ");
34 status = apr_socket_close(conn->skt);
36 serf__log_nopref(SOCK_VERBOSE, "closed socket, status %d\n", status);
42 static apr_status_t clean_resp(void *data)
44 serf_request_t *request = data;
46 /* The request's RESPOOL is being cleared. */
48 /* If the response has allocated some buckets, then destroy them (since
49 the bucket may hold resources other than memory in RESPOOL). Also
50 make sure to set their fields to NULL so connection closure does
51 not attempt to free them again. */
52 if (request->resp_bkt) {
53 serf_bucket_destroy(request->resp_bkt);
54 request->resp_bkt = NULL;
56 if (request->req_bkt) {
57 serf_bucket_destroy(request->req_bkt);
58 request->req_bkt = NULL;
61 /* ### should we worry about debug stuff, like that performed in
62 ### destroy_request()? should we worry about calling req->handler
63 ### to notify this "cancellation" due to pool clearing? */
65 /* This pool just got cleared/destroyed. Don't try to destroy the pool
66 (again) when the request is canceled. */
67 request->respool = NULL;
72 /* cleanup for conns */
73 static apr_status_t clean_conn(void *data)
75 serf_connection_t *conn = data;
77 serf__log(CONN_VERBOSE, __FILE__, "cleaning up connection 0x%x\n",
79 serf_connection_close(conn);
84 /* Check if there is data waiting to be sent over the socket. This can happen
86 - The connection queue has atleast one request with unwritten data.
87 - All requests are written and the ssl layer wrote some data while reading
88 the response. This can happen when the server triggers a renegotiation,
89 e.g. after the first and only request on that connection was received.
90 Returns 1 if data is pending on CONN, NULL if not.
91 If NEXT_REQ is not NULL, it will be filled in with the next available request
92 with unwritten data. */
94 request_or_data_pending(serf_request_t **next_req, serf_connection_t *conn)
96 serf_request_t *request = conn->requests;
98 while (request != NULL && request->req_bkt == NULL &&
99 request->writing_started)
100 request = request->next;
105 if (request != NULL) {
107 } else if (conn->ostream_head) {
112 status = serf_bucket_peek(conn->ostream_head, &dummy,
114 if (!SERF_BUCKET_READ_ERROR(status) && len) {
115 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
116 "All requests written but still data pending.\n");
124 /* Update the pollset for this connection. We tweak the pollset based on
125 * whether we want to read and/or write, given conditions within the
126 * connection. If the connection is not (yet) in the pollset, then it
129 apr_status_t serf__conn_update_pollset(serf_connection_t *conn)
131 serf_context_t *ctx = conn->ctx;
133 apr_pollfd_t desc = { 0 };
139 /* Remove the socket from the poll set. */
140 desc.desc_type = APR_POLL_SOCKET;
141 desc.desc.s = conn->skt;
142 desc.reqevents = conn->reqevents;
144 status = ctx->pollset_rm(ctx->pollset_baton,
146 if (status && !APR_STATUS_IS_NOTFOUND(status))
149 /* Now put it back in with the correct read/write values. */
150 desc.reqevents = APR_POLLHUP | APR_POLLERR;
151 if (conn->requests &&
152 conn->state != SERF_CONN_INIT) {
153 /* If there are any outstanding events, then we want to read. */
154 /* ### not true. we only want to read IF we have sent some data */
155 desc.reqevents |= APR_POLLIN;
157 /* Don't write if OpenSSL told us that it needs to read data first. */
158 if (conn->stop_writing != 1) {
160 /* If the connection is not closing down and
161 * has unwritten data or
162 * there are any requests that still have buckets to write out,
163 * then we want to write.
166 conn->state != SERF_CONN_CLOSING)
167 desc.reqevents |= APR_POLLOUT;
170 if ((conn->probable_keepalive_limit &&
171 conn->completed_requests > conn->probable_keepalive_limit) ||
172 (conn->max_outstanding_requests &&
173 conn->completed_requests - conn->completed_responses >=
174 conn->max_outstanding_requests)) {
175 /* we wouldn't try to write any way right now. */
177 else if (request_or_data_pending(NULL, conn)) {
178 desc.reqevents |= APR_POLLOUT;
184 /* If we can have async responses, always look for something to read. */
185 if (conn->async_responses) {
186 desc.reqevents |= APR_POLLIN;
189 /* save our reqevents, so we can pass it in to remove later. */
190 conn->reqevents = desc.reqevents;
192 /* Note: even if we don't want to read/write this socket, we still
193 * want to poll it for hangups and errors.
195 return ctx->pollset_add(ctx->pollset_baton,
196 &desc, &conn->baton);
199 #ifdef SERF_DEBUG_BUCKET_USE
201 /* Make sure all response buckets were drained. */
202 static void check_buckets_drained(serf_connection_t *conn)
204 serf_request_t *request = conn->requests;
206 for ( ; request ; request = request->next ) {
207 if (request->resp_bkt != NULL) {
208 /* ### crap. can't do this. this allocator may have un-drained
209 * ### REQUEST buckets.
211 /* serf_debug__entered_loop(request->resp_bkt->allocator); */
212 /* ### for now, pretend we closed the conn (resets the tracking) */
213 serf_debug__closed_conn(request->resp_bkt->allocator);
220 static void destroy_ostream(serf_connection_t *conn)
222 if (conn->ostream_head != NULL) {
223 serf_bucket_destroy(conn->ostream_head);
224 conn->ostream_head = NULL;
225 conn->ostream_tail = NULL;
229 static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
231 serf_connection_t *conn = baton;
236 static apr_status_t do_conn_setup(serf_connection_t *conn)
239 serf_bucket_t *ostream;
241 if (conn->ostream_head == NULL) {
242 conn->ostream_head = serf_bucket_aggregate_create(conn->allocator);
245 if (conn->ostream_tail == NULL) {
246 conn->ostream_tail = serf__bucket_stream_create(conn->allocator,
251 ostream = conn->ostream_tail;
253 status = (*conn->setup)(conn->skt,
259 /* extra destroy here since it wasn't added to the head bucket yet. */
260 serf_bucket_destroy(conn->ostream_tail);
261 destroy_ostream(conn);
265 serf_bucket_aggregate_append(conn->ostream_head,
271 /* Set up the input and output stream buckets.
272 When a tunnel over an http proxy is needed, create a socket bucket and
273 empty aggregate bucket for sending and receiving unencrypted requests
276 After the tunnel is there, or no tunnel was needed, ask the application
277 to create the input and output buckets, which should take care of the
281 static apr_status_t prepare_conn_streams(serf_connection_t *conn,
282 serf_bucket_t **istream,
283 serf_bucket_t **ostreamt,
284 serf_bucket_t **ostreamh)
288 if (conn->stream == NULL) {
289 conn->latency = apr_time_now() - conn->connect_time;
292 /* Do we need a SSL tunnel first? */
293 if (conn->state == SERF_CONN_CONNECTED) {
294 /* If the connection does not have an associated bucket, then
295 * call the setup callback to get one.
297 if (conn->stream == NULL) {
298 status = do_conn_setup(conn);
303 *ostreamt = conn->ostream_tail;
304 *ostreamh = conn->ostream_head;
305 *istream = conn->stream;
307 /* SSL tunnel needed and not set up yet, get a direct unencrypted
308 stream for this socket */
309 if (conn->stream == NULL) {
310 *istream = serf_bucket_socket_create(conn->skt,
313 /* Don't create the ostream bucket chain including the ssl_encrypt
314 bucket yet. This ensure the CONNECT request is sent unencrypted
316 *ostreamt = *ostreamh = conn->ssltunnel_ostream;
322 /* Create and connect sockets for any connections which don't have them
323 * yet. This is the core of our lazy-connect behavior.
325 apr_status_t serf__open_connections(serf_context_t *ctx)
329 for (i = ctx->conns->nelts; i--; ) {
330 serf_connection_t *conn = GET_CONN(ctx, i);
331 serf__authn_info_t *authn_info;
335 conn->seen_in_pollset = 0;
337 if (conn->skt != NULL) {
338 #ifdef SERF_DEBUG_BUCKET_USE
339 check_buckets_drained(conn);
344 /* Delay opening until we have something to deliver! */
345 if (conn->requests == NULL) {
349 apr_pool_clear(conn->skt_pool);
350 apr_pool_cleanup_register(conn->skt_pool, conn, clean_skt, clean_skt);
352 status = apr_socket_create(&skt, conn->address->family,
354 #if APR_MAJOR_VERSION > 0
358 serf__log(SOCK_VERBOSE, __FILE__,
359 "created socket for conn 0x%x, status %d\n", conn, status);
360 if (status != APR_SUCCESS)
363 /* Set the socket to be non-blocking */
364 if ((status = apr_socket_timeout_set(skt, 0)) != APR_SUCCESS)
367 /* Disable Nagle's algorithm */
368 if ((status = apr_socket_opt_set(skt,
369 APR_TCP_NODELAY, 1)) != APR_SUCCESS)
372 /* Configured. Store it into the connection now. */
375 /* Remember time when we started connecting to server to calculate
377 conn->connect_time = apr_time_now();
379 /* Now that the socket is set up, let's connect it. This should
380 * return immediately.
382 status = apr_socket_connect(skt, conn->address);
383 serf__log_skt(SOCK_VERBOSE, __FILE__, skt,
384 "connected socket for conn 0x%x, status %d\n",
386 if (status != APR_SUCCESS) {
387 if (!APR_STATUS_IS_EINPROGRESS(status))
391 /* Flag our pollset as dirty now that we have a new socket. */
392 conn->dirty_conn = 1;
393 ctx->dirty_pollset = 1;
395 /* If the authentication was already started on another connection,
396 prepare this connection (it might be possible to skip some
397 part of the handshaking). */
398 if (ctx->proxy_address) {
399 authn_info = &ctx->proxy_authn_info;
400 if (authn_info->scheme) {
401 authn_info->scheme->init_conn_func(authn_info->scheme, 407,
406 authn_info = serf__get_authn_info_for_server(conn);
407 if (authn_info->scheme) {
408 authn_info->scheme->init_conn_func(authn_info->scheme, 401,
412 /* Does this connection require a SSL tunnel over the proxy? */
413 if (ctx->proxy_address && strcmp(conn->host_info.scheme, "https") == 0)
414 serf__ssltunnel_connect(conn);
416 serf_bucket_t *dummy1, *dummy2;
418 conn->state = SERF_CONN_CONNECTED;
420 status = prepare_conn_streams(conn, &conn->stream,
431 static apr_status_t no_more_writes(serf_connection_t *conn)
433 /* Note that we should hold new requests until we open our new socket. */
434 conn->state = SERF_CONN_CLOSING;
435 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
436 "stop writing on conn 0x%x\n", conn);
438 /* Clear our iovec. */
441 /* Update the pollset to know we don't want to write on this socket any
444 conn->dirty_conn = 1;
445 conn->ctx->dirty_pollset = 1;
449 /* Read the 'Connection' header from the response. Return SERF_ERROR_CLOSING if
450 * the header contains value 'close' indicating the server is closing the
451 * connection right after this response.
452 * Otherwise returns APR_SUCCESS.
454 static apr_status_t is_conn_closing(serf_bucket_t *response)
459 hdrs = serf_bucket_response_get_headers(response);
460 val = serf_bucket_headers_get(hdrs, "Connection");
461 if (val && strcasecmp("close", val) == 0)
463 return SERF_ERROR_CLOSING;
469 static void link_requests(serf_request_t **list, serf_request_t **tail,
470 serf_request_t *request)
477 (*tail)->next = request;
482 static apr_status_t destroy_request(serf_request_t *request)
484 serf_connection_t *conn = request->conn;
486 /* The request and response buckets are no longer needed,
487 nor is the request's pool. */
488 if (request->resp_bkt) {
489 serf_debug__closed_conn(request->resp_bkt->allocator);
490 serf_bucket_destroy(request->resp_bkt);
491 request->resp_bkt = NULL;
493 if (request->req_bkt) {
494 serf_debug__closed_conn(request->req_bkt->allocator);
495 serf_bucket_destroy(request->req_bkt);
496 request->req_bkt = NULL;
499 serf_debug__bucket_alloc_check(request->allocator);
500 if (request->respool) {
501 /* ### unregister the pool cleanup for self? */
502 apr_pool_destroy(request->respool);
505 serf_bucket_mem_free(conn->allocator, request);
510 static apr_status_t cancel_request(serf_request_t *request,
511 serf_request_t **list,
514 /* If we haven't run setup, then we won't have a handler to call. */
515 if (request->handler && notify_request) {
516 /* We actually don't care what the handler returns.
517 * We have bigger matters at hand.
519 (*request->handler)(request, NULL, request->handler_baton,
523 if (*list == request) {
524 *list = request->next;
527 serf_request_t *scan = *list;
529 while (scan->next && scan->next != request)
533 scan->next = scan->next->next;
537 return destroy_request(request);
540 static apr_status_t remove_connection(serf_context_t *ctx,
541 serf_connection_t *conn)
543 apr_pollfd_t desc = { 0 };
545 desc.desc_type = APR_POLL_SOCKET;
546 desc.desc.s = conn->skt;
547 desc.reqevents = conn->reqevents;
549 return ctx->pollset_rm(ctx->pollset_baton,
553 /* A socket was closed, inform the application. */
554 static void handle_conn_closed(serf_connection_t *conn, apr_status_t status)
556 (*conn->closed)(conn, conn->closed_baton, status,
560 static apr_status_t reset_connection(serf_connection_t *conn,
561 int requeue_requests)
563 serf_context_t *ctx = conn->ctx;
565 serf_request_t *old_reqs;
567 conn->probable_keepalive_limit = conn->completed_responses;
568 conn->completed_requests = 0;
569 conn->completed_responses = 0;
571 old_reqs = conn->requests;
573 conn->requests = NULL;
574 conn->requests_tail = NULL;
576 /* Handle all outstanding requests. These have either not been written yet,
577 or have been written but the expected reply wasn't received yet. */
579 /* If we haven't started to write the connection, bring it over
580 * unchanged to our new socket.
581 * Do not copy a CONNECT request to the new connection, the ssl tunnel
582 * setup code will create a new CONNECT request already.
584 if (requeue_requests && !old_reqs->writing_started &&
585 !old_reqs->ssltunnel) {
587 serf_request_t *req = old_reqs;
588 old_reqs = old_reqs->next;
590 link_requests(&conn->requests, &conn->requests_tail, req);
593 /* Request has been consumed, or we don't want to requeue the
594 request. Either way, inform the application that the request
596 cancel_request(old_reqs, &old_reqs, requeue_requests);
600 /* Requests queue has been prepared for a new socket, close the old one. */
601 if (conn->skt != NULL) {
602 remove_connection(ctx, conn);
603 status = apr_socket_close(conn->skt);
604 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
605 "closed socket, status %d\n", status);
606 if (conn->closed != NULL) {
607 handle_conn_closed(conn, status);
612 if (conn->stream != NULL) {
613 serf_bucket_destroy(conn->stream);
617 destroy_ostream(conn);
619 /* Don't try to resume any writes */
622 conn->dirty_conn = 1;
623 conn->ctx->dirty_pollset = 1;
624 conn->state = SERF_CONN_INIT;
626 serf__log(CONN_VERBOSE, __FILE__, "reset connection 0x%x\n", conn);
628 conn->status = APR_SUCCESS;
630 /* Let our context know that we've 'reset' the socket already. */
631 conn->seen_in_pollset |= APR_POLLHUP;
633 /* Found the connection. Closed it. All done. */
637 static apr_status_t socket_writev(serf_connection_t *conn)
642 status = apr_socket_sendv(conn->skt, conn->vec,
643 conn->vec_len, &written);
644 if (status && !APR_STATUS_IS_EAGAIN(status))
645 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
646 "socket_sendv error %d\n", status);
648 /* did we write everything? */
653 serf__log_skt(SOCK_MSG_VERBOSE, __FILE__, conn->skt,
654 "--- socket_sendv:\n");
656 for (i = 0; i < conn->vec_len; i++) {
657 len += conn->vec[i].iov_len;
659 serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s",
660 conn->vec[i].iov_len - (len - written),
661 conn->vec[i].iov_base);
663 memmove(conn->vec, &conn->vec[i],
664 sizeof(struct iovec) * (conn->vec_len - i));
667 conn->vec[0].iov_base = (char *)conn->vec[0].iov_base + (conn->vec[0].iov_len - (len - written));
668 conn->vec[0].iov_len = len - written;
671 serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s",
672 conn->vec[i].iov_len, conn->vec[i].iov_base);
675 if (len == written) {
678 serf__log_nopref(SOCK_MSG_VERBOSE, "-(%d)-\n", written);
680 /* Log progress information */
681 serf__context_progress_delta(conn->ctx, 0, written);
687 static apr_status_t setup_request(serf_request_t *request)
689 serf_connection_t *conn = request->conn;
692 /* Now that we are about to serve the request, allocate a pool. */
693 apr_pool_create(&request->respool, conn->pool);
694 request->allocator = serf_bucket_allocator_create(request->respool,
696 apr_pool_cleanup_register(request->respool, request,
697 clean_resp, clean_resp);
699 /* Fill in the rest of the values for the request. */
700 status = request->setup(request, request->setup_baton,
703 &request->acceptor_baton,
705 &request->handler_baton,
710 /* write data out to the connection */
711 static apr_status_t write_to_connection(serf_connection_t *conn)
713 if (conn->probable_keepalive_limit &&
714 conn->completed_requests > conn->probable_keepalive_limit) {
716 conn->dirty_conn = 1;
717 conn->ctx->dirty_pollset = 1;
719 /* backoff for now. */
723 /* Keep reading and sending until we run out of stuff to read, or
724 * writing would block.
727 serf_request_t *request;
728 int stop_reading = 0;
730 apr_status_t read_status;
731 serf_bucket_t *ostreamt;
732 serf_bucket_t *ostreamh;
733 int max_outstanding_requests = conn->max_outstanding_requests;
735 /* If we're setting up an ssl tunnel, we can't send real requests
736 at yet, as they need to be encrypted and our encrypt buckets
737 aren't created yet as we still need to read the unencrypted
738 response of the CONNECT request. */
739 if (conn->state != SERF_CONN_CONNECTED)
740 max_outstanding_requests = 1;
742 if (max_outstanding_requests &&
743 conn->completed_requests -
744 conn->completed_responses >= max_outstanding_requests) {
745 /* backoff for now. */
749 /* If we have unwritten data, then write what we can. */
750 while (conn->vec_len) {
751 status = socket_writev(conn);
753 /* If the write would have blocked, then we're done. Don't try
754 * to write anything else to the socket.
756 if (APR_STATUS_IS_EAGAIN(status))
758 if (APR_STATUS_IS_EPIPE(status) ||
759 APR_STATUS_IS_ECONNRESET(status) ||
760 APR_STATUS_IS_ECONNABORTED(status))
761 return no_more_writes(conn);
765 /* ### can we have a short write, yet no EAGAIN? a short write
766 ### would imply unwritten_len > 0 ... */
767 /* assert: unwritten_len == 0. */
769 /* We may need to move forward to a request which has something
772 if (!request_or_data_pending(&request, conn)) {
773 /* No more requests (with data) are registered with the
774 * connection, and no data is pending on the outgoing stream.
775 * Let's update the pollset so that we don't try to write to this
778 conn->dirty_conn = 1;
779 conn->ctx->dirty_pollset = 1;
783 status = prepare_conn_streams(conn, &conn->stream, &ostreamt, &ostreamh);
789 if (request->req_bkt == NULL) {
790 read_status = setup_request(request);
792 /* Something bad happened. Propagate any errors. */
797 if (!request->writing_started) {
798 request->writing_started = 1;
799 serf_bucket_aggregate_append(ostreamt, request->req_bkt);
803 /* ### optimize at some point by using read_for_sendfile */
804 /* TODO: now that read_iovec will effectively try to return as much
805 data as available, we probably don't want to read ALL_AVAIL, but
806 a lower number, like the size of one or a few TCP packets, the
807 available TCP buffer size ... */
808 read_status = serf_bucket_read_iovec(ostreamh,
814 if (!conn->hit_eof) {
815 if (APR_STATUS_IS_EAGAIN(read_status)) {
816 /* We read some stuff, but should not try to read again. */
819 else if (read_status == SERF_ERROR_WAIT_CONN) {
820 /* The bucket told us that it can't provide more data until
821 more data is read from the socket. This normally happens
822 during a SSL handshake.
824 We should avoid looking for writability for a while so
825 that (hopefully) something will appear in the bucket so
826 we can actually write something. otherwise, we could
827 end up in a CPU spin: socket wants something, but we
828 don't have anything (and keep returning EAGAIN)
830 conn->stop_writing = 1;
831 conn->dirty_conn = 1;
832 conn->ctx->dirty_pollset = 1;
834 else if (read_status && !APR_STATUS_IS_EOF(read_status)) {
835 /* Something bad happened. Propagate any errors. */
840 /* If we got some data, then deliver it. */
841 /* ### what to do if we got no data?? is that a problem? */
842 if (conn->vec_len > 0) {
843 status = socket_writev(conn);
845 /* If we can't write any more, or an error occurred, then
848 if (APR_STATUS_IS_EAGAIN(status))
850 if (APR_STATUS_IS_EPIPE(status))
851 return no_more_writes(conn);
852 if (APR_STATUS_IS_ECONNRESET(status) ||
853 APR_STATUS_IS_ECONNABORTED(status)) {
854 return no_more_writes(conn);
860 if (read_status == SERF_ERROR_WAIT_CONN) {
862 conn->stop_writing = 1;
863 conn->dirty_conn = 1;
864 conn->ctx->dirty_pollset = 1;
866 else if (request && read_status && conn->hit_eof &&
867 conn->vec_len == 0) {
868 /* If we hit the end of the request bucket and all of its data has
869 * been written, then clear it out to signify that we're done
870 * sending the request. On the next iteration through this loop:
871 * - if there are remaining bytes they will be written, and as the
872 * request bucket will be completely read it will be destroyed then.
873 * - we'll see if there are other requests that need to be sent
877 serf_bucket_destroy(request->req_bkt);
878 request->req_bkt = NULL;
880 /* If our connection has async responses enabled, we're not
881 * going to get a reply back, so kill the request.
883 if (conn->async_responses) {
884 conn->requests = request->next;
885 destroy_request(request);
888 conn->completed_requests++;
890 if (conn->probable_keepalive_limit &&
891 conn->completed_requests > conn->probable_keepalive_limit) {
892 /* backoff for now. */
904 /* A response message was received from the server, so call
905 the handler as specified on the original request. */
906 static apr_status_t handle_response(serf_request_t *request,
909 apr_status_t status = APR_SUCCESS;
910 int consumed_response = 0;
912 /* Only enable the new authentication framework if the program has
913 * registered an authentication credential callback.
915 * This permits older Serf apps to still handle authentication
916 * themselves by not registering credential callbacks.
918 if (request->conn->ctx->cred_cb) {
919 status = serf__handle_auth_response(&consumed_response,
922 request->handler_baton,
925 if (SERF_BUCKET_READ_ERROR(status)) {
926 /* Report the request as 'died'/'cancelled' to the application */
927 (void)(*request->handler)(request,
929 request->handler_baton,
937 if (!consumed_response) {
938 return (*request->handler)(request,
940 request->handler_baton,
947 /* An async response message was received from the server. */
948 static apr_status_t handle_async_response(serf_connection_t *conn,
953 if (conn->current_async_response == NULL) {
954 conn->current_async_response =
955 (*conn->async_acceptor)(NULL, conn->stream,
956 conn->async_acceptor_baton, pool);
959 status = (*conn->async_handler)(NULL, conn->current_async_response,
960 conn->async_handler_baton, pool);
962 if (APR_STATUS_IS_EOF(status)) {
963 serf_bucket_destroy(conn->current_async_response);
964 conn->current_async_response = NULL;
965 status = APR_SUCCESS;
973 serf__provide_credentials(serf_context_t *ctx,
976 serf_request_t *request, void *baton,
977 int code, const char *authn_type,
981 serf_connection_t *conn = request->conn;
982 serf_request_t *authn_req = request;
985 if (request->ssltunnel == 1 &&
986 conn->state == SERF_CONN_SETUP_SSLTUNNEL) {
987 /* This is a CONNECT request to set up an SSL tunnel over a proxy.
988 This request is created by serf, so if the proxy requires
989 authentication, we can't ask the application for credentials with
992 Solution: setup the first request created by the application on
993 this connection, and use that request and its handler_baton to
994 call back to the application. */
996 authn_req = request->next;
997 /* assert: app_request != NULL */
1001 if (!authn_req->req_bkt) {
1002 apr_status_t status;
1004 status = setup_request(authn_req);
1005 /* If we can't setup a request, don't bother setting up the
1012 /* Ask the application. */
1013 status = (*ctx->cred_cb)(username, password,
1014 authn_req, authn_req->handler_baton,
1015 code, authn_type, realm, pool);
1022 /* read data from the connection */
1023 static apr_status_t read_from_connection(serf_connection_t *conn)
1025 apr_status_t status;
1026 apr_pool_t *tmppool;
1027 int close_connection = FALSE;
1029 /* Whatever is coming in on the socket corresponds to the first request
1032 serf_request_t *request = conn->requests;
1034 /* If the stop_writing flag was set on the connection, reset it now because
1035 there is some data to read. */
1036 if (conn->stop_writing) {
1037 conn->stop_writing = 0;
1038 conn->dirty_conn = 1;
1039 conn->ctx->dirty_pollset = 1;
1042 /* assert: request != NULL */
1044 if ((status = apr_pool_create(&tmppool, conn->pool)) != APR_SUCCESS)
1047 /* Invoke response handlers until we have no more work. */
1049 serf_bucket_t *dummy1, *dummy2;
1051 apr_pool_clear(tmppool);
1053 /* Only interested in the input stream here. */
1054 status = prepare_conn_streams(conn, &conn->stream, &dummy1, &dummy2);
1059 /* We have a different codepath when we can have async responses. */
1060 if (conn->async_responses) {
1061 /* TODO What about socket errors? */
1062 status = handle_async_response(conn, tmppool);
1063 if (APR_STATUS_IS_EAGAIN(status)) {
1064 status = APR_SUCCESS;
1073 /* We are reading a response for a request we haven't
1076 * This shouldn't normally happen EXCEPT:
1078 * 1) when the other end has closed the socket and we're
1079 * pending an EOF return.
1080 * 2) Doing the initial SSL handshake - we'll get EAGAIN
1081 * as the SSL buckets will hide the handshake from us
1082 * but not return any data.
1083 * 3) When the server sends us an SSL alert.
1085 * In these cases, we should not receive any actual user data.
1087 * 4) When the server sends a error response, like 408 Request timeout.
1088 * This response should be passed to the application.
1090 * If we see an EOF (due to either an expired timeout or the server
1091 * sending the SSL 'close notify' shutdown alert), we'll reset the
1092 * connection and open a new one.
1094 if (request->req_bkt || !request->writing_started) {
1098 status = serf_bucket_peek(conn->stream, &data, &len);
1100 if (APR_STATUS_IS_EOF(status)) {
1101 reset_connection(conn, 1);
1102 status = APR_SUCCESS;
1105 else if (APR_STATUS_IS_EAGAIN(status) && !len) {
1106 status = APR_SUCCESS;
1108 } else if (status && !APR_STATUS_IS_EAGAIN(status)) {
1113 /* Unexpected response from the server */
1117 /* If the request doesn't have a response bucket, then call the
1118 * acceptor to get one created.
1120 if (request->resp_bkt == NULL) {
1121 request->resp_bkt = (*request->acceptor)(request, conn->stream,
1122 request->acceptor_baton,
1124 apr_pool_clear(tmppool);
1127 status = handle_response(request, tmppool);
1129 /* Some systems will not generate a HUP poll event so we have to
1130 * handle the ECONNRESET issue and ECONNABORT here.
1132 if (APR_STATUS_IS_ECONNRESET(status) ||
1133 APR_STATUS_IS_ECONNABORTED(status) ||
1134 status == SERF_ERROR_REQUEST_LOST) {
1135 /* If the connection had ever been good, be optimistic & try again.
1136 * If it has never tried again (incl. a retry), fail.
1138 if (conn->completed_responses) {
1139 reset_connection(conn, 1);
1140 status = APR_SUCCESS;
1142 else if (status == SERF_ERROR_REQUEST_LOST) {
1143 status = SERF_ERROR_ABORTED_CONNECTION;
1148 /* If our response handler says it can't do anything more, we now
1149 * treat that as a success.
1151 if (APR_STATUS_IS_EAGAIN(status)) {
1152 /* It is possible that while reading the response, the ssl layer
1153 has prepared some data to send. If this was the last request,
1154 serf will not check for socket writability, so force this here.
1156 if (request_or_data_pending(&request, conn) && !request) {
1157 conn->dirty_conn = 1;
1158 conn->ctx->dirty_pollset = 1;
1160 status = APR_SUCCESS;
1164 /* If we received APR_SUCCESS, run this loop again. */
1169 close_connection = is_conn_closing(request->resp_bkt);
1171 if (!APR_STATUS_IS_EOF(status) &&
1172 close_connection != SERF_ERROR_CLOSING) {
1173 /* Whether success, or an error, there is no more to do unless
1174 * this request has been completed.
1179 /* The response has been fully-read, so that means the request has
1180 * either been fully-delivered (most likely), or that we don't need to
1181 * write the rest of it anymore, e.g. when a 408 Request timeout was
1183 * Remove it from our queue and loop to read another response.
1185 conn->requests = request->next;
1187 destroy_request(request);
1189 request = conn->requests;
1191 /* If we're truly empty, update our tail. */
1192 if (request == NULL) {
1193 conn->requests_tail = NULL;
1196 conn->completed_responses++;
1198 /* We've to rebuild pollset since completed_responses is changed. */
1199 conn->dirty_conn = 1;
1200 conn->ctx->dirty_pollset = 1;
1202 /* This means that we're being advised that the connection is done. */
1203 if (close_connection == SERF_ERROR_CLOSING) {
1204 reset_connection(conn, 1);
1205 if (APR_STATUS_IS_EOF(status))
1206 status = APR_SUCCESS;
1210 /* The server is suddenly deciding to serve more responses than we've
1213 * Let our requests go.
1215 if (conn->probable_keepalive_limit &&
1216 conn->completed_responses > conn->probable_keepalive_limit) {
1217 conn->probable_keepalive_limit = 0;
1220 /* If we just ran out of requests or have unwritten requests, then
1221 * update the pollset. We don't want to read from this socket any
1222 * more. We are definitely done with this loop, too.
1224 if (request == NULL || !request->writing_started) {
1225 conn->dirty_conn = 1;
1226 conn->ctx->dirty_pollset = 1;
1227 status = APR_SUCCESS;
1233 apr_pool_destroy(tmppool);
1237 /* process all events on the connection */
1238 apr_status_t serf__process_connection(serf_connection_t *conn,
1241 apr_status_t status;
1243 /* POLLHUP/ERR should come after POLLIN so if there's an error message or
1244 * the like sitting on the connection, we give the app a chance to read
1245 * it before we trigger a reset condition.
1247 if ((events & APR_POLLIN) != 0) {
1248 if ((status = read_from_connection(conn)) != APR_SUCCESS)
1251 /* If we decided to reset our connection, return now as we don't
1254 if ((conn->seen_in_pollset & APR_POLLHUP) != 0) {
1258 if ((events & APR_POLLHUP) != 0) {
1259 /* The connection got reset by the server. On Windows this can happen
1260 when all data is read, so just cleanup the connection and open
1262 If we haven't had any successful responses on this connection,
1263 then error out as it is likely a server issue. */
1264 if (conn->completed_responses) {
1265 return reset_connection(conn, 1);
1267 return SERF_ERROR_ABORTED_CONNECTION;
1269 if ((events & APR_POLLERR) != 0) {
1270 /* We might be talking to a buggy HTTP server that doesn't
1271 * do lingering-close. (httpd < 2.1.8 does this.)
1275 * http://issues.apache.org/bugzilla/show_bug.cgi?id=35292
1277 if (conn->completed_requests && !conn->probable_keepalive_limit) {
1278 return reset_connection(conn, 1);
1281 /* If possible, get the error from the platform's socket layer and
1282 convert it to an APR status code. */
1284 apr_os_sock_t osskt;
1285 if (!apr_os_sock_get(&osskt, conn->skt)) {
1287 apr_socklen_t l = sizeof(error);
1289 if (!getsockopt(osskt, SOL_SOCKET, SO_ERROR, (char*)&error,
1291 status = APR_FROM_OS_ERROR(error);
1293 /* Handle fallback for multi-homed servers.
1295 ### Improve algorithm to find better than just 'next'?
1297 Current Windows versions already handle re-ordering for
1298 api users by using statistics on the recently failed
1299 connections to order the list of addresses. */
1300 if (conn->completed_requests == 0
1301 && conn->address->next != NULL
1302 && (APR_STATUS_IS_ECONNREFUSED(status)
1303 || APR_STATUS_IS_TIMEUP(status)
1304 || APR_STATUS_IS_ENETUNREACH(status))) {
1306 conn->address = conn->address->next;
1307 return reset_connection(conn, 1);
1315 return APR_EGENERAL;
1317 if ((events & APR_POLLOUT) != 0) {
1318 if ((status = write_to_connection(conn)) != APR_SUCCESS)
1324 serf_connection_t *serf_connection_create(
1325 serf_context_t *ctx,
1326 apr_sockaddr_t *address,
1327 serf_connection_setup_t setup,
1329 serf_connection_closed_t closed,
1333 serf_connection_t *conn = apr_pcalloc(pool, sizeof(*conn));
1336 conn->status = APR_SUCCESS;
1337 /* Ignore server address if proxy was specified. */
1338 conn->address = ctx->proxy_address ? ctx->proxy_address : address;
1339 conn->setup = setup;
1340 conn->setup_baton = setup_baton;
1341 conn->closed = closed;
1342 conn->closed_baton = closed_baton;
1344 conn->allocator = serf_bucket_allocator_create(pool, NULL, NULL);
1345 conn->stream = NULL;
1346 conn->ostream_head = NULL;
1347 conn->ostream_tail = NULL;
1348 conn->baton.type = SERF_IO_CONN;
1349 conn->baton.u.conn = conn;
1351 conn->state = SERF_CONN_INIT;
1352 conn->latency = -1; /* unknown */
1354 /* Create a subpool for our connection. */
1355 apr_pool_create(&conn->skt_pool, conn->pool);
1357 /* register a cleanup */
1358 apr_pool_cleanup_register(conn->pool, conn, clean_conn,
1359 apr_pool_cleanup_null);
1361 /* Add the connection to the context. */
1362 *(serf_connection_t **)apr_array_push(ctx->conns) = conn;
1364 serf__log(CONN_VERBOSE, __FILE__, "created connection 0x%x\n",
1370 apr_status_t serf_connection_create2(
1371 serf_connection_t **conn,
1372 serf_context_t *ctx,
1373 apr_uri_t host_info,
1374 serf_connection_setup_t setup,
1376 serf_connection_closed_t closed,
1380 apr_status_t status = APR_SUCCESS;
1381 serf_connection_t *c;
1382 apr_sockaddr_t *host_address = NULL;
1384 /* Set the port number explicitly, needed to create the socket later. */
1385 if (!host_info.port) {
1386 host_info.port = apr_uri_port_of_scheme(host_info.scheme);
1389 /* Only lookup the address of the server if no proxy server was
1391 if (!ctx->proxy_address) {
1392 status = apr_sockaddr_info_get(&host_address,
1394 APR_UNSPEC, host_info.port, 0, pool);
1399 c = serf_connection_create(ctx, host_address, setup, setup_baton,
1400 closed, closed_baton, pool);
1402 /* We're not interested in the path following the hostname. */
1403 c->host_url = apr_uri_unparse(c->pool,
1405 APR_URI_UNP_OMITPATHINFO |
1406 APR_URI_UNP_OMITUSERINFO);
1408 /* Store the host info without the path on the connection. */
1409 (void)apr_uri_parse(c->pool, c->host_url, &(c->host_info));
1410 if (!c->host_info.port) {
1411 c->host_info.port = apr_uri_port_of_scheme(c->host_info.scheme);
1419 apr_status_t serf_connection_reset(
1420 serf_connection_t *conn)
1422 return reset_connection(conn, 0);
1426 apr_status_t serf_connection_close(
1427 serf_connection_t *conn)
1430 serf_context_t *ctx = conn->ctx;
1431 apr_status_t status;
1433 for (i = ctx->conns->nelts; i--; ) {
1434 serf_connection_t *conn_seq = GET_CONN(ctx, i);
1436 if (conn_seq == conn) {
1437 while (conn->requests) {
1438 serf_request_cancel(conn->requests);
1440 if (conn->skt != NULL) {
1441 remove_connection(ctx, conn);
1442 status = apr_socket_close(conn->skt);
1443 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
1444 "closed socket, status %d\n",
1446 if (conn->closed != NULL) {
1447 handle_conn_closed(conn, status);
1451 if (conn->stream != NULL) {
1452 serf_bucket_destroy(conn->stream);
1453 conn->stream = NULL;
1456 destroy_ostream(conn);
1458 /* Remove the connection from the context. We don't want to
1459 * deal with it any more.
1461 if (i < ctx->conns->nelts - 1) {
1462 /* move later connections over this one. */
1465 &GET_CONN(ctx, i + 1),
1466 (ctx->conns->nelts - i - 1) * sizeof(serf_connection_t *));
1468 --ctx->conns->nelts;
1470 serf__log(CONN_VERBOSE, __FILE__, "closed connection 0x%x\n",
1473 /* Found the connection. Closed it. All done. */
1478 /* We didn't find the specified connection. */
1479 /* ### doc talks about this w.r.t poll structures. use something else? */
1480 return APR_NOTFOUND;
1484 void serf_connection_set_max_outstanding_requests(
1485 serf_connection_t *conn,
1486 unsigned int max_requests)
1488 if (max_requests == 0)
1489 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
1490 "Set max. nr. of outstanding requests for this "
1491 "connection to unlimited.\n");
1493 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
1494 "Limit max. nr. of outstanding requests for this "
1495 "connection to %u.\n", max_requests);
1497 conn->max_outstanding_requests = max_requests;
1501 void serf_connection_set_async_responses(
1502 serf_connection_t *conn,
1503 serf_response_acceptor_t acceptor,
1504 void *acceptor_baton,
1505 serf_response_handler_t handler,
1506 void *handler_baton)
1508 conn->async_responses = 1;
1509 conn->async_acceptor = acceptor;
1510 conn->async_acceptor_baton = acceptor_baton;
1511 conn->async_handler = handler;
1512 conn->async_handler_baton = handler_baton;
1515 static serf_request_t *
1516 create_request(serf_connection_t *conn,
1517 serf_request_setup_t setup,
1522 serf_request_t *request;
1524 request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
1525 request->conn = conn;
1526 request->setup = setup;
1527 request->setup_baton = setup_baton;
1528 request->handler = NULL;
1529 request->respool = NULL;
1530 request->req_bkt = NULL;
1531 request->resp_bkt = NULL;
1532 request->priority = priority;
1533 request->writing_started = 0;
1534 request->ssltunnel = ssltunnel;
1535 request->next = NULL;
1536 request->auth_baton = NULL;
1541 serf_request_t *serf_connection_request_create(
1542 serf_connection_t *conn,
1543 serf_request_setup_t setup,
1546 serf_request_t *request;
1548 request = create_request(conn, setup, setup_baton,
1550 0 /* ssl tunnel */);
1552 /* Link the request to the end of the request chain. */
1553 link_requests(&conn->requests, &conn->requests_tail, request);
1555 /* Ensure our pollset becomes writable in context run */
1556 conn->ctx->dirty_pollset = 1;
1557 conn->dirty_conn = 1;
1562 static serf_request_t *
1563 priority_request_create(serf_connection_t *conn,
1565 serf_request_setup_t setup,
1568 serf_request_t *request;
1569 serf_request_t *iter, *prev;
1571 request = create_request(conn, setup, setup_baton,
1575 /* Link the new request after the last written request. */
1576 iter = conn->requests;
1579 /* Find a request that has data which needs to be delivered. */
1580 while (iter != NULL && iter->req_bkt == NULL && iter->writing_started) {
1585 /* A CONNECT request to setup an ssltunnel has absolute priority over all
1586 other requests on the connection, so:
1587 a. add it first to the queue
1588 b. ensure that other priority requests are added after the CONNECT
1590 if (!request->ssltunnel) {
1591 /* Advance to next non priority request */
1592 while (iter != NULL && iter->priority) {
1599 request->next = iter;
1600 prev->next = request;
1602 request->next = iter;
1603 conn->requests = request;
1606 /* Ensure our pollset becomes writable in context run */
1607 conn->ctx->dirty_pollset = 1;
1608 conn->dirty_conn = 1;
1613 serf_request_t *serf_connection_priority_request_create(
1614 serf_connection_t *conn,
1615 serf_request_setup_t setup,
1618 return priority_request_create(conn,
1619 0, /* not a ssltunnel CONNECT request */
1620 setup, setup_baton);
1623 serf_request_t *serf__ssltunnel_request_create(serf_connection_t *conn,
1624 serf_request_setup_t setup,
1627 return priority_request_create(conn,
1628 1, /* This is a ssltunnel CONNECT request */
1629 setup, setup_baton);
1632 apr_status_t serf_request_cancel(serf_request_t *request)
1634 return cancel_request(request, &request->conn->requests, 0);
1637 apr_status_t serf_request_is_written(serf_request_t *request)
1639 if (request->writing_started && !request->req_bkt)
1645 apr_pool_t *serf_request_get_pool(const serf_request_t *request)
1647 return request->respool;
1651 serf_bucket_alloc_t *serf_request_get_alloc(
1652 const serf_request_t *request)
1654 return request->allocator;
1658 serf_connection_t *serf_request_get_conn(
1659 const serf_request_t *request)
1661 return request->conn;
1665 void serf_request_set_handler(
1666 serf_request_t *request,
1667 const serf_response_handler_t handler,
1668 const void **handler_baton)
1670 request->handler = handler;
1671 request->handler_baton = handler_baton;
1675 serf_bucket_t *serf_request_bucket_request_create(
1676 serf_request_t *request,
1679 serf_bucket_t *body,
1680 serf_bucket_alloc_t *allocator)
1682 serf_bucket_t *req_bkt, *hdrs_bkt;
1683 serf_connection_t *conn = request->conn;
1684 serf_context_t *ctx = conn->ctx;
1687 ssltunnel = ctx->proxy_address &&
1688 (strcmp(conn->host_info.scheme, "https") == 0);
1690 req_bkt = serf_bucket_request_create(method, uri, body, allocator);
1691 hdrs_bkt = serf_bucket_request_get_headers(req_bkt);
1693 /* Use absolute uri's in requests to a proxy. USe relative uri's in
1694 requests directly to a server or sent through an SSL tunnel. */
1695 if (ctx->proxy_address && conn->host_url &&
1696 !(ssltunnel && !request->ssltunnel)) {
1698 serf_bucket_request_set_root(req_bkt, conn->host_url);
1701 if (conn->host_info.hostinfo)
1702 serf_bucket_headers_setn(hdrs_bkt, "Host",
1703 conn->host_info.hostinfo);
1705 /* Setup server authorization headers, unless this is a CONNECT request. */
1706 if (!request->ssltunnel) {
1707 serf__authn_info_t *authn_info;
1708 authn_info = serf__get_authn_info_for_server(conn);
1709 if (authn_info->scheme)
1710 authn_info->scheme->setup_request_func(HOST, 0, conn, request,
1715 /* Setup proxy authorization headers.
1716 Don't set these headers on the requests to the server if we're using
1717 an SSL tunnel, only on the CONNECT request to setup the tunnel. */
1718 if (ctx->proxy_authn_info.scheme) {
1719 if (strcmp(conn->host_info.scheme, "https") == 0) {
1720 if (request->ssltunnel)
1721 ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
1726 ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
1736 apr_interval_time_t serf_connection_get_latency(serf_connection_t *conn)
1738 if (conn->ctx->proxy_address) {
1739 /* Detecting network latency for proxied connection is not implemented
1744 return conn->latency;