blob: 1a093263c34767f9fe1327b50d34fbc6a8d7c121 [file] [log] [blame]
Willy Tarreau92fb9832007-10-16 17:34:28 +02001/*
2 * UNIX SOCK_STREAM protocol layer (uxst)
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 <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>
35#include <common/time.h>
36#include <common/version.h>
37
38#include <types/acl.h>
39#include <types/capture.h>
40#include <types/client.h>
41#include <types/global.h>
42#include <types/polling.h>
43#include <types/proxy.h>
44#include <types/server.h>
45
46#include <proto/acl.h>
47#include <proto/backend.h>
48#include <proto/buffers.h>
Willy Tarreau3e76e722007-10-17 18:57:38 +020049#include <proto/dumpstats.h>
Willy Tarreau92fb9832007-10-16 17:34:28 +020050#include <proto/fd.h>
51#include <proto/log.h>
52#include <proto/protocols.h>
53#include <proto/proto_uxst.h>
54#include <proto/queue.h>
Willy Tarreau3e76e722007-10-17 18:57:38 +020055#include <proto/senddata.h>
Willy Tarreau92fb9832007-10-16 17:34:28 +020056#include <proto/session.h>
57#include <proto/stream_sock.h>
58#include <proto/task.h>
59
60#ifndef MAXPATHLEN
61#define MAXPATHLEN 128
62#endif
63
64/* This function creates a named PF_UNIX stream socket at address <path>. Note
Willy Tarreaue6ad2b12007-10-18 12:45:54 +020065 * that the path cannot be NULL nor empty. <uid> and <gid> different of -1 will
66 * be used to change the socket owner. If <mode> is not 0, it will be used to
67 * restrict access to the socket. While it is known not to be portable on every
68 * OS, it's still useful where it works.
Willy Tarreau92fb9832007-10-16 17:34:28 +020069 * It returns the assigned file descriptor, or -1 in the event of an error.
70 */
Willy Tarreaue6ad2b12007-10-18 12:45:54 +020071static int create_uxst_socket(const char *path, uid_t uid, gid_t gid, mode_t mode)
Willy Tarreau92fb9832007-10-16 17:34:28 +020072{
73 char tempname[MAXPATHLEN];
74 char backname[MAXPATHLEN];
75 struct sockaddr_un addr;
76
77 int ret, sock;
78
79 /* 1. create socket names */
80 if (!path[0]) {
81 Alert("Invalid name for a UNIX socket. Aborting.\n");
82 goto err_return;
83 }
84
85 ret = snprintf(tempname, MAXPATHLEN, "%s.%d.tmp", path, pid);
86 if (ret < 0 || ret >= MAXPATHLEN) {
87 Alert("name too long for UNIX socket. Aborting.\n");
88 goto err_return;
89 }
90
91 ret = snprintf(backname, MAXPATHLEN, "%s.%d.bak", path, pid);
92 if (ret < 0 || ret >= MAXPATHLEN) {
93 Alert("name too long for UNIX socket. Aborting.\n");
94 goto err_return;
95 }
96
97 /* 2. clean existing orphaned entries */
98 if (unlink(tempname) < 0 && errno != ENOENT) {
99 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
100 goto err_return;
101 }
102
103 if (unlink(backname) < 0 && errno != ENOENT) {
104 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
105 goto err_return;
106 }
107
108 /* 3. backup existing socket */
109 if (link(path, backname) < 0 && errno != ENOENT) {
110 Alert("error when trying to preserve previous UNIX socket. Aborting.\n");
111 goto err_return;
112 }
113
114 /* 4. prepare new socket */
115 addr.sun_family = AF_UNIX;
116 strncpy(addr.sun_path, tempname, sizeof(addr.sun_path));
117 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
118
119 sock = socket(PF_UNIX, SOCK_STREAM, 0);
120 if (sock < 0) {
121 Alert("cannot create socket for UNIX listener. Aborting.\n");
122 goto err_unlink_back;
123 }
124
125 if (sock >= global.maxsock) {
126 Alert("socket(): not enough free sockets for UNIX listener. Raise -n argument. Aborting.\n");
127 goto err_unlink_temp;
128 }
129
130 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
131 Alert("cannot make UNIX socket non-blocking. Aborting.\n");
132 goto err_unlink_temp;
133 }
134
135 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
136 /* note that bind() creates the socket <tempname> on the file system */
137 Alert("cannot bind socket for UNIX listener. Aborting.\n");
138 goto err_unlink_temp;
139 }
140
Willy Tarreaue6ad2b12007-10-18 12:45:54 +0200141 if (((uid != -1 || gid != -1) && (chown(tempname, uid, gid) == -1)) ||
142 (mode != 0 && chmod(tempname, mode) == -1)) {
143 Alert("cannot change UNIX socket ownership. Aborting.\n");
144 goto err_unlink_temp;
145 }
146
Willy Tarreau92fb9832007-10-16 17:34:28 +0200147 if (listen(sock, 0) < 0) {
148 Alert("cannot listen to socket for UNIX listener. Aborting.\n");
149 goto err_unlink_temp;
150 }
151
152 /* 5. install.
153 * Point of no return: we are ready, we'll switch the sockets. We don't
154 * fear loosing the socket <path> because we have a copy of it in
155 * backname.
156 */
157 if (rename(tempname, path) < 0) {
158 Alert("cannot switch final and temporary sockets for UNIX listener. Aborting.\n");
159 goto err_rename;
160 }
161
162 /* 6. cleanup */
163 unlink(backname); /* no need to keep this one either */
164
165 return sock;
166
167 err_rename:
168 ret = rename(backname, path);
169 if (ret < 0 && errno == ENOENT)
170 unlink(path);
171 err_unlink_temp:
172 unlink(tempname);
173 close(sock);
174 err_unlink_back:
175 unlink(backname);
176 err_return:
177 return -1;
178}
179
180/* Tries to destroy the UNIX stream socket <path>. The socket must not be used
181 * anymore. It practises best effort, and no error is returned.
182 */
183static void destroy_uxst_socket(const char *path)
184{
185 struct sockaddr_un addr;
186 int sock, ret;
187
188 /* We might have been chrooted, so we may not be able to access the
189 * socket. In order to avoid bothering the other end, we connect with a
190 * wrong protocol, namely SOCK_DGRAM. The return code from connect()
191 * is enough to know if the socket is still live or not. If it's live
192 * in mode SOCK_STREAM, we get EPROTOTYPE or anything else but not
193 * ECONNREFUSED. In this case, we do not touch it because it's used
194 * by some other process.
195 */
196 sock = socket(PF_UNIX, SOCK_DGRAM, 0);
197 if (sock < 0)
198 return;
199
200 addr.sun_family = AF_UNIX;
201 strncpy(addr.sun_path, path, sizeof(addr.sun_path));
Willy Tarreau10ae5482007-10-18 16:15:52 +0200202 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200203 ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
204 if (ret < 0 && errno == ECONNREFUSED) {
205 /* Connect failed: the socket still exists but is not used
206 * anymore. Let's remove this socket now.
207 */
208 unlink(path);
209 }
210 close(sock);
211}
212
213
214/* This function creates all UNIX sockets bound to the protocol entry <proto>.
215 * It is intended to be used as the protocol's bind_all() function.
216 * The sockets will be registered but not added to any fd_set, in order not to
217 * loose them across the fork(). A call to uxst_enable_listeners() is needed
218 * to complete initialization.
219 *
220 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
221 */
222static int uxst_bind_listeners(struct protocol *proto)
223{
224 struct listener *listener;
225 int err = ERR_NONE;
226 int fd;
227
228 list_for_each_entry(listener, &proto->listeners, proto_list) {
229 if (listener->state != LI_INIT)
230 continue; /* already started */
231
Willy Tarreaue6ad2b12007-10-18 12:45:54 +0200232 fd = create_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path,
233 listener->perm.ux.uid,
234 listener->perm.ux.gid,
235 listener->perm.ux.mode);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200236 if (fd == -1) {
237 err |= ERR_FATAL;
238 continue;
239 }
240
241 /* the socket is listening */
242 listener->fd = fd;
243 listener->state = LI_LISTEN;
244
245 /* the function for the accept() event */
246 fd_insert(fd);
247 fdtab[fd].cb[DIR_RD].f = listener->accept;
248 fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
249 fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
250 fdtab[fd].owner = (struct task *)listener; /* reference the listener instead of a task */
251 fdtab[fd].state = FD_STLISTEN;
252 fdtab[fd].peeraddr = NULL;
253 fdtab[fd].peerlen = 0;
254 fdtab[fd].listener = NULL;
255 fdtab[fd].ev = 0;
256 }
257
258 return err;
259}
260
261/* This function adds the UNIX sockets file descriptors to the polling lists
262 * for all listeners in the LI_LISTEN state. It is intended to be used as the
263 * protocol's enable_all() primitive, after the fork(). It always returns
264 * ERR_NONE.
265 */
266static int uxst_enable_listeners(struct protocol *proto)
267{
268 struct listener *listener;
269
270 list_for_each_entry(listener, &proto->listeners, proto_list) {
271 if (listener->state == LI_LISTEN) {
272 EV_FD_SET(listener->fd, DIR_RD);
273 listener->state = LI_READY;
274 }
275 }
276 return ERR_NONE;
277}
278
279/* This function stops all listening UNIX sockets bound to the protocol
280 * <proto>. It does not detaches them from the protocol.
281 * It always returns ERR_NONE.
282 */
283static int uxst_unbind_listeners(struct protocol *proto)
284{
285 struct listener *listener;
286
287 list_for_each_entry(listener, &proto->listeners, proto_list) {
288 if (listener->state != LI_INIT) {
289 EV_FD_CLR(listener->fd, DIR_RD);
290 close(listener->fd);
291 listener->state = LI_INIT;
292 destroy_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path);
293 }
294 }
295 return ERR_NONE;
296}
297
298/*
299 * This function is called on a read event from a listen socket, corresponding
300 * to an accept. It tries to accept as many connections as possible.
301 * It returns 0. Since we use UNIX sockets on the local system for monitoring
302 * purposes and other related things, we do not need to output as many messages
303 * as with TCP which can fall under attack.
304 */
305int uxst_event_accept(int fd) {
306 struct listener *l = (struct listener *)fdtab[fd].owner;
307 struct session *s;
308 struct task *t;
309 int cfd;
310 int max_accept;
311
312 if (global.nbproc > 1)
313 max_accept = 8; /* let other processes catch some connections too */
314 else
315 max_accept = -1;
316
317 while (max_accept--) {
318 struct sockaddr_storage addr;
319 socklen_t laddr = sizeof(addr);
320
321 if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) == -1) {
322 switch (errno) {
323 case EAGAIN:
324 case EINTR:
325 case ECONNABORTED:
326 return 0; /* nothing more to accept */
327 case ENFILE:
328 /* Process reached system FD limit. Check system tunables. */
329 return 0;
330 case EMFILE:
331 /* Process reached process FD limit. Check 'ulimit-n'. */
332 return 0;
333 case ENOBUFS:
334 case ENOMEM:
335 /* Process reached system memory limit. Check system tunables. */
336 return 0;
337 default:
338 return 0;
339 }
340 }
341
342 if (l->nbconn >= l->maxconn) {
343 /* too many connections, we shoot this one and return.
344 * FIXME: it would be better to simply switch the listener's
345 * state to LI_FULL and disable the FD. We could re-enable
346 * it upon fd_delete(), but this requires all protocols to
347 * be switched.
348 */
349 close(cfd);
350 return 0;
351 }
352
353 if ((s = pool_alloc2(pool2_session)) == NULL) {
354 Alert("out of memory in uxst_event_accept().\n");
355 close(cfd);
356 return 0;
357 }
358
359 if ((t = pool_alloc2(pool2_task)) == NULL) {
360 Alert("out of memory in uxst_event_accept().\n");
361 close(cfd);
362 pool_free2(pool2_session, s);
363 return 0;
364 }
365
366 s->cli_addr = addr;
367
368 /* FIXME: should be checked earlier */
369 if (cfd >= global.maxsock) {
370 Alert("accept(): not enough free sockets. Raise -n argument. Giving up.\n");
371 close(cfd);
372 pool_free2(pool2_task, t);
373 pool_free2(pool2_session, s);
374 return 0;
375 }
376
377 if (fcntl(cfd, F_SETFL, O_NONBLOCK) == -1) {
378 Alert("accept(): cannot set the socket in non blocking mode. Giving up\n");
379 close(cfd);
380 pool_free2(pool2_task, t);
381 pool_free2(pool2_session, s);
382 return 0;
383 }
384
385 t->wq = NULL;
386 t->qlist.p = NULL;
387 t->state = TASK_IDLE;
388 t->process = l->handler;
389 t->context = s;
390
391 s->task = t;
392 s->fe = NULL;
393 s->be = NULL;
394
395 s->cli_state = CL_STDATA;
396 s->srv_state = SV_STIDLE;
397 s->req = s->rep = NULL; /* will be allocated later */
398
399 s->cli_fd = cfd;
400 s->srv_fd = -1;
401 s->srv = NULL;
402 s->pend_pos = NULL;
403
404 memset(&s->logs, 0, sizeof(s->logs));
405 memset(&s->txn, 0, sizeof(s->txn));
406
Willy Tarreau3e76e722007-10-17 18:57:38 +0200407 s->data_state = DATA_ST_INIT;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200408 s->data_source = DATA_SRC_NONE;
409 s->uniq_id = totalconn;
410
411 if ((s->req = pool_alloc2(pool2_buffer)) == NULL) { /* no memory */
412 close(cfd); /* nothing can be done for this fd without memory */
413 pool_free2(pool2_task, t);
414 pool_free2(pool2_session, s);
415 return 0;
416 }
417
418 if ((s->rep = pool_alloc2(pool2_buffer)) == NULL) { /* no memory */
419 pool_free2(pool2_buffer, s->req);
420 close(cfd); /* nothing can be done for this fd without memory */
421 pool_free2(pool2_task, t);
422 pool_free2(pool2_session, s);
423 return 0;
424 }
425
426 buffer_init(s->req);
427 buffer_init(s->rep);
428 s->req->rlim += BUFSIZE;
429 s->rep->rlim += BUFSIZE;
430
431 fd_insert(cfd);
432 fdtab[cfd].owner = t;
433 fdtab[cfd].listener = l;
434 fdtab[cfd].state = FD_STREADY;
435 fdtab[cfd].cb[DIR_RD].f = l->proto->read;
436 fdtab[cfd].cb[DIR_RD].b = s->req;
437 fdtab[cfd].cb[DIR_WR].f = l->proto->write;
438 fdtab[cfd].cb[DIR_WR].b = s->rep;
439 fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
440 fdtab[cfd].peerlen = sizeof(s->cli_addr);
441 fdtab[cfd].ev = 0;
442
443
444 tv_eternity(&s->req->rex);
445 tv_eternity(&s->req->wex);
446 tv_eternity(&s->req->cex);
447 tv_eternity(&s->rep->rex);
448 tv_eternity(&s->rep->wex);
449
450 tv_eternity(&s->req->wto);
451 tv_eternity(&s->req->cto);
452 tv_eternity(&s->req->rto);
453 tv_eternity(&s->rep->rto);
454 tv_eternity(&s->rep->cto);
455 tv_eternity(&s->rep->wto);
456
457 if (l->timeout)
458 s->req->rto = *l->timeout;
459
460 if (l->timeout)
461 s->rep->wto = *l->timeout;
462
463 tv_eternity(&t->expire);
464 if (l->timeout && tv_isset(l->timeout)) {
465 EV_FD_SET(cfd, DIR_RD);
466 tv_add(&s->req->rex, &now, &s->req->rto);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200467 t->expire = s->req->rex;
468 }
469
470 task_queue(t);
471 task_wakeup(t);
472
473 l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
474 if (l->nbconn >= l->maxconn) {
475 EV_FD_CLR(l->fd, DIR_RD);
476 l->state = LI_FULL;
477 }
478 actconn++;
479 totalconn++;
480
481 //fprintf(stderr, "accepting from %p => %d conn, %d total, task=%p, cfd=%d, maxfd=%d\n", p, actconn, totalconn, t, cfd, maxfd);
482 } /* end of while (p->feconn < p->maxconn) */
483 //fprintf(stderr,"fct %s:%d\n", __FUNCTION__, __LINE__);
484 return 0;
485}
486
487/*
488 * manages the client FSM and its socket. It returns 1 if a state has changed
489 * (and a resync may be needed), otherwise 0.
490 */
491static int process_uxst_cli(struct session *t)
492{
493 int s = t->srv_state;
494 int c = t->cli_state;
495 struct buffer *req = t->req;
496 struct buffer *rep = t->rep;
497 //fprintf(stderr,"fct %s:%d\n", __FUNCTION__, __LINE__);
498 if (c == CL_STDATA) {
499 /* FIXME: this error handling is partly buggy because we always report
500 * a 'DATA' phase while we don't know if the server was in IDLE, CONN
501 * or HEADER phase. BTW, it's not logical to expire the client while
502 * we're waiting for the server to connect.
503 */
504 /* read or write error */
505 if (rep->flags & BF_WRITE_ERROR || req->flags & BF_READ_ERROR) {
506 buffer_shutr(req);
507 buffer_shutw(rep);
508 fd_delete(t->cli_fd);
509 t->cli_state = CL_STCLOSE;
510 if (!(t->flags & SN_ERR_MASK))
511 t->flags |= SN_ERR_CLICL;
512 if (!(t->flags & SN_FINST_MASK)) {
513 if (t->pend_pos)
514 t->flags |= SN_FINST_Q;
515 else if (s == SV_STCONN)
516 t->flags |= SN_FINST_C;
517 else
518 t->flags |= SN_FINST_D;
519 }
520 return 1;
521 }
522 /* last read, or end of server write */
523 else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
524 EV_FD_CLR(t->cli_fd, DIR_RD);
525 buffer_shutr(req);
526 t->cli_state = CL_STSHUTR;
527 return 1;
528 }
529 /* last server read and buffer empty */
530 else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) {
531 EV_FD_CLR(t->cli_fd, DIR_WR);
532 buffer_shutw(rep);
533 shutdown(t->cli_fd, SHUT_WR);
534 /* We must ensure that the read part is still alive when switching
535 * to shutw */
536 EV_FD_SET(t->cli_fd, DIR_RD);
537 tv_add_ifset(&req->rex, &now, &req->rto);
538 t->cli_state = CL_STSHUTW;
539 //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
540 return 1;
541 }
542 /* read timeout */
543 else if (tv_isle(&req->rex, &now)) {
544 EV_FD_CLR(t->cli_fd, DIR_RD);
545 buffer_shutr(req);
546 t->cli_state = CL_STSHUTR;
547 if (!(t->flags & SN_ERR_MASK))
548 t->flags |= SN_ERR_CLITO;
549 if (!(t->flags & SN_FINST_MASK)) {
550 if (t->pend_pos)
551 t->flags |= SN_FINST_Q;
552 else if (s == SV_STCONN)
553 t->flags |= SN_FINST_C;
554 else
555 t->flags |= SN_FINST_D;
556 }
557 return 1;
558 }
559 /* write timeout */
560 else if (tv_isle(&rep->wex, &now)) {
561 EV_FD_CLR(t->cli_fd, DIR_WR);
562 buffer_shutw(rep);
563 shutdown(t->cli_fd, SHUT_WR);
564 /* We must ensure that the read part is still alive when switching
565 * to shutw */
566 EV_FD_SET(t->cli_fd, DIR_RD);
567 tv_add_ifset(&req->rex, &now, &req->rto);
568
569 t->cli_state = CL_STSHUTW;
570 if (!(t->flags & SN_ERR_MASK))
571 t->flags |= SN_ERR_CLITO;
572 if (!(t->flags & SN_FINST_MASK)) {
573 if (t->pend_pos)
574 t->flags |= SN_FINST_Q;
575 else if (s == SV_STCONN)
576 t->flags |= SN_FINST_C;
577 else
578 t->flags |= SN_FINST_D;
579 }
580 return 1;
581 }
582
583 if (req->l >= req->rlim - req->data) {
584 /* no room to read more data */
585 if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
586 /* stop reading until we get some space */
587 tv_eternity(&req->rex);
588 }
589 } else {
590 /* there's still some space in the buffer */
591 if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
592 if (!tv_isset(&req->rto) ||
593 (t->srv_state < SV_STDATA && tv_isset(&req->wto)))
594 /* If the client has no timeout, or if the server not ready yet, and we
595 * know for sure that it can expire, then it's cleaner to disable the
596 * timeout on the client side so that too low values cannot make the
597 * sessions abort too early.
598 */
599 tv_eternity(&req->rex);
600 else
601 tv_add(&req->rex, &now, &req->rto);
602 }
603 }
604
605 if ((rep->l == 0) ||
606 ((s < SV_STDATA) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
607 if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
608 /* stop writing */
609 tv_eternity(&rep->wex);
610 }
611 } else {
612 /* buffer not empty */
613 if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
614 /* restart writing */
615 if (tv_add_ifset(&rep->wex, &now, &rep->wto)) {
616 /* FIXME: to prevent the client from expiring read timeouts during writes,
617 * we refresh it. */
618 req->rex = rep->wex;
619 }
620 else
621 tv_eternity(&rep->wex);
622 }
623 }
624 return 0; /* other cases change nothing */
625 }
626 else if (c == CL_STSHUTR) {
627 if (rep->flags & BF_WRITE_ERROR) {
628 buffer_shutw(rep);
629 fd_delete(t->cli_fd);
630 t->cli_state = CL_STCLOSE;
631 if (!(t->flags & SN_ERR_MASK))
632 t->flags |= SN_ERR_CLICL;
633 if (!(t->flags & SN_FINST_MASK)) {
634 if (t->pend_pos)
635 t->flags |= SN_FINST_Q;
636 else if (s == SV_STCONN)
637 t->flags |= SN_FINST_C;
638 else
639 t->flags |= SN_FINST_D;
640 }
641 return 1;
642 }
643 else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) {
644 buffer_shutw(rep);
645 fd_delete(t->cli_fd);
646 t->cli_state = CL_STCLOSE;
647 return 1;
648 }
649 else if (tv_isle(&rep->wex, &now)) {
650 buffer_shutw(rep);
651 fd_delete(t->cli_fd);
652 t->cli_state = CL_STCLOSE;
653 if (!(t->flags & SN_ERR_MASK))
654 t->flags |= SN_ERR_CLITO;
655 if (!(t->flags & SN_FINST_MASK)) {
656 if (t->pend_pos)
657 t->flags |= SN_FINST_Q;
658 else if (s == SV_STCONN)
659 t->flags |= SN_FINST_C;
660 else
661 t->flags |= SN_FINST_D;
662 }
663 return 1;
664 }
665
666 if (rep->l == 0) {
667 if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
668 /* stop writing */
669 tv_eternity(&rep->wex);
670 }
671 } else {
672 /* buffer not empty */
673 if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
674 /* restart writing */
675 if (!tv_add_ifset(&rep->wex, &now, &rep->wto))
676 tv_eternity(&rep->wex);
677 }
678 }
679 return 0;
680 }
681 else if (c == CL_STSHUTW) {
682 if (req->flags & BF_READ_ERROR) {
683 buffer_shutr(req);
684 fd_delete(t->cli_fd);
685 t->cli_state = CL_STCLOSE;
686 if (!(t->flags & SN_ERR_MASK))
687 t->flags |= SN_ERR_CLICL;
688 if (!(t->flags & SN_FINST_MASK)) {
689 if (t->pend_pos)
690 t->flags |= SN_FINST_Q;
691 else if (s == SV_STCONN)
692 t->flags |= SN_FINST_C;
693 else
694 t->flags |= SN_FINST_D;
695 }
696 return 1;
697 }
698 else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
699 buffer_shutr(req);
700 fd_delete(t->cli_fd);
701 t->cli_state = CL_STCLOSE;
702 return 1;
703 }
704 else if (tv_isle(&req->rex, &now)) {
705 buffer_shutr(req);
706 fd_delete(t->cli_fd);
707 t->cli_state = CL_STCLOSE;
708 if (!(t->flags & SN_ERR_MASK))
709 t->flags |= SN_ERR_CLITO;
710 if (!(t->flags & SN_FINST_MASK)) {
711 if (t->pend_pos)
712 t->flags |= SN_FINST_Q;
713 else if (s == SV_STCONN)
714 t->flags |= SN_FINST_C;
715 else
716 t->flags |= SN_FINST_D;
717 }
718 return 1;
719 }
720 else if (req->l >= req->rlim - req->data) {
721 /* no room to read more data */
722
723 /* FIXME-20050705: is it possible for a client to maintain a session
724 * after the timeout by sending more data after it receives a close ?
725 */
726
727 if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
728 /* stop reading until we get some space */
729 tv_eternity(&req->rex);
730 //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
731 }
732 } else {
733 /* there's still some space in the buffer */
734 if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
735 if (!tv_add_ifset(&req->rex, &now, &req->rto))
736 tv_eternity(&req->rex);
737 //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
738 }
739 }
740 return 0;
741 }
742 else { /* CL_STCLOSE: nothing to do */
743 if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
744 int len;
745 len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n", t->uniq_id, t->be?t->be->id:"",
746 (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
747 write(1, trash, len);
748 }
749 return 0;
750 }
751 return 0;
752}
753
754#if 0
755 /* FIXME! This part has not been completely converted yet, and it may
756 * still be very specific to TCPv4 ! Also, it relies on some parameters
757 * such as conn_retries which are not set upon accept().
758 */
759/*
760 * Manages the server FSM and its socket. It returns 1 if a state has changed
761 * (and a resync may be needed), otherwise 0.
762 */
763static int process_uxst_srv(struct session *t)
764{
765 int s = t->srv_state;
766 int c = t->cli_state;
767 struct buffer *req = t->req;
768 struct buffer *rep = t->rep;
769 int conn_err;
770
771 if (s == SV_STIDLE) {
772 if (c == CL_STCLOSE || c == CL_STSHUTW ||
773 (c == CL_STSHUTR &&
774 (t->req->l == 0 || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
775 tv_eternity(&req->cex);
776 if (t->pend_pos)
777 t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
778 srv_close_with_err(t, SN_ERR_CLICL, t->pend_pos ? SN_FINST_Q : SN_FINST_C);
779 return 1;
780 }
781 else {
782 /* FIXME: reimplement the TARPIT check here */
783
784 /* Right now, we will need to create a connection to the server.
785 * We might already have tried, and got a connection pending, in
786 * which case we will not do anything till it's pending. It's up
787 * to any other session to release it and wake us up again.
788 */
789 if (t->pend_pos) {
790 if (!tv_isle(&req->cex, &now))
791 return 0;
792 else {
793 /* we've been waiting too long here */
794 tv_eternity(&req->cex);
795 t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
796 srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_Q);
797 if (t->srv)
798 t->srv->failed_conns++;
799 if (t->fe)
800 t->fe->failed_conns++;
801 return 1;
802 }
803 }
804
805 do {
806 /* first, get a connection */
807 if (srv_redispatch_connect(t))
808 return t->srv_state != SV_STIDLE;
809
810 /* try to (re-)connect to the server, and fail if we expire the
811 * number of retries.
812 */
813 if (srv_retryable_connect(t)) {
814 t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
815 return t->srv_state != SV_STIDLE;
816 }
817 } while (1);
818 }
819 }
820 else if (s == SV_STCONN) { /* connection in progress */
821 if (c == CL_STCLOSE || c == CL_STSHUTW ||
822 (c == CL_STSHUTR &&
823 ((t->req->l == 0 && !(req->flags & BF_WRITE_STATUS)) ||
824 t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
825 tv_eternity(&req->cex);
826 fd_delete(t->srv_fd);
827 if (t->srv)
828 t->srv->cur_sess--;
829
830 srv_close_with_err(t, SN_ERR_CLICL, SN_FINST_C);
831 return 1;
832 }
833 if (!(req->flags & BF_WRITE_STATUS) && !tv_isle(&req->cex, &now)) {
834 //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);
835 return 0; /* nothing changed */
836 }
837 else if (!(req->flags & BF_WRITE_STATUS) || (req->flags & BF_WRITE_ERROR)) {
838 /* timeout, asynchronous connect error or first write error */
839 //fprintf(stderr,"2: c=%d, s=%d\n", c, s);
840
841 fd_delete(t->srv_fd);
842 if (t->srv)
843 t->srv->cur_sess--;
844
845 if (!(req->flags & BF_WRITE_STATUS))
846 conn_err = SN_ERR_SRVTO; // it was a connect timeout.
847 else
848 conn_err = SN_ERR_SRVCL; // it was an asynchronous connect error.
849
850 /* ensure that we have enough retries left */
851 if (srv_count_retry_down(t, conn_err))
852 return 1;
853
854 if (t->srv && t->conn_retries == 0 && t->be->options & PR_O_REDISP) {
855 /* We're on our last chance, and the REDISP option was specified.
856 * We will ignore cookie and force to balance or use the dispatcher.
857 */
858 /* let's try to offer this slot to anybody */
859 if (may_dequeue_tasks(t->srv, t->be))
860 task_wakeup(t->srv->queue_mgt);
861
862 if (t->srv)
863 t->srv->failed_conns++;
864 t->be->failed_conns++;
865
866 t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
867 t->srv = NULL; /* it's left to the dispatcher to choose a server */
868
869 /* first, get a connection */
870 if (srv_redispatch_connect(t))
871 return t->srv_state != SV_STIDLE;
872 }
873
874 do {
875 /* Now we will try to either reconnect to the same server or
876 * connect to another server. If the connection gets queued
877 * because all servers are saturated, then we will go back to
878 * the SV_STIDLE state.
879 */
880 if (srv_retryable_connect(t)) {
881 t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
882 return t->srv_state != SV_STCONN;
883 }
884
885 /* we need to redispatch the connection to another server */
886 if (srv_redispatch_connect(t))
887 return t->srv_state != SV_STCONN;
888 } while (1);
889 }
890 else { /* no error or write 0 */
891 t->logs.t_connect = tv_ms_elapsed(&t->logs.tv_accept, &now);
892
893 //fprintf(stderr,"3: c=%d, s=%d\n", c, s);
894 if (req->l == 0) /* nothing to write */ {
895 EV_FD_CLR(t->srv_fd, DIR_WR);
896 tv_eternity(&req->wex);
897 } else /* need the right to write */ {
898 EV_FD_SET(t->srv_fd, DIR_WR);
899 if (tv_add_ifset(&req->wex, &now, &req->wto)) {
900 /* FIXME: to prevent the server from expiring read timeouts during writes,
901 * we refresh it. */
902 rep->rex = req->wex;
903 }
904 else
905 tv_eternity(&req->wex);
906 }
907
908 EV_FD_SET(t->srv_fd, DIR_RD);
909 if (!tv_add_ifset(&rep->rex, &now, &rep->rto))
910 tv_eternity(&rep->rex);
911
912 t->srv_state = SV_STDATA;
913 if (t->srv)
914 t->srv->cum_sess++;
915 rep->rlim = rep->data + BUFSIZE; /* no rewrite needed */
916
917 /* if the user wants to log as soon as possible, without counting
918 bytes from the server, then this is the right moment. */
919 if (t->fe && t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
920 t->logs.t_close = t->logs.t_connect; /* to get a valid end date */
921 //uxst_sess_log(t);
922 }
923 tv_eternity(&req->cex);
924 return 1;
925 }
926 }
927 else if (s == SV_STDATA) {
928 /* read or write error */
929 if (req->flags & BF_WRITE_ERROR || rep->flags & BF_READ_ERROR) {
930 buffer_shutr(rep);
931 buffer_shutw(req);
932 fd_delete(t->srv_fd);
933 if (t->srv) {
934 t->srv->cur_sess--;
935 t->srv->failed_resp++;
936 }
937 t->be->failed_resp++;
938 t->srv_state = SV_STCLOSE;
939 if (!(t->flags & SN_ERR_MASK))
940 t->flags |= SN_ERR_SRVCL;
941 if (!(t->flags & SN_FINST_MASK))
942 t->flags |= SN_FINST_D;
943 /* We used to have a free connection slot. Since we'll never use it,
944 * we have to inform the server that it may be used by another session.
945 */
946 if (may_dequeue_tasks(t->srv, t->be))
947 task_wakeup(t->srv->queue_mgt);
948
949 return 1;
950 }
951 /* last read, or end of client write */
952 else if (rep->flags & BF_READ_NULL || c == CL_STSHUTW || c == CL_STCLOSE) {
953 EV_FD_CLR(t->srv_fd, DIR_RD);
954 buffer_shutr(rep);
955 t->srv_state = SV_STSHUTR;
956 //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
957 return 1;
958 }
959 /* end of client read and no more data to send */
960 else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->l == 0)) {
961 EV_FD_CLR(t->srv_fd, DIR_WR);
962 buffer_shutw(req);
963 shutdown(t->srv_fd, SHUT_WR);
964 /* We must ensure that the read part is still alive when switching
965 * to shutw */
966 EV_FD_SET(t->srv_fd, DIR_RD);
967 tv_add_ifset(&rep->rex, &now, &rep->rto);
968
969 t->srv_state = SV_STSHUTW;
970 return 1;
971 }
972 /* read timeout */
973 else if (tv_isle(&rep->rex, &now)) {
974 EV_FD_CLR(t->srv_fd, DIR_RD);
975 buffer_shutr(rep);
976 t->srv_state = SV_STSHUTR;
977 if (!(t->flags & SN_ERR_MASK))
978 t->flags |= SN_ERR_SRVTO;
979 if (!(t->flags & SN_FINST_MASK))
980 t->flags |= SN_FINST_D;
981 return 1;
982 }
983 /* write timeout */
984 else if (tv_isle(&req->wex, &now)) {
985 EV_FD_CLR(t->srv_fd, DIR_WR);
986 buffer_shutw(req);
987 shutdown(t->srv_fd, SHUT_WR);
988 /* We must ensure that the read part is still alive when switching
989 * to shutw */
990 EV_FD_SET(t->srv_fd, DIR_RD);
991 tv_add_ifset(&rep->rex, &now, &rep->rto);
992 t->srv_state = SV_STSHUTW;
993 if (!(t->flags & SN_ERR_MASK))
994 t->flags |= SN_ERR_SRVTO;
995 if (!(t->flags & SN_FINST_MASK))
996 t->flags |= SN_FINST_D;
997 return 1;
998 }
999
1000 /* recompute request time-outs */
1001 if (req->l == 0) {
1002 if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
1003 /* stop writing */
1004 tv_eternity(&req->wex);
1005 }
1006 }
1007 else { /* buffer not empty, there are still data to be transferred */
1008 if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
1009 /* restart writing */
1010 if (tv_add_ifset(&req->wex, &now, &req->wto)) {
1011 /* FIXME: to prevent the server from expiring read timeouts during writes,
1012 * we refresh it. */
1013 rep->rex = req->wex;
1014 }
1015 else
1016 tv_eternity(&req->wex);
1017 }
1018 }
1019
1020 /* recompute response time-outs */
1021 if (rep->l == BUFSIZE) { /* no room to read more data */
1022 if (EV_FD_COND_C(t->srv_fd, DIR_RD)) {
1023 tv_eternity(&rep->rex);
1024 }
1025 }
1026 else {
1027 if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
1028 if (!tv_add_ifset(&rep->rex, &now, &rep->rto))
1029 tv_eternity(&rep->rex);
1030 }
1031 }
1032
1033 return 0; /* other cases change nothing */
1034 }
1035 else if (s == SV_STSHUTR) {
1036 if (req->flags & BF_WRITE_ERROR) {
1037 //EV_FD_CLR(t->srv_fd, DIR_WR);
1038 buffer_shutw(req);
1039 fd_delete(t->srv_fd);
1040 if (t->srv) {
1041 t->srv->cur_sess--;
1042 t->srv->failed_resp++;
1043 }
1044 t->be->failed_resp++;
1045 //close(t->srv_fd);
1046 t->srv_state = SV_STCLOSE;
1047 if (!(t->flags & SN_ERR_MASK))
1048 t->flags |= SN_ERR_SRVCL;
1049 if (!(t->flags & SN_FINST_MASK))
1050 t->flags |= SN_FINST_D;
1051 /* We used to have a free connection slot. Since we'll never use it,
1052 * we have to inform the server that it may be used by another session.
1053 */
1054 if (may_dequeue_tasks(t->srv, t->be))
1055 task_wakeup(t->srv->queue_mgt);
1056
1057 return 1;
1058 }
1059 else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->l == 0)) {
1060 //EV_FD_CLR(t->srv_fd, DIR_WR);
1061 buffer_shutw(req);
1062 fd_delete(t->srv_fd);
1063 if (t->srv)
1064 t->srv->cur_sess--;
1065 //close(t->srv_fd);
1066 t->srv_state = SV_STCLOSE;
1067 /* We used to have a free connection slot. Since we'll never use it,
1068 * we have to inform the server that it may be used by another session.
1069 */
1070 if (may_dequeue_tasks(t->srv, t->be))
1071 task_wakeup(t->srv->queue_mgt);
1072
1073 return 1;
1074 }
1075 else if (tv_isle(&req->wex, &now)) {
1076 //EV_FD_CLR(t->srv_fd, DIR_WR);
1077 buffer_shutw(req);
1078 fd_delete(t->srv_fd);
1079 if (t->srv)
1080 t->srv->cur_sess--;
1081 //close(t->srv_fd);
1082 t->srv_state = SV_STCLOSE;
1083 if (!(t->flags & SN_ERR_MASK))
1084 t->flags |= SN_ERR_SRVTO;
1085 if (!(t->flags & SN_FINST_MASK))
1086 t->flags |= SN_FINST_D;
1087 /* We used to have a free connection slot. Since we'll never use it,
1088 * we have to inform the server that it may be used by another session.
1089 */
1090 if (may_dequeue_tasks(t->srv, t->be))
1091 task_wakeup(t->srv->queue_mgt);
1092
1093 return 1;
1094 }
1095 else if (req->l == 0) {
1096 if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
1097 /* stop writing */
1098 tv_eternity(&req->wex);
1099 }
1100 }
1101 else { /* buffer not empty */
1102 if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
1103 /* restart writing */
1104 if (!tv_add_ifset(&req->wex, &now, &req->wto))
1105 tv_eternity(&req->wex);
1106 }
1107 }
1108 return 0;
1109 }
1110 else if (s == SV_STSHUTW) {
1111 if (rep->flags & BF_READ_ERROR) {
1112 //EV_FD_CLR(t->srv_fd, DIR_RD);
1113 buffer_shutr(rep);
1114 fd_delete(t->srv_fd);
1115 if (t->srv) {
1116 t->srv->cur_sess--;
1117 t->srv->failed_resp++;
1118 }
1119 t->be->failed_resp++;
1120 //close(t->srv_fd);
1121 t->srv_state = SV_STCLOSE;
1122 if (!(t->flags & SN_ERR_MASK))
1123 t->flags |= SN_ERR_SRVCL;
1124 if (!(t->flags & SN_FINST_MASK))
1125 t->flags |= SN_FINST_D;
1126 /* We used to have a free connection slot. Since we'll never use it,
1127 * we have to inform the server that it may be used by another session.
1128 */
1129 if (may_dequeue_tasks(t->srv, t->be))
1130 task_wakeup(t->srv->queue_mgt);
1131
1132 return 1;
1133 }
1134 else if (rep->flags & BF_READ_NULL || c == CL_STSHUTW || c == CL_STCLOSE) {
1135 //EV_FD_CLR(t->srv_fd, DIR_RD);
1136 buffer_shutr(rep);
1137 fd_delete(t->srv_fd);
1138 if (t->srv)
1139 t->srv->cur_sess--;
1140 //close(t->srv_fd);
1141 t->srv_state = SV_STCLOSE;
1142 /* We used to have a free connection slot. Since we'll never use it,
1143 * we have to inform the server that it may be used by another session.
1144 */
1145 if (may_dequeue_tasks(t->srv, t->be))
1146 task_wakeup(t->srv->queue_mgt);
1147
1148 return 1;
1149 }
1150 else if (tv_isle(&rep->rex, &now)) {
1151 //EV_FD_CLR(t->srv_fd, DIR_RD);
1152 buffer_shutr(rep);
1153 fd_delete(t->srv_fd);
1154 if (t->srv)
1155 t->srv->cur_sess--;
1156 //close(t->srv_fd);
1157 t->srv_state = SV_STCLOSE;
1158 if (!(t->flags & SN_ERR_MASK))
1159 t->flags |= SN_ERR_SRVTO;
1160 if (!(t->flags & SN_FINST_MASK))
1161 t->flags |= SN_FINST_D;
1162 /* We used to have a free connection slot. Since we'll never use it,
1163 * we have to inform the server that it may be used by another session.
1164 */
1165 if (may_dequeue_tasks(t->srv, t->be))
1166 task_wakeup(t->srv->queue_mgt);
1167
1168 return 1;
1169 }
1170 else if (rep->l == BUFSIZE) { /* no room to read more data */
1171 if (EV_FD_COND_C(t->srv_fd, DIR_RD)) {
1172 tv_eternity(&rep->rex);
1173 }
1174 }
1175 else {
1176 if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
1177 if (!tv_add_ifset(&rep->rex, &now, &rep->rto))
1178 tv_eternity(&rep->rex);
1179 }
1180 }
1181 return 0;
1182 }
1183 else { /* SV_STCLOSE : nothing to do */
1184 if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
1185 int len;
1186 len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n",
1187 t->uniq_id, t->be->id, (unsigned short)t->cli_fd, (unsigned short)t->srv_fd);
1188 write(1, trash, len);
1189 }
1190 return 0;
1191 }
1192 return 0;
1193}
1194
1195/* Processes the client and server jobs of a session task, then
1196 * puts it back to the wait queue in a clean state, or
1197 * cleans up its resources if it must be deleted. Returns
1198 * the time the task accepts to wait, or TIME_ETERNITY for
1199 * infinity.
1200 */
1201void process_uxst_session(struct task *t, struct timeval *next)
1202{
1203 struct session *s = t->context;
1204 int fsm_resync = 0;
1205
1206 do {
1207 fsm_resync = 0;
1208 fsm_resync |= process_uxst_cli(s);
1209 if (s->srv_state == SV_STIDLE) {
1210 if (s->cli_state == CL_STCLOSE || s->cli_state == CL_STSHUTW) {
1211 s->srv_state = SV_STCLOSE;
1212 fsm_resync |= 1;
1213 continue;
1214 }
1215 if (s->cli_state == CL_STSHUTR ||
1216 (s->req->l >= s->req->rlim - s->req->data)) {
1217 if (s->req->l == 0) {
1218 s->srv_state = SV_STCLOSE;
1219 fsm_resync |= 1;
1220 continue;
1221 }
1222 /* OK we have some remaining data to process */
1223 /* Just as an exercice, we copy the req into the resp,
1224 * and flush the req.
1225 */
1226 memcpy(s->rep->data, s->req->data, sizeof(s->rep->data));
1227 s->rep->l = s->req->l;
1228 s->rep->rlim = s->rep->data + BUFSIZE;
1229 s->rep->w = s->rep->data;
1230 s->rep->lr = s->rep->r = s->rep->data + s->rep->l;
1231
1232 s->req->l = 0;
1233 s->srv_state = SV_STCLOSE;
1234
1235 fsm_resync |= 1;
1236 continue;
1237 }
1238 }
1239 } while (fsm_resync);
1240
1241 if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
1242 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
1243 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
1244
1245 t->expire = s->req->rex;
1246 tv_min(&t->expire, &s->req->rex, &s->req->wex);
1247 tv_bound(&t->expire, &s->req->cex);
1248 tv_bound(&t->expire, &s->rep->rex);
1249 tv_bound(&t->expire, &s->rep->wex);
1250
1251 /* restore t to its place in the task list */
1252 task_queue(t);
1253
1254 *next = t->expire;
1255 return; /* nothing more to do */
1256 }
1257
1258 if (s->fe)
1259 s->fe->feconn--;
1260 if (s->be && (s->flags & SN_BE_ASSIGNED))
1261 s->be->beconn--;
1262 actconn--;
1263
1264 if (unlikely((global.mode & MODE_DEBUG) &&
1265 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
1266 int len;
1267 len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n",
1268 s->uniq_id, s->be->id,
1269 (unsigned short)s->cli_fd, (unsigned short)s->srv_fd);
1270 write(1, trash, len);
1271 }
1272
1273 s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
1274 if (s->req != NULL)
1275 s->logs.bytes_in = s->req->total;
1276 if (s->rep != NULL)
1277 s->logs.bytes_out = s->rep->total;
1278
1279 if (s->fe) {
1280 s->fe->bytes_in += s->logs.bytes_in;
1281 s->fe->bytes_out += s->logs.bytes_out;
1282 }
1283 if (s->be && (s->be != s->fe)) {
1284 s->be->bytes_in += s->logs.bytes_in;
1285 s->be->bytes_out += s->logs.bytes_out;
1286 }
1287 if (s->srv) {
1288 s->srv->bytes_in += s->logs.bytes_in;
1289 s->srv->bytes_out += s->logs.bytes_out;
1290 }
1291
1292 /* let's do a final log if we need it */
1293 if (s->logs.logwait &&
1294 !(s->flags & SN_MONITOR) &&
1295 (s->req->total || !(s->fe && s->fe->options & PR_O_NULLNOLOG))) {
1296 //uxst_sess_log(s);
1297 }
1298
1299 /* the task MUST not be in the run queue anymore */
1300 task_delete(t);
1301 session_free(s);
1302 task_free(t);
1303 tv_eternity(next);
1304}
1305#endif /* not converted */
1306
1307
1308/* Processes data exchanges on the statistics socket. The client processing
1309 * is called and the task is put back in the wait queue or it is cleared.
1310 * In order to ease the transition, we simply simulate the server status
Willy Tarreau3e76e722007-10-17 18:57:38 +02001311 * for now. It only knows states SV_STIDLE, SV_STDATA and SV_STCLOSE. Returns
1312 * in <next> the task's expiration date.
Willy Tarreau92fb9832007-10-16 17:34:28 +02001313 */
1314void process_uxst_stats(struct task *t, struct timeval *next)
1315{
1316 struct session *s = t->context;
1317 struct listener *listener;
1318 int fsm_resync = 0;
1319
Willy Tarreau3e76e722007-10-17 18:57:38 +02001320 /* we need to be in DATA phase on the "server" side */
1321 if (s->srv_state == SV_STIDLE) {
1322 s->srv_state = SV_STDATA;
1323 s->data_source = DATA_SRC_STATS;
1324 }
1325
Willy Tarreau92fb9832007-10-16 17:34:28 +02001326 do {
Willy Tarreau3e76e722007-10-17 18:57:38 +02001327 fsm_resync = process_uxst_cli(s);
1328 if (s->srv_state != SV_STDATA)
1329 continue;
1330
1331 if (s->cli_state == CL_STCLOSE || s->cli_state == CL_STSHUTW) {
1332 s->srv_state = SV_STCLOSE;
1333 fsm_resync |= 1;
1334 continue;
1335 }
1336
1337 if (s->data_state == DATA_ST_INIT) {
1338 if ((s->req->l >= 10) && (memcmp(s->req->data, "show stat\n", 10) == 0)) {
1339 /* send the stats, and changes the data_state */
1340 if (stats_dump_raw(s, NULL, 0) != 0) {
Willy Tarreau92fb9832007-10-16 17:34:28 +02001341 s->srv_state = SV_STCLOSE;
1342 fsm_resync |= 1;
1343 continue;
1344 }
Willy Tarreau3e76e722007-10-17 18:57:38 +02001345 }
1346 else if (s->cli_state == CL_STSHUTR || (s->req->l >= s->req->rlim - s->req->data)) {
Willy Tarreau92fb9832007-10-16 17:34:28 +02001347 s->srv_state = SV_STCLOSE;
Willy Tarreau92fb9832007-10-16 17:34:28 +02001348 fsm_resync |= 1;
1349 continue;
1350 }
1351 }
Willy Tarreau3e76e722007-10-17 18:57:38 +02001352
1353 if (s->data_state == DATA_ST_INIT)
1354 continue;
1355
1356 /* OK we have some remaining data to process. Just for the
1357 * sake of an exercice, we copy the req into the resp,
1358 * and flush the req. This produces a simple echo function.
1359 */
1360 if (stats_dump_raw(s, NULL, 0) != 0) {
1361 s->srv_state = SV_STCLOSE;
1362 fsm_resync |= 1;
1363 continue;
1364 }
Willy Tarreau92fb9832007-10-16 17:34:28 +02001365 } while (fsm_resync);
1366
1367 if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
1368 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
1369 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
1370
1371 t->expire = s->req->rex;
1372 tv_min(&t->expire, &s->req->rex, &s->req->wex);
1373 tv_bound(&t->expire, &s->req->cex);
1374 tv_bound(&t->expire, &s->rep->rex);
1375 tv_bound(&t->expire, &s->rep->wex);
1376
1377 /* restore t to its place in the task list */
1378 task_queue(t);
1379
1380 *next = t->expire;
1381 return; /* nothing more to do */
1382 }
1383
1384 actconn--;
1385 listener = fdtab[s->cli_fd].listener;
1386 if (listener) {
1387 listener->nbconn--;
1388 if (listener->state == LI_FULL &&
1389 listener->nbconn < listener->maxconn) {
1390 /* we should reactivate the listener */
1391 EV_FD_SET(listener->fd, DIR_RD);
1392 listener->state = LI_READY;
1393 }
1394 }
1395
1396 /* the task MUST not be in the run queue anymore */
1397 task_delete(t);
1398 session_free(s);
1399 task_free(t);
1400 tv_eternity(next);
1401}
1402
1403/* Note: must not be declared <const> as its list will be overwritten */
1404static struct protocol proto_unix = {
1405 .name = "unix_stream",
1406 .sock_domain = PF_UNIX,
1407 .sock_type = SOCK_STREAM,
1408 .sock_prot = 0,
1409 .sock_family = AF_UNIX,
Willy Tarreau106bf272007-10-28 12:09:45 +01001410 .sock_addrlen = sizeof(struct sockaddr_un),
1411 .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path),/* path len */
Willy Tarreau92fb9832007-10-16 17:34:28 +02001412 .read = &stream_sock_read,
1413 .write = &stream_sock_write,
1414 .bind_all = uxst_bind_listeners,
1415 .unbind_all = uxst_unbind_listeners,
1416 .enable_all = uxst_enable_listeners,
1417 .listeners = LIST_HEAD_INIT(proto_unix.listeners),
1418 .nb_listeners = 0,
1419};
1420
1421/* Adds listener to the list of unix stream listeners */
1422void uxst_add_listener(struct listener *listener)
1423{
1424 listener->proto = &proto_unix;
1425 LIST_ADDQ(&proto_unix.listeners, &listener->proto_list);
1426 proto_unix.nb_listeners++;
1427}
1428
1429__attribute__((constructor))
1430static void __uxst_protocol_init(void)
1431{
1432 protocol_register(&proto_unix);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001433}
1434
1435
1436/*
1437 * Local variables:
1438 * c-indent-level: 8
1439 * c-basic-offset: 8
1440 * End:
1441 */