~ubuntu-branches/ubuntu/quantal/haproxy/quantal

« back to all changes in this revision

Viewing changes to src/stream_sock.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2007-08-17 09:33:41 UTC
  • Revision ID: james.westby@ubuntu.com-20070817093341-h0t6aeeoyzo25z3r
Tags: upstream-1.3.12.dfsg
ImportĀ upstreamĀ versionĀ 1.3.12.dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Functions operating on SOCK_STREAM and buffers.
 
3
 *
 
4
 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version
 
9
 * 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 */
 
12
 
 
13
#include <errno.h>
 
14
#include <fcntl.h>
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
 
 
18
#include <sys/socket.h>
 
19
#include <sys/stat.h>
 
20
#include <sys/types.h>
 
21
 
 
22
#include <common/compat.h>
 
23
#include <common/config.h>
 
24
#include <common/standard.h>
 
25
#include <common/time.h>
 
26
 
 
27
#include <types/buffers.h>
 
28
#include <types/global.h>
 
29
#include <types/polling.h>
 
30
#include <types/session.h>
 
31
 
 
32
#include <proto/client.h>
 
33
#include <proto/fd.h>
 
34
#include <proto/stream_sock.h>
 
35
#include <proto/task.h>
 
36
 
 
37
 
 
38
/*
 
39
 * this function is called on a read event from a stream socket.
 
40
 * It returns 0 if we have a high confidence that we will not be
 
41
 * able to read more data without polling first. Returns non-zero
 
42
 * otherwise.
 
43
 */
 
44
int stream_sock_read(int fd) {
 
45
        __label__ out_eternity, out_wakeup, out_error;
 
46
        struct buffer *b = fdtab[fd].cb[DIR_RD].b;
 
47
        int ret, max, retval;
 
48
        int read_poll = MAX_READ_POLL_LOOPS;
 
49
 
 
50
#ifdef DEBUG_FULL
 
51
        fprintf(stderr,"stream_sock_read : fd=%d, owner=%p\n", fd, fdtab[fd].owner);
 
52
#endif
 
53
 
 
54
        retval = 1;
 
55
 
 
56
        if (unlikely(fdtab[fd].ev & FD_POLL_HUP)) {
 
57
                /* connection closed */
 
58
                b->flags |= BF_READ_NULL;
 
59
                goto out_eternity;
 
60
        }
 
61
        else if (unlikely(fdtab[fd].state == FD_STERROR || (fdtab[fd].ev & FD_POLL_ERR))) {
 
62
                goto out_error;
 
63
        }
 
64
 
 
65
        while (1) {
 
66
                /*
 
67
                 * 1. compute the maximum block size we can read at once.
 
68
                 */
 
69
                if (b->l == 0) { /* let's realign the buffer to optimize I/O */
 
70
                        b->r = b->w = b->lr  = b->data;
 
71
                        max = b->rlim - b->data;
 
72
                }
 
73
                else if (b->r > b->w) {
 
74
                        max = b->rlim - b->r;
 
75
                }
 
76
                else {
 
77
                        max = b->w - b->r;
 
78
                        /* FIXME: theorically, if w>0, we shouldn't have rlim < data+size anymore
 
79
                         * since it means that the rewrite protection has been removed. This
 
80
                         * implies that the if statement can be removed.
 
81
                         */
 
82
                        if (max > b->rlim - b->data)
 
83
                                max = b->rlim - b->data;
 
84
                }
 
85
            
 
86
                if (unlikely(max == 0)) {
 
87
                        /* Not anymore room to store data. This should theorically
 
88
                         * never happen, but better safe than sorry !
 
89
                         */
 
90
                        EV_FD_CLR(fd, DIR_RD);
 
91
                        goto out_eternity;
 
92
                }
 
93
 
 
94
                /*
 
95
                 * 2. read the largest possible block
 
96
                 */
 
97
#ifndef MSG_NOSIGNAL
 
98
                {
 
99
                        int skerr;
 
100
                        socklen_t lskerr = sizeof(skerr);
 
101
 
 
102
                        ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
 
103
                        if (ret == -1 || skerr)
 
104
                                ret = -1;
 
105
                        else
 
106
                                ret = recv(fd, b->r, max, 0);
 
107
                }
 
108
#else
 
109
                ret = recv(fd, b->r, max, MSG_NOSIGNAL);
 
110
#endif
 
111
                if (ret > 0) {
 
112
                        b->r += ret;
 
113
                        b->l += ret;
 
114
                        b->flags |= BF_PARTIAL_READ;
 
115
        
 
116
                        if (b->r == b->data + BUFSIZE) {
 
117
                                b->r = b->data; /* wrap around the buffer */
 
118
                        }
 
119
 
 
120
                        b->total += ret;
 
121
 
 
122
                        if (b->l == b->rlim - b->data) {
 
123
                                /* The buffer is now full, there's no point in going through
 
124
                                 * the loop again.
 
125
                                 */
 
126
                                EV_FD_CLR(fd, DIR_RD);
 
127
                                goto out_eternity;
 
128
                        }
 
129
 
 
130
                        /* if too many bytes were missing from last read, it means that
 
131
                         * it's pointless trying to read again because the system does
 
132
                         * not have them in buffers.
 
133
                         */
 
134
                        if (ret < max)
 
135
                                break;
 
136
 
 
137
                        /* generally if we read something smaller than 1 or 2 MSS,
 
138
                         * it means that it's not worth trying to read again. It may
 
139
                         * also happen on headers, but the application then can stop
 
140
                         * reading before we start polling.
 
141
                         */
 
142
                        if (ret < MIN_RET_FOR_READ_LOOP)
 
143
                                break;
 
144
 
 
145
                        if (--read_poll <= 0)
 
146
                                break;
 
147
 
 
148
                }
 
149
                else if (ret == 0) {
 
150
                        /* connection closed */
 
151
                        b->flags |= BF_READ_NULL;
 
152
                        goto out_eternity;
 
153
                }
 
154
                else if (errno == EAGAIN) {
 
155
                        /* Ignore EAGAIN but inform the poller that there is
 
156
                         * nothing to read left. But we may have done some work
 
157
                         * justifying to notify the task.
 
158
                         */
 
159
                        retval = 0;
 
160
                        break;
 
161
                }
 
162
                else {
 
163
                        goto out_error;
 
164
                }
 
165
        } /* while (1) */
 
166
 
 
167
        /*
 
168
         * The only way to get out of this loop is to have stopped reading
 
169
         * without any error nor close, either by limiting the number of
 
170
         * loops, or because of an EAGAIN. We only rearm the timer if we
 
171
         * have at least read something.
 
172
         */
 
173
 
 
174
        if (b->flags & BF_PARTIAL_READ) {
 
175
                if (tv_add_ifset(&b->rex, &now, &b->rto))
 
176
                        goto out_wakeup;
 
177
        out_eternity:
 
178
                tv_eternity(&b->rex);
 
179
        }
 
180
 
 
181
 out_wakeup:
 
182
        if (b->flags & BF_READ_STATUS)
 
183
                task_wakeup(fdtab[fd].owner);
 
184
        fdtab[fd].ev &= ~FD_POLL_RD;
 
185
        return retval;
 
186
 
 
187
 out_error:
 
188
        /* There was an error. we must wakeup the task. No need to clear
 
189
         * the events, the task will do it.
 
190
         */
 
191
        fdtab[fd].state = FD_STERROR;
 
192
        b->flags |= BF_READ_ERROR;
 
193
        goto out_eternity;
 
194
}
 
