/src/httpd/srclib/apr/buckets/apr_buckets_socket.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Licensed to the Apache Software Foundation (ASF) under one or more |
2 | | * contributor license agreements. See the NOTICE file distributed with |
3 | | * this work for additional information regarding copyright ownership. |
4 | | * The ASF licenses this file to You under the Apache License, Version 2.0 |
5 | | * (the "License"); you may not use this file except in compliance with |
6 | | * the License. You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include "apr_buckets.h" |
18 | | |
19 | | static apr_status_t socket_bucket_read(apr_bucket *a, const char **str, |
20 | | apr_size_t *len, apr_read_type_e block) |
21 | 0 | { |
22 | 0 | apr_socket_t *p = a->data; |
23 | 0 | char *buf; |
24 | 0 | apr_status_t rv; |
25 | 0 | apr_interval_time_t timeout; |
26 | |
|
27 | 0 | if (block == APR_NONBLOCK_READ) { |
28 | 0 | apr_socket_timeout_get(p, &timeout); |
29 | 0 | apr_socket_timeout_set(p, 0); |
30 | 0 | } |
31 | |
|
32 | 0 | *str = NULL; |
33 | 0 | *len = APR_BUCKET_BUFF_SIZE; |
34 | 0 | buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */ |
35 | |
|
36 | 0 | rv = apr_socket_recv(p, buf, len); |
37 | |
|
38 | 0 | if (block == APR_NONBLOCK_READ) { |
39 | 0 | apr_socket_timeout_set(p, timeout); |
40 | 0 | } |
41 | |
|
42 | 0 | if (rv != APR_SUCCESS && rv != APR_EOF) { |
43 | 0 | apr_bucket_free(buf); |
44 | 0 | return rv; |
45 | 0 | } |
46 | | /* |
47 | | * If there's more to read we have to keep the rest of the socket |
48 | | * for later. XXX: Note that more complicated bucket types that |
49 | | * refer to data not in memory and must therefore have a read() |
50 | | * function similar to this one should be wary of copying this |
51 | | * code because if they have a destroy function they probably |
52 | | * want to migrate the bucket's subordinate structure from the |
53 | | * old bucket to a raw new one and adjust it as appropriate, |
54 | | * rather than destroying the old one and creating a completely |
55 | | * new bucket. |
56 | | * |
57 | | * Even if there is nothing more to read, don't close the socket here |
58 | | * as we have to use it to send any response :) We could shut it |
59 | | * down for reading, but there is no benefit to doing so. |
60 | | */ |
61 | 0 | if (*len > 0) { |
62 | 0 | apr_bucket_heap *h; |
63 | | /* Change the current bucket to refer to what we read */ |
64 | 0 | a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free); |
65 | 0 | h = a->data; |
66 | 0 | h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */ |
67 | 0 | *str = buf; |
68 | 0 | APR_BUCKET_INSERT_AFTER(a, apr_bucket_socket_create(p, a->list)); |
69 | 0 | } |
70 | 0 | else { |
71 | 0 | apr_bucket_free(buf); |
72 | 0 | a = apr_bucket_immortal_make(a, "", 0); |
73 | 0 | *str = a->data; |
74 | 0 | } |
75 | 0 | return APR_SUCCESS; |
76 | 0 | } |
77 | | |
78 | | APR_DECLARE(apr_bucket *) apr_bucket_socket_make(apr_bucket *b, apr_socket_t *p) |
79 | 0 | { |
80 | | /* |
81 | | * XXX: We rely on a cleanup on some pool or other to actually |
82 | | * destroy the socket. We should probably explicitly call apr to |
83 | | * destroy it instead. |
84 | | * |
85 | | * Note that typically the socket is allocated from the connection pool |
86 | | * so it will disappear when the connection is finished. |
87 | | */ |
88 | 0 | b->type = &apr_bucket_type_socket; |
89 | 0 | b->length = (apr_size_t)(-1); |
90 | 0 | b->start = -1; |
91 | 0 | b->data = p; |
92 | |
|
93 | 0 | return b; |
94 | 0 | } |
95 | | |
96 | | APR_DECLARE(apr_bucket *) apr_bucket_socket_create(apr_socket_t *p, |
97 | | apr_bucket_alloc_t *list) |
98 | 0 | { |
99 | 0 | apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); |
100 | |
|
101 | 0 | APR_BUCKET_INIT(b); |
102 | 0 | b->free = apr_bucket_free; |
103 | 0 | b->list = list; |
104 | 0 | return apr_bucket_socket_make(b, p); |
105 | 0 | } |
106 | | |
107 | | APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_socket = { |
108 | | "SOCKET", 5, APR_BUCKET_DATA, |
109 | | apr_bucket_destroy_noop, |
110 | | socket_bucket_read, |
111 | | apr_bucket_setaside_notimpl, |
112 | | apr_bucket_split_notimpl, |
113 | | apr_bucket_copy_notimpl |
114 | | }; |