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>
21
#include "serf_bucket_util.h"
23
#include "serf_private.h"
25
/* cleanup for sockets */
26
static apr_status_t clean_skt(void *data)
28
serf_connection_t *conn = data;
29
apr_status_t status = APR_SUCCESS;
32
status = apr_socket_close(conn->skt);
39
static apr_status_t clean_resp(void *data)
41
serf_request_t *req = data;
43
/* This pool just got cleared/destroyed. Don't try to destroy the pool
44
* (again) when the request is canceled.
51
/* cleanup for conns */
52
static apr_status_t clean_conn(void *data)
54
serf_connection_t *conn = data;
56
serf_connection_close(conn);
61
/* Update the pollset for this connection. We tweak the pollset based on
62
* whether we want to read and/or write, given conditions within the
63
* connection. If the connection is not (yet) in the pollset, then it
66
apr_status_t serf__conn_update_pollset(serf_connection_t *conn)
68
serf_context_t *ctx = conn->ctx;
70
apr_pollfd_t desc = { 0 };
76
/* Remove the socket from the poll set. */
77
desc.desc_type = APR_POLL_SOCKET;
78
desc.desc.s = conn->skt;
79
desc.reqevents = conn->reqevents;
81
status = ctx->pollset_rm(ctx->pollset_baton,
83
if (status && !APR_STATUS_IS_NOTFOUND(status))
86
/* Now put it back in with the correct read/write values. */
87
desc.reqevents = APR_POLLHUP | APR_POLLERR;
89
/* If there are any outstanding events, then we want to read. */
90
/* ### not true. we only want to read IF we have sent some data */
91
desc.reqevents |= APR_POLLIN;
93
/* If the connection has unwritten data, or there are any requests
94
* that still have buckets to write out, then we want to write.
97
desc.reqevents |= APR_POLLOUT;
99
serf_request_t *request = conn->requests;
101
if ((conn->probable_keepalive_limit &&
102
conn->completed_requests > conn->probable_keepalive_limit) ||
103
(conn->max_outstanding_requests &&
104
conn->completed_requests - conn->completed_responses >=
105
conn->max_outstanding_requests)) {
106
/* we wouldn't try to write any way right now. */
109
while (request != NULL && request->req_bkt == NULL &&
111
request = request->next;
113
desc.reqevents |= APR_POLLOUT;
118
/* If we can have async responses, always look for something to read. */
119
if (conn->async_responses) {
120
desc.reqevents |= APR_POLLIN;
123
/* save our reqevents, so we can pass it in to remove later. */
124
conn->reqevents = desc.reqevents;
126
/* Note: even if we don't want to read/write this socket, we still
127
* want to poll it for hangups and errors.
129
return ctx->pollset_add(ctx->pollset_baton,
130
&desc, &conn->baton);
133
#ifdef SERF_DEBUG_BUCKET_USE
135
/* Make sure all response buckets were drained. */
136
static void check_buckets_drained(serf_connection_t *conn)
138
serf_request_t *request = conn->requests;
140
for ( ; request ; request = request->next ) {
141
if (request->resp_bkt != NULL) {
142
/* ### crap. can't do this. this allocator may have un-drained
143
* ### REQUEST buckets.
145
/* serf_debug__entered_loop(request->resp_bkt->allocator); */
146
/* ### for now, pretend we closed the conn (resets the tracking) */
147
serf_debug__closed_conn(request->resp_bkt->allocator);
154
/* Create and connect sockets for any connections which don't have them
155
* yet. This is the core of our lazy-connect behavior.
157
apr_status_t serf__open_connections(serf_context_t *ctx)
161
for (i = ctx->conns->nelts; i--; ) {
162
serf_connection_t *conn = GET_CONN(ctx, i);
165
apr_sockaddr_t *serv_addr;
167
conn->seen_in_pollset = 0;
169
if (conn->skt != NULL) {
170
#ifdef SERF_DEBUG_BUCKET_USE
171
check_buckets_drained(conn);
176
/* Delay opening until we have something to deliver! */
177
if (conn->requests == NULL) {
181
apr_pool_clear(conn->skt_pool);
182
apr_pool_cleanup_register(conn->skt_pool, conn, clean_skt, clean_skt);
184
/* Do we have to connect to a proxy server? */
185
if (ctx->proxy_address)
186
serv_addr = ctx->proxy_address;
188
serv_addr = conn->address;
190
if ((status = apr_socket_create(&skt, serv_addr->family,
192
#if APR_MAJOR_VERSION > 0
195
conn->skt_pool)) != APR_SUCCESS)
198
/* Set the socket to be non-blocking */
199
if ((status = apr_socket_timeout_set(skt, 0)) != APR_SUCCESS)
202
/* Disable Nagle's algorithm */
203
if ((status = apr_socket_opt_set(skt,
204
APR_TCP_NODELAY, 1)) != APR_SUCCESS)
207
/* Configured. Store it into the connection now. */
210
/* Now that the socket is set up, let's connect it. This should
211
* return immediately.
213
if ((status = apr_socket_connect(skt,
214
serv_addr)) != APR_SUCCESS) {
215
if (!APR_STATUS_IS_EINPROGRESS(status))
219
/* Flag our pollset as dirty now that we have a new socket. */
220
conn->dirty_conn = 1;
221
ctx->dirty_pollset = 1;
223
/* If the authentication was already started on another connection,
224
prepare this connection (it might be possible to skip some
225
part of the handshaking). */
226
if (ctx->proxy_address) {
227
if (conn->ctx->proxy_authn_info.scheme)
228
conn->ctx->proxy_authn_info.scheme->init_conn_func(407, conn,
232
if (conn->ctx->authn_info.scheme)
233
conn->ctx->authn_info.scheme->init_conn_func(401, conn,
240
static apr_status_t no_more_writes(serf_connection_t *conn,
241
serf_request_t *request)
243
/* Note that we should hold new requests until we open our new socket. */
246
/* We can take the *next* request in our list and assume it hasn't
247
* been written yet and 'save' it for the new socket.
249
conn->hold_requests = request->next;
250
conn->hold_requests_tail = conn->requests_tail;
251
request->next = NULL;
252
conn->requests_tail = request;
254
/* Clear our iovec. */
257
/* Update the pollset to know we don't want to write on this socket any
260
conn->dirty_conn = 1;
261
conn->ctx->dirty_pollset = 1;
265
/* Read the 'Connection' header from the response. Return SERF_ERROR_CLOSING if
266
* the header contains value 'close' indicating the server is closing the
267
* connection right after this response.
268
* Otherwise returns APR_SUCCESS.
270
static apr_status_t is_conn_closing(serf_bucket_t *response)
275
hdrs = serf_bucket_response_get_headers(response);
276
val = serf_bucket_headers_get(hdrs, "Connection");
277
if (val && strcasecmp("close", val) == 0)
279
return SERF_ERROR_CLOSING;
285
static void link_requests(serf_request_t **list, serf_request_t **tail,
286
serf_request_t *request)
293
(*tail)->next = request;
298
static apr_status_t destroy_request(serf_request_t *request)
300
serf_connection_t *conn = request->conn;
302
/* The request and response buckets are no longer needed,
303
nor is the request's pool. */
304
if (request->resp_bkt) {
305
serf_debug__closed_conn(request->resp_bkt->allocator);
306
serf_bucket_destroy(request->resp_bkt);
308
if (request->req_bkt) {
309
serf_debug__closed_conn(request->req_bkt->allocator);
310
serf_bucket_destroy(request->req_bkt);
313
serf_debug__bucket_alloc_check(request->allocator);
314
if (request->respool) {
315
apr_pool_destroy(request->respool);
318
serf_bucket_mem_free(conn->allocator, request);
323
static apr_status_t cancel_request(serf_request_t *request,
324
serf_request_t **list,
327
/* If we haven't run setup, then we won't have a handler to call. */
328
if (request->handler && notify_request) {
329
/* We actually don't care what the handler returns.
330
* We have bigger matters at hand.
332
(*request->handler)(request, NULL, request->handler_baton,
336
if (*list == request) {
337
*list = request->next;
340
serf_request_t *scan = *list;
342
while (scan->next && scan->next != request)
346
scan->next = scan->next->next;
350
return destroy_request(request);
353
static apr_status_t remove_connection(serf_context_t *ctx,
354
serf_connection_t *conn)
356
apr_pollfd_t desc = { 0 };
358
desc.desc_type = APR_POLL_SOCKET;
359
desc.desc.s = conn->skt;
360
desc.reqevents = conn->reqevents;
362
return ctx->pollset_rm(ctx->pollset_baton,
366
static void destroy_ostream(serf_connection_t *conn)
368
if (conn->ostream_head != NULL) {
369
serf_bucket_destroy(conn->ostream_head);
370
conn->ostream_head = NULL;
371
conn->ostream_tail = NULL;
375
/* A socket was closed, inform the application. */
376
static void handle_conn_closed(serf_connection_t *conn, apr_status_t status)
378
(*conn->closed)(conn, conn->closed_baton, status,
382
static apr_status_t reset_connection(serf_connection_t *conn,
383
int requeue_requests)
385
serf_context_t *ctx = conn->ctx;
387
serf_request_t *old_reqs, *held_reqs, *held_reqs_tail;
389
conn->probable_keepalive_limit = conn->completed_responses;
390
conn->completed_requests = 0;
391
conn->completed_responses = 0;
393
old_reqs = conn->requests;
394
held_reqs = conn->hold_requests;
395
held_reqs_tail = conn->hold_requests_tail;
398
conn->hold_requests = NULL;
399
conn->hold_requests_tail = NULL;
403
conn->requests = NULL;
404
conn->requests_tail = NULL;
407
/* If we haven't started to write the connection, bring it over
408
* unchanged to our new socket. Otherwise, call the cancel function.
410
if (requeue_requests && !old_reqs->written) {
411
serf_request_t *req = old_reqs;
412
old_reqs = old_reqs->next;
414
link_requests(&conn->requests, &conn->requests_tail, req);
417
cancel_request(old_reqs, &old_reqs, requeue_requests);
421
if (conn->requests_tail) {
422
conn->requests_tail->next = held_reqs;
425
conn->requests = held_reqs;
427
if (held_reqs_tail) {
428
conn->requests_tail = held_reqs_tail;
431
if (conn->skt != NULL) {
432
remove_connection(ctx, conn);
433
status = apr_socket_close(conn->skt);
434
if (conn->closed != NULL) {
435
handle_conn_closed(conn, status);
440
if (conn->stream != NULL) {
441
serf_bucket_destroy(conn->stream);
445
destroy_ostream(conn);
447
/* Don't try to resume any writes */
450
conn->dirty_conn = 1;
451
conn->ctx->dirty_pollset = 1;
453
conn->status = APR_SUCCESS;
455
/* Let our context know that we've 'reset' the socket already. */
456
conn->seen_in_pollset |= APR_POLLHUP;
458
/* Found the connection. Closed it. All done. */
462
static apr_status_t socket_writev(serf_connection_t *conn)
467
status = apr_socket_sendv(conn->skt, conn->vec,
468
conn->vec_len, &written);
470
/* did we write everything? */
475
for (i = 0; i < conn->vec_len; i++) {
476
len += conn->vec[i].iov_len;
479
memmove(conn->vec, &conn->vec[i],
480
sizeof(struct iovec) * (conn->vec_len - i));
483
conn->vec[0].iov_base = (char *)conn->vec[0].iov_base + (conn->vec[0].iov_len - (len - written));
484
conn->vec[0].iov_len = len - written;
488
if (len == written) {
492
/* Log progress information */
493
serf__context_progress_delta(conn->ctx, 0, written);
499
static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
501
serf_connection_t *conn = baton;
506
static apr_status_t do_conn_setup(serf_connection_t *conn)
509
serf_bucket_t *ostream;
511
if (conn->ostream_head == NULL) {
512
conn->ostream_head = serf_bucket_aggregate_create(conn->allocator);
515
if (conn->ostream_tail == NULL) {
516
conn->ostream_tail = serf__bucket_stream_create(conn->allocator,
521
ostream = conn->ostream_tail;
523
status = (*conn->setup)(conn->skt,
529
/* extra destroy here since it wasn't added to the head bucket yet. */
530
serf_bucket_destroy(conn->ostream_tail);
531
destroy_ostream(conn);
535
serf_bucket_aggregate_append(conn->ostream_head,
541
/* write data out to the connection */
542
static apr_status_t write_to_connection(serf_connection_t *conn)
544
serf_request_t *request = conn->requests;
546
if (conn->probable_keepalive_limit &&
547
conn->completed_requests > conn->probable_keepalive_limit) {
548
/* backoff for now. */
552
/* Find a request that has data which needs to be delivered. */
553
while (request != NULL &&
554
request->req_bkt == NULL && request->written)
555
request = request->next;
557
/* assert: request != NULL || conn->vec_len */
559
/* Keep reading and sending until we run out of stuff to read, or
560
* writing would block.
563
int stop_reading = 0;
565
apr_status_t read_status;
567
if (conn->max_outstanding_requests &&
568
conn->completed_requests -
569
conn->completed_responses >= conn->max_outstanding_requests) {
570
/* backoff for now. */
574
/* If we have unwritten data, then write what we can. */
575
while (conn->vec_len) {
576
status = socket_writev(conn);
578
/* If the write would have blocked, then we're done. Don't try
579
* to write anything else to the socket.
581
if (APR_STATUS_IS_EAGAIN(status))
583
if (APR_STATUS_IS_EPIPE(status))
584
return no_more_writes(conn, request);
588
/* ### can we have a short write, yet no EAGAIN? a short write
589
### would imply unwritten_len > 0 ... */
590
/* assert: unwritten_len == 0. */
592
/* We may need to move forward to a request which has something
595
while (request != NULL &&
596
request->req_bkt == NULL && request->written)
597
request = request->next;
599
if (request == NULL) {
600
/* No more requests (with data) are registered with the
601
* connection. Let's update the pollset so that we don't
602
* try to write to this socket again.
604
conn->dirty_conn = 1;
605
conn->ctx->dirty_pollset = 1;
609
/* If the connection does not have an associated bucket, then
610
* call the setup callback to get one.
612
if (conn->stream == NULL) {
613
status = do_conn_setup(conn);
619
if (request->req_bkt == NULL) {
620
/* Now that we are about to serve the request, allocate a pool. */
621
apr_pool_create(&request->respool, conn->pool);
622
request->allocator = serf_bucket_allocator_create(request->respool,
624
apr_pool_cleanup_register(request->respool, request,
625
clean_resp, clean_resp);
627
/* Fill in the rest of the values for the request. */
628
read_status = request->setup(request, request->setup_baton,
631
&request->acceptor_baton,
633
&request->handler_baton,
637
/* Something bad happened. Propagate any errors. */
641
request->written = 1;
642
serf_bucket_aggregate_append(conn->ostream_tail, request->req_bkt);
645
/* ### optimize at some point by using read_for_sendfile */
646
read_status = serf_bucket_read_iovec(conn->ostream_head,
652
if (!conn->hit_eof) {
653
if (APR_STATUS_IS_EAGAIN(read_status)) {
654
/* We read some stuff, but should not try to read again. */
657
/* ### we should avoid looking for writability for a while so
658
### that (hopefully) something will appear in the bucket so
659
### we can actually write something. otherwise, we could
660
### end up in a CPU spin: socket wants something, but we
661
### don't have anything (and keep returning EAGAIN)
664
else if (read_status && !APR_STATUS_IS_EOF(read_status)) {
665
/* Something bad happened. Propagate any errors. */
670
/* If we got some data, then deliver it. */
671
/* ### what to do if we got no data?? is that a problem? */
672
if (conn->vec_len > 0) {
673
status = socket_writev(conn);
675
/* If we can't write any more, or an error occurred, then
678
if (APR_STATUS_IS_EAGAIN(status))
680
if (APR_STATUS_IS_EPIPE(status))
681
return no_more_writes(conn, request);
682
if (APR_STATUS_IS_ECONNRESET(status)) {
683
return no_more_writes(conn, request);
690
conn->vec_len == 0) {
691
/* If we hit the end of the request bucket and all of its data has
692
* been written, then clear it out to signify that we're done
693
* sending the request. On the next iteration through this loop:
694
* - if there are remaining bytes they will be written, and as the
695
* request bucket will be completely read it will be destroyed then.
696
* - we'll see if there are other requests that need to be sent
700
request->req_bkt = NULL;
702
/* If our connection has async responses enabled, we're not
703
* going to get a reply back, so kill the request.
705
if (conn->async_responses) {
706
conn->requests = request->next;
707
destroy_request(request);
710
conn->completed_requests++;
712
if (conn->probable_keepalive_limit &&
713
conn->completed_requests > conn->probable_keepalive_limit) {
714
/* backoff for now. */
726
/* A response message was received from the server, so call
727
the handler as specified on the original request. */
728
static apr_status_t handle_response(serf_request_t *request,
732
int consumed_response = 0;
734
/* Only enable the new authentication framework if the program has
735
* registered an authentication credential callback.
737
* This permits older Serf apps to still handle authentication
738
* themselves by not registering credential callbacks.
740
if (request->conn->ctx->cred_cb) {
741
status = serf__handle_auth_response(&consumed_response,
744
request->handler_baton,
747
/* If there was an error reading the response (maybe there wasn't
748
enough data available), don't bother passing the response to the
751
If the authentication was tried, but failed, pass the response
752
to the application, maybe it can do better. */
753
if (APR_STATUS_IS_EOF(status) ||
754
APR_STATUS_IS_EAGAIN(status)) {
759
if (!consumed_response) {
760
return (*request->handler)(request,
762
request->handler_baton,
769
/* An async response message was received from the server. */
770
static apr_status_t handle_async_response(serf_connection_t *conn,
775
if (conn->current_async_response == NULL) {
776
conn->current_async_response =
777
(*conn->async_acceptor)(NULL, conn->stream,
778
conn->async_acceptor_baton, pool);
781
status = (*conn->async_handler)(NULL, conn->current_async_response,
782
conn->async_handler_baton, pool);
784
if (APR_STATUS_IS_EOF(status)) {
785
serf_bucket_destroy(conn->current_async_response);
786
conn->current_async_response = NULL;
787
status = APR_SUCCESS;
793
/* read data from the connection */
794
static apr_status_t read_from_connection(serf_connection_t *conn)
798
int close_connection = FALSE;
800
/* Whatever is coming in on the socket corresponds to the first request
803
serf_request_t *request = conn->requests;
805
/* assert: request != NULL */
807
if ((status = apr_pool_create(&tmppool, conn->pool)) != APR_SUCCESS)
810
/* Invoke response handlers until we have no more work. */
812
apr_pool_clear(tmppool);
814
/* If the connection does not have an associated bucket, then
815
* call the setup callback to get one.
817
if (conn->stream == NULL) {
818
status = do_conn_setup(conn);
824
/* We have a different codepath when we can have async responses. */
825
if (conn->async_responses) {
826
/* TODO What about socket errors? */
827
status = handle_async_response(conn, tmppool);
828
if (APR_STATUS_IS_EAGAIN(status)) {
829
status = APR_SUCCESS;
838
/* We are reading a response for a request we haven't
841
* This shouldn't normally happen EXCEPT:
843
* 1) when the other end has closed the socket and we're
844
* pending an EOF return.
845
* 2) Doing the initial SSL handshake - we'll get EAGAIN
846
* as the SSL buckets will hide the handshake from us
847
* but not return any data.
849
* In these cases, we should not receive any actual user data.
851
* If we see an EOF (due to an expired timeout), we'll reset the
852
* connection and open a new one.
854
if (request->req_bkt || !request->written) {
858
status = serf_bucket_read(conn->stream, SERF_READ_ALL_AVAIL,
861
if (!status && len) {
862
status = APR_EGENERAL;
864
else if (APR_STATUS_IS_EOF(status)) {
865
reset_connection(conn, 1);
866
status = APR_SUCCESS;
868
else if (APR_STATUS_IS_EAGAIN(status)) {
869
status = APR_SUCCESS;
875
/* If the request doesn't have a response bucket, then call the
876
* acceptor to get one created.
878
if (request->resp_bkt == NULL) {
879
request->resp_bkt = (*request->acceptor)(request, conn->stream,
880
request->acceptor_baton,
882
apr_pool_clear(tmppool);
885
status = handle_response(request, tmppool);
887
/* Some systems will not generate a HUP poll event so we have to
888
* handle the ECONNRESET issue here.
890
if (APR_STATUS_IS_ECONNRESET(status) ||
891
status == SERF_ERROR_REQUEST_LOST) {
892
reset_connection(conn, 1);
893
status = APR_SUCCESS;
897
/* If our response handler says it can't do anything more, we now
898
* treat that as a success.
900
if (APR_STATUS_IS_EAGAIN(status)) {
901
status = APR_SUCCESS;
905
/* If we received APR_SUCCESS, run this loop again. */
910
close_connection = is_conn_closing(request->resp_bkt);
912
if (!APR_STATUS_IS_EOF(status) &&
913
close_connection != SERF_ERROR_CLOSING) {
914
/* Whether success, or an error, there is no more to do unless
915
* this request has been completed.
920
/* The request has been fully-delivered, and the response has
921
* been fully-read. Remove it from our queue and loop to read
924
conn->requests = request->next;
926
destroy_request(request);
928
request = conn->requests;
930
/* If we're truly empty, update our tail. */
931
if (request == NULL) {
932
conn->requests_tail = NULL;
935
conn->completed_responses++;
937
/* This means that we're being advised that the connection is done. */
938
if (close_connection == SERF_ERROR_CLOSING) {
939
reset_connection(conn, 1);
940
if (APR_STATUS_IS_EOF(status))
941
status = APR_SUCCESS;
945
/* The server is suddenly deciding to serve more responses than we've
948
* Let our requests go.
950
if (conn->probable_keepalive_limit &&
951
conn->completed_responses > conn->probable_keepalive_limit) {
952
conn->probable_keepalive_limit = 0;
955
/* If we just ran out of requests or have unwritten requests, then
956
* update the pollset. We don't want to read from this socket any
957
* more. We are definitely done with this loop, too.
959
if (request == NULL || !request->written) {
960
conn->dirty_conn = 1;
961
conn->ctx->dirty_pollset = 1;
962
status = APR_SUCCESS;
968
apr_pool_destroy(tmppool);
972
/* process all events on the connection */
973
apr_status_t serf__process_connection(serf_connection_t *conn,
978
/* POLLHUP/ERR should come after POLLIN so if there's an error message or
979
* the like sitting on the connection, we give the app a chance to read
980
* it before we trigger a reset condition.
982
if ((events & APR_POLLIN) != 0) {
983
if ((status = read_from_connection(conn)) != APR_SUCCESS)
986
/* If we decided to reset our connection, return now as we don't
989
if ((conn->seen_in_pollset & APR_POLLHUP) != 0) {
993
if ((events & APR_POLLHUP) != 0) {
994
return APR_ECONNRESET;
996
if ((events & APR_POLLERR) != 0) {
997
/* We might be talking to a buggy HTTP server that doesn't
998
* do lingering-close. (httpd < 2.1.8 does this.)
1002
* http://issues.apache.org/bugzilla/show_bug.cgi?id=35292
1004
if (!conn->probable_keepalive_limit) {
1005
return reset_connection(conn, 1);
1007
return APR_EGENERAL;
1009
if ((events & APR_POLLOUT) != 0) {
1010
if ((status = write_to_connection(conn)) != APR_SUCCESS)
1016
serf_connection_t *serf_connection_create(
1017
serf_context_t *ctx,
1018
apr_sockaddr_t *address,
1019
serf_connection_setup_t setup,
1021
serf_connection_closed_t closed,
1025
serf_connection_t *conn = apr_pcalloc(pool, sizeof(*conn));
1028
conn->status = APR_SUCCESS;
1029
conn->address = address;
1030
conn->setup = setup;
1031
conn->setup_baton = setup_baton;
1032
conn->closed = closed;
1033
conn->closed_baton = closed_baton;
1035
conn->allocator = serf_bucket_allocator_create(pool, NULL, NULL);
1036
conn->stream = NULL;
1037
conn->ostream_head = NULL;
1038
conn->ostream_tail = NULL;
1039
conn->baton.type = SERF_IO_CONN;
1040
conn->baton.u.conn = conn;
1043
/* Create a subpool for our connection. */
1044
apr_pool_create(&conn->skt_pool, conn->pool);
1046
/* register a cleanup */
1047
apr_pool_cleanup_register(conn->pool, conn, clean_conn, apr_pool_cleanup_null);
1049
/* Add the connection to the context. */
1050
*(serf_connection_t **)apr_array_push(ctx->conns) = conn;
1055
apr_status_t serf_connection_create2(
1056
serf_connection_t **conn,
1057
serf_context_t *ctx,
1058
apr_uri_t host_info,
1059
serf_connection_setup_t setup,
1061
serf_connection_closed_t closed,
1065
apr_status_t status;
1066
serf_connection_t *c;
1067
apr_sockaddr_t *host_address;
1069
/* Support for HTTPS proxies is not implemented yet. */
1070
if (ctx->proxy_address && strcmp(host_info.scheme, "https") == 0)
1071
return APR_ENOTIMPL;
1073
/* Parse the url, store the address of the server. */
1074
status = apr_sockaddr_info_get(&host_address,
1076
APR_UNSPEC, host_info.port, 0, pool);
1080
c = serf_connection_create(ctx, host_address, setup, setup_baton,
1081
closed, closed_baton, pool);
1083
/* We're not interested in the path following the hostname. */
1084
c->host_url = apr_uri_unparse(c->pool,
1086
APR_URI_UNP_OMITPATHINFO);
1087
c->host_info = host_info;
1094
apr_status_t serf_connection_reset(
1095
serf_connection_t *conn)
1097
return reset_connection(conn, 0);
1101
apr_status_t serf_connection_close(
1102
serf_connection_t *conn)
1105
serf_context_t *ctx = conn->ctx;
1106
apr_status_t status;
1108
for (i = ctx->conns->nelts; i--; ) {
1109
serf_connection_t *conn_seq = GET_CONN(ctx, i);
1111
if (conn_seq == conn) {
1112
while (conn->requests) {
1113
serf_request_cancel(conn->requests);
1115
if (conn->skt != NULL) {
1116
remove_connection(ctx, conn);
1117
status = apr_socket_close(conn->skt);
1118
if (conn->closed != NULL) {
1119
handle_conn_closed(conn, status);
1123
if (conn->stream != NULL) {
1124
serf_bucket_destroy(conn->stream);
1125
conn->stream = NULL;
1128
/* Remove the connection from the context. We don't want to
1129
* deal with it any more.
1131
if (i < ctx->conns->nelts - 1) {
1132
/* move later connections over this one. */
1135
&GET_CONN(ctx, i + 1),
1136
(ctx->conns->nelts - i - 1) * sizeof(serf_connection_t *));
1138
--ctx->conns->nelts;
1140
/* Found the connection. Closed it. All done. */
1145
/* We didn't find the specified connection. */
1146
/* ### doc talks about this w.r.t poll structures. use something else? */
1147
return APR_NOTFOUND;
1151
void serf_connection_set_max_outstanding_requests(
1152
serf_connection_t *conn,
1153
unsigned int max_requests)
1155
conn->max_outstanding_requests = max_requests;
1159
void serf_connection_set_async_responses(
1160
serf_connection_t *conn,
1161
serf_response_acceptor_t acceptor,
1162
void *acceptor_baton,
1163
serf_response_handler_t handler,
1164
void *handler_baton)
1166
conn->async_responses = 1;
1167
conn->async_acceptor = acceptor;
1168
conn->async_acceptor_baton = acceptor_baton;
1169
conn->async_handler = handler;
1170
conn->async_handler_baton = handler_baton;
1174
serf_request_t *serf_connection_request_create(
1175
serf_connection_t *conn,
1176
serf_request_setup_t setup,
1179
serf_request_t *request;
1181
request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
1182
request->conn = conn;
1183
request->setup = setup;
1184
request->setup_baton = setup_baton;
1185
request->handler = NULL;
1186
request->respool = NULL;
1187
request->req_bkt = NULL;
1188
request->resp_bkt = NULL;
1189
request->written = 0;
1190
request->next = NULL;
1192
/* Link the request to the end of the request chain. */
1193
if (conn->closing) {
1194
link_requests(&conn->hold_requests, &conn->hold_requests_tail, request);
1197
link_requests(&conn->requests, &conn->requests_tail, request);
1199
/* Ensure our pollset becomes writable in context run */
1200
conn->ctx->dirty_pollset = 1;
1201
conn->dirty_conn = 1;
1208
serf_request_t *serf_connection_priority_request_create(
1209
serf_connection_t *conn,
1210
serf_request_setup_t setup,
1213
serf_request_t *request;
1214
serf_request_t *iter, *prev;
1216
request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
1217
request->conn = conn;
1218
request->setup = setup;
1219
request->setup_baton = setup_baton;
1220
request->handler = NULL;
1221
request->respool = NULL;
1222
request->req_bkt = NULL;
1223
request->resp_bkt = NULL;
1224
request->written = 0;
1225
request->next = NULL;
1227
/* Link the new request after the last written request, but before all
1228
upcoming requests. */
1229
if (conn->closing) {
1230
iter = conn->hold_requests;
1233
iter = conn->requests;
1237
/* Find a request that has data which needs to be delivered. */
1238
while (iter != NULL && iter->req_bkt == NULL && iter->written) {
1244
request->next = iter;
1245
prev->next = request;
1247
request->next = iter;
1248
if (conn->closing) {
1249
conn->hold_requests = request;
1252
conn->requests = request;
1256
if (! conn->closing) {
1257
/* Ensure our pollset becomes writable in context run */
1258
conn->ctx->dirty_pollset = 1;
1259
conn->dirty_conn = 1;
1266
apr_status_t serf_request_cancel(serf_request_t *request)
1268
return cancel_request(request, &request->conn->requests, 0);
1272
apr_pool_t *serf_request_get_pool(const serf_request_t *request)
1274
return request->respool;
1278
serf_bucket_alloc_t *serf_request_get_alloc(
1279
const serf_request_t *request)
1281
return request->allocator;
1285
serf_connection_t *serf_request_get_conn(
1286
const serf_request_t *request)
1288
return request->conn;
1292
void serf_request_set_handler(
1293
serf_request_t *request,
1294
const serf_response_handler_t handler,
1295
const void **handler_baton)
1297
request->handler = handler;
1298
request->handler_baton = handler_baton;
1302
serf_bucket_t *serf_request_bucket_request_create(
1303
serf_request_t *request,
1306
serf_bucket_t *body,
1307
serf_bucket_alloc_t *allocator)
1309
serf_bucket_t *req_bkt, *hdrs_bkt;
1310
serf_connection_t *conn = request->conn;
1311
serf_context_t *ctx = conn->ctx;
1313
req_bkt = serf_bucket_request_create(method, uri, body, allocator);
1314
hdrs_bkt = serf_bucket_request_get_headers(req_bkt);
1317
if (ctx->proxy_address && conn->host_url)
1318
serf_bucket_request_set_root(req_bkt, conn->host_url);
1320
if (conn->host_info.hostinfo)
1321
serf_bucket_headers_setn(hdrs_bkt, "Host",
1322
conn->host_info.hostinfo);
1324
/* Setup server authorization headers */
1325
if (ctx->authn_info.scheme)
1326
ctx->authn_info.scheme->setup_request_func(401, conn, method, uri,
1329
/* Setup proxy authorization headers */
1330
if (ctx->proxy_authn_info.scheme)
1331
ctx->proxy_authn_info.scheme->setup_request_func(407, conn, method,