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