1 /* ====================================================================
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
18 * ====================================================================
21 #include <apr_pools.h>
23 #include <apr_version.h>
24 #include <apr_portable.h>
27 #include "serf_bucket_util.h"
29 #include "serf_private.h"
31 /* cleanup for sockets */
32 static apr_status_t clean_skt(void *data)
34 serf_connection_t *conn = data;
35 apr_status_t status = APR_SUCCESS;
38 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt, "cleanup - ");
39 status = apr_socket_close(conn->skt);
41 serf__log_nopref(SOCK_VERBOSE, "closed socket, status %d\n", status);
47 static apr_status_t clean_resp(void *data)
49 serf_request_t *request = data;
51 /* The request's RESPOOL is being cleared. */
53 /* If the response has allocated some buckets, then destroy them (since
54 the bucket may hold resources other than memory in RESPOOL). Also
55 make sure to set their fields to NULL so connection closure does
56 not attempt to free them again. */
57 if (request->resp_bkt) {
58 serf_bucket_destroy(request->resp_bkt);
59 request->resp_bkt = NULL;
61 if (request->req_bkt) {
62 serf_bucket_destroy(request->req_bkt);
63 request->req_bkt = NULL;
66 /* ### should we worry about debug stuff, like that performed in
67 ### destroy_request()? should we worry about calling req->handler
68 ### to notify this "cancellation" due to pool clearing? */
70 /* This pool just got cleared/destroyed. Don't try to destroy the pool
71 (again) when the request is canceled. */
72 request->respool = NULL;
77 /* cleanup for conns */
78 static apr_status_t clean_conn(void *data)
80 serf_connection_t *conn = data;
82 serf__log(CONN_VERBOSE, __FILE__, "cleaning up connection 0x%x\n",
84 serf_connection_close(conn);
89 /* Check if there is data waiting to be sent over the socket. This can happen
91 - The connection queue has atleast one request with unwritten data.
92 - All requests are written and the ssl layer wrote some data while reading
93 the response. This can happen when the server triggers a renegotiation,
94 e.g. after the first and only request on that connection was received.
95 Returns 1 if data is pending on CONN, NULL if not.
96 If NEXT_REQ is not NULL, it will be filled in with the next available request
97 with unwritten data. */
99 request_or_data_pending(serf_request_t **next_req, serf_connection_t *conn)
101 serf_request_t *request = conn->requests;
103 while (request != NULL && request->req_bkt == NULL &&
104 request->writing_started)
105 request = request->next;
110 if (request != NULL) {
112 } else if (conn->ostream_head) {
117 status = serf_bucket_peek(conn->ostream_head, &dummy,
119 if (!SERF_BUCKET_READ_ERROR(status) && len) {
120 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
121 "All requests written but still data pending.\n");
129 /* Update the pollset for this connection. We tweak the pollset based on
130 * whether we want to read and/or write, given conditions within the
131 * connection. If the connection is not (yet) in the pollset, then it
134 apr_status_t serf__conn_update_pollset(serf_connection_t *conn)
136 serf_context_t *ctx = conn->ctx;
138 apr_pollfd_t desc = { 0 };
144 /* Remove the socket from the poll set. */
145 desc.desc_type = APR_POLL_SOCKET;
146 desc.desc.s = conn->skt;
147 desc.reqevents = conn->reqevents;
149 status = ctx->pollset_rm(ctx->pollset_baton,
150 &desc, &conn->baton);
151 if (status && !APR_STATUS_IS_NOTFOUND(status))
154 /* Now put it back in with the correct read/write values. */
155 desc.reqevents = APR_POLLHUP | APR_POLLERR;
156 if (conn->requests &&
157 conn->state != SERF_CONN_INIT) {
158 /* If there are any outstanding events, then we want to read. */
159 /* ### not true. we only want to read IF we have sent some data */
160 desc.reqevents |= APR_POLLIN;
162 /* Don't write if OpenSSL told us that it needs to read data first. */
163 if (conn->stop_writing != 1) {
165 /* If the connection is not closing down and
166 * has unwritten data or
167 * there are any requests that still have buckets to write out,
168 * then we want to write.
171 conn->state != SERF_CONN_CLOSING)
172 desc.reqevents |= APR_POLLOUT;
175 if ((conn->probable_keepalive_limit &&
176 conn->completed_requests > conn->probable_keepalive_limit) ||
177 (conn->max_outstanding_requests &&
178 conn->completed_requests - conn->completed_responses >=
179 conn->max_outstanding_requests)) {
180 /* we wouldn't try to write any way right now. */
182 else if (request_or_data_pending(NULL, conn)) {
183 desc.reqevents |= APR_POLLOUT;
189 /* If we can have async responses, always look for something to read. */
190 if (conn->async_responses) {
191 desc.reqevents |= APR_POLLIN;
194 /* save our reqevents, so we can pass it in to remove later. */
195 conn->reqevents = desc.reqevents;
197 /* Note: even if we don't want to read/write this socket, we still
198 * want to poll it for hangups and errors.
200 return ctx->pollset_add(ctx->pollset_baton,
201 &desc, &conn->baton);
204 #ifdef SERF_DEBUG_BUCKET_USE
206 /* Make sure all response buckets were drained. */
207 static void check_buckets_drained(serf_connection_t *conn)
209 serf_request_t *request = conn->requests;
211 for ( ; request ; request = request->next ) {
212 if (request->resp_bkt != NULL) {
213 /* ### crap. can't do this. this allocator may have un-drained
214 * ### REQUEST buckets.
216 /* serf_debug__entered_loop(request->resp_bkt->allocator); */
217 /* ### for now, pretend we closed the conn (resets the tracking) */
218 serf_debug__closed_conn(request->resp_bkt->allocator);
225 static void destroy_ostream(serf_connection_t *conn)
227 if (conn->ostream_head != NULL) {
228 serf_bucket_destroy(conn->ostream_head);
229 conn->ostream_head = NULL;
230 conn->ostream_tail = NULL;
234 static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
236 serf_connection_t *conn = baton;
241 static apr_status_t do_conn_setup(serf_connection_t *conn)
244 serf_bucket_t *ostream;
246 if (conn->ostream_head == NULL) {
247 conn->ostream_head = serf_bucket_aggregate_create(conn->allocator);
250 if (conn->ostream_tail == NULL) {
251 conn->ostream_tail = serf__bucket_stream_create(conn->allocator,
256 ostream = conn->ostream_tail;
258 status = (*conn->setup)(conn->skt,
264 /* extra destroy here since it wasn't added to the head bucket yet. */
265 serf_bucket_destroy(conn->ostream_tail);
266 destroy_ostream(conn);
270 serf_bucket_aggregate_append(conn->ostream_head,
276 /* Set up the input and output stream buckets.
277 When a tunnel over an http proxy is needed, create a socket bucket and
278 empty aggregate bucket for sending and receiving unencrypted requests
281 After the tunnel is there, or no tunnel was needed, ask the application
282 to create the input and output buckets, which should take care of the
286 static apr_status_t prepare_conn_streams(serf_connection_t *conn,
287 serf_bucket_t **istream,
288 serf_bucket_t **ostreamt,
289 serf_bucket_t **ostreamh)
293 if (conn->stream == NULL) {
294 conn->latency = apr_time_now() - conn->connect_time;
297 /* Do we need a SSL tunnel first? */
298 if (conn->state == SERF_CONN_CONNECTED) {
299 /* If the connection does not have an associated bucket, then
300 * call the setup callback to get one.
302 if (conn->stream == NULL) {
303 status = do_conn_setup(conn);
308 *ostreamt = conn->ostream_tail;
309 *ostreamh = conn->ostream_head;
310 *istream = conn->stream;
312 /* SSL tunnel needed and not set up yet, get a direct unencrypted
313 stream for this socket */
314 if (conn->stream == NULL) {
315 *istream = serf_bucket_socket_create(conn->skt,
318 /* Don't create the ostream bucket chain including the ssl_encrypt
319 bucket yet. This ensure the CONNECT request is sent unencrypted
321 *ostreamt = *ostreamh = conn->ssltunnel_ostream;
327 /* Create and connect sockets for any connections which don't have them
328 * yet. This is the core of our lazy-connect behavior.
330 apr_status_t serf__open_connections(serf_context_t *ctx)
334 for (i = ctx->conns->nelts; i--; ) {
335 serf_connection_t *conn = GET_CONN(ctx, i);
336 serf__authn_info_t *authn_info;
340 conn->seen_in_pollset = 0;
342 if (conn->skt != NULL) {
343 #ifdef SERF_DEBUG_BUCKET_USE
344 check_buckets_drained(conn);
349 /* Delay opening until we have something to deliver! */
350 if (conn->requests == NULL) {
354 apr_pool_clear(conn->skt_pool);
355 apr_pool_cleanup_register(conn->skt_pool, conn, clean_skt, clean_skt);
357 status = apr_socket_create(&skt, conn->address->family,
359 #if APR_MAJOR_VERSION > 0
363 serf__log(SOCK_VERBOSE, __FILE__,
364 "created socket for conn 0x%x, status %d\n", conn, status);
365 if (status != APR_SUCCESS)
368 /* Set the socket to be non-blocking */
369 if ((status = apr_socket_timeout_set(skt, 0)) != APR_SUCCESS)
372 /* Disable Nagle's algorithm */
373 if ((status = apr_socket_opt_set(skt,
374 APR_TCP_NODELAY, 1)) != APR_SUCCESS)
377 /* Configured. Store it into the connection now. */
380 /* Remember time when we started connecting to server to calculate
382 conn->connect_time = apr_time_now();
384 /* Now that the socket is set up, let's connect it. This should
385 * return immediately.
387 status = apr_socket_connect(skt, conn->address);
388 serf__log_skt(SOCK_VERBOSE, __FILE__, skt,
389 "connected socket for conn 0x%x, status %d\n",
391 if (status != APR_SUCCESS) {
392 if (!APR_STATUS_IS_EINPROGRESS(status))
396 /* Flag our pollset as dirty now that we have a new socket. */
397 conn->dirty_conn = 1;
398 ctx->dirty_pollset = 1;
400 /* If the authentication was already started on another connection,
401 prepare this connection (it might be possible to skip some
402 part of the handshaking). */
403 if (ctx->proxy_address) {
404 authn_info = &ctx->proxy_authn_info;
405 if (authn_info->scheme) {
406 authn_info->scheme->init_conn_func(authn_info->scheme, 407,
411 authn_info = serf__get_authn_info_for_server(conn);
412 if (authn_info->scheme) {
413 authn_info->scheme->init_conn_func(authn_info->scheme, 401,
417 /* Does this connection require a SSL tunnel over the proxy? */
418 if (ctx->proxy_address && strcmp(conn->host_info.scheme, "https") == 0)
419 serf__ssltunnel_connect(conn);
421 serf_bucket_t *dummy1, *dummy2;
423 conn->state = SERF_CONN_CONNECTED;
425 status = prepare_conn_streams(conn, &conn->stream,
436 static apr_status_t no_more_writes(serf_connection_t *conn)
438 /* Note that we should hold new requests until we open our new socket. */
439 conn->state = SERF_CONN_CLOSING;
440 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
441 "stop writing on conn 0x%x\n", conn);
443 /* Clear our iovec. */
446 /* Update the pollset to know we don't want to write on this socket any
449 conn->dirty_conn = 1;
450 conn->ctx->dirty_pollset = 1;
454 /* Read the 'Connection' header from the response. Return SERF_ERROR_CLOSING if
455 * the header contains value 'close' indicating the server is closing the
456 * connection right after this response.
457 * Otherwise returns APR_SUCCESS.
459 static apr_status_t is_conn_closing(serf_bucket_t *response)
464 hdrs = serf_bucket_response_get_headers(response);
465 val = serf_bucket_headers_get(hdrs, "Connection");
466 if (val && strcasecmp("close", val) == 0)
468 return SERF_ERROR_CLOSING;
474 static void link_requests(serf_request_t **list, serf_request_t **tail,
475 serf_request_t *request)
482 (*tail)->next = request;
487 static apr_status_t destroy_request(serf_request_t *request)
489 serf_connection_t *conn = request->conn;
491 /* The request and response buckets are no longer needed,
492 nor is the request's pool. */
493 if (request->resp_bkt) {
494 serf_debug__closed_conn(request->resp_bkt->allocator);
495 serf_bucket_destroy(request->resp_bkt);
496 request->resp_bkt = NULL;
498 if (request->req_bkt) {
499 serf_debug__closed_conn(request->req_bkt->allocator);
500 serf_bucket_destroy(request->req_bkt);
501 request->req_bkt = NULL;
504 serf_debug__bucket_alloc_check(request->allocator);
505 if (request->respool) {
506 /* ### unregister the pool cleanup for self? */
507 apr_pool_destroy(request->respool);
510 serf_bucket_mem_free(conn->allocator, request);
515 static apr_status_t cancel_request(serf_request_t *request,
516 serf_request_t **list,
519 /* If we haven't run setup, then we won't have a handler to call. */
520 if (request->handler && notify_request) {
521 /* We actually don't care what the handler returns.
522 * We have bigger matters at hand.
524 (*request->handler)(request, NULL, request->handler_baton,
528 if (*list == request) {
529 *list = request->next;
532 serf_request_t *scan = *list;
534 while (scan->next && scan->next != request)
538 scan->next = scan->next->next;
542 return destroy_request(request);
545 static apr_status_t remove_connection(serf_context_t *ctx,
546 serf_connection_t *conn)
548 apr_pollfd_t desc = { 0 };
550 desc.desc_type = APR_POLL_SOCKET;
551 desc.desc.s = conn->skt;
552 desc.reqevents = conn->reqevents;
554 return ctx->pollset_rm(ctx->pollset_baton,
555 &desc, &conn->baton);
558 /* A socket was closed, inform the application. */
559 static void handle_conn_closed(serf_connection_t *conn, apr_status_t status)
561 (*conn->closed)(conn, conn->closed_baton, status,
565 static apr_status_t reset_connection(serf_connection_t *conn,
566 int requeue_requests)
568 serf_context_t *ctx = conn->ctx;
570 serf_request_t *old_reqs;
572 conn->probable_keepalive_limit = conn->completed_responses;
573 conn->completed_requests = 0;
574 conn->completed_responses = 0;
576 old_reqs = conn->requests;
578 conn->requests = NULL;
579 conn->requests_tail = NULL;
581 /* Handle all outstanding requests. These have either not been written yet,
582 or have been written but the expected reply wasn't received yet. */
584 /* If we haven't started to write the connection, bring it over
585 * unchanged to our new socket.
586 * Do not copy a CONNECT request to the new connection, the ssl tunnel
587 * setup code will create a new CONNECT request already.
589 if (requeue_requests && !old_reqs->writing_started &&
590 !old_reqs->ssltunnel) {
592 serf_request_t *req = old_reqs;
593 old_reqs = old_reqs->next;
595 link_requests(&conn->requests, &conn->requests_tail, req);
598 /* Request has been consumed, or we don't want to requeue the
599 request. Either way, inform the application that the request
601 cancel_request(old_reqs, &old_reqs, requeue_requests);
605 /* Requests queue has been prepared for a new socket, close the old one. */
606 if (conn->skt != NULL) {
607 remove_connection(ctx, conn);
608 status = apr_socket_close(conn->skt);
609 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
610 "closed socket, status %d\n", status);
611 if (conn->closed != NULL) {
612 handle_conn_closed(conn, status);
617 if (conn->stream != NULL) {
618 serf_bucket_destroy(conn->stream);
622 destroy_ostream(conn);
624 /* Don't try to resume any writes */
627 conn->dirty_conn = 1;
628 conn->ctx->dirty_pollset = 1;
629 conn->state = SERF_CONN_INIT;
632 conn->connect_time = 0;
634 conn->stop_writing = 0;
636 serf__log(CONN_VERBOSE, __FILE__, "reset connection 0x%x\n", conn);
638 conn->status = APR_SUCCESS;
640 /* Let our context know that we've 'reset' the socket already. */
641 conn->seen_in_pollset |= APR_POLLHUP;
643 /* Found the connection. Closed it. All done. */
647 static apr_status_t socket_writev(serf_connection_t *conn)
652 status = apr_socket_sendv(conn->skt, conn->vec,
653 conn->vec_len, &written);
654 if (status && !APR_STATUS_IS_EAGAIN(status))
655 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
656 "socket_sendv error %d\n", status);
658 /* did we write everything? */
663 serf__log_skt(SOCK_MSG_VERBOSE, __FILE__, conn->skt,
664 "--- socket_sendv:\n");
666 for (i = 0; i < conn->vec_len; i++) {
667 len += conn->vec[i].iov_len;
669 serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s",
670 conn->vec[i].iov_len - (len - written),
671 conn->vec[i].iov_base);
673 memmove(conn->vec, &conn->vec[i],
674 sizeof(struct iovec) * (conn->vec_len - i));
677 conn->vec[0].iov_base = (char *)conn->vec[0].iov_base + (conn->vec[0].iov_len - (len - written));
678 conn->vec[0].iov_len = len - written;
681 serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s",
682 conn->vec[i].iov_len, conn->vec[i].iov_base);
685 if (len == written) {
688 serf__log_nopref(SOCK_MSG_VERBOSE, "-(%d)-\n", written);
690 /* Log progress information */
691 serf__context_progress_delta(conn->ctx, 0, written);
697 static apr_status_t setup_request(serf_request_t *request)
699 serf_connection_t *conn = request->conn;
702 /* Now that we are about to serve the request, allocate a pool. */
703 apr_pool_create(&request->respool, conn->pool);
704 request->allocator = serf_bucket_allocator_create(request->respool,
706 apr_pool_cleanup_register(request->respool, request,
707 clean_resp, clean_resp);
709 /* Fill in the rest of the values for the request. */
710 status = request->setup(request, request->setup_baton,
713 &request->acceptor_baton,
715 &request->handler_baton,
720 /* write data out to the connection */
721 static apr_status_t write_to_connection(serf_connection_t *conn)
723 if (conn->probable_keepalive_limit &&
724 conn->completed_requests > conn->probable_keepalive_limit) {
726 conn->dirty_conn = 1;
727 conn->ctx->dirty_pollset = 1;
729 /* backoff for now. */
733 /* Keep reading and sending until we run out of stuff to read, or
734 * writing would block.
737 serf_request_t *request;
738 int stop_reading = 0;
740 apr_status_t read_status;
741 serf_bucket_t *ostreamt;
742 serf_bucket_t *ostreamh;
743 int max_outstanding_requests = conn->max_outstanding_requests;
745 /* If we're setting up an ssl tunnel, we can't send real requests
746 at yet, as they need to be encrypted and our encrypt buckets
747 aren't created yet as we still need to read the unencrypted
748 response of the CONNECT request. */
749 if (conn->state != SERF_CONN_CONNECTED)
750 max_outstanding_requests = 1;
752 if (max_outstanding_requests &&
753 conn->completed_requests -
754 conn->completed_responses >= max_outstanding_requests) {
755 /* backoff for now. */
759 /* If we have unwritten data, then write what we can. */
760 while (conn->vec_len) {
761 status = socket_writev(conn);
763 /* If the write would have blocked, then we're done. Don't try
764 * to write anything else to the socket.
766 if (APR_STATUS_IS_EAGAIN(status))
768 if (APR_STATUS_IS_EPIPE(status) ||
769 APR_STATUS_IS_ECONNRESET(status) ||
770 APR_STATUS_IS_ECONNABORTED(status))
771 return no_more_writes(conn);
775 /* ### can we have a short write, yet no EAGAIN? a short write
776 ### would imply unwritten_len > 0 ... */
777 /* assert: unwritten_len == 0. */
779 /* We may need to move forward to a request which has something
782 if (!request_or_data_pending(&request, conn)) {
783 /* No more requests (with data) are registered with the
784 * connection, and no data is pending on the outgoing stream.
785 * Let's update the pollset so that we don't try to write to this
788 conn->dirty_conn = 1;
789 conn->ctx->dirty_pollset = 1;
793 status = prepare_conn_streams(conn, &conn->stream, &ostreamt, &ostreamh);
799 if (request->req_bkt == NULL) {
800 read_status = setup_request(request);
802 /* Something bad happened. Propagate any errors. */
807 if (!request->writing_started) {
808 request->writing_started = 1;
809 serf_bucket_aggregate_append(ostreamt, request->req_bkt);
813 /* ### optimize at some point by using read_for_sendfile */
814 /* TODO: now that read_iovec will effectively try to return as much
815 data as available, we probably don't want to read ALL_AVAIL, but
816 a lower number, like the size of one or a few TCP packets, the
817 available TCP buffer size ... */
818 read_status = serf_bucket_read_iovec(ostreamh,
824 if (!conn->hit_eof) {
825 if (APR_STATUS_IS_EAGAIN(read_status)) {
826 /* We read some stuff, but should not try to read again. */
829 else if (read_status == SERF_ERROR_WAIT_CONN) {
830 /* The bucket told us that it can't provide more data until
831 more data is read from the socket. This normally happens
832 during a SSL handshake.
834 We should avoid looking for writability for a while so
835 that (hopefully) something will appear in the bucket so
836 we can actually write something. otherwise, we could
837 end up in a CPU spin: socket wants something, but we
838 don't have anything (and keep returning EAGAIN)
840 conn->stop_writing = 1;
841 conn->dirty_conn = 1;
842 conn->ctx->dirty_pollset = 1;
844 else if (read_status && !APR_STATUS_IS_EOF(read_status)) {
845 /* Something bad happened. Propagate any errors. */
850 /* If we got some data, then deliver it. */
851 /* ### what to do if we got no data?? is that a problem? */
852 if (conn->vec_len > 0) {
853 status = socket_writev(conn);
855 /* If we can't write any more, or an error occurred, then
858 if (APR_STATUS_IS_EAGAIN(status))
860 if (APR_STATUS_IS_EPIPE(status))
861 return no_more_writes(conn);
862 if (APR_STATUS_IS_ECONNRESET(status) ||
863 APR_STATUS_IS_ECONNABORTED(status)) {
864 return no_more_writes(conn);
870 if (read_status == SERF_ERROR_WAIT_CONN) {
872 conn->stop_writing = 1;
873 conn->dirty_conn = 1;
874 conn->ctx->dirty_pollset = 1;
876 else if (request && read_status && conn->hit_eof &&
877 conn->vec_len == 0) {
878 /* If we hit the end of the request bucket and all of its data has
879 * been written, then clear it out to signify that we're done
880 * sending the request. On the next iteration through this loop:
881 * - if there are remaining bytes they will be written, and as the
882 * request bucket will be completely read it will be destroyed then.
883 * - we'll see if there are other requests that need to be sent
887 serf_bucket_destroy(request->req_bkt);
888 request->req_bkt = NULL;
890 /* If our connection has async responses enabled, we're not
891 * going to get a reply back, so kill the request.
893 if (conn->async_responses) {
894 conn->requests = request->next;
895 destroy_request(request);
898 conn->completed_requests++;
900 if (conn->probable_keepalive_limit &&
901 conn->completed_requests > conn->probable_keepalive_limit) {
902 /* backoff for now. */
914 /* A response message was received from the server, so call
915 the handler as specified on the original request. */
916 static apr_status_t handle_response(serf_request_t *request,
919 apr_status_t status = APR_SUCCESS;
920 int consumed_response = 0;
922 /* Only enable the new authentication framework if the program has
923 * registered an authentication credential callback.
925 * This permits older Serf apps to still handle authentication
926 * themselves by not registering credential callbacks.
928 if (request->conn->ctx->cred_cb) {
929 status = serf__handle_auth_response(&consumed_response,
932 request->handler_baton,
935 /* If there was an error reading the response (maybe there wasn't
936 enough data available), don't bother passing the response to the
939 If the authentication was tried, but failed, pass the response
940 to the application, maybe it can do better. */
946 if (!consumed_response) {
947 return (*request->handler)(request,
949 request->handler_baton,
956 /* An async response message was received from the server. */
957 static apr_status_t handle_async_response(serf_connection_t *conn,
962 if (conn->current_async_response == NULL) {
963 conn->current_async_response =
964 (*conn->async_acceptor)(NULL, conn->stream,
965 conn->async_acceptor_baton, pool);
968 status = (*conn->async_handler)(NULL, conn->current_async_response,
969 conn->async_handler_baton, pool);
971 if (APR_STATUS_IS_EOF(status)) {
972 serf_bucket_destroy(conn->current_async_response);
973 conn->current_async_response = NULL;
974 status = APR_SUCCESS;
982 serf__provide_credentials(serf_context_t *ctx,
985 serf_request_t *request, void *baton,
986 int code, const char *authn_type,
990 serf_connection_t *conn = request->conn;
991 serf_request_t *authn_req = request;
994 if (request->ssltunnel == 1 &&
995 conn->state == SERF_CONN_SETUP_SSLTUNNEL) {
996 /* This is a CONNECT request to set up an SSL tunnel over a proxy.
997 This request is created by serf, so if the proxy requires
998 authentication, we can't ask the application for credentials with
1001 Solution: setup the first request created by the application on
1002 this connection, and use that request and its handler_baton to
1003 call back to the application. */
1005 authn_req = request->next;
1006 /* assert: app_request != NULL */
1008 return APR_EGENERAL;
1010 if (!authn_req->req_bkt) {
1011 apr_status_t status;
1013 status = setup_request(authn_req);
1014 /* If we can't setup a request, don't bother setting up the
1021 /* Ask the application. */
1022 status = (*ctx->cred_cb)(username, password,
1023 authn_req, authn_req->handler_baton,
1024 code, authn_type, realm, pool);
1031 /* read data from the connection */
1032 static apr_status_t read_from_connection(serf_connection_t *conn)
1034 apr_status_t status;
1035 apr_pool_t *tmppool;
1036 int close_connection = FALSE;
1038 /* Whatever is coming in on the socket corresponds to the first request
1041 serf_request_t *request = conn->requests;
1043 /* If the stop_writing flag was set on the connection, reset it now because
1044 there is some data to read. */
1045 if (conn->stop_writing) {
1046 conn->stop_writing = 0;
1047 conn->dirty_conn = 1;
1048 conn->ctx->dirty_pollset = 1;
1051 /* assert: request != NULL */
1053 if ((status = apr_pool_create(&tmppool, conn->pool)) != APR_SUCCESS)
1056 /* Invoke response handlers until we have no more work. */
1058 serf_bucket_t *dummy1, *dummy2;
1060 apr_pool_clear(tmppool);
1062 /* Only interested in the input stream here. */
1063 status = prepare_conn_streams(conn, &conn->stream, &dummy1, &dummy2);
1068 /* We have a different codepath when we can have async responses. */
1069 if (conn->async_responses) {
1070 /* TODO What about socket errors? */
1071 status = handle_async_response(conn, tmppool);
1072 if (APR_STATUS_IS_EAGAIN(status)) {
1073 status = APR_SUCCESS;
1082 /* We are reading a response for a request we haven't
1085 * This shouldn't normally happen EXCEPT:
1087 * 1) when the other end has closed the socket and we're
1088 * pending an EOF return.
1089 * 2) Doing the initial SSL handshake - we'll get EAGAIN
1090 * as the SSL buckets will hide the handshake from us
1091 * but not return any data.
1092 * 3) When the server sends us an SSL alert.
1094 * In these cases, we should not receive any actual user data.
1096 * 4) When the server sends a error response, like 408 Request timeout.
1097 * This response should be passed to the application.
1099 * If we see an EOF (due to either an expired timeout or the server
1100 * sending the SSL 'close notify' shutdown alert), we'll reset the
1101 * connection and open a new one.
1103 if (request->req_bkt || !request->writing_started) {
1107 status = serf_bucket_peek(conn->stream, &data, &len);
1109 if (APR_STATUS_IS_EOF(status)) {
1110 reset_connection(conn, 1);
1111 status = APR_SUCCESS;
1114 else if (APR_STATUS_IS_EAGAIN(status) && !len) {
1115 status = APR_SUCCESS;
1117 } else if (status && !APR_STATUS_IS_EAGAIN(status)) {
1122 /* Unexpected response from the server */
1126 /* If the request doesn't have a response bucket, then call the
1127 * acceptor to get one created.
1129 if (request->resp_bkt == NULL) {
1130 request->resp_bkt = (*request->acceptor)(request, conn->stream,
1131 request->acceptor_baton,
1133 apr_pool_clear(tmppool);
1136 status = handle_response(request, tmppool);
1138 /* Some systems will not generate a HUP poll event so we have to
1139 * handle the ECONNRESET issue and ECONNABORT here.
1141 if (APR_STATUS_IS_ECONNRESET(status) ||
1142 APR_STATUS_IS_ECONNABORTED(status) ||
1143 status == SERF_ERROR_REQUEST_LOST) {
1144 /* If the connection had ever been good, be optimistic & try again.
1145 * If it has never tried again (incl. a retry), fail.
1147 if (conn->completed_responses) {
1148 reset_connection(conn, 1);
1149 status = APR_SUCCESS;
1151 else if (status == SERF_ERROR_REQUEST_LOST) {
1152 status = SERF_ERROR_ABORTED_CONNECTION;
1157 /* If our response handler says it can't do anything more, we now
1158 * treat that as a success.
1160 if (APR_STATUS_IS_EAGAIN(status)) {
1161 /* It is possible that while reading the response, the ssl layer
1162 has prepared some data to send. If this was the last request,
1163 serf will not check for socket writability, so force this here.
1165 if (request_or_data_pending(&request, conn) && !request) {
1166 conn->dirty_conn = 1;
1167 conn->ctx->dirty_pollset = 1;
1169 status = APR_SUCCESS;
1173 /* If we received APR_SUCCESS, run this loop again. */
1178 close_connection = is_conn_closing(request->resp_bkt);
1180 if (!APR_STATUS_IS_EOF(status) &&
1181 close_connection != SERF_ERROR_CLOSING) {
1182 /* Whether success, or an error, there is no more to do unless
1183 * this request has been completed.
1188 /* The response has been fully-read, so that means the request has
1189 * either been fully-delivered (most likely), or that we don't need to
1190 * write the rest of it anymore, e.g. when a 408 Request timeout was
1192 * Remove it from our queue and loop to read another response.
1194 conn->requests = request->next;
1196 destroy_request(request);
1198 request = conn->requests;
1200 /* If we're truly empty, update our tail. */
1201 if (request == NULL) {
1202 conn->requests_tail = NULL;
1205 conn->completed_responses++;
1207 /* We've to rebuild pollset since completed_responses is changed. */
1208 conn->dirty_conn = 1;
1209 conn->ctx->dirty_pollset = 1;
1211 /* This means that we're being advised that the connection is done. */
1212 if (close_connection == SERF_ERROR_CLOSING) {
1213 reset_connection(conn, 1);
1214 if (APR_STATUS_IS_EOF(status))
1215 status = APR_SUCCESS;
1219 /* The server is suddenly deciding to serve more responses than we've
1222 * Let our requests go.
1224 if (conn->probable_keepalive_limit &&
1225 conn->completed_responses > conn->probable_keepalive_limit) {
1226 conn->probable_keepalive_limit = 0;
1229 /* If we just ran out of requests or have unwritten requests, then
1230 * update the pollset. We don't want to read from this socket any
1231 * more. We are definitely done with this loop, too.
1233 if (request == NULL || !request->writing_started) {
1234 conn->dirty_conn = 1;
1235 conn->ctx->dirty_pollset = 1;
1236 status = APR_SUCCESS;
1242 apr_pool_destroy(tmppool);
1246 /* process all events on the connection */
1247 apr_status_t serf__process_connection(serf_connection_t *conn,
1250 apr_status_t status;
1252 /* POLLHUP/ERR should come after POLLIN so if there's an error message or
1253 * the like sitting on the connection, we give the app a chance to read
1254 * it before we trigger a reset condition.
1256 if ((events & APR_POLLIN) != 0) {
1257 if ((status = read_from_connection(conn)) != APR_SUCCESS)
1260 /* If we decided to reset our connection, return now as we don't
1263 if ((conn->seen_in_pollset & APR_POLLHUP) != 0) {
1267 if ((events & APR_POLLHUP) != 0) {
1268 /* The connection got reset by the server. On Windows this can happen
1269 when all data is read, so just cleanup the connection and open
1271 If we haven't had any successful responses on this connection,
1272 then error out as it is likely a server issue. */
1273 if (conn->completed_responses) {
1274 return reset_connection(conn, 1);
1276 return SERF_ERROR_ABORTED_CONNECTION;
1278 if ((events & APR_POLLERR) != 0) {
1279 /* We might be talking to a buggy HTTP server that doesn't
1280 * do lingering-close. (httpd < 2.1.8 does this.)
1284 * http://issues.apache.org/bugzilla/show_bug.cgi?id=35292
1286 if (conn->completed_requests && !conn->probable_keepalive_limit) {
1287 return reset_connection(conn, 1);
1290 /* If possible, get the error from the platform's socket layer and
1291 convert it to an APR status code. */
1293 apr_os_sock_t osskt;
1294 if (!apr_os_sock_get(&osskt, conn->skt)) {
1296 apr_socklen_t l = sizeof(error);
1298 if (!getsockopt(osskt, SOL_SOCKET, SO_ERROR, (char*)&error,
1300 status = APR_FROM_OS_ERROR(error);
1302 /* Handle fallback for multi-homed servers.
1304 ### Improve algorithm to find better than just 'next'?
1306 Current Windows versions already handle re-ordering for
1307 api users by using statistics on the recently failed
1308 connections to order the list of addresses. */
1309 if (conn->completed_requests == 0
1310 && conn->address->next != NULL
1311 && (APR_STATUS_IS_ECONNREFUSED(status)
1312 || APR_STATUS_IS_TIMEUP(status)
1313 || APR_STATUS_IS_ENETUNREACH(status))) {
1315 conn->address = conn->address->next;
1316 return reset_connection(conn, 1);
1324 return APR_EGENERAL;
1326 if ((events & APR_POLLOUT) != 0) {
1327 if ((status = write_to_connection(conn)) != APR_SUCCESS)
1333 serf_connection_t *serf_connection_create(
1334 serf_context_t *ctx,
1335 apr_sockaddr_t *address,
1336 serf_connection_setup_t setup,
1338 serf_connection_closed_t closed,
1342 serf_connection_t *conn = apr_pcalloc(pool, sizeof(*conn));
1345 conn->status = APR_SUCCESS;
1346 /* Ignore server address if proxy was specified. */
1347 conn->address = ctx->proxy_address ? ctx->proxy_address : address;
1348 conn->setup = setup;
1349 conn->setup_baton = setup_baton;
1350 conn->closed = closed;
1351 conn->closed_baton = closed_baton;
1353 conn->allocator = serf_bucket_allocator_create(pool, NULL, NULL);
1354 conn->stream = NULL;
1355 conn->ostream_head = NULL;
1356 conn->ostream_tail = NULL;
1357 conn->baton.type = SERF_IO_CONN;
1358 conn->baton.u.conn = conn;
1360 conn->state = SERF_CONN_INIT;
1361 conn->latency = -1; /* unknown */
1363 /* Create a subpool for our connection. */
1364 apr_pool_create(&conn->skt_pool, conn->pool);
1366 /* register a cleanup */
1367 apr_pool_cleanup_register(conn->pool, conn, clean_conn,
1368 apr_pool_cleanup_null);
1370 /* Add the connection to the context. */
1371 *(serf_connection_t **)apr_array_push(ctx->conns) = conn;
1373 serf__log(CONN_VERBOSE, __FILE__, "created connection 0x%x\n",
1379 apr_status_t serf_connection_create2(
1380 serf_connection_t **conn,
1381 serf_context_t *ctx,
1382 apr_uri_t host_info,
1383 serf_connection_setup_t setup,
1385 serf_connection_closed_t closed,
1389 apr_status_t status = APR_SUCCESS;
1390 serf_connection_t *c;
1391 apr_sockaddr_t *host_address = NULL;
1393 /* Set the port number explicitly, needed to create the socket later. */
1394 if (!host_info.port) {
1395 host_info.port = apr_uri_port_of_scheme(host_info.scheme);
1398 /* Only lookup the address of the server if no proxy server was
1400 if (!ctx->proxy_address) {
1401 status = apr_sockaddr_info_get(&host_address,
1403 APR_UNSPEC, host_info.port, 0, pool);
1408 c = serf_connection_create(ctx, host_address, setup, setup_baton,
1409 closed, closed_baton, pool);
1411 /* We're not interested in the path following the hostname. */
1412 c->host_url = apr_uri_unparse(c->pool,
1414 APR_URI_UNP_OMITPATHINFO |
1415 APR_URI_UNP_OMITUSERINFO);
1417 /* Store the host info without the path on the connection. */
1418 (void)apr_uri_parse(c->pool, c->host_url, &(c->host_info));
1419 if (!c->host_info.port) {
1420 c->host_info.port = apr_uri_port_of_scheme(c->host_info.scheme);
1428 apr_status_t serf_connection_reset(
1429 serf_connection_t *conn)
1431 return reset_connection(conn, 0);
1435 apr_status_t serf_connection_close(
1436 serf_connection_t *conn)
1439 serf_context_t *ctx = conn->ctx;
1440 apr_status_t status;
1442 for (i = ctx->conns->nelts; i--; ) {
1443 serf_connection_t *conn_seq = GET_CONN(ctx, i);
1445 if (conn_seq == conn) {
1446 while (conn->requests) {
1447 serf_request_cancel(conn->requests);
1449 if (conn->skt != NULL) {
1450 remove_connection(ctx, conn);
1451 status = apr_socket_close(conn->skt);
1452 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
1453 "closed socket, status %d\n",
1455 if (conn->closed != NULL) {
1456 handle_conn_closed(conn, status);
1460 if (conn->stream != NULL) {
1461 serf_bucket_destroy(conn->stream);
1462 conn->stream = NULL;
1465 destroy_ostream(conn);
1467 /* Remove the connection from the context. We don't want to
1468 * deal with it any more.
1470 if (i < ctx->conns->nelts - 1) {
1471 /* move later connections over this one. */
1474 &GET_CONN(ctx, i + 1),
1475 (ctx->conns->nelts - i - 1) * sizeof(serf_connection_t *));
1477 --ctx->conns->nelts;
1479 serf__log(CONN_VERBOSE, __FILE__, "closed connection 0x%x\n",
1482 /* Found the connection. Closed it. All done. */
1487 /* We didn't find the specified connection. */
1488 /* ### doc talks about this w.r.t poll structures. use something else? */
1489 return APR_NOTFOUND;
1493 void serf_connection_set_max_outstanding_requests(
1494 serf_connection_t *conn,
1495 unsigned int max_requests)
1497 if (max_requests == 0)
1498 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
1499 "Set max. nr. of outstanding requests for this "
1500 "connection to unlimited.\n");
1502 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
1503 "Limit max. nr. of outstanding requests for this "
1504 "connection to %u.\n", max_requests);
1506 conn->max_outstanding_requests = max_requests;
1510 void serf_connection_set_async_responses(
1511 serf_connection_t *conn,
1512 serf_response_acceptor_t acceptor,
1513 void *acceptor_baton,
1514 serf_response_handler_t handler,
1515 void *handler_baton)
1517 conn->async_responses = 1;
1518 conn->async_acceptor = acceptor;
1519 conn->async_acceptor_baton = acceptor_baton;
1520 conn->async_handler = handler;
1521 conn->async_handler_baton = handler_baton;
1524 static serf_request_t *
1525 create_request(serf_connection_t *conn,
1526 serf_request_setup_t setup,
1531 serf_request_t *request;
1533 request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
1534 request->conn = conn;
1535 request->setup = setup;
1536 request->setup_baton = setup_baton;
1537 request->handler = NULL;
1538 request->respool = NULL;
1539 request->req_bkt = NULL;
1540 request->resp_bkt = NULL;
1541 request->priority = priority;
1542 request->writing_started = 0;
1543 request->ssltunnel = ssltunnel;
1544 request->next = NULL;
1545 request->auth_baton = NULL;
1550 serf_request_t *serf_connection_request_create(
1551 serf_connection_t *conn,
1552 serf_request_setup_t setup,
1555 serf_request_t *request;
1557 request = create_request(conn, setup, setup_baton,
1559 0 /* ssl tunnel */);
1561 /* Link the request to the end of the request chain. */
1562 link_requests(&conn->requests, &conn->requests_tail, request);
1564 /* Ensure our pollset becomes writable in context run */
1565 conn->ctx->dirty_pollset = 1;
1566 conn->dirty_conn = 1;
1571 static serf_request_t *
1572 priority_request_create(serf_connection_t *conn,
1574 serf_request_setup_t setup,
1577 serf_request_t *request;
1578 serf_request_t *iter, *prev;
1580 request = create_request(conn, setup, setup_baton,
1584 /* Link the new request after the last written request. */
1585 iter = conn->requests;
1588 /* Find a request that has data which needs to be delivered. */
1589 while (iter != NULL && iter->req_bkt == NULL && iter->writing_started) {
1594 /* A CONNECT request to setup an ssltunnel has absolute priority over all
1595 other requests on the connection, so:
1596 a. add it first to the queue
1597 b. ensure that other priority requests are added after the CONNECT
1599 if (!request->ssltunnel) {
1600 /* Advance to next non priority request */
1601 while (iter != NULL && iter->priority) {
1608 request->next = iter;
1609 prev->next = request;
1611 request->next = iter;
1612 conn->requests = request;
1615 /* Ensure our pollset becomes writable in context run */
1616 conn->ctx->dirty_pollset = 1;
1617 conn->dirty_conn = 1;
1622 serf_request_t *serf_connection_priority_request_create(
1623 serf_connection_t *conn,
1624 serf_request_setup_t setup,
1627 return priority_request_create(conn,
1628 0, /* not a ssltunnel CONNECT request */
1629 setup, setup_baton);
1632 serf_request_t *serf__ssltunnel_request_create(serf_connection_t *conn,
1633 serf_request_setup_t setup,
1636 return priority_request_create(conn,
1637 1, /* This is a ssltunnel CONNECT request */
1638 setup, setup_baton);
1641 apr_status_t serf_request_cancel(serf_request_t *request)
1643 return cancel_request(request, &request->conn->requests, 0);
1646 apr_status_t serf_request_is_written(serf_request_t *request)
1648 if (request->writing_started && !request->req_bkt)
1654 apr_pool_t *serf_request_get_pool(const serf_request_t *request)
1656 return request->respool;
1660 serf_bucket_alloc_t *serf_request_get_alloc(
1661 const serf_request_t *request)
1663 return request->allocator;
1667 serf_connection_t *serf_request_get_conn(
1668 const serf_request_t *request)
1670 return request->conn;
1674 void serf_request_set_handler(
1675 serf_request_t *request,
1676 const serf_response_handler_t handler,
1677 const void **handler_baton)
1679 request->handler = handler;
1680 request->handler_baton = handler_baton;
1684 serf_bucket_t *serf_request_bucket_request_create(
1685 serf_request_t *request,
1688 serf_bucket_t *body,
1689 serf_bucket_alloc_t *allocator)
1691 serf_bucket_t *req_bkt, *hdrs_bkt;
1692 serf_connection_t *conn = request->conn;
1693 serf_context_t *ctx = conn->ctx;
1696 ssltunnel = ctx->proxy_address &&
1697 (strcmp(conn->host_info.scheme, "https") == 0);
1699 req_bkt = serf_bucket_request_create(method, uri, body, allocator);
1700 hdrs_bkt = serf_bucket_request_get_headers(req_bkt);
1702 /* Use absolute uri's in requests to a proxy. USe relative uri's in
1703 requests directly to a server or sent through an SSL tunnel. */
1704 if (ctx->proxy_address && conn->host_url &&
1705 !(ssltunnel && !request->ssltunnel)) {
1707 serf_bucket_request_set_root(req_bkt, conn->host_url);
1710 if (conn->host_info.hostinfo)
1711 serf_bucket_headers_setn(hdrs_bkt, "Host",
1712 conn->host_info.hostinfo);
1714 /* Setup server authorization headers, unless this is a CONNECT request. */
1715 if (!request->ssltunnel) {
1716 serf__authn_info_t *authn_info;
1717 authn_info = serf__get_authn_info_for_server(conn);
1718 if (authn_info->scheme)
1719 authn_info->scheme->setup_request_func(HOST, 0, conn, request,
1724 /* Setup proxy authorization headers.
1725 Don't set these headers on the requests to the server if we're using
1726 an SSL tunnel, only on the CONNECT request to setup the tunnel. */
1727 if (ctx->proxy_authn_info.scheme) {
1728 if (strcmp(conn->host_info.scheme, "https") == 0) {
1729 if (request->ssltunnel)
1730 ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
1735 ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
1745 apr_interval_time_t serf_connection_get_latency(serf_connection_t *conn)
1747 if (conn->ctx->proxy_address) {
1748 /* Detecting network latency for proxied connection is not implemented
1753 return conn->latency;