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 /* Update the pollset for this connection. We tweak the pollset based on
85 * whether we want to read and/or write, given conditions within the
86 * connection. If the connection is not (yet) in the pollset, then it
89 apr_status_t serf__conn_update_pollset(serf_connection_t *conn)
91 serf_context_t *ctx = conn->ctx;
93 apr_pollfd_t desc = { 0 };
99 /* Remove the socket from the poll set. */
100 desc.desc_type = APR_POLL_SOCKET;
101 desc.desc.s = conn->skt;
102 desc.reqevents = conn->reqevents;
104 status = ctx->pollset_rm(ctx->pollset_baton,
106 if (status && !APR_STATUS_IS_NOTFOUND(status))
109 /* Now put it back in with the correct read/write values. */
110 desc.reqevents = APR_POLLHUP | APR_POLLERR;
111 if (conn->requests &&
112 conn->state != SERF_CONN_INIT) {
113 /* If there are any outstanding events, then we want to read. */
114 /* ### not true. we only want to read IF we have sent some data */
115 desc.reqevents |= APR_POLLIN;
117 /* Don't write if OpenSSL told us that it needs to read data first. */
118 if (conn->stop_writing != 1) {
120 /* If the connection is not closing down and
121 * has unwritten data or
122 * there are any requests that still have buckets to write out,
123 * then we want to write.
126 conn->state != SERF_CONN_CLOSING)
127 desc.reqevents |= APR_POLLOUT;
129 serf_request_t *request = conn->requests;
131 if ((conn->probable_keepalive_limit &&
132 conn->completed_requests > conn->probable_keepalive_limit) ||
133 (conn->max_outstanding_requests &&
134 conn->completed_requests - conn->completed_responses >=
135 conn->max_outstanding_requests)) {
136 /* we wouldn't try to write any way right now. */
139 while (request != NULL && request->req_bkt == NULL &&
141 request = request->next;
143 desc.reqevents |= APR_POLLOUT;
149 /* If we can have async responses, always look for something to read. */
150 if (conn->async_responses) {
151 desc.reqevents |= APR_POLLIN;
154 /* save our reqevents, so we can pass it in to remove later. */
155 conn->reqevents = desc.reqevents;
157 /* Note: even if we don't want to read/write this socket, we still
158 * want to poll it for hangups and errors.
160 return ctx->pollset_add(ctx->pollset_baton,
161 &desc, &conn->baton);
164 #ifdef SERF_DEBUG_BUCKET_USE
166 /* Make sure all response buckets were drained. */
167 static void check_buckets_drained(serf_connection_t *conn)
169 serf_request_t *request = conn->requests;
171 for ( ; request ; request = request->next ) {
172 if (request->resp_bkt != NULL) {
173 /* ### crap. can't do this. this allocator may have un-drained
174 * ### REQUEST buckets.
176 /* serf_debug__entered_loop(request->resp_bkt->allocator); */
177 /* ### for now, pretend we closed the conn (resets the tracking) */
178 serf_debug__closed_conn(request->resp_bkt->allocator);
185 static void destroy_ostream(serf_connection_t *conn)
187 if (conn->ostream_head != NULL) {
188 serf_bucket_destroy(conn->ostream_head);
189 conn->ostream_head = NULL;
190 conn->ostream_tail = NULL;
194 static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
196 serf_connection_t *conn = baton;
201 static apr_status_t do_conn_setup(serf_connection_t *conn)
204 serf_bucket_t *ostream;
206 if (conn->ostream_head == NULL) {
207 conn->ostream_head = serf_bucket_aggregate_create(conn->allocator);
210 if (conn->ostream_tail == NULL) {
211 conn->ostream_tail = serf__bucket_stream_create(conn->allocator,
216 ostream = conn->ostream_tail;
218 status = (*conn->setup)(conn->skt,
224 /* extra destroy here since it wasn't added to the head bucket yet. */
225 serf_bucket_destroy(conn->ostream_tail);
226 destroy_ostream(conn);
230 serf_bucket_aggregate_append(conn->ostream_head,
236 /* Set up the input and output stream buckets.
237 When a tunnel over an http proxy is needed, create a socket bucket and
238 empty aggregate bucket for sending and receiving unencrypted requests
241 After the tunnel is there, or no tunnel was needed, ask the application
242 to create the input and output buckets, which should take care of the
246 static apr_status_t prepare_conn_streams(serf_connection_t *conn,
247 serf_bucket_t **istream,
248 serf_bucket_t **ostreamt,
249 serf_bucket_t **ostreamh)
253 if (conn->stream == NULL) {
254 conn->latency = apr_time_now() - conn->connect_time;
257 /* Do we need a SSL tunnel first? */
258 if (conn->state == SERF_CONN_CONNECTED) {
259 /* If the connection does not have an associated bucket, then
260 * call the setup callback to get one.
262 if (conn->stream == NULL) {
263 status = do_conn_setup(conn);
268 *ostreamt = conn->ostream_tail;
269 *ostreamh = conn->ostream_head;
270 *istream = conn->stream;
272 /* SSL tunnel needed and not set up yet, get a direct unencrypted
273 stream for this socket */
274 if (conn->stream == NULL) {
275 *istream = serf_bucket_socket_create(conn->skt,
278 /* Don't create the ostream bucket chain including the ssl_encrypt
279 bucket yet. This ensure the CONNECT request is sent unencrypted
281 *ostreamt = *ostreamh = conn->ssltunnel_ostream;
287 /* Create and connect sockets for any connections which don't have them
288 * yet. This is the core of our lazy-connect behavior.
290 apr_status_t serf__open_connections(serf_context_t *ctx)
294 for (i = ctx->conns->nelts; i--; ) {
295 serf_connection_t *conn = GET_CONN(ctx, i);
296 serf__authn_info_t *authn_info;
300 conn->seen_in_pollset = 0;
302 if (conn->skt != NULL) {
303 #ifdef SERF_DEBUG_BUCKET_USE
304 check_buckets_drained(conn);
309 /* Delay opening until we have something to deliver! */
310 if (conn->requests == NULL) {
314 apr_pool_clear(conn->skt_pool);
315 apr_pool_cleanup_register(conn->skt_pool, conn, clean_skt, clean_skt);
317 status = apr_socket_create(&skt, conn->address->family,
319 #if APR_MAJOR_VERSION > 0
323 serf__log(SOCK_VERBOSE, __FILE__,
324 "created socket for conn 0x%x, status %d\n", conn, status);
325 if (status != APR_SUCCESS)
328 /* Set the socket to be non-blocking */
329 if ((status = apr_socket_timeout_set(skt, 0)) != APR_SUCCESS)
332 /* Disable Nagle's algorithm */
333 if ((status = apr_socket_opt_set(skt,
334 APR_TCP_NODELAY, 1)) != APR_SUCCESS)
337 /* Configured. Store it into the connection now. */
340 /* Remember time when we started connecting to server to calculate
342 conn->connect_time = apr_time_now();
344 /* Now that the socket is set up, let's connect it. This should
345 * return immediately.
347 status = apr_socket_connect(skt, conn->address);
348 serf__log_skt(SOCK_VERBOSE, __FILE__, skt,
349 "connected socket for conn 0x%x, status %d\n",
351 if (status != APR_SUCCESS) {
352 if (!APR_STATUS_IS_EINPROGRESS(status))
356 /* Flag our pollset as dirty now that we have a new socket. */
357 conn->dirty_conn = 1;
358 ctx->dirty_pollset = 1;
360 /* If the authentication was already started on another connection,
361 prepare this connection (it might be possible to skip some
362 part of the handshaking). */
363 if (ctx->proxy_address) {
364 authn_info = &ctx->proxy_authn_info;
365 if (authn_info->scheme) {
366 authn_info->scheme->init_conn_func(authn_info->scheme, 407,
371 authn_info = serf__get_authn_info_for_server(conn);
372 if (authn_info->scheme) {
373 authn_info->scheme->init_conn_func(authn_info->scheme, 401,
377 /* Does this connection require a SSL tunnel over the proxy? */
378 if (ctx->proxy_address && strcmp(conn->host_info.scheme, "https") == 0)
379 serf__ssltunnel_connect(conn);
381 serf_bucket_t *dummy1, *dummy2;
383 conn->state = SERF_CONN_CONNECTED;
385 status = prepare_conn_streams(conn, &conn->stream,
396 static apr_status_t no_more_writes(serf_connection_t *conn,
397 serf_request_t *request)
399 /* Note that we should hold new requests until we open our new socket. */
400 conn->state = SERF_CONN_CLOSING;
401 serf__log(CONN_VERBOSE, __FILE__, "stop writing on conn 0x%x\n",
404 /* Clear our iovec. */
407 /* Update the pollset to know we don't want to write on this socket any
410 conn->dirty_conn = 1;
411 conn->ctx->dirty_pollset = 1;
415 /* Read the 'Connection' header from the response. Return SERF_ERROR_CLOSING if
416 * the header contains value 'close' indicating the server is closing the
417 * connection right after this response.
418 * Otherwise returns APR_SUCCESS.
420 static apr_status_t is_conn_closing(serf_bucket_t *response)
425 hdrs = serf_bucket_response_get_headers(response);
426 val = serf_bucket_headers_get(hdrs, "Connection");
427 if (val && strcasecmp("close", val) == 0)
429 return SERF_ERROR_CLOSING;
435 static void link_requests(serf_request_t **list, serf_request_t **tail,
436 serf_request_t *request)
443 (*tail)->next = request;
448 static apr_status_t destroy_request(serf_request_t *request)
450 serf_connection_t *conn = request->conn;
452 /* The request and response buckets are no longer needed,
453 nor is the request's pool. */
454 if (request->resp_bkt) {
455 serf_debug__closed_conn(request->resp_bkt->allocator);
456 serf_bucket_destroy(request->resp_bkt);
457 request->resp_bkt = NULL;
459 if (request->req_bkt) {
460 serf_debug__closed_conn(request->req_bkt->allocator);
461 serf_bucket_destroy(request->req_bkt);
462 request->req_bkt = NULL;
465 serf_debug__bucket_alloc_check(request->allocator);
466 if (request->respool) {
467 /* ### unregister the pool cleanup for self? */
468 apr_pool_destroy(request->respool);
471 serf_bucket_mem_free(conn->allocator, request);
476 static apr_status_t cancel_request(serf_request_t *request,
477 serf_request_t **list,
480 /* If we haven't run setup, then we won't have a handler to call. */
481 if (request->handler && notify_request) {
482 /* We actually don't care what the handler returns.
483 * We have bigger matters at hand.
485 (*request->handler)(request, NULL, request->handler_baton,
489 if (*list == request) {
490 *list = request->next;
493 serf_request_t *scan = *list;
495 while (scan->next && scan->next != request)
499 scan->next = scan->next->next;
503 return destroy_request(request);
506 static apr_status_t remove_connection(serf_context_t *ctx,
507 serf_connection_t *conn)
509 apr_pollfd_t desc = { 0 };
511 desc.desc_type = APR_POLL_SOCKET;
512 desc.desc.s = conn->skt;
513 desc.reqevents = conn->reqevents;
515 return ctx->pollset_rm(ctx->pollset_baton,
519 /* A socket was closed, inform the application. */
520 static void handle_conn_closed(serf_connection_t *conn, apr_status_t status)
522 (*conn->closed)(conn, conn->closed_baton, status,
526 static apr_status_t reset_connection(serf_connection_t *conn,
527 int requeue_requests)
529 serf_context_t *ctx = conn->ctx;
531 serf_request_t *old_reqs;
533 conn->probable_keepalive_limit = conn->completed_responses;
534 conn->completed_requests = 0;
535 conn->completed_responses = 0;
537 old_reqs = conn->requests;
539 conn->requests = NULL;
540 conn->requests_tail = NULL;
542 /* Handle all outstanding requests. These have either not been written yet,
543 or have been written but the expected reply wasn't received yet. */
545 /* If we haven't started to write the connection, bring it over
546 * unchanged to our new socket.
548 if (requeue_requests && !old_reqs->written) {
549 serf_request_t *req = old_reqs;
550 old_reqs = old_reqs->next;
552 link_requests(&conn->requests, &conn->requests_tail, req);
555 /* Request has been consumed, or we don't want to requeue the
556 request. Either way, inform the application that the request
558 cancel_request(old_reqs, &old_reqs, requeue_requests);
562 /* Requests queue has been prepared for a new socket, close the old one. */
563 if (conn->skt != NULL) {
564 remove_connection(ctx, conn);
565 status = apr_socket_close(conn->skt);
566 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
567 "closed socket, status %d\n", status);
568 if (conn->closed != NULL) {
569 handle_conn_closed(conn, status);
574 if (conn->stream != NULL) {
575 serf_bucket_destroy(conn->stream);
579 destroy_ostream(conn);
581 /* Don't try to resume any writes */
584 conn->dirty_conn = 1;
585 conn->ctx->dirty_pollset = 1;
586 conn->state = SERF_CONN_INIT;
588 serf__log(CONN_VERBOSE, __FILE__, "reset connection 0x%x\n", conn);
590 conn->status = APR_SUCCESS;
592 /* Let our context know that we've 'reset' the socket already. */
593 conn->seen_in_pollset |= APR_POLLHUP;
595 /* Found the connection. Closed it. All done. */
599 static apr_status_t socket_writev(serf_connection_t *conn)
604 status = apr_socket_sendv(conn->skt, conn->vec,
605 conn->vec_len, &written);
606 if (status && !APR_STATUS_IS_EAGAIN(status))
607 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
608 "socket_sendv error %d\n", status);
610 /* did we write everything? */
615 serf__log_skt(SOCK_MSG_VERBOSE, __FILE__, conn->skt,
616 "--- socket_sendv:\n");
618 for (i = 0; i < conn->vec_len; i++) {
619 len += conn->vec[i].iov_len;
621 serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s",
622 conn->vec[i].iov_len - (len - written),
623 conn->vec[i].iov_base);
625 memmove(conn->vec, &conn->vec[i],
626 sizeof(struct iovec) * (conn->vec_len - i));
629 conn->vec[0].iov_base = (char *)conn->vec[0].iov_base + (conn->vec[0].iov_len - (len - written));
630 conn->vec[0].iov_len = len - written;
633 serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s",
634 conn->vec[i].iov_len, conn->vec[i].iov_base);
637 if (len == written) {
640 serf__log_nopref(SOCK_MSG_VERBOSE, "-(%d)-\n", written);
642 /* Log progress information */
643 serf__context_progress_delta(conn->ctx, 0, written);
649 static apr_status_t setup_request(serf_request_t *request)
651 serf_connection_t *conn = request->conn;
654 /* Now that we are about to serve the request, allocate a pool. */
655 apr_pool_create(&request->respool, conn->pool);
656 request->allocator = serf_bucket_allocator_create(request->respool,
658 apr_pool_cleanup_register(request->respool, request,
659 clean_resp, clean_resp);
661 /* Fill in the rest of the values for the request. */
662 status = request->setup(request, request->setup_baton,
665 &request->acceptor_baton,
667 &request->handler_baton,
672 /* write data out to the connection */
673 static apr_status_t write_to_connection(serf_connection_t *conn)
675 serf_request_t *request = conn->requests;
677 if (conn->probable_keepalive_limit &&
678 conn->completed_requests > conn->probable_keepalive_limit) {
680 conn->dirty_conn = 1;
681 conn->ctx->dirty_pollset = 1;
683 /* backoff for now. */
687 /* Find a request that has data which needs to be delivered. */
688 while (request != NULL &&
689 request->req_bkt == NULL && request->written)
690 request = request->next;
692 /* assert: request != NULL || conn->vec_len */
694 /* Keep reading and sending until we run out of stuff to read, or
695 * writing would block.
698 int stop_reading = 0;
700 apr_status_t read_status;
701 serf_bucket_t *ostreamt, *ostreamh;
702 int max_outstanding_requests = conn->max_outstanding_requests;
704 /* If we're setting up an ssl tunnel, we can't send real requests
705 at yet, as they need to be encrypted and our encrypt buckets
706 aren't created yet as we still need to read the unencrypted
707 response of the CONNECT request. */
708 if (conn->state != SERF_CONN_CONNECTED)
709 max_outstanding_requests = 1;
711 if (max_outstanding_requests &&
712 conn->completed_requests -
713 conn->completed_responses >= max_outstanding_requests) {
714 /* backoff for now. */
718 /* If we have unwritten data, then write what we can. */
719 while (conn->vec_len) {
720 status = socket_writev(conn);
722 /* If the write would have blocked, then we're done. Don't try
723 * to write anything else to the socket.
725 if (APR_STATUS_IS_EAGAIN(status))
727 if (APR_STATUS_IS_EPIPE(status) ||
728 APR_STATUS_IS_ECONNRESET(status) ||
729 APR_STATUS_IS_ECONNABORTED(status))
730 return no_more_writes(conn, request);
734 /* ### can we have a short write, yet no EAGAIN? a short write
735 ### would imply unwritten_len > 0 ... */
736 /* assert: unwritten_len == 0. */
738 /* We may need to move forward to a request which has something
741 while (request != NULL &&
742 request->req_bkt == NULL && request->written)
743 request = request->next;
745 if (request == NULL) {
746 /* No more requests (with data) are registered with the
747 * connection. Let's update the pollset so that we don't
748 * try to write to this socket again.
750 conn->dirty_conn = 1;
751 conn->ctx->dirty_pollset = 1;
755 status = prepare_conn_streams(conn, &conn->stream, &ostreamt, &ostreamh);
760 if (request->req_bkt == NULL) {
761 read_status = setup_request(request);
763 /* Something bad happened. Propagate any errors. */
768 if (!request->written) {
769 request->written = 1;
770 serf_bucket_aggregate_append(ostreamt, request->req_bkt);
773 /* ### optimize at some point by using read_for_sendfile */
774 /* TODO: now that read_iovec will effectively try to return as much
775 data as available, we probably don't want to read ALL_AVAIL, but
776 a lower number, like the size of one or a few TCP packets, the
777 available TCP buffer size ... */
778 read_status = serf_bucket_read_iovec(ostreamh,
784 if (!conn->hit_eof) {
785 if (APR_STATUS_IS_EAGAIN(read_status)) {
786 /* We read some stuff, but should not try to read again. */
789 else if (read_status == SERF_ERROR_WAIT_CONN) {
790 /* The bucket told us that it can't provide more data until
791 more data is read from the socket. This normally happens
792 during a SSL handshake.
794 We should avoid looking for writability for a while so
795 that (hopefully) something will appear in the bucket so
796 we can actually write something. otherwise, we could
797 end up in a CPU spin: socket wants something, but we
798 don't have anything (and keep returning EAGAIN)
800 conn->stop_writing = 1;
801 conn->dirty_conn = 1;
802 conn->ctx->dirty_pollset = 1;
804 else if (read_status && !APR_STATUS_IS_EOF(read_status)) {
805 /* Something bad happened. Propagate any errors. */
810 /* If we got some data, then deliver it. */
811 /* ### what to do if we got no data?? is that a problem? */
812 if (conn->vec_len > 0) {
813 status = socket_writev(conn);
815 /* If we can't write any more, or an error occurred, then
818 if (APR_STATUS_IS_EAGAIN(status))
820 if (APR_STATUS_IS_EPIPE(status))
821 return no_more_writes(conn, request);
822 if (APR_STATUS_IS_ECONNRESET(status) ||
823 APR_STATUS_IS_ECONNABORTED(status)) {
824 return no_more_writes(conn, request);
830 if (read_status == SERF_ERROR_WAIT_CONN) {
832 conn->stop_writing = 1;
833 conn->dirty_conn = 1;
834 conn->ctx->dirty_pollset = 1;
836 else if (read_status && conn->hit_eof && conn->vec_len == 0) {
837 /* If we hit the end of the request bucket and all of its data has
838 * been written, then clear it out to signify that we're done
839 * sending the request. On the next iteration through this loop:
840 * - if there are remaining bytes they will be written, and as the
841 * request bucket will be completely read it will be destroyed then.
842 * - we'll see if there are other requests that need to be sent
846 serf_bucket_destroy(request->req_bkt);
847 request->req_bkt = NULL;
849 /* If our connection has async responses enabled, we're not
850 * going to get a reply back, so kill the request.
852 if (conn->async_responses) {
853 conn->requests = request->next;
854 destroy_request(request);
857 conn->completed_requests++;
859 if (conn->probable_keepalive_limit &&
860 conn->completed_requests > conn->probable_keepalive_limit) {
861 /* backoff for now. */
873 /* A response message was received from the server, so call
874 the handler as specified on the original request. */
875 static apr_status_t handle_response(serf_request_t *request,
878 apr_status_t status = APR_SUCCESS;
879 int consumed_response = 0;
881 /* Only enable the new authentication framework if the program has
882 * registered an authentication credential callback.
884 * This permits older Serf apps to still handle authentication
885 * themselves by not registering credential callbacks.
887 if (request->conn->ctx->cred_cb) {
888 status = serf__handle_auth_response(&consumed_response,
891 request->handler_baton,
894 /* If there was an error reading the response (maybe there wasn't
895 enough data available), don't bother passing the response to the
898 If the authentication was tried, but failed, pass the response
899 to the application, maybe it can do better. */
900 if (APR_STATUS_IS_EOF(status) ||
901 APR_STATUS_IS_EAGAIN(status)) {
906 if (!consumed_response) {
907 return (*request->handler)(request,
909 request->handler_baton,
916 /* An async response message was received from the server. */
917 static apr_status_t handle_async_response(serf_connection_t *conn,
922 if (conn->current_async_response == NULL) {
923 conn->current_async_response =
924 (*conn->async_acceptor)(NULL, conn->stream,
925 conn->async_acceptor_baton, pool);
928 status = (*conn->async_handler)(NULL, conn->current_async_response,
929 conn->async_handler_baton, pool);
931 if (APR_STATUS_IS_EOF(status)) {
932 serf_bucket_destroy(conn->current_async_response);
933 conn->current_async_response = NULL;
934 status = APR_SUCCESS;
942 serf__provide_credentials(serf_context_t *ctx,
945 serf_request_t *request, void *baton,
946 int code, const char *authn_type,
950 serf_connection_t *conn = request->conn;
951 serf_request_t *authn_req = request;
954 if (request->ssltunnel == 1 &&
955 conn->state == SERF_CONN_SETUP_SSLTUNNEL) {
956 /* This is a CONNECT request to set up an SSL tunnel over a proxy.
957 This request is created by serf, so if the proxy requires
958 authentication, we can't ask the application for credentials with
961 Solution: setup the first request created by the application on
962 this connection, and use that request and its handler_baton to
963 call back to the application. */
965 authn_req = request->next;
966 /* assert: app_request != NULL */
970 if (!authn_req->req_bkt) {
973 status = setup_request(authn_req);
974 /* If we can't setup a request, don't bother setting up the
981 /* Ask the application. */
982 status = (*ctx->cred_cb)(username, password,
983 authn_req, authn_req->handler_baton,
984 code, authn_type, realm, pool);
991 /* read data from the connection */
992 static apr_status_t read_from_connection(serf_connection_t *conn)
996 int close_connection = FALSE;
998 /* Whatever is coming in on the socket corresponds to the first request
1001 serf_request_t *request = conn->requests;
1003 /* If the stop_writing flag was set on the connection, reset it now because
1004 there is some data to read. */
1005 if (conn->stop_writing) {
1006 conn->stop_writing = 0;
1007 conn->dirty_conn = 1;
1008 conn->ctx->dirty_pollset = 1;
1011 /* assert: request != NULL */
1013 if ((status = apr_pool_create(&tmppool, conn->pool)) != APR_SUCCESS)
1016 /* Invoke response handlers until we have no more work. */
1018 serf_bucket_t *dummy1, *dummy2;
1020 apr_pool_clear(tmppool);
1022 /* Only interested in the input stream here. */
1023 status = prepare_conn_streams(conn, &conn->stream, &dummy1, &dummy2);
1028 /* We have a different codepath when we can have async responses. */
1029 if (conn->async_responses) {
1030 /* TODO What about socket errors? */
1031 status = handle_async_response(conn, tmppool);
1032 if (APR_STATUS_IS_EAGAIN(status)) {
1033 status = APR_SUCCESS;
1042 /* We are reading a response for a request we haven't
1045 * This shouldn't normally happen EXCEPT:
1047 * 1) when the other end has closed the socket and we're
1048 * pending an EOF return.
1049 * 2) Doing the initial SSL handshake - we'll get EAGAIN
1050 * as the SSL buckets will hide the handshake from us
1051 * but not return any data.
1052 * 3) When the server sends us an SSL alert.
1054 * In these cases, we should not receive any actual user data.
1056 * 4) When the server sends a error response, like 408 Request timeout.
1057 * This response should be passed to the application.
1059 * If we see an EOF (due to either an expired timeout or the server
1060 * sending the SSL 'close notify' shutdown alert), we'll reset the
1061 * connection and open a new one.
1063 if (request->req_bkt || !request->written) {
1067 status = serf_bucket_peek(conn->stream, &data, &len);
1069 if (APR_STATUS_IS_EOF(status)) {
1070 reset_connection(conn, 1);
1071 status = APR_SUCCESS;
1074 else if (APR_STATUS_IS_EAGAIN(status) && !len) {
1075 status = APR_SUCCESS;
1077 } else if (status && !APR_STATUS_IS_EAGAIN(status)) {
1082 /* Unexpected response from the server */
1086 /* If the request doesn't have a response bucket, then call the
1087 * acceptor to get one created.
1089 if (request->resp_bkt == NULL) {
1090 request->resp_bkt = (*request->acceptor)(request, conn->stream,
1091 request->acceptor_baton,
1093 apr_pool_clear(tmppool);
1096 status = handle_response(request, tmppool);
1098 /* Some systems will not generate a HUP poll event so we have to
1099 * handle the ECONNRESET issue and ECONNABORT here.
1101 if (APR_STATUS_IS_ECONNRESET(status) ||
1102 APR_STATUS_IS_ECONNABORTED(status) ||
1103 status == SERF_ERROR_REQUEST_LOST) {
1104 /* If the connection had ever been good, be optimistic & try again.
1105 * If it has never tried again (incl. a retry), fail.
1107 if (conn->completed_responses) {
1108 reset_connection(conn, 1);
1109 status = APR_SUCCESS;
1111 else if (status == SERF_ERROR_REQUEST_LOST) {
1112 status = SERF_ERROR_ABORTED_CONNECTION;
1117 /* If our response handler says it can't do anything more, we now
1118 * treat that as a success.
1120 if (APR_STATUS_IS_EAGAIN(status)) {
1121 status = APR_SUCCESS;
1125 /* If we received APR_SUCCESS, run this loop again. */
1130 close_connection = is_conn_closing(request->resp_bkt);
1132 if (!APR_STATUS_IS_EOF(status) &&
1133 close_connection != SERF_ERROR_CLOSING) {
1134 /* Whether success, or an error, there is no more to do unless
1135 * this request has been completed.
1140 /* The response has been fully-read, so that means the request has
1141 * either been fully-delivered (most likely), or that we don't need to
1142 * write the rest of it anymore, e.g. when a 408 Request timeout was
1144 * Remove it from our queue and loop to read another response.
1146 conn->requests = request->next;
1148 destroy_request(request);
1150 request = conn->requests;
1152 /* If we're truly empty, update our tail. */
1153 if (request == NULL) {
1154 conn->requests_tail = NULL;
1157 conn->completed_responses++;
1159 /* We've to rebuild pollset since completed_responses is changed. */
1160 conn->dirty_conn = 1;
1161 conn->ctx->dirty_pollset = 1;
1163 /* This means that we're being advised that the connection is done. */
1164 if (close_connection == SERF_ERROR_CLOSING) {
1165 reset_connection(conn, 1);
1166 if (APR_STATUS_IS_EOF(status))
1167 status = APR_SUCCESS;
1171 /* The server is suddenly deciding to serve more responses than we've
1174 * Let our requests go.
1176 if (conn->probable_keepalive_limit &&
1177 conn->completed_responses > conn->probable_keepalive_limit) {
1178 conn->probable_keepalive_limit = 0;
1181 /* If we just ran out of requests or have unwritten requests, then
1182 * update the pollset. We don't want to read from this socket any
1183 * more. We are definitely done with this loop, too.
1185 if (request == NULL || !request->written) {
1186 conn->dirty_conn = 1;
1187 conn->ctx->dirty_pollset = 1;
1188 status = APR_SUCCESS;
1194 apr_pool_destroy(tmppool);
1198 /* process all events on the connection */
1199 apr_status_t serf__process_connection(serf_connection_t *conn,
1202 apr_status_t status;
1204 /* POLLHUP/ERR should come after POLLIN so if there's an error message or
1205 * the like sitting on the connection, we give the app a chance to read
1206 * it before we trigger a reset condition.
1208 if ((events & APR_POLLIN) != 0) {
1209 if ((status = read_from_connection(conn)) != APR_SUCCESS)
1212 /* If we decided to reset our connection, return now as we don't
1215 if ((conn->seen_in_pollset & APR_POLLHUP) != 0) {
1219 if ((events & APR_POLLHUP) != 0) {
1220 /* The connection got reset by the server. On Windows this can happen
1221 when all data is read, so just cleanup the connection and open
1223 If we haven't had any successful responses on this connection,
1224 then error out as it is likely a server issue. */
1225 if (conn->completed_responses) {
1226 return reset_connection(conn, 1);
1228 return SERF_ERROR_ABORTED_CONNECTION;
1230 if ((events & APR_POLLERR) != 0) {
1231 /* We might be talking to a buggy HTTP server that doesn't
1232 * do lingering-close. (httpd < 2.1.8 does this.)
1236 * http://issues.apache.org/bugzilla/show_bug.cgi?id=35292
1238 if (conn->completed_requests && !conn->probable_keepalive_limit) {
1239 return reset_connection(conn, 1);
1242 /* If possible, get the error from the platform's socket layer and
1243 convert it to an APR status code. */
1245 apr_os_sock_t osskt;
1246 if (!apr_os_sock_get(&osskt, conn->skt)) {
1248 apr_socklen_t l = sizeof(error);
1250 if (!getsockopt(osskt, SOL_SOCKET, SO_ERROR, (char*)&error, &l))
1251 return APR_FROM_OS_ERROR(error);
1255 return APR_EGENERAL;
1257 if ((events & APR_POLLOUT) != 0) {
1258 if ((status = write_to_connection(conn)) != APR_SUCCESS)
1264 serf_connection_t *serf_connection_create(
1265 serf_context_t *ctx,
1266 apr_sockaddr_t *address,
1267 serf_connection_setup_t setup,
1269 serf_connection_closed_t closed,
1273 serf_connection_t *conn = apr_pcalloc(pool, sizeof(*conn));
1276 conn->status = APR_SUCCESS;
1277 /* Ignore server address if proxy was specified. */
1278 conn->address = ctx->proxy_address ? ctx->proxy_address : address;
1279 conn->setup = setup;
1280 conn->setup_baton = setup_baton;
1281 conn->closed = closed;
1282 conn->closed_baton = closed_baton;
1284 conn->allocator = serf_bucket_allocator_create(pool, NULL, NULL);
1285 conn->stream = NULL;
1286 conn->ostream_head = NULL;
1287 conn->ostream_tail = NULL;
1288 conn->baton.type = SERF_IO_CONN;
1289 conn->baton.u.conn = conn;
1291 conn->state = SERF_CONN_INIT;
1292 conn->latency = -1; /* unknown */
1294 /* Create a subpool for our connection. */
1295 apr_pool_create(&conn->skt_pool, conn->pool);
1297 /* register a cleanup */
1298 apr_pool_cleanup_register(conn->pool, conn, clean_conn,
1299 apr_pool_cleanup_null);
1301 /* Add the connection to the context. */
1302 *(serf_connection_t **)apr_array_push(ctx->conns) = conn;
1304 serf__log(CONN_VERBOSE, __FILE__, "created connection 0x%x\n",
1310 apr_status_t serf_connection_create2(
1311 serf_connection_t **conn,
1312 serf_context_t *ctx,
1313 apr_uri_t host_info,
1314 serf_connection_setup_t setup,
1316 serf_connection_closed_t closed,
1320 apr_status_t status = APR_SUCCESS;
1321 serf_connection_t *c;
1322 apr_sockaddr_t *host_address = NULL;
1324 /* Set the port number explicitly, needed to create the socket later. */
1325 if (!host_info.port) {
1326 host_info.port = apr_uri_port_of_scheme(host_info.scheme);
1329 /* Only lookup the address of the server if no proxy server was
1331 if (!ctx->proxy_address) {
1332 status = apr_sockaddr_info_get(&host_address,
1334 APR_UNSPEC, host_info.port, 0, pool);
1339 c = serf_connection_create(ctx, host_address, setup, setup_baton,
1340 closed, closed_baton, pool);
1342 /* We're not interested in the path following the hostname. */
1343 c->host_url = apr_uri_unparse(c->pool,
1345 APR_URI_UNP_OMITPATHINFO);
1347 /* Store the host info without the path on the connection. */
1348 (void)apr_uri_parse(c->pool, c->host_url, &(c->host_info));
1349 if (!c->host_info.port) {
1350 c->host_info.port = apr_uri_port_of_scheme(c->host_info.scheme);
1358 apr_status_t serf_connection_reset(
1359 serf_connection_t *conn)
1361 return reset_connection(conn, 0);
1365 apr_status_t serf_connection_close(
1366 serf_connection_t *conn)
1369 serf_context_t *ctx = conn->ctx;
1370 apr_status_t status;
1372 for (i = ctx->conns->nelts; i--; ) {
1373 serf_connection_t *conn_seq = GET_CONN(ctx, i);
1375 if (conn_seq == conn) {
1376 while (conn->requests) {
1377 serf_request_cancel(conn->requests);
1379 if (conn->skt != NULL) {
1380 remove_connection(ctx, conn);
1381 status = apr_socket_close(conn->skt);
1382 serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
1383 "closed socket, status %d\n",
1385 if (conn->closed != NULL) {
1386 handle_conn_closed(conn, status);
1390 if (conn->stream != NULL) {
1391 serf_bucket_destroy(conn->stream);
1392 conn->stream = NULL;
1395 destroy_ostream(conn);
1397 /* Remove the connection from the context. We don't want to
1398 * deal with it any more.
1400 if (i < ctx->conns->nelts - 1) {
1401 /* move later connections over this one. */
1404 &GET_CONN(ctx, i + 1),
1405 (ctx->conns->nelts - i - 1) * sizeof(serf_connection_t *));
1407 --ctx->conns->nelts;
1409 serf__log(CONN_VERBOSE, __FILE__, "closed connection 0x%x\n",
1412 /* Found the connection. Closed it. All done. */
1417 /* We didn't find the specified connection. */
1418 /* ### doc talks about this w.r.t poll structures. use something else? */
1419 return APR_NOTFOUND;
1423 void serf_connection_set_max_outstanding_requests(
1424 serf_connection_t *conn,
1425 unsigned int max_requests)
1427 if (max_requests == 0)
1428 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
1429 "Set max. nr. of outstanding requests for this "
1430 "connection to unlimited.\n");
1432 serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
1433 "Limit max. nr. of outstanding requests for this "
1434 "connection to %u.\n", max_requests);
1436 conn->max_outstanding_requests = max_requests;
1440 void serf_connection_set_async_responses(
1441 serf_connection_t *conn,
1442 serf_response_acceptor_t acceptor,
1443 void *acceptor_baton,
1444 serf_response_handler_t handler,
1445 void *handler_baton)
1447 conn->async_responses = 1;
1448 conn->async_acceptor = acceptor;
1449 conn->async_acceptor_baton = acceptor_baton;
1450 conn->async_handler = handler;
1451 conn->async_handler_baton = handler_baton;
1454 static serf_request_t *
1455 create_request(serf_connection_t *conn,
1456 serf_request_setup_t setup,
1461 serf_request_t *request;
1463 request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
1464 request->conn = conn;
1465 request->setup = setup;
1466 request->setup_baton = setup_baton;
1467 request->handler = NULL;
1468 request->respool = NULL;
1469 request->req_bkt = NULL;
1470 request->resp_bkt = NULL;
1471 request->priority = priority;
1472 request->written = 0;
1473 request->ssltunnel = ssltunnel;
1474 request->next = NULL;
1479 serf_request_t *serf_connection_request_create(
1480 serf_connection_t *conn,
1481 serf_request_setup_t setup,
1484 serf_request_t *request;
1486 request = create_request(conn, setup, setup_baton,
1488 0 /* ssl tunnel */);
1490 /* Link the request to the end of the request chain. */
1491 link_requests(&conn->requests, &conn->requests_tail, request);
1493 /* Ensure our pollset becomes writable in context run */
1494 conn->ctx->dirty_pollset = 1;
1495 conn->dirty_conn = 1;
1500 static serf_request_t *
1501 priority_request_create(serf_connection_t *conn,
1503 serf_request_setup_t setup,
1506 serf_request_t *request;
1507 serf_request_t *iter, *prev;
1509 request = create_request(conn, setup, setup_baton,
1513 /* Link the new request after the last written request. */
1514 iter = conn->requests;
1517 /* Find a request that has data which needs to be delivered. */
1518 while (iter != NULL && iter->req_bkt == NULL && iter->written) {
1523 /* A CONNECT request to setup an ssltunnel has absolute priority over all
1524 other requests on the connection, so:
1525 a. add it first to the queue
1526 b. ensure that other priority requests are added after the CONNECT
1528 if (!request->ssltunnel) {
1529 /* Advance to next non priority request */
1530 while (iter != NULL && iter->priority) {
1537 request->next = iter;
1538 prev->next = request;
1540 request->next = iter;
1541 conn->requests = request;
1544 /* Ensure our pollset becomes writable in context run */
1545 conn->ctx->dirty_pollset = 1;
1546 conn->dirty_conn = 1;
1551 serf_request_t *serf_connection_priority_request_create(
1552 serf_connection_t *conn,
1553 serf_request_setup_t setup,
1556 return priority_request_create(conn,
1557 0, /* not a ssltunnel CONNECT request */
1558 setup, setup_baton);
1561 serf_request_t *serf__ssltunnel_request_create(serf_connection_t *conn,
1562 serf_request_setup_t setup,
1565 return priority_request_create(conn,
1566 1, /* This is a ssltunnel CONNECT request */
1567 setup, setup_baton);
1570 apr_status_t serf_request_cancel(serf_request_t *request)
1572 return cancel_request(request, &request->conn->requests, 0);
1575 apr_status_t serf_request_is_written(serf_request_t *request)
1577 if (request->written && !request->req_bkt)
1583 apr_pool_t *serf_request_get_pool(const serf_request_t *request)
1585 return request->respool;
1589 serf_bucket_alloc_t *serf_request_get_alloc(
1590 const serf_request_t *request)
1592 return request->allocator;
1596 serf_connection_t *serf_request_get_conn(
1597 const serf_request_t *request)
1599 return request->conn;
1603 void serf_request_set_handler(
1604 serf_request_t *request,
1605 const serf_response_handler_t handler,
1606 const void **handler_baton)
1608 request->handler = handler;
1609 request->handler_baton = handler_baton;
1613 serf_bucket_t *serf_request_bucket_request_create(
1614 serf_request_t *request,
1617 serf_bucket_t *body,
1618 serf_bucket_alloc_t *allocator)
1620 serf_bucket_t *req_bkt, *hdrs_bkt;
1621 serf_connection_t *conn = request->conn;
1622 serf_context_t *ctx = conn->ctx;
1625 ssltunnel = ctx->proxy_address &&
1626 (strcmp(conn->host_info.scheme, "https") == 0);
1628 req_bkt = serf_bucket_request_create(method, uri, body, allocator);
1629 hdrs_bkt = serf_bucket_request_get_headers(req_bkt);
1631 /* Use absolute uri's in requests to a proxy. USe relative uri's in
1632 requests directly to a server or sent through an SSL tunnel. */
1633 if (ctx->proxy_address && conn->host_url &&
1634 !(ssltunnel && !request->ssltunnel)) {
1636 serf_bucket_request_set_root(req_bkt, conn->host_url);
1639 if (conn->host_info.hostinfo)
1640 serf_bucket_headers_setn(hdrs_bkt, "Host",
1641 conn->host_info.hostinfo);
1643 /* Setup server authorization headers, unless this is a CONNECT request. */
1644 if (!request->ssltunnel) {
1645 serf__authn_info_t *authn_info;
1646 authn_info = serf__get_authn_info_for_server(conn);
1647 if (authn_info->scheme)
1648 authn_info->scheme->setup_request_func(HOST, 0, conn, request,
1653 /* Setup proxy authorization headers.
1654 Don't set these headers on the requests to the server if we're using
1655 an SSL tunnel, only on the CONNECT request to setup the tunnel. */
1656 if (ctx->proxy_authn_info.scheme) {
1657 if (strcmp(conn->host_info.scheme, "https") == 0) {
1658 if (request->ssltunnel)
1659 ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
1664 ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
1674 apr_interval_time_t serf_connection_get_latency(serf_connection_t *conn)
1676 if (conn->ctx->proxy_address) {
1677 /* Detecting network latency for proxied connection is not implemented
1682 return conn->latency;