blob: cbc859e2760515c6c99dcc6a093abf17102e70c2 [file] [log] [blame]
Willy Tarreau92fb9832007-10-16 17:34:28 +02001/*
2 * UNIX SOCK_STREAM protocol layer (uxst)
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreau92fb9832007-10-16 17:34:28 +02005 *
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 <ctype.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <syslog.h>
20#include <time.h>
21
22#include <sys/param.h>
23#include <sys/socket.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include <sys/un.h>
27
28#include <common/compat.h>
29#include <common/config.h>
30#include <common/debug.h>
Willy Tarreaud740bab2007-10-28 11:14:07 +010031#include <common/errors.h>
Willy Tarreau92fb9832007-10-16 17:34:28 +020032#include <common/memory.h>
33#include <common/mini-clist.h>
34#include <common/standard.h>
Willy Tarreau0c303ee2008-07-07 00:09:58 +020035#include <common/ticks.h>
Willy Tarreau92fb9832007-10-16 17:34:28 +020036#include <common/time.h>
37#include <common/version.h>
38
Willy Tarreau92fb9832007-10-16 17:34:28 +020039#include <types/global.h>
Willy Tarreau92fb9832007-10-16 17:34:28 +020040
41#include <proto/acl.h>
42#include <proto/backend.h>
43#include <proto/buffers.h>
Willy Tarreau3e76e722007-10-17 18:57:38 +020044#include <proto/dumpstats.h>
Willy Tarreau92fb9832007-10-16 17:34:28 +020045#include <proto/fd.h>
46#include <proto/log.h>
47#include <proto/protocols.h>
48#include <proto/proto_uxst.h>
49#include <proto/queue.h>
50#include <proto/session.h>
51#include <proto/stream_sock.h>
52#include <proto/task.h>
53
54#ifndef MAXPATHLEN
55#define MAXPATHLEN 128
56#endif
57
Willy Tarreaudabf2e22007-10-28 21:59:24 +010058static int uxst_bind_listeners(struct protocol *proto);
59static int uxst_unbind_listeners(struct protocol *proto);
60
61/* Note: must not be declared <const> as its list will be overwritten */
62static struct protocol proto_unix = {
63 .name = "unix_stream",
64 .sock_domain = PF_UNIX,
65 .sock_type = SOCK_STREAM,
66 .sock_prot = 0,
67 .sock_family = AF_UNIX,
68 .sock_addrlen = sizeof(struct sockaddr_un),
69 .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path),/* path len */
70 .read = &stream_sock_read,
71 .write = &stream_sock_write,
72 .bind_all = uxst_bind_listeners,
73 .unbind_all = uxst_unbind_listeners,
74 .enable_all = enable_all_listeners,
75 .disable_all = disable_all_listeners,
76 .listeners = LIST_HEAD_INIT(proto_unix.listeners),
77 .nb_listeners = 0,
78};
79
80
81/********************************
82 * 1) low-level socket functions
83 ********************************/
84
85
Willy Tarreau92fb9832007-10-16 17:34:28 +020086/* This function creates a named PF_UNIX stream socket at address <path>. Note
Willy Tarreaue6ad2b12007-10-18 12:45:54 +020087 * that the path cannot be NULL nor empty. <uid> and <gid> different of -1 will
88 * be used to change the socket owner. If <mode> is not 0, it will be used to
89 * restrict access to the socket. While it is known not to be portable on every
90 * OS, it's still useful where it works.
Willy Tarreau92fb9832007-10-16 17:34:28 +020091 * It returns the assigned file descriptor, or -1 in the event of an error.
92 */
Willy Tarreaue6ad2b12007-10-18 12:45:54 +020093static int create_uxst_socket(const char *path, uid_t uid, gid_t gid, mode_t mode)
Willy Tarreau92fb9832007-10-16 17:34:28 +020094{
95 char tempname[MAXPATHLEN];
96 char backname[MAXPATHLEN];
97 struct sockaddr_un addr;
98
99 int ret, sock;
100
101 /* 1. create socket names */
102 if (!path[0]) {
103 Alert("Invalid name for a UNIX socket. Aborting.\n");
104 goto err_return;
105 }
106
107 ret = snprintf(tempname, MAXPATHLEN, "%s.%d.tmp", path, pid);
108 if (ret < 0 || ret >= MAXPATHLEN) {
109 Alert("name too long for UNIX socket. Aborting.\n");
110 goto err_return;
111 }
112
113 ret = snprintf(backname, MAXPATHLEN, "%s.%d.bak", path, pid);
114 if (ret < 0 || ret >= MAXPATHLEN) {
115 Alert("name too long for UNIX socket. Aborting.\n");
116 goto err_return;
117 }
118
119 /* 2. clean existing orphaned entries */
120 if (unlink(tempname) < 0 && errno != ENOENT) {
121 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
122 goto err_return;
123 }
124
125 if (unlink(backname) < 0 && errno != ENOENT) {
126 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
127 goto err_return;
128 }
129
130 /* 3. backup existing socket */
131 if (link(path, backname) < 0 && errno != ENOENT) {
132 Alert("error when trying to preserve previous UNIX socket. Aborting.\n");
133 goto err_return;
134 }
135
136 /* 4. prepare new socket */
137 addr.sun_family = AF_UNIX;
138 strncpy(addr.sun_path, tempname, sizeof(addr.sun_path));
139 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
140
141 sock = socket(PF_UNIX, SOCK_STREAM, 0);
142 if (sock < 0) {
143 Alert("cannot create socket for UNIX listener. Aborting.\n");
144 goto err_unlink_back;
145 }
146
147 if (sock >= global.maxsock) {
148 Alert("socket(): not enough free sockets for UNIX listener. Raise -n argument. Aborting.\n");
149 goto err_unlink_temp;
150 }
151
152 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
153 Alert("cannot make UNIX socket non-blocking. Aborting.\n");
154 goto err_unlink_temp;
155 }
156
157 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
158 /* note that bind() creates the socket <tempname> on the file system */
159 Alert("cannot bind socket for UNIX listener. Aborting.\n");
160 goto err_unlink_temp;
161 }
162
Willy Tarreaue6ad2b12007-10-18 12:45:54 +0200163 if (((uid != -1 || gid != -1) && (chown(tempname, uid, gid) == -1)) ||
164 (mode != 0 && chmod(tempname, mode) == -1)) {
165 Alert("cannot change UNIX socket ownership. Aborting.\n");
166 goto err_unlink_temp;
167 }
168
Willy Tarreau92fb9832007-10-16 17:34:28 +0200169 if (listen(sock, 0) < 0) {
170 Alert("cannot listen to socket for UNIX listener. Aborting.\n");
171 goto err_unlink_temp;
172 }
173
174 /* 5. install.
175 * Point of no return: we are ready, we'll switch the sockets. We don't
176 * fear loosing the socket <path> because we have a copy of it in
177 * backname.
178 */
179 if (rename(tempname, path) < 0) {
180 Alert("cannot switch final and temporary sockets for UNIX listener. Aborting.\n");
181 goto err_rename;
182 }
183
184 /* 6. cleanup */
185 unlink(backname); /* no need to keep this one either */
186
187 return sock;
188
189 err_rename:
190 ret = rename(backname, path);
191 if (ret < 0 && errno == ENOENT)
192 unlink(path);
193 err_unlink_temp:
194 unlink(tempname);
195 close(sock);
196 err_unlink_back:
197 unlink(backname);
198 err_return:
199 return -1;
200}
201
202/* Tries to destroy the UNIX stream socket <path>. The socket must not be used
203 * anymore. It practises best effort, and no error is returned.
204 */
205static void destroy_uxst_socket(const char *path)
206{
207 struct sockaddr_un addr;
208 int sock, ret;
209
210 /* We might have been chrooted, so we may not be able to access the
211 * socket. In order to avoid bothering the other end, we connect with a
212 * wrong protocol, namely SOCK_DGRAM. The return code from connect()
213 * is enough to know if the socket is still live or not. If it's live
214 * in mode SOCK_STREAM, we get EPROTOTYPE or anything else but not
215 * ECONNREFUSED. In this case, we do not touch it because it's used
216 * by some other process.
217 */
218 sock = socket(PF_UNIX, SOCK_DGRAM, 0);
219 if (sock < 0)
220 return;
221
222 addr.sun_family = AF_UNIX;
223 strncpy(addr.sun_path, path, sizeof(addr.sun_path));
Willy Tarreau10ae5482007-10-18 16:15:52 +0200224 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200225 ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
226 if (ret < 0 && errno == ECONNREFUSED) {
227 /* Connect failed: the socket still exists but is not used
228 * anymore. Let's remove this socket now.
229 */
230 unlink(path);
231 }
232 close(sock);
233}
234
235
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100236/********************************
237 * 2) listener-oriented functions
238 ********************************/
239
240
241/* This function creates the UNIX socket associated to the listener. It changes
242 * the state from ASSIGNED to LISTEN. The socket is NOT enabled for polling.
243 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
244 */
245static int uxst_bind_listener(struct listener *listener)
246{
247 int fd;
248
249 if (listener->state != LI_ASSIGNED)
250 return ERR_NONE; /* already bound */
251
252 fd = create_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path,
253 listener->perm.ux.uid,
254 listener->perm.ux.gid,
255 listener->perm.ux.mode);
256 if (fd == -1)
257 return ERR_FATAL;
258
259 /* the socket is now listening */
260 listener->fd = fd;
261 listener->state = LI_LISTEN;
262
263 /* the function for the accept() event */
264 fd_insert(fd);
265 fdtab[fd].cb[DIR_RD].f = listener->accept;
266 fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
267 fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
Willy Tarreaueabf3132008-08-29 23:36:51 +0200268 fdtab[fd].owner = listener; /* reference the listener instead of a task */
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100269 fdtab[fd].state = FD_STLISTEN;
270 fdtab[fd].peeraddr = NULL;
271 fdtab[fd].peerlen = 0;
272 fdtab[fd].listener = NULL;
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100273 return ERR_NONE;
274}
275
276/* This function closes the UNIX sockets for the specified listener.
277 * The listener enters the LI_ASSIGNED state. It always returns ERR_NONE.
278 */
279static int uxst_unbind_listener(struct listener *listener)
280{
281 if (listener->state == LI_READY)
282 EV_FD_CLR(listener->fd, DIR_RD);
283
284 if (listener->state >= LI_LISTEN) {
Willy Tarreau8eebe5e2007-10-28 22:07:08 +0100285 fd_delete(listener->fd);
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100286 listener->state = LI_ASSIGNED;
287 destroy_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path);
288 }
289 return ERR_NONE;
290}
291
292/* Add a listener to the list of unix stream listeners. The listener's state
293 * is automatically updated from LI_INIT to LI_ASSIGNED. The number of
294 * listeners is updated. This is the function to use to add a new listener.
295 */
296void uxst_add_listener(struct listener *listener)
297{
298 if (listener->state != LI_INIT)
299 return;
300 listener->state = LI_ASSIGNED;
301 listener->proto = &proto_unix;
302 LIST_ADDQ(&proto_unix.listeners, &listener->proto_list);
303 proto_unix.nb_listeners++;
304}
305
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100306/********************************
307 * 3) protocol-oriented functions
308 ********************************/
309
310
Willy Tarreau92fb9832007-10-16 17:34:28 +0200311/* This function creates all UNIX sockets bound to the protocol entry <proto>.
312 * It is intended to be used as the protocol's bind_all() function.
313 * The sockets will be registered but not added to any fd_set, in order not to
314 * loose them across the fork(). A call to uxst_enable_listeners() is needed
315 * to complete initialization.
316 *
317 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
318 */
319static int uxst_bind_listeners(struct protocol *proto)
320{
321 struct listener *listener;
322 int err = ERR_NONE;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200323
324 list_for_each_entry(listener, &proto->listeners, proto_list) {
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100325 err |= uxst_bind_listener(listener);
326 if (err != ERR_NONE)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200327 continue;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200328 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200329 return err;
330}
331
Willy Tarreau92fb9832007-10-16 17:34:28 +0200332
333/* This function stops all listening UNIX sockets bound to the protocol
334 * <proto>. It does not detaches them from the protocol.
335 * It always returns ERR_NONE.
336 */
337static int uxst_unbind_listeners(struct protocol *proto)
338{
339 struct listener *listener;
340
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100341 list_for_each_entry(listener, &proto->listeners, proto_list)
342 uxst_unbind_listener(listener);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200343 return ERR_NONE;
344}
345
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100346
347/********************************
348 * 4) high-level functions
349 ********************************/
350
351
Willy Tarreau92fb9832007-10-16 17:34:28 +0200352/*
353 * This function is called on a read event from a listen socket, corresponding
354 * to an accept. It tries to accept as many connections as possible.
355 * It returns 0. Since we use UNIX sockets on the local system for monitoring
356 * purposes and other related things, we do not need to output as many messages
357 * as with TCP which can fall under attack.
358 */
359int uxst_event_accept(int fd) {
Willy Tarreaueabf3132008-08-29 23:36:51 +0200360 struct listener *l = fdtab[fd].owner;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200361 struct session *s;
362 struct task *t;
363 int cfd;
364 int max_accept;
365
366 if (global.nbproc > 1)
367 max_accept = 8; /* let other processes catch some connections too */
368 else
369 max_accept = -1;
370
371 while (max_accept--) {
372 struct sockaddr_storage addr;
373 socklen_t laddr = sizeof(addr);
374
375 if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) == -1) {
376 switch (errno) {
377 case EAGAIN:
378 case EINTR:
379 case ECONNABORTED:
380 return 0; /* nothing more to accept */
381 case ENFILE:
382 /* Process reached system FD limit. Check system tunables. */
383 return 0;
384 case EMFILE:
385 /* Process reached process FD limit. Check 'ulimit-n'. */
386 return 0;
387 case ENOBUFS:
388 case ENOMEM:
389 /* Process reached system memory limit. Check system tunables. */
390 return 0;
391 default:
392 return 0;
393 }
394 }
395
396 if (l->nbconn >= l->maxconn) {
397 /* too many connections, we shoot this one and return.
398 * FIXME: it would be better to simply switch the listener's
399 * state to LI_FULL and disable the FD. We could re-enable
400 * it upon fd_delete(), but this requires all protocols to
401 * be switched.
402 */
Willy Tarreaua11e9762008-12-01 01:44:25 +0100403 goto out_close;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200404 }
405
406 if ((s = pool_alloc2(pool2_session)) == NULL) {
407 Alert("out of memory in uxst_event_accept().\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100408 goto out_close;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200409 }
410
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100411 LIST_ADDQ(&sessions, &s->list);
412
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100413 s->flags = 0;
Willy Tarreauf8533202008-08-16 14:55:08 +0200414 s->term_trace = 0;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100415
Willy Tarreau92fb9832007-10-16 17:34:28 +0200416 if ((t = pool_alloc2(pool2_task)) == NULL) {
417 Alert("out of memory in uxst_event_accept().\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100418 goto out_free_session;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200419 }
420
421 s->cli_addr = addr;
422
423 /* FIXME: should be checked earlier */
424 if (cfd >= global.maxsock) {
425 Alert("accept(): not enough free sockets. Raise -n argument. Giving up.\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100426 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200427 }
428
429 if (fcntl(cfd, F_SETFL, O_NONBLOCK) == -1) {
430 Alert("accept(): cannot set the socket in non blocking mode. Giving up\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100431 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200432 }
433
Willy Tarreau9789f7b2008-06-24 08:17:16 +0200434 task_init(t);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200435 t->process = l->handler;
436 t->context = s;
Willy Tarreau91e99932008-06-30 07:51:00 +0200437 t->nice = -64; /* we want to boost priority for local stats */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200438
439 s->task = t;
440 s->fe = NULL;
441 s->be = NULL;
442
443 s->cli_state = CL_STDATA;
444 s->srv_state = SV_STIDLE;
445 s->req = s->rep = NULL; /* will be allocated later */
446
Willy Tarreaua11e9762008-12-01 01:44:25 +0100447 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
448 s->si[0].err_type = SI_ET_NONE;
449 s->si[0].err_loc = NULL;
450 s->si[0].owner = t;
451 s->si[0].shutr = stream_sock_shutr;
452 s->si[0].shutw = stream_sock_shutw;
453 s->si[0].fd = cfd;
454 s->si[0].flags = SI_FL_NONE;
455 s->si[0].exp = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200456 s->cli_fd = cfd;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100457
458 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
459 s->si[1].err_type = SI_ET_NONE;
460 s->si[1].err_loc = NULL;
461 s->si[1].owner = t;
462 s->si[1].shutr = stream_sock_shutr;
463 s->si[1].shutw = stream_sock_shutw;
464 s->si[1].exp = TICK_ETERNITY;
465 s->si[1].fd = -1; /* just to help with debugging */
466 s->si[1].flags = SI_FL_NONE;
467
468 s->srv = s->prev_srv = s->srv_conn = NULL;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200469 s->pend_pos = NULL;
470
471 memset(&s->logs, 0, sizeof(s->logs));
472 memset(&s->txn, 0, sizeof(s->txn));
473
Willy Tarreau3e76e722007-10-17 18:57:38 +0200474 s->data_state = DATA_ST_INIT;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200475 s->data_source = DATA_SRC_NONE;
476 s->uniq_id = totalconn;
477
Willy Tarreaua11e9762008-12-01 01:44:25 +0100478 if ((s->req = pool_alloc2(pool2_buffer)) == NULL)
479 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200480
Willy Tarreaua11e9762008-12-01 01:44:25 +0100481 s->req->prod = &s->si[0];
482 s->req->cons = &s->si[1];
483 s->si[0].ib = s->si[1].ob = s->req;
484 s->req->flags |= BF_READ_ATTACHED; /* the producer is already connected */
485
486 if (!s->req->analysers)
487 buffer_write_ena(s->req); /* don't wait to establish connection */
488
489 s->req->wto = TICK_ETERNITY;
490 s->req->cto = TICK_ETERNITY;
491 s->req->rto = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200492
Willy Tarreaua11e9762008-12-01 01:44:25 +0100493 if ((s->rep = pool_alloc2(pool2_buffer)) == NULL)
494 goto out_free_req;
495
Willy Tarreau92fb9832007-10-16 17:34:28 +0200496 buffer_init(s->rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200497
Willy Tarreaua11e9762008-12-01 01:44:25 +0100498 s->rep->prod = &s->si[1];
499 s->rep->cons = &s->si[0];
500 s->si[0].ob = s->si[1].ib = s->rep;
501
502 s->rep->rto = TICK_ETERNITY;
503 s->rep->cto = TICK_ETERNITY;
504 s->rep->wto = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200505
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200506 s->req->rex = TICK_ETERNITY;
507 s->req->wex = TICK_ETERNITY;
Willy Tarreauffab5b42008-08-17 18:03:28 +0200508 s->req->analyse_exp = TICK_ETERNITY;
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200509 s->rep->rex = TICK_ETERNITY;
510 s->rep->wex = TICK_ETERNITY;
Willy Tarreauffab5b42008-08-17 18:03:28 +0200511 s->rep->analyse_exp = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200512
Willy Tarreaua11e9762008-12-01 01:44:25 +0100513 t->expire = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200514
Willy Tarreaua11e9762008-12-01 01:44:25 +0100515 if (l->timeout) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200516 s->req->rto = *l->timeout;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200517 s->rep->wto = *l->timeout;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200518 }
519
Willy Tarreaua11e9762008-12-01 01:44:25 +0100520 fd_insert(cfd);
521 fdtab[cfd].owner = &s->si[0];
522 fdtab[cfd].listener = l;
523 fdtab[cfd].state = FD_STREADY;
524 fdtab[cfd].cb[DIR_RD].f = l->proto->read;
525 fdtab[cfd].cb[DIR_RD].b = s->req;
526 fdtab[cfd].cb[DIR_WR].f = l->proto->write;
527 fdtab[cfd].cb[DIR_WR].b = s->rep;
528 fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
529 fdtab[cfd].peerlen = sizeof(s->cli_addr);
530
531 EV_FD_SET(cfd, DIR_RD);
532
Willy Tarreaufdccded2008-08-29 18:19:04 +0200533 task_wakeup(t, TASK_WOKEN_INIT);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200534
535 l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
536 if (l->nbconn >= l->maxconn) {
537 EV_FD_CLR(l->fd, DIR_RD);
538 l->state = LI_FULL;
539 }
540 actconn++;
541 totalconn++;
542
543 //fprintf(stderr, "accepting from %p => %d conn, %d total, task=%p, cfd=%d, maxfd=%d\n", p, actconn, totalconn, t, cfd, maxfd);
544 } /* end of while (p->feconn < p->maxconn) */
545 //fprintf(stderr,"fct %s:%d\n", __FUNCTION__, __LINE__);
546 return 0;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100547
548 out_free_req:
549 pool_free2(pool2_buffer, s->req);
550 out_free_task:
551 pool_free2(pool2_task, t);
552 out_free_session:
553 LIST_DEL(&s->list);
554 pool_free2(pool2_session, s);
555 out_close:
556 close(cfd);
557 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200558}
559
560/*
561 * manages the client FSM and its socket. It returns 1 if a state has changed
562 * (and a resync may be needed), otherwise 0.
563 */
564static int process_uxst_cli(struct session *t)
565{
566 int s = t->srv_state;
567 int c = t->cli_state;
568 struct buffer *req = t->req;
569 struct buffer *rep = t->rep;
570 //fprintf(stderr,"fct %s:%d\n", __FUNCTION__, __LINE__);
571 if (c == CL_STDATA) {
572 /* FIXME: this error handling is partly buggy because we always report
573 * a 'DATA' phase while we don't know if the server was in IDLE, CONN
574 * or HEADER phase. BTW, it's not logical to expire the client while
575 * we're waiting for the server to connect.
576 */
577 /* read or write error */
578 if (rep->flags & BF_WRITE_ERROR || req->flags & BF_READ_ERROR) {
Willy Tarreauba392ce2008-08-16 21:13:23 +0200579 buffer_shutr(req);
580 buffer_shutw(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200581 fd_delete(t->cli_fd);
582 t->cli_state = CL_STCLOSE;
583 if (!(t->flags & SN_ERR_MASK))
584 t->flags |= SN_ERR_CLICL;
585 if (!(t->flags & SN_FINST_MASK)) {
586 if (t->pend_pos)
587 t->flags |= SN_FINST_Q;
588 else if (s == SV_STCONN)
589 t->flags |= SN_FINST_C;
590 else
591 t->flags |= SN_FINST_D;
592 }
593 return 1;
594 }
595 /* last read, or end of server write */
596 else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
597 EV_FD_CLR(t->cli_fd, DIR_RD);
598 buffer_shutr(req);
599 t->cli_state = CL_STSHUTR;
600 return 1;
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100601 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200602 /* last server read and buffer empty */
Willy Tarreaue393fe22008-08-16 22:18:07 +0200603 else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->flags & BF_EMPTY)) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200604 EV_FD_CLR(t->cli_fd, DIR_WR);
Willy Tarreauba392ce2008-08-16 21:13:23 +0200605 buffer_shutw(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200606 shutdown(t->cli_fd, SHUT_WR);
607 /* We must ensure that the read part is still alive when switching
608 * to shutw */
609 EV_FD_SET(t->cli_fd, DIR_RD);
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200610 req->rex = tick_add_ifset(now_ms, req->rto);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200611 t->cli_state = CL_STSHUTW;
612 //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
613 return 1;
614 }
615 /* read timeout */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200616 else if (tick_is_expired(req->rex, now_ms)) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200617 EV_FD_CLR(t->cli_fd, DIR_RD);
618 buffer_shutr(req);
619 t->cli_state = CL_STSHUTR;
620 if (!(t->flags & SN_ERR_MASK))
621 t->flags |= SN_ERR_CLITO;
622 if (!(t->flags & SN_FINST_MASK)) {
623 if (t->pend_pos)
624 t->flags |= SN_FINST_Q;
625 else if (s == SV_STCONN)
626 t->flags |= SN_FINST_C;
627 else
628 t->flags |= SN_FINST_D;
629 }
630 return 1;
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100631 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200632 /* write timeout */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200633 else if (tick_is_expired(rep->wex, now_ms)) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200634 EV_FD_CLR(t->cli_fd, DIR_WR);
Willy Tarreauba392ce2008-08-16 21:13:23 +0200635 buffer_shutw(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200636 shutdown(t->cli_fd, SHUT_WR);
637 /* We must ensure that the read part is still alive when switching
638 * to shutw */
639 EV_FD_SET(t->cli_fd, DIR_RD);
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200640 req->rex = tick_add_ifset(now_ms, req->rto);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200641
642 t->cli_state = CL_STSHUTW;
643 if (!(t->flags & SN_ERR_MASK))
644 t->flags |= SN_ERR_CLITO;
645 if (!(t->flags & SN_FINST_MASK)) {
646 if (t->pend_pos)
647 t->flags |= SN_FINST_Q;
648 else if (s == SV_STCONN)
649 t->flags |= SN_FINST_C;
650 else
651 t->flags |= SN_FINST_D;
652 }
653 return 1;
654 }
655
Willy Tarreaue393fe22008-08-16 22:18:07 +0200656 if (req->flags & BF_FULL) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200657 /* no room to read more data */
658 if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
659 /* stop reading until we get some space */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200660 req->rex = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200661 }
662 } else {
663 /* there's still some space in the buffer */
664 if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200665 if (!req->rto ||
666 (t->srv_state < SV_STDATA && req->wto))
Willy Tarreau92fb9832007-10-16 17:34:28 +0200667 /* If the client has no timeout, or if the server not ready yet, and we
668 * know for sure that it can expire, then it's cleaner to disable the
669 * timeout on the client side so that too low values cannot make the
670 * sessions abort too early.
671 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200672 req->rex = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200673 else
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200674 req->rex = tick_add(now_ms, req->rto);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200675 }
676 }
677
Willy Tarreaue393fe22008-08-16 22:18:07 +0200678 if ((rep->flags & BF_EMPTY) ||
Willy Tarreau92fb9832007-10-16 17:34:28 +0200679 ((s < SV_STDATA) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
680 if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
681 /* stop writing */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200682 rep->wex = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200683 }
684 } else {
685 /* buffer not empty */
686 if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
687 /* restart writing */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200688 rep->wex = tick_add_ifset(now_ms, rep->wto);
689 if (rep->wex) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200690 /* FIXME: to prevent the client from expiring read timeouts during writes,
691 * we refresh it. */
692 req->rex = rep->wex;
693 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200694 }
695 }
696 return 0; /* other cases change nothing */
697 }
698 else if (c == CL_STSHUTR) {
699 if (rep->flags & BF_WRITE_ERROR) {
Willy Tarreauba392ce2008-08-16 21:13:23 +0200700 buffer_shutw(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200701 fd_delete(t->cli_fd);
702 t->cli_state = CL_STCLOSE;
703 if (!(t->flags & SN_ERR_MASK))
704 t->flags |= SN_ERR_CLICL;
705 if (!(t->flags & SN_FINST_MASK)) {
706 if (t->pend_pos)
707 t->flags |= SN_FINST_Q;
708 else if (s == SV_STCONN)
709 t->flags |= SN_FINST_C;
710 else
711 t->flags |= SN_FINST_D;
712 }
713 return 1;
714 }
Willy Tarreaue393fe22008-08-16 22:18:07 +0200715 else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->flags & BF_EMPTY)) {
Willy Tarreauba392ce2008-08-16 21:13:23 +0200716 buffer_shutw(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200717 fd_delete(t->cli_fd);
718 t->cli_state = CL_STCLOSE;
719 return 1;
720 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200721 else if (tick_is_expired(rep->wex, now_ms)) {
Willy Tarreauba392ce2008-08-16 21:13:23 +0200722 buffer_shutw(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200723 fd_delete(t->cli_fd);
724 t->cli_state = CL_STCLOSE;
725 if (!(t->flags & SN_ERR_MASK))
726 t->flags |= SN_ERR_CLITO;
727 if (!(t->flags & SN_FINST_MASK)) {
728 if (t->pend_pos)
729 t->flags |= SN_FINST_Q;
730 else if (s == SV_STCONN)
731 t->flags |= SN_FINST_C;
732 else
733 t->flags |= SN_FINST_D;
734 }
735 return 1;
736 }
737
Willy Tarreaue393fe22008-08-16 22:18:07 +0200738 if (rep->flags & BF_EMPTY) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200739 if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
740 /* stop writing */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200741 rep->wex = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200742 }
743 } else {
744 /* buffer not empty */
745 if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
746 /* restart writing */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200747 rep->wex = tick_add_ifset(now_ms, rep->wto);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200748 }
749 }
750 return 0;
751 }
752 else if (c == CL_STSHUTW) {
753 if (req->flags & BF_READ_ERROR) {
Willy Tarreauba392ce2008-08-16 21:13:23 +0200754 buffer_shutr(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200755 fd_delete(t->cli_fd);
756 t->cli_state = CL_STCLOSE;
757 if (!(t->flags & SN_ERR_MASK))
758 t->flags |= SN_ERR_CLICL;
759 if (!(t->flags & SN_FINST_MASK)) {
760 if (t->pend_pos)
761 t->flags |= SN_FINST_Q;
762 else if (s == SV_STCONN)
763 t->flags |= SN_FINST_C;
764 else
765 t->flags |= SN_FINST_D;
766 }
767 return 1;
768 }
769 else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
Willy Tarreauba392ce2008-08-16 21:13:23 +0200770 buffer_shutr(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200771 fd_delete(t->cli_fd);
772 t->cli_state = CL_STCLOSE;
773 return 1;
774 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200775 else if (tick_is_expired(req->rex, now_ms)) {
Willy Tarreauba392ce2008-08-16 21:13:23 +0200776 buffer_shutr(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200777 fd_delete(t->cli_fd);
778 t->cli_state = CL_STCLOSE;
779 if (!(t->flags & SN_ERR_MASK))
780 t->flags |= SN_ERR_CLITO;
781 if (!(t->flags & SN_FINST_MASK)) {
782 if (t->pend_pos)
783 t->flags |= SN_FINST_Q;
784 else if (s == SV_STCONN)
785 t->flags |= SN_FINST_C;
786 else
787 t->flags |= SN_FINST_D;
788 }
789 return 1;
790 }
Willy Tarreaue393fe22008-08-16 22:18:07 +0200791 else if (req->flags & BF_FULL) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200792 /* no room to read more data */
793
794 /* FIXME-20050705: is it possible for a client to maintain a session
795 * after the timeout by sending more data after it receives a close ?
796 */
797
798 if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
799 /* stop reading until we get some space */
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200800 req->rex = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200801 }
802 } else {
803 /* there's still some space in the buffer */
804 if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200805 req->rex = tick_add_ifset(now_ms, req->rto);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200806 }
807 }
808 return 0;
809 }
810 else { /* CL_STCLOSE: nothing to do */
811 if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
812 int len;
813 len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n", t->uniq_id, t->be?t->be->id:"",
Willy Tarreaufa7e1022008-10-19 07:30:41 +0200814 (unsigned short)t->cli_fd, (unsigned short)t->req->cons->fd);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200815 write(1, trash, len);
816 }
817 return 0;
818 }
819 return 0;
820}
821
822#if 0
823 /* FIXME! This part has not been completely converted yet, and it may
824 * still be very specific to TCPv4 ! Also, it relies on some parameters
825 * such as conn_retries which are not set upon accept().
826 */
827/*
828 * Manages the server FSM and its socket. It returns 1 if a state has changed
829 * (and a resync may be needed), otherwise 0.
830 */
831static int process_uxst_srv(struct session *t)
832{
833 int s = t->srv_state;
834 int c = t->cli_state;
835 struct buffer *req = t->req;
836 struct buffer *rep = t->rep;
837 int conn_err;
838
839 if (s == SV_STIDLE) {
840 if (c == CL_STCLOSE || c == CL_STSHUTW ||
841 (c == CL_STSHUTR &&
Willy Tarreaue393fe22008-08-16 22:18:07 +0200842 (t->req->flags & BF_EMPTY || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200843 tv_eternity(&req->cex);
844 if (t->pend_pos)
845 t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
846 srv_close_with_err(t, SN_ERR_CLICL, t->pend_pos ? SN_FINST_Q : SN_FINST_C);
847 return 1;
848 }
849 else {
850 /* FIXME: reimplement the TARPIT check here */
851
852 /* Right now, we will need to create a connection to the server.
853 * We might already have tried, and got a connection pending, in
854 * which case we will not do anything till it's pending. It's up
855 * to any other session to release it and wake us up again.
856 */
857 if (t->pend_pos) {
858 if (!tv_isle(&req->cex, &now))
859 return 0;
860 else {
861 /* we've been waiting too long here */
862 tv_eternity(&req->cex);
863 t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
864 srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_Q);
865 if (t->srv)
866 t->srv->failed_conns++;
867 if (t->fe)
868 t->fe->failed_conns++;
869 return 1;
870 }
871 }
872
873 do {
874 /* first, get a connection */
875 if (srv_redispatch_connect(t))
876 return t->srv_state != SV_STIDLE;
877
878 /* try to (re-)connect to the server, and fail if we expire the
879 * number of retries.
880 */
881 if (srv_retryable_connect(t)) {
882 t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
883 return t->srv_state != SV_STIDLE;
884 }
885 } while (1);
886 }
887 }
888 else if (s == SV_STCONN) { /* connection in progress */
889 if (c == CL_STCLOSE || c == CL_STSHUTW ||
890 (c == CL_STSHUTR &&
Willy Tarreau3da77c52008-08-29 09:58:42 +0200891 ((t->req->flags & BF_EMPTY && !(req->flags & BF_WRITE_ACTIVITY)) ||
Willy Tarreau92fb9832007-10-16 17:34:28 +0200892 t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
893 tv_eternity(&req->cex);
894 fd_delete(t->srv_fd);
895 if (t->srv)
896 t->srv->cur_sess--;
897
898 srv_close_with_err(t, SN_ERR_CLICL, SN_FINST_C);
899 return 1;
900 }
Willy Tarreau3da77c52008-08-29 09:58:42 +0200901 if (!(req->flags & BF_WRITE_ACTIVITY) && !tv_isle(&req->cex, &now)) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200902 //fprintf(stderr,"1: c=%d, s=%d, now=%d.%06d, exp=%d.%06d\n", c, s, now.tv_sec, now.tv_usec, req->cex.tv_sec, req->cex.tv_usec);
903 return 0; /* nothing changed */
904 }
Willy Tarreau3da77c52008-08-29 09:58:42 +0200905 else if (!(req->flags & BF_WRITE_ACTIVITY) || (req->flags & BF_WRITE_ERROR)) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200906 /* timeout, asynchronous connect error or first write error */
907 //fprintf(stderr,"2: c=%d, s=%d\n", c, s);
908
909 fd_delete(t->srv_fd);
910 if (t->srv)
911 t->srv->cur_sess--;
912
Willy Tarreau3da77c52008-08-29 09:58:42 +0200913 if (!(req->flags & BF_WRITE_ACTIVITY))
Willy Tarreau92fb9832007-10-16 17:34:28 +0200914 conn_err = SN_ERR_SRVTO; // it was a connect timeout.
915 else
916 conn_err = SN_ERR_SRVCL; // it was an asynchronous connect error.
917
918 /* ensure that we have enough retries left */
919 if (srv_count_retry_down(t, conn_err))
920 return 1;
921
922 if (t->srv && t->conn_retries == 0 && t->be->options & PR_O_REDISP) {
923 /* We're on our last chance, and the REDISP option was specified.
924 * We will ignore cookie and force to balance or use the dispatcher.
925 */
926 /* let's try to offer this slot to anybody */
927 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau7c669d72008-06-20 15:04:11 +0200928 process_srv_queue(t->srv);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200929
930 if (t->srv)
931 t->srv->failed_conns++;
932 t->be->failed_conns++;
933
934 t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
935 t->srv = NULL; /* it's left to the dispatcher to choose a server */
936
937 /* first, get a connection */
938 if (srv_redispatch_connect(t))
939 return t->srv_state != SV_STIDLE;
940 }
941
942 do {
943 /* Now we will try to either reconnect to the same server or
944 * connect to another server. If the connection gets queued
945 * because all servers are saturated, then we will go back to
946 * the SV_STIDLE state.
947 */
948 if (srv_retryable_connect(t)) {
949 t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
950 return t->srv_state != SV_STCONN;
951 }
952
953 /* we need to redispatch the connection to another server */
954 if (srv_redispatch_connect(t))
955 return t->srv_state != SV_STCONN;
956 } while (1);
957 }
958 else { /* no error or write 0 */
959 t->logs.t_connect = tv_ms_elapsed(&t->logs.tv_accept, &now);
960
961 //fprintf(stderr,"3: c=%d, s=%d\n", c, s);
Willy Tarreaue393fe22008-08-16 22:18:07 +0200962 if (req->flags & BF_EMPTY) /* nothing to write */ {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200963 EV_FD_CLR(t->srv_fd, DIR_WR);
964 tv_eternity(&req->wex);
965 } else /* need the right to write */ {
966 EV_FD_SET(t->srv_fd, DIR_WR);
967 if (tv_add_ifset(&req->wex, &now, &req->wto)) {
968 /* FIXME: to prevent the server from expiring read timeouts during writes,
969 * we refresh it. */
970 rep->rex = req->wex;
971 }
972 else
973 tv_eternity(&req->wex);
974 }
975
976 EV_FD_SET(t->srv_fd, DIR_RD);
977 if (!tv_add_ifset(&rep->rex, &now, &rep->rto))
978 tv_eternity(&rep->rex);
979
980 t->srv_state = SV_STDATA;
981 if (t->srv)
982 t->srv->cum_sess++;
Willy Tarreaue393fe22008-08-16 22:18:07 +0200983 buffer_set_rlim(rep, BUFSIZE); /* no rewrite needed */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200984
985 /* if the user wants to log as soon as possible, without counting
986 bytes from the server, then this is the right moment. */
987 if (t->fe && t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
988 t->logs.t_close = t->logs.t_connect; /* to get a valid end date */
989 //uxst_sess_log(t);
990 }
991 tv_eternity(&req->cex);
992 return 1;
993 }
994 }
995 else if (s == SV_STDATA) {
996 /* read or write error */
997 if (req->flags & BF_WRITE_ERROR || rep->flags & BF_READ_ERROR) {
Willy Tarreauba392ce2008-08-16 21:13:23 +0200998 buffer_shutr(rep);
999 buffer_shutw(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001000 fd_delete(t->srv_fd);
1001 if (t->srv) {
1002 t->srv->cur_sess--;
1003 t->srv->failed_resp++;
1004 }
1005 t->be->failed_resp++;
1006 t->srv_state = SV_STCLOSE;
1007 if (!(t->flags & SN_ERR_MASK))
1008 t->flags |= SN_ERR_SRVCL;
1009 if (!(t->flags & SN_FINST_MASK))
1010 t->flags |= SN_FINST_D;
1011 /* We used to have a free connection slot. Since we'll never use it,
1012 * we have to inform the server that it may be used by another session.
1013 */
1014 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau7c669d72008-06-20 15:04:11 +02001015 process_srv_queue(t->srv);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001016
1017 return 1;
1018 }
1019 /* last read, or end of client write */
1020 else if (rep->flags & BF_READ_NULL || c == CL_STSHUTW || c == CL_STCLOSE) {
1021 EV_FD_CLR(t->srv_fd, DIR_RD);
1022 buffer_shutr(rep);
1023 t->srv_state = SV_STSHUTR;
1024 //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
1025 return 1;
1026 }
1027 /* end of client read and no more data to send */
Willy Tarreaue393fe22008-08-16 22:18:07 +02001028 else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->flags & BF_EMPTY)) {
Willy Tarreau92fb9832007-10-16 17:34:28 +02001029 EV_FD_CLR(t->srv_fd, DIR_WR);
Willy Tarreauba392ce2008-08-16 21:13:23 +02001030 buffer_shutw(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001031 shutdown(t->srv_fd, SHUT_WR);
1032 /* We must ensure that the read part is still alive when switching
1033 * to shutw */
1034 EV_FD_SET(t->srv_fd, DIR_RD);
1035 tv_add_ifset(&rep->rex, &now, &rep->rto);
1036
1037 t->srv_state = SV_STSHUTW;
1038 return 1;
1039 }
1040 /* read timeout */
1041 else if (tv_isle(&rep->rex, &now)) {
1042 EV_FD_CLR(t->srv_fd, DIR_RD);
1043 buffer_shutr(rep);
1044 t->srv_state = SV_STSHUTR;
1045 if (!(t->flags & SN_ERR_MASK))
1046 t->flags |= SN_ERR_SRVTO;
1047 if (!(t->flags & SN_FINST_MASK))
1048 t->flags |= SN_FINST_D;
1049 return 1;
1050 }
1051 /* write timeout */
1052 else if (tv_isle(&req->wex, &now)) {
1053 EV_FD_CLR(t->srv_fd, DIR_WR);
Willy Tarreauba392ce2008-08-16 21:13:23 +02001054 buffer_shutw(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001055 shutdown(t->srv_fd, SHUT_WR);
1056 /* We must ensure that the read part is still alive when switching
1057 * to shutw */
1058 EV_FD_SET(t->srv_fd, DIR_RD);
1059 tv_add_ifset(&rep->rex, &now, &rep->rto);
1060 t->srv_state = SV_STSHUTW;
1061 if (!(t->flags & SN_ERR_MASK))
1062 t->flags |= SN_ERR_SRVTO;
1063 if (!(t->flags & SN_FINST_MASK))
1064 t->flags |= SN_FINST_D;
1065 return 1;
1066 }
1067
1068 /* recompute request time-outs */
Willy Tarreaue393fe22008-08-16 22:18:07 +02001069 if (req->flags & BF_EMPTY) {
Willy Tarreau92fb9832007-10-16 17:34:28 +02001070 if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
1071 /* stop writing */
1072 tv_eternity(&req->wex);
1073 }
1074 }
1075 else { /* buffer not empty, there are still data to be transferred */
1076 if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
1077 /* restart writing */
1078 if (tv_add_ifset(&req->wex, &now, &req->wto)) {
1079 /* FIXME: to prevent the server from expiring read timeouts during writes,
1080 * we refresh it. */
1081 rep->rex = req->wex;
1082 }
1083 else
1084 tv_eternity(&req->wex);
1085 }
1086 }
1087
1088 /* recompute response time-outs */
1089 if (rep->l == BUFSIZE) { /* no room to read more data */
1090 if (EV_FD_COND_C(t->srv_fd, DIR_RD)) {
1091 tv_eternity(&rep->rex);
1092 }
1093 }
1094 else {
1095 if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
1096 if (!tv_add_ifset(&rep->rex, &now, &rep->rto))
1097 tv_eternity(&rep->rex);
1098 }
1099 }
1100
1101 return 0; /* other cases change nothing */
1102 }
1103 else if (s == SV_STSHUTR) {
1104 if (req->flags & BF_WRITE_ERROR) {
1105 //EV_FD_CLR(t->srv_fd, DIR_WR);
Willy Tarreauba392ce2008-08-16 21:13:23 +02001106 buffer_shutw(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001107 fd_delete(t->srv_fd);
1108 if (t->srv) {
1109 t->srv->cur_sess--;
1110 t->srv->failed_resp++;
1111 }
1112 t->be->failed_resp++;
1113 //close(t->srv_fd);
1114 t->srv_state = SV_STCLOSE;
1115 if (!(t->flags & SN_ERR_MASK))
1116 t->flags |= SN_ERR_SRVCL;
1117 if (!(t->flags & SN_FINST_MASK))
1118 t->flags |= SN_FINST_D;
1119 /* We used to have a free connection slot. Since we'll never use it,
1120 * we have to inform the server that it may be used by another session.
1121 */
1122 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau7c669d72008-06-20 15:04:11 +02001123 process_srv_queue(t->srv);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001124
1125 return 1;
1126 }
Willy Tarreaue393fe22008-08-16 22:18:07 +02001127 else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->flags & BF_EMPTY)) {
Willy Tarreau92fb9832007-10-16 17:34:28 +02001128 //EV_FD_CLR(t->srv_fd, DIR_WR);
Willy Tarreauba392ce2008-08-16 21:13:23 +02001129 buffer_shutw(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001130 fd_delete(t->srv_fd);
1131 if (t->srv)
1132 t->srv->cur_sess--;
1133 //close(t->srv_fd);
1134 t->srv_state = SV_STCLOSE;
1135 /* We used to have a free connection slot. Since we'll never use it,
1136 * we have to inform the server that it may be used by another session.
1137 */
1138 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau7c669d72008-06-20 15:04:11 +02001139 process_srv_queue(t->srv);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001140
1141 return 1;
1142 }
1143 else if (tv_isle(&req->wex, &now)) {
1144 //EV_FD_CLR(t->srv_fd, DIR_WR);
Willy Tarreauba392ce2008-08-16 21:13:23 +02001145 buffer_shutw(req);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001146 fd_delete(t->srv_fd);
1147 if (t->srv)
1148 t->srv->cur_sess--;
1149 //close(t->srv_fd);
1150 t->srv_state = SV_STCLOSE;
1151 if (!(t->flags & SN_ERR_MASK))
1152 t->flags |= SN_ERR_SRVTO;
1153 if (!(t->flags & SN_FINST_MASK))
1154 t->flags |= SN_FINST_D;
1155 /* We used to have a free connection slot. Since we'll never use it,
1156 * we have to inform the server that it may be used by another session.
1157 */
1158 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau7c669d72008-06-20 15:04:11 +02001159 process_srv_queue(t->srv);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001160
1161 return 1;
1162 }
Willy Tarreaue393fe22008-08-16 22:18:07 +02001163 else if (req->flags & BF_EMPTY) {
Willy Tarreau92fb9832007-10-16 17:34:28 +02001164 if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
1165 /* stop writing */
1166 tv_eternity(&req->wex);
1167 }
1168 }
1169 else { /* buffer not empty */
1170 if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
1171 /* restart writing */
1172 if (!tv_add_ifset(&req->wex, &now, &req->wto))
1173 tv_eternity(&req->wex);
1174 }
1175 }
1176 return 0;
1177 }
1178 else if (s == SV_STSHUTW) {
1179 if (rep->flags & BF_READ_ERROR) {
1180 //EV_FD_CLR(t->srv_fd, DIR_RD);
Willy Tarreauba392ce2008-08-16 21:13:23 +02001181 buffer_shutr(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001182 fd_delete(t->srv_fd);
1183 if (t->srv) {
1184 t->srv->cur_sess--;
1185 t->srv->failed_resp++;
1186 }
1187 t->be->failed_resp++;
1188 //close(t->srv_fd);
1189 t->srv_state = SV_STCLOSE;
1190 if (!(t->flags & SN_ERR_MASK))
1191 t->flags |= SN_ERR_SRVCL;
1192 if (!(t->flags & SN_FINST_MASK))
1193 t->flags |= SN_FINST_D;
1194 /* We used to have a free connection slot. Since we'll never use it,
1195 * we have to inform the server that it may be used by another session.
1196 */
1197 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau7c669d72008-06-20 15:04:11 +02001198 process_srv_queue(t->srv);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001199
1200 return 1;
1201 }
1202 else if (rep->flags & BF_READ_NULL || c == CL_STSHUTW || c == CL_STCLOSE) {
1203 //EV_FD_CLR(t->srv_fd, DIR_RD);
Willy Tarreauba392ce2008-08-16 21:13:23 +02001204 buffer_shutr(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001205 fd_delete(t->srv_fd);
1206 if (t->srv)
1207 t->srv->cur_sess--;
1208 //close(t->srv_fd);
1209 t->srv_state = SV_STCLOSE;
1210 /* We used to have a free connection slot. Since we'll never use it,
1211 * we have to inform the server that it may be used by another session.
1212 */
1213 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau7c669d72008-06-20 15:04:11 +02001214 process_srv_queue(t->srv);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001215
1216 return 1;
1217 }
1218 else if (tv_isle(&rep->rex, &now)) {
1219 //EV_FD_CLR(t->srv_fd, DIR_RD);
Willy Tarreauba392ce2008-08-16 21:13:23 +02001220 buffer_shutr(rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001221 fd_delete(t->srv_fd);
1222 if (t->srv)
1223 t->srv->cur_sess--;
1224 //close(t->srv_fd);
1225 t->srv_state = SV_STCLOSE;
1226 if (!(t->flags & SN_ERR_MASK))
1227 t->flags |= SN_ERR_SRVTO;
1228 if (!(t->flags & SN_FINST_MASK))
1229 t->flags |= SN_FINST_D;
1230 /* We used to have a free connection slot. Since we'll never use it,
1231 * we have to inform the server that it may be used by another session.
1232 */
1233 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau7c669d72008-06-20 15:04:11 +02001234 process_srv_queue(t->srv);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001235
1236 return 1;
1237 }
1238 else if (rep->l == BUFSIZE) { /* no room to read more data */
1239 if (EV_FD_COND_C(t->srv_fd, DIR_RD)) {
1240 tv_eternity(&rep->rex);
1241 }
1242 }
1243 else {
1244 if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
1245 if (!tv_add_ifset(&rep->rex, &now, &rep->rto))
1246 tv_eternity(&rep->rex);
1247 }
1248 }
1249 return 0;
1250 }
1251 else { /* SV_STCLOSE : nothing to do */
1252 if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
1253 int len;
1254 len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n",
1255 t->uniq_id, t->be->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
1256 write(1, trash, len);
1257 }
1258 return 0;
1259 }
1260 return 0;
1261}
1262
1263/* Processes the client and server jobs of a session task, then
1264 * puts it back to the wait queue in a clean state, or
1265 * cleans up its resources if it must be deleted. Returns
1266 * the time the task accepts to wait, or TIME_ETERNITY for
1267 * infinity.
1268 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001269void process_uxst_session(struct task *t, int *next)
Willy Tarreau92fb9832007-10-16 17:34:28 +02001270{
1271 struct session *s = t->context;
1272 int fsm_resync = 0;
1273
1274 do {
1275 fsm_resync = 0;
1276 fsm_resync |= process_uxst_cli(s);
1277 if (s->srv_state == SV_STIDLE) {
1278 if (s->cli_state == CL_STCLOSE || s->cli_state == CL_STSHUTW) {
1279 s->srv_state = SV_STCLOSE;
1280 fsm_resync |= 1;
1281 continue;
1282 }
1283 if (s->cli_state == CL_STSHUTR ||
Willy Tarreaue393fe22008-08-16 22:18:07 +02001284 (s->req->flags & BF_FULL)) {
1285 if (s->req->flags & BF_EMPTY) {
Willy Tarreau92fb9832007-10-16 17:34:28 +02001286 s->srv_state = SV_STCLOSE;
1287 fsm_resync |= 1;
1288 continue;
1289 }
1290 /* OK we have some remaining data to process */
1291 /* Just as an exercice, we copy the req into the resp,
1292 * and flush the req.
1293 */
1294 memcpy(s->rep->data, s->req->data, sizeof(s->rep->data));
1295 s->rep->l = s->req->l;
Willy Tarreaue393fe22008-08-16 22:18:07 +02001296 buffer_set_rlim(s->rep, BUFSIZE);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001297 s->rep->w = s->rep->data;
1298 s->rep->lr = s->rep->r = s->rep->data + s->rep->l;
1299
1300 s->req->l = 0;
1301 s->srv_state = SV_STCLOSE;
1302
1303 fsm_resync |= 1;
1304 continue;
1305 }
1306 }
1307 } while (fsm_resync);
1308
1309 if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +01001310
1311 if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
1312 session_process_counters(s);
1313
Willy Tarreau92fb9832007-10-16 17:34:28 +02001314 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
1315 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
1316
1317 t->expire = s->req->rex;
1318 tv_min(&t->expire, &s->req->rex, &s->req->wex);
1319 tv_bound(&t->expire, &s->req->cex);
1320 tv_bound(&t->expire, &s->rep->rex);
1321 tv_bound(&t->expire, &s->rep->wex);
1322
1323 /* restore t to its place in the task list */
1324 task_queue(t);
1325
1326 *next = t->expire;
1327 return; /* nothing more to do */
1328 }
1329
1330 if (s->fe)
1331 s->fe->feconn--;
1332 if (s->be && (s->flags & SN_BE_ASSIGNED))
1333 s->be->beconn--;
1334 actconn--;
1335
1336 if (unlikely((global.mode & MODE_DEBUG) &&
1337 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
1338 int len;
1339 len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n",
1340 s->uniq_id, s->be->id,
1341 (unsigned short)s->cli_fd, (unsigned short)s->srv_fd);
1342 write(1, trash, len);
1343 }
1344
1345 s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +01001346 session_process_counters(s);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001347
1348 /* let's do a final log if we need it */
1349 if (s->logs.logwait &&
1350 !(s->flags & SN_MONITOR) &&
1351 (s->req->total || !(s->fe && s->fe->options & PR_O_NULLNOLOG))) {
1352 //uxst_sess_log(s);
1353 }
1354
1355 /* the task MUST not be in the run queue anymore */
1356 task_delete(t);
1357 session_free(s);
1358 task_free(t);
1359 tv_eternity(next);
1360}
1361#endif /* not converted */
1362
1363
1364/* Processes data exchanges on the statistics socket. The client processing
1365 * is called and the task is put back in the wait queue or it is cleared.
1366 * In order to ease the transition, we simply simulate the server status
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001367 * for now. It only knows states SV_STIDLE, SV_STCONN, SV_STDATA, and
1368 * SV_STCLOSE. Returns in <next> the task's expiration date.
Willy Tarreau92fb9832007-10-16 17:34:28 +02001369 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001370void process_uxst_stats(struct task *t, int *next)
Willy Tarreau92fb9832007-10-16 17:34:28 +02001371{
1372 struct session *s = t->context;
1373 struct listener *listener;
1374 int fsm_resync = 0;
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001375 int last_rep_l;
Willy Tarreau92fb9832007-10-16 17:34:28 +02001376
1377 do {
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001378 char *args[MAX_UXST_ARGS + 1];
1379 char *line, *p;
1380 int arg;
1381
Willy Tarreau3e76e722007-10-17 18:57:38 +02001382 fsm_resync = process_uxst_cli(s);
Willy Tarreau3e76e722007-10-17 18:57:38 +02001383
1384 if (s->cli_state == CL_STCLOSE || s->cli_state == CL_STSHUTW) {
1385 s->srv_state = SV_STCLOSE;
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001386 break;
Willy Tarreau3e76e722007-10-17 18:57:38 +02001387 }
1388
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001389 switch (s->srv_state) {
1390 case SV_STIDLE:
1391 /* stats output not initialized yet */
1392 memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
1393 s->data_source = DATA_SRC_STATS;
1394 s->srv_state = SV_STCONN;
1395 fsm_resync |= 1;
1396 break;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001397
Willy Tarreauadfb8562008-08-11 15:24:42 +02001398 case SV_STCONN: /* should be changed to SV_STHEADERS or something more obvious */
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001399 /* stats initialized, but waiting for the command */
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001400 line = s->req->data;
1401 p = memchr(line, '\n', s->req->l);
1402
1403 if (!p)
1404 continue;
1405
1406 *p = '\0';
1407
1408 while (isspace((unsigned char)*line))
1409 line++;
1410
1411 arg = 0;
1412 args[arg] = line;
1413
1414 while (*line && arg < MAX_UXST_ARGS) {
1415 if (isspace((unsigned char)*line)) {
1416 *line++ = '\0';
1417
1418 while (isspace((unsigned char)*line))
1419 line++;
1420
1421 args[++arg] = line;
Willy Tarreaua8efd362008-01-03 10:19:15 +01001422 continue;
1423 }
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001424
1425 line++;
Willy Tarreaua8efd362008-01-03 10:19:15 +01001426 }
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001427
1428 while (++arg <= MAX_UXST_ARGS)
1429 args[arg] = line;
1430
1431 if (!strcmp(args[0], "show")) {
1432 if (!strcmp(args[1], "stat")) {
1433 if (*args[2] && *args[3] && *args[4]) {
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001434 s->data_ctx.stats.flags |= STAT_BOUND;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001435 s->data_ctx.stats.iid = atoi(args[2]);
1436 s->data_ctx.stats.type = atoi(args[3]);
1437 s->data_ctx.stats.sid = atoi(args[4]);
1438 }
1439
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001440 s->data_ctx.stats.flags |= STAT_SHOW_STAT;
1441 s->data_ctx.stats.flags |= STAT_FMT_CSV;
1442 s->srv_state = SV_STDATA;
1443 fsm_resync |= 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +02001444 continue;
1445 }
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001446
1447 if (!strcmp(args[1], "info")) {
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001448 s->data_ctx.stats.flags |= STAT_SHOW_INFO;
1449 s->data_ctx.stats.flags |= STAT_FMT_CSV;
1450 s->srv_state = SV_STDATA;
1451 fsm_resync |= 1;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001452 continue;
1453 }
Willy Tarreau92fb9832007-10-16 17:34:28 +02001454 }
Willy Tarreau3e76e722007-10-17 18:57:38 +02001455
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +01001456 s->srv_state = SV_STCLOSE;
1457 fsm_resync |= 1;
Willy Tarreau3e76e722007-10-17 18:57:38 +02001458 continue;
1459
Willy Tarreau39f7e6d2008-03-17 21:38:24 +01001460 case SV_STDATA:
1461 /* OK we have to process the request. Since it is possible
1462 * that we get there with the client output paused, we
1463 * will simply check that we have really sent some data
1464 * and wake the client up if needed.
1465 */
1466 last_rep_l = s->rep->l;
1467 if (stats_dump_raw(s, NULL) != 0) {
1468 s->srv_state = SV_STCLOSE;
1469 fsm_resync |= 1;
1470 }
1471 if (s->rep->l != last_rep_l)
1472 fsm_resync |= 1;
1473 break;
Willy Tarreau3e76e722007-10-17 18:57:38 +02001474 }
Willy Tarreau92fb9832007-10-16 17:34:28 +02001475 } while (fsm_resync);
1476
1477 if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
1478 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
1479 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
1480
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001481 t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
1482 tick_first(s->rep->rex, s->rep->wex));
Willy Tarreau92fb9832007-10-16 17:34:28 +02001483
1484 /* restore t to its place in the task list */
1485 task_queue(t);
1486
1487 *next = t->expire;
1488 return; /* nothing more to do */
1489 }
1490
1491 actconn--;
1492 listener = fdtab[s->cli_fd].listener;
1493 if (listener) {
1494 listener->nbconn--;
1495 if (listener->state == LI_FULL &&
1496 listener->nbconn < listener->maxconn) {
1497 /* we should reactivate the listener */
1498 EV_FD_SET(listener->fd, DIR_RD);
1499 listener->state = LI_READY;
1500 }
1501 }
1502
1503 /* the task MUST not be in the run queue anymore */
1504 task_delete(t);
1505 session_free(s);
1506 task_free(t);
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001507 *next = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +02001508}
1509
Willy Tarreau92fb9832007-10-16 17:34:28 +02001510__attribute__((constructor))
1511static void __uxst_protocol_init(void)
1512{
1513 protocol_register(&proto_unix);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001514}
1515
1516
1517/*
1518 * Local variables:
1519 * c-indent-level: 8
1520 * c-basic-offset: 8
1521 * End:
1522 */