bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / network_io / beos / sendrecv.c
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_private.h"
18 #if BEOS_BONE /* BONE uses the unix code - woohoo */
19 #include "../unix/sendrecv.c"
20 #else
21 #include "apr_arch_networkio.h"
22 #include "apr_time.h"
23
24 apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
25 {
26     struct timeval tv, *tvptr;
27     fd_set fdset;
28     int srv;
29
30     do {
31         FD_ZERO(&fdset);
32         FD_SET(sock->socketdes, &fdset);
33         if (sock->timeout < 0) {
34             tvptr = NULL;
35         }
36         else {
37             tv.tv_sec = sock->timeout / APR_USEC_PER_SEC;
38             tv.tv_usec = sock->timeout % APR_USEC_PER_SEC;
39             tvptr = &tv;
40         }
41         srv = select(sock->socketdes + 1,
42             for_read ? &fdset : NULL,
43             for_read ? NULL : &fdset, 
44             NULL,
45             tvptr);
46             /* TODO - timeout should be smaller on repeats of this loop */
47     } while (srv == -1 && errno == EINTR);
48
49     if (srv == 0) {
50         return APR_TIMEUP;
51     }
52     else if (srv < 0) {
53         return errno;
54     }
55     return APR_SUCCESS;
56 }
57
58 #define SEND_WAIT APR_USEC_PER_SEC / 10
59
60 APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf,
61                                           apr_size_t *len)
62 {
63     apr_ssize_t rv;
64         
65     do {
66         rv = send(sock->socketdes, buf, (*len), 0);
67     } while (rv == -1 && errno == EINTR);
68
69     if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) {
70         apr_int32_t snooze_val = SEND_WAIT;
71         apr_int32_t zzz = 0;  
72         
73         do {
74             rv = send(sock->socketdes, buf, (*len), 0);
75             if (rv == -1 && errno == EWOULDBLOCK){
76                 apr_sleep (snooze_val);
77                 zzz += snooze_val;
78                 snooze_val += SEND_WAIT;
79                 /* have we passed our timeout value */
80                 if (zzz > (sock->timeout * APR_USEC_PER_SEC))
81                     break;
82             }
83         } while (rv == -1 && (errno == EINTR || errno == EWOULDBLOCK));
84     }
85     if (rv == -1) {
86         *len = 0;
87         return errno;
88     }
89     (*len) = rv;
90
91     return APR_SUCCESS;
92 }
93
94 APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, 
95                                           apr_size_t *len)
96 {
97     apr_ssize_t rv;
98    
99     do {
100         rv = recv(sock->socketdes, buf, (*len), 0);
101     } while (rv == -1 && errno == EINTR);
102
103     if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) {
104         apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1);
105         if (arv != APR_SUCCESS) {
106             *len = 0;
107             return arv;
108         }
109         else {
110             do {
111                 rv = recv(sock->socketdes, buf, (*len), 0);
112             } while (rv == -1 && errno == EINTR);
113         }
114     }
115     if (rv == -1) {
116         (*len) = 0;
117         return errno;
118     }
119     (*len) = rv;
120     if (rv == 0)
121         return APR_EOF;
122     return APR_SUCCESS;
123 }
124
125 /* BeOS doesn't have writev for sockets so we use the following instead...
126  */
127 APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t * sock, 
128                                            const struct iovec *vec,
129                                            apr_int32_t nvec, apr_size_t *len)
130 {
131     *len = vec[0].iov_len;
132     return apr_socket_send(sock, vec[0].iov_base, len);
133 }
134
135 APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, 
136                                             apr_sockaddr_t *where,
137                                             apr_int32_t flags, const char *buf,
138                                             apr_size_t *len)
139 {
140     apr_ssize_t rv;
141
142     do {
143         rv = sendto(sock->socketdes, buf, (*len), flags,
144                     (const struct sockaddr*)&where->sa,
145                     where->salen);
146     } while (rv == -1 && errno == EINTR);
147
148     if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
149         && sock->timeout != 0) {
150         apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
151         if (arv != APR_SUCCESS) {
152             *len = 0;
153             return arv;
154         } else {
155             do {
156                 rv = sendto(sock->socketdes, buf, (*len), flags,
157                             (const struct sockaddr*)&where->sa,
158                             where->salen);
159             } while (rv == -1 && errno == EINTR);
160         }
161     }
162     if (rv == -1) {
163         *len = 0;
164         return errno;
165     }
166     *len = rv;
167     return APR_SUCCESS;
168 }
169
170 APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from,
171                                               apr_socket_t *sock,
172                                               apr_int32_t flags, char *buf,
173                                               apr_size_t *len)
174 {
175     apr_ssize_t rv;
176
177     if (from == NULL){
178         return APR_ENOMEM;
179         /* Not sure if this is correct.  Maybe we should just allocate
180            the memory??
181          */
182     }
183
184     do {
185         rv = recvfrom(sock->socketdes, buf, (*len), flags,
186                       (struct sockaddr*)&from->sa, &from->salen);
187     } while (rv == -1 && errno == EINTR);
188
189     if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
190         sock->timeout != 0) {
191         apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1);
192         if (arv != APR_SUCCESS) {
193             *len = 0;
194             return arv;
195         } else {
196             do {
197                 rv = recvfrom(sock->socketdes, buf, (*len), flags,
198                               (struct sockaddr*)&from->sa, &from->salen);
199                 } while (rv == -1 && errno == EINTR);
200         }
201     }
202     if (rv == -1) {
203         (*len) = 0;
204         return errno;
205     }
206
207     (*len) = rv;
208     if (rv == 0)
209         return APR_EOF;
210
211     return APR_SUCCESS;
212 }
213
214 /* deprecated */
215 APR_DECLARE(apr_status_t) apr_send(apr_socket_t *sock, const char *buf,
216                                    apr_size_t *len)
217 {
218     return apr_socket_send(sock, buf, len);
219 }
220
221 /* deprecated */
222 APR_DECLARE(apr_status_t) apr_sendv(apr_socket_t * sock, 
223                                     const struct iovec *vec,
224                                     apr_int32_t nvec, apr_size_t *len)
225 {
226     return apr_socket_sendv(sock, vec, nvec, len);
227 }
228
229 /* deprecated */
230 APR_DECLARE(apr_status_t) apr_sendto(apr_socket_t *sock, apr_sockaddr_t *where,
231                                      apr_int32_t flags, const char *buf,
232                                      apr_size_t *len)
233 {
234     return apr_socket_sendto(sock, where, flags, buf, len);
235 }
236
237 /* deprecated */
238 APR_DECLARE(apr_status_t) apr_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock,
239                                        apr_int32_t flags, char *buf,
240                                        apr_size_t *len)
241 {
242     return apr_socket_recvfrom(from, sock, flags, buf, len);
243 }
244
245 /* deprecated */
246 APR_DECLARE(apr_status_t) apr_recv(apr_socket_t *sock, char *buf, 
247                                    apr_size_t *len)
248 {
249     return apr_socket_recv(sock, buf, len);
250 }
251
252 #endif