195
 
 
196
 
 
197
/*
 
198
 * this function is called on a write event from a stream socket.
 
199
 * It returns 0 if we have a high confidence that we will not be
 
200
 * able to write more data without polling first. Returns non-zero
 
201
 * otherwise.
 
202
 */
 
203
int stream_sock_write(int fd) {
 
204
        __label__ out_eternity, out_wakeup, out_error;
 
205
        struct buffer *b = fdtab[fd].cb[DIR_WR].b;
 
206
        int ret, max, retval;
 
207
        int write_poll = MAX_WRITE_POLL_LOOPS;
 
208
 
 
209
#ifdef DEBUG_FULL
 
210
        fprintf(stderr,"stream_sock_write : fd=%d, owner=%p\n", fd, fdtab[fd].owner);
 
211
#endif
 
212
 
 
213
        retval = 1;
 
214
        if (unlikely(fdtab[fd].state == FD_STERROR || (fdtab[fd].ev & FD_POLL_ERR)))
 
215
                goto out_error;
 
216
 
 
217
        while (1) {
 
218
                if (b->l == 0) { /* let's realign the buffer to optimize I/O */
 
219
                        b->r = b->w = b->lr  = b->data;
 
220
                        max = 0;
 
221
                }
 
222
                else if (b->r > b->w) {
 
223
                        max = b->r - b->w;
 
224
                }
 
225
                else {
 
226
                        max = b->data + BUFSIZE - b->w;
 
227
                }
 
228
 
 
229
                if (max == 0) {
 
230
                        /* may be we have received a connection acknowledgement in TCP mode without data */
 
231
                        if (likely(fdtab[fd].state == FD_STCONN)) {
 
232
                                struct session *s = fdtab[fd].owner->context;
 
233
 
 
234
                                /* We have no data to send to check the connection, and
 
235
                                 * getsockopt() will not inform us whether the connection
 
236
                                 * is still pending. So we'll reuse connect() to check the
 
237
                                 * state of the socket. This has the advantage of givig us
 
238
                                 * the following info :
 
239
                                 *  - error
 
240
                                 *  - connecting (EALREADY, EINPROGRESS)
 
241
                                 *  - connected (EISCONN, 0)
 
242
                                 */
 
243
                                if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == 0))
 
244
                                        errno = 0;
 
245
 
 
246
                                if (errno == EALREADY || errno == EINPROGRESS) {
 
247
                                        retval = 0;
 
248
                                        goto out_wakeup;
 
249
                                }
 
250
 
 
251
                                if (errno && errno != EISCONN)
 
252
                                        goto out_error;
 
253
 
 
254
                                /* OK we just need to indicate that we got a connection
 
255
                                 * and that we wrote nothing.
 
256
                                 */
 
257
                                b->flags |= BF_WRITE_NULL;
 
258
                                fdtab[fd].state = FD_STREADY;
 
259
                        }
 
260
 
 
261
                        /* Funny, we were called to write something but there wasn't
 
262
                         * anything. Theorically we cannot get there, but just in case,
 
263
                         * let's disable the write event and pretend we never came there.
 
264
                         */
 
265
                        EV_FD_CLR(fd, DIR_WR);
 
266
                        goto out_eternity;
 
267
                }
 
268
 
 
269
#ifndef MSG_NOSIGNAL
 
270
                {
 
271
                        int skerr;
 
272
                        socklen_t lskerr = sizeof(skerr);
 
273
 
 
274
                        ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr);
 
275
                        if (ret == -1 || skerr)
 
276
                                ret = -1;
 
277
                        else
 
278
                                ret = send(fd, b->w, max, MSG_DONTWAIT);
 
279
                }
 
280
#else
 
281
                ret = send(fd, b->w, max, MSG_DONTWAIT | MSG_NOSIGNAL);
 
282
#endif
 
283
 
 
284
                if (ret > 0) {
 
285
                        b->l -= ret;
 
286
                        b->w += ret;
 
287
            
 
288
                        b->flags |= BF_PARTIAL_WRITE;
 
289
            
 
290
                        if (b->w == b->data + BUFSIZE) {
 
291
                                b->w = b->data; /* wrap around the buffer */
 
292
                        }
 
293
 
 
294
                        if (!b->l) {
 
295
                                EV_FD_CLR(fd, DIR_WR);
 
296
                                goto out_eternity;
 
297
                        }
 
298
 
 
299
                        /* if the system buffer is full, don't insist */
 
300
                        if (ret < max)
 
301
                                break;
 
302
 
 
303
                        if (--write_poll <= 0)
 
304
                                break;
 
305
                }
 
306
                else if (ret == 0 || errno == EAGAIN) {
 
307
                        /* nothing written, just pretend we were never called
 
308
                         * and wait for the socket to be ready. But we may have
 
309
                         * done some work justifying to notify the task.
 
310
                         */
 
311
                        retval = 0;
 
312
                        break;
 
313
                }
 
314
                else {
 
315
                        goto out_error;
 
316
                }
 
317
        } /* while (1) */
 
318
 
 
319
        /*
 
320
         * The only way to get out of this loop is to have stopped writing
 
321
         * without any error, either by limiting the number of loops, or
 
322
         * because of an EAGAIN. We only rearm the timer if we have at least
 
323
         * written something.
 
324
         */
 
325
 
 
326
        if (b->flags & BF_PARTIAL_WRITE) {
 
327
                if (tv_add_ifset(&b->wex, &now, &b->wto)) {
 
328
                        /* FIXME: to prevent the client from expiring read timeouts during writes,
 
329
                         * we refresh it. A solution would be to merge read+write timeouts into a
 
330
                         * unique one, although that needs some study particularly on full-duplex
 
331
                         * TCP connections. */
 
332
                        if (!(b->flags & BF_SHUTR_STATUS))
 
333
                                b->rex = b->wex;
 
334
                        goto out_wakeup;
 
335
                }
 
336
        out_eternity:
 
337
                tv_eternity(&b->wex);
 
338
        }
 
339
 
 
340
 out_wakeup:
 
341
        if (b->flags & BF_WRITE_STATUS)
 
342
                task_wakeup(fdtab[fd].owner);
 
343
        fdtab[fd].ev &= ~FD_POLL_WR;
 
344
        return retval;
 
345
 
 
346
 out_error:
 
347
        /* There was an error. we must wakeup the task. No need to clear
 
348
         * the events, the task will do it.
 
349
         */
 
350
        fdtab[fd].state = FD_STERROR;
 
351
        b->flags |= BF_WRITE_ERROR;
 
352
        goto out_eternity;
 
353
 
 
354
 
 
355
}
 
356
 
 
357
 
 
358
 
 
359
/*
 
360
 * Local variables:
 
361
 *  c-indent-level: 8
 
362
 *  c-basic-offset: 8
 
363
 * End:
 
364
 */