blob: a053992277104da41e11f8bca01936463dd33aa5 [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>
Willy Tarreaub1356cf2008-12-07 16:06:43 +010051#include <proto/stream_interface.h>
Willy Tarreau92fb9832007-10-16 17:34:28 +020052#include <proto/stream_sock.h>
53#include <proto/task.h>
54
55#ifndef MAXPATHLEN
56#define MAXPATHLEN 128
57#endif
58
Willy Tarreaudabf2e22007-10-28 21:59:24 +010059static int uxst_bind_listeners(struct protocol *proto);
60static int uxst_unbind_listeners(struct protocol *proto);
61
62/* Note: must not be declared <const> as its list will be overwritten */
63static struct protocol proto_unix = {
64 .name = "unix_stream",
65 .sock_domain = PF_UNIX,
66 .sock_type = SOCK_STREAM,
67 .sock_prot = 0,
68 .sock_family = AF_UNIX,
69 .sock_addrlen = sizeof(struct sockaddr_un),
70 .l3_addrlen = sizeof(((struct sockaddr_un*)0)->sun_path),/* path len */
71 .read = &stream_sock_read,
72 .write = &stream_sock_write,
73 .bind_all = uxst_bind_listeners,
74 .unbind_all = uxst_unbind_listeners,
75 .enable_all = enable_all_listeners,
76 .disable_all = disable_all_listeners,
77 .listeners = LIST_HEAD_INIT(proto_unix.listeners),
78 .nb_listeners = 0,
79};
80
Willy Tarreau43e0e392009-07-26 18:16:43 +020081const char unix_sock_usage_msg[] =
82 "Unknown command. Please enter one of the following commands only :\n"
83 " show info : report information about the running process\n"
84 " show stat : report counters for each proxy and server\n"
85 " show errors : report last request and response errors for each proxy\n"
86 " show sess : report the list of current sessions\n"
87 "\n";
88
89const struct chunk unix_sock_usage = {
90 .str = (char *)&unix_sock_usage_msg,
91 .len = sizeof(unix_sock_usage_msg)-1
92};
Willy Tarreaudabf2e22007-10-28 21:59:24 +010093
94/********************************
95 * 1) low-level socket functions
96 ********************************/
97
98
Willy Tarreau92fb9832007-10-16 17:34:28 +020099/* This function creates a named PF_UNIX stream socket at address <path>. Note
Willy Tarreaue6ad2b12007-10-18 12:45:54 +0200100 * that the path cannot be NULL nor empty. <uid> and <gid> different of -1 will
101 * be used to change the socket owner. If <mode> is not 0, it will be used to
102 * restrict access to the socket. While it is known not to be portable on every
103 * OS, it's still useful where it works.
Willy Tarreau92fb9832007-10-16 17:34:28 +0200104 * It returns the assigned file descriptor, or -1 in the event of an error.
105 */
Willy Tarreaue6ad2b12007-10-18 12:45:54 +0200106static int create_uxst_socket(const char *path, uid_t uid, gid_t gid, mode_t mode)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200107{
108 char tempname[MAXPATHLEN];
109 char backname[MAXPATHLEN];
110 struct sockaddr_un addr;
111
112 int ret, sock;
113
114 /* 1. create socket names */
115 if (!path[0]) {
116 Alert("Invalid name for a UNIX socket. Aborting.\n");
117 goto err_return;
118 }
119
120 ret = snprintf(tempname, MAXPATHLEN, "%s.%d.tmp", path, pid);
121 if (ret < 0 || ret >= MAXPATHLEN) {
122 Alert("name too long for UNIX socket. Aborting.\n");
123 goto err_return;
124 }
125
126 ret = snprintf(backname, MAXPATHLEN, "%s.%d.bak", path, pid);
127 if (ret < 0 || ret >= MAXPATHLEN) {
128 Alert("name too long for UNIX socket. Aborting.\n");
129 goto err_return;
130 }
131
132 /* 2. clean existing orphaned entries */
133 if (unlink(tempname) < 0 && errno != ENOENT) {
134 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
135 goto err_return;
136 }
137
138 if (unlink(backname) < 0 && errno != ENOENT) {
139 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
140 goto err_return;
141 }
142
143 /* 3. backup existing socket */
144 if (link(path, backname) < 0 && errno != ENOENT) {
145 Alert("error when trying to preserve previous UNIX socket. Aborting.\n");
146 goto err_return;
147 }
148
149 /* 4. prepare new socket */
150 addr.sun_family = AF_UNIX;
151 strncpy(addr.sun_path, tempname, sizeof(addr.sun_path));
152 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
153
154 sock = socket(PF_UNIX, SOCK_STREAM, 0);
155 if (sock < 0) {
156 Alert("cannot create socket for UNIX listener. Aborting.\n");
157 goto err_unlink_back;
158 }
159
160 if (sock >= global.maxsock) {
161 Alert("socket(): not enough free sockets for UNIX listener. Raise -n argument. Aborting.\n");
162 goto err_unlink_temp;
163 }
164
165 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
166 Alert("cannot make UNIX socket non-blocking. Aborting.\n");
167 goto err_unlink_temp;
168 }
169
170 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
171 /* note that bind() creates the socket <tempname> on the file system */
172 Alert("cannot bind socket for UNIX listener. Aborting.\n");
173 goto err_unlink_temp;
174 }
175
Willy Tarreaue6ad2b12007-10-18 12:45:54 +0200176 if (((uid != -1 || gid != -1) && (chown(tempname, uid, gid) == -1)) ||
177 (mode != 0 && chmod(tempname, mode) == -1)) {
178 Alert("cannot change UNIX socket ownership. Aborting.\n");
179 goto err_unlink_temp;
180 }
181
Willy Tarreau92fb9832007-10-16 17:34:28 +0200182 if (listen(sock, 0) < 0) {
183 Alert("cannot listen to socket for UNIX listener. Aborting.\n");
184 goto err_unlink_temp;
185 }
186
187 /* 5. install.
188 * Point of no return: we are ready, we'll switch the sockets. We don't
189 * fear loosing the socket <path> because we have a copy of it in
190 * backname.
191 */
192 if (rename(tempname, path) < 0) {
193 Alert("cannot switch final and temporary sockets for UNIX listener. Aborting.\n");
194 goto err_rename;
195 }
196
197 /* 6. cleanup */
198 unlink(backname); /* no need to keep this one either */
199
200 return sock;
201
202 err_rename:
203 ret = rename(backname, path);
204 if (ret < 0 && errno == ENOENT)
205 unlink(path);
206 err_unlink_temp:
207 unlink(tempname);
208 close(sock);
209 err_unlink_back:
210 unlink(backname);
211 err_return:
212 return -1;
213}
214
215/* Tries to destroy the UNIX stream socket <path>. The socket must not be used
216 * anymore. It practises best effort, and no error is returned.
217 */
218static void destroy_uxst_socket(const char *path)
219{
220 struct sockaddr_un addr;
221 int sock, ret;
222
223 /* We might have been chrooted, so we may not be able to access the
224 * socket. In order to avoid bothering the other end, we connect with a
225 * wrong protocol, namely SOCK_DGRAM. The return code from connect()
226 * is enough to know if the socket is still live or not. If it's live
227 * in mode SOCK_STREAM, we get EPROTOTYPE or anything else but not
228 * ECONNREFUSED. In this case, we do not touch it because it's used
229 * by some other process.
230 */
231 sock = socket(PF_UNIX, SOCK_DGRAM, 0);
232 if (sock < 0)
233 return;
234
235 addr.sun_family = AF_UNIX;
236 strncpy(addr.sun_path, path, sizeof(addr.sun_path));
Willy Tarreau10ae5482007-10-18 16:15:52 +0200237 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200238 ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
239 if (ret < 0 && errno == ECONNREFUSED) {
240 /* Connect failed: the socket still exists but is not used
241 * anymore. Let's remove this socket now.
242 */
243 unlink(path);
244 }
245 close(sock);
246}
247
248
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100249/********************************
250 * 2) listener-oriented functions
251 ********************************/
252
253
254/* This function creates the UNIX socket associated to the listener. It changes
255 * the state from ASSIGNED to LISTEN. The socket is NOT enabled for polling.
256 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
257 */
258static int uxst_bind_listener(struct listener *listener)
259{
260 int fd;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100261
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100262 if (listener->state != LI_ASSIGNED)
263 return ERR_NONE; /* already bound */
264
265 fd = create_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path,
266 listener->perm.ux.uid,
267 listener->perm.ux.gid,
268 listener->perm.ux.mode);
269 if (fd == -1)
270 return ERR_FATAL;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100271
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100272 /* the socket is now listening */
273 listener->fd = fd;
274 listener->state = LI_LISTEN;
275
276 /* the function for the accept() event */
277 fd_insert(fd);
278 fdtab[fd].cb[DIR_RD].f = listener->accept;
279 fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
280 fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
Willy Tarreaueabf3132008-08-29 23:36:51 +0200281 fdtab[fd].owner = listener; /* reference the listener instead of a task */
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100282 fdtab[fd].state = FD_STLISTEN;
283 fdtab[fd].peeraddr = NULL;
284 fdtab[fd].peerlen = 0;
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100285 return ERR_NONE;
286}
287
288/* This function closes the UNIX sockets for the specified listener.
289 * The listener enters the LI_ASSIGNED state. It always returns ERR_NONE.
290 */
291static int uxst_unbind_listener(struct listener *listener)
292{
293 if (listener->state == LI_READY)
294 EV_FD_CLR(listener->fd, DIR_RD);
295
296 if (listener->state >= LI_LISTEN) {
Willy Tarreau8eebe5e2007-10-28 22:07:08 +0100297 fd_delete(listener->fd);
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100298 listener->state = LI_ASSIGNED;
299 destroy_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path);
300 }
301 return ERR_NONE;
302}
303
304/* Add a listener to the list of unix stream listeners. The listener's state
305 * is automatically updated from LI_INIT to LI_ASSIGNED. The number of
306 * listeners is updated. This is the function to use to add a new listener.
307 */
308void uxst_add_listener(struct listener *listener)
309{
310 if (listener->state != LI_INIT)
311 return;
312 listener->state = LI_ASSIGNED;
313 listener->proto = &proto_unix;
314 LIST_ADDQ(&proto_unix.listeners, &listener->proto_list);
315 proto_unix.nb_listeners++;
316}
317
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100318/********************************
319 * 3) protocol-oriented functions
320 ********************************/
321
322
Willy Tarreau92fb9832007-10-16 17:34:28 +0200323/* This function creates all UNIX sockets bound to the protocol entry <proto>.
324 * It is intended to be used as the protocol's bind_all() function.
325 * The sockets will be registered but not added to any fd_set, in order not to
326 * loose them across the fork(). A call to uxst_enable_listeners() is needed
327 * to complete initialization.
328 *
329 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
330 */
331static int uxst_bind_listeners(struct protocol *proto)
332{
333 struct listener *listener;
334 int err = ERR_NONE;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200335
336 list_for_each_entry(listener, &proto->listeners, proto_list) {
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100337 err |= uxst_bind_listener(listener);
338 if (err != ERR_NONE)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200339 continue;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200340 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200341 return err;
342}
343
Willy Tarreau92fb9832007-10-16 17:34:28 +0200344
345/* This function stops all listening UNIX sockets bound to the protocol
346 * <proto>. It does not detaches them from the protocol.
347 * It always returns ERR_NONE.
348 */
349static int uxst_unbind_listeners(struct protocol *proto)
350{
351 struct listener *listener;
352
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100353 list_for_each_entry(listener, &proto->listeners, proto_list)
354 uxst_unbind_listener(listener);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200355 return ERR_NONE;
356}
357
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100358
359/********************************
360 * 4) high-level functions
361 ********************************/
362
363
Willy Tarreau92fb9832007-10-16 17:34:28 +0200364/*
365 * This function is called on a read event from a listen socket, corresponding
366 * to an accept. It tries to accept as many connections as possible.
367 * It returns 0. Since we use UNIX sockets on the local system for monitoring
368 * purposes and other related things, we do not need to output as many messages
369 * as with TCP which can fall under attack.
370 */
371int uxst_event_accept(int fd) {
Willy Tarreaueabf3132008-08-29 23:36:51 +0200372 struct listener *l = fdtab[fd].owner;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200373 struct session *s;
374 struct task *t;
375 int cfd;
376 int max_accept;
377
378 if (global.nbproc > 1)
379 max_accept = 8; /* let other processes catch some connections too */
380 else
381 max_accept = -1;
382
Willy Tarreau2d045592009-03-28 11:02:18 +0100383 while (max_accept--) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200384 struct sockaddr_storage addr;
385 socklen_t laddr = sizeof(addr);
386
387 if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) == -1) {
388 switch (errno) {
389 case EAGAIN:
390 case EINTR:
391 case ECONNABORTED:
392 return 0; /* nothing more to accept */
393 case ENFILE:
394 /* Process reached system FD limit. Check system tunables. */
395 return 0;
396 case EMFILE:
397 /* Process reached process FD limit. Check 'ulimit-n'. */
398 return 0;
399 case ENOBUFS:
400 case ENOMEM:
401 /* Process reached system memory limit. Check system tunables. */
402 return 0;
403 default:
404 return 0;
405 }
406 }
407
Willy Tarreau2d045592009-03-28 11:02:18 +0100408 if (l->nbconn >= l->maxconn || actconn >= global.maxconn) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200409 /* too many connections, we shoot this one and return.
410 * FIXME: it would be better to simply switch the listener's
411 * state to LI_FULL and disable the FD. We could re-enable
412 * it upon fd_delete(), but this requires all protocols to
413 * be switched.
414 */
Willy Tarreaua11e9762008-12-01 01:44:25 +0100415 goto out_close;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200416 }
417
418 if ((s = pool_alloc2(pool2_session)) == NULL) {
419 Alert("out of memory in uxst_event_accept().\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100420 goto out_close;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200421 }
422
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100423 LIST_ADDQ(&sessions, &s->list);
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100424 LIST_INIT(&s->back_refs);
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100425
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100426 s->flags = 0;
Willy Tarreauf8533202008-08-16 14:55:08 +0200427 s->term_trace = 0;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100428
Willy Tarreaua4613182009-03-21 18:13:21 +0100429 if ((t = task_new()) == NULL) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200430 Alert("out of memory in uxst_event_accept().\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100431 goto out_free_session;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200432 }
433
434 s->cli_addr = addr;
435
436 /* FIXME: should be checked earlier */
437 if (cfd >= global.maxsock) {
438 Alert("accept(): not enough free sockets. Raise -n argument. Giving up.\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100439 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200440 }
441
442 if (fcntl(cfd, F_SETFL, O_NONBLOCK) == -1) {
443 Alert("accept(): cannot set the socket in non blocking mode. Giving up\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100444 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200445 }
446
Willy Tarreau92fb9832007-10-16 17:34:28 +0200447 t->process = l->handler;
448 t->context = s;
Willy Tarreau91e99932008-06-30 07:51:00 +0200449 t->nice = -64; /* we want to boost priority for local stats */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200450
451 s->task = t;
Willy Tarreaub5654f62008-12-07 16:45:10 +0100452 s->listener = l;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200453 s->fe = NULL;
454 s->be = NULL;
455
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100456 s->ana_state = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200457 s->req = s->rep = NULL; /* will be allocated later */
458
Willy Tarreaua11e9762008-12-01 01:44:25 +0100459 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
460 s->si[0].err_type = SI_ET_NONE;
461 s->si[0].err_loc = NULL;
462 s->si[0].owner = t;
463 s->si[0].shutr = stream_sock_shutr;
464 s->si[0].shutw = stream_sock_shutw;
Willy Tarreau3ffeba12008-12-14 14:42:35 +0100465 s->si[0].chk_rcv = stream_sock_chk_rcv;
466 s->si[0].chk_snd = stream_sock_chk_snd;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100467 s->si[0].fd = cfd;
468 s->si[0].flags = SI_FL_NONE;
469 s->si[0].exp = TICK_ETERNITY;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100470
471 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
472 s->si[1].err_type = SI_ET_NONE;
473 s->si[1].err_loc = NULL;
474 s->si[1].owner = t;
475 s->si[1].shutr = stream_sock_shutr;
476 s->si[1].shutw = stream_sock_shutw;
Willy Tarreau3ffeba12008-12-14 14:42:35 +0100477 s->si[1].chk_rcv = stream_sock_chk_rcv;
478 s->si[1].chk_snd = stream_sock_chk_snd;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100479 s->si[1].exp = TICK_ETERNITY;
480 s->si[1].fd = -1; /* just to help with debugging */
481 s->si[1].flags = SI_FL_NONE;
482
483 s->srv = s->prev_srv = s->srv_conn = NULL;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200484 s->pend_pos = NULL;
485
486 memset(&s->logs, 0, sizeof(s->logs));
487 memset(&s->txn, 0, sizeof(s->txn));
488
Willy Tarreau3dfe6cd2008-12-07 22:29:48 +0100489 s->logs.tv_accept = now; /* corrected date for internal use */
490
Willy Tarreau3e76e722007-10-17 18:57:38 +0200491 s->data_state = DATA_ST_INIT;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200492 s->data_source = DATA_SRC_NONE;
493 s->uniq_id = totalconn;
494
Willy Tarreaua11e9762008-12-01 01:44:25 +0100495 if ((s->req = pool_alloc2(pool2_buffer)) == NULL)
496 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200497
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100498 buffer_init(s->req);
Willy Tarreaua11e9762008-12-01 01:44:25 +0100499 s->req->prod = &s->si[0];
500 s->req->cons = &s->si[1];
501 s->si[0].ib = s->si[1].ob = s->req;
502 s->req->flags |= BF_READ_ATTACHED; /* the producer is already connected */
Willy Tarreau1b194fe2009-03-21 21:10:04 +0100503 s->req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
Willy Tarreaua11e9762008-12-01 01:44:25 +0100504
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100505 s->req->analysers = l->analysers;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100506
507 s->req->wto = TICK_ETERNITY;
508 s->req->cto = TICK_ETERNITY;
509 s->req->rto = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200510
Willy Tarreaua11e9762008-12-01 01:44:25 +0100511 if ((s->rep = pool_alloc2(pool2_buffer)) == NULL)
512 goto out_free_req;
513
Willy Tarreau92fb9832007-10-16 17:34:28 +0200514 buffer_init(s->rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200515
Willy Tarreaua11e9762008-12-01 01:44:25 +0100516 s->rep->prod = &s->si[1];
517 s->rep->cons = &s->si[0];
518 s->si[0].ob = s->si[1].ib = s->rep;
519
520 s->rep->rto = TICK_ETERNITY;
521 s->rep->cto = TICK_ETERNITY;
522 s->rep->wto = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200523
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200524 s->req->rex = TICK_ETERNITY;
525 s->req->wex = TICK_ETERNITY;
Willy Tarreauffab5b42008-08-17 18:03:28 +0200526 s->req->analyse_exp = TICK_ETERNITY;
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200527 s->rep->rex = TICK_ETERNITY;
528 s->rep->wex = TICK_ETERNITY;
Willy Tarreauffab5b42008-08-17 18:03:28 +0200529 s->rep->analyse_exp = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200530
Willy Tarreaua11e9762008-12-01 01:44:25 +0100531 t->expire = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200532
Willy Tarreaua11e9762008-12-01 01:44:25 +0100533 if (l->timeout) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200534 s->req->rto = *l->timeout;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200535 s->rep->wto = *l->timeout;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200536 }
537
Willy Tarreaua11e9762008-12-01 01:44:25 +0100538 fd_insert(cfd);
539 fdtab[cfd].owner = &s->si[0];
Willy Tarreaua11e9762008-12-01 01:44:25 +0100540 fdtab[cfd].state = FD_STREADY;
541 fdtab[cfd].cb[DIR_RD].f = l->proto->read;
542 fdtab[cfd].cb[DIR_RD].b = s->req;
543 fdtab[cfd].cb[DIR_WR].f = l->proto->write;
544 fdtab[cfd].cb[DIR_WR].b = s->rep;
545 fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
546 fdtab[cfd].peerlen = sizeof(s->cli_addr);
547
548 EV_FD_SET(cfd, DIR_RD);
549
Willy Tarreaufdccded2008-08-29 18:19:04 +0200550 task_wakeup(t, TASK_WOKEN_INIT);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200551
552 l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
553 if (l->nbconn >= l->maxconn) {
554 EV_FD_CLR(l->fd, DIR_RD);
555 l->state = LI_FULL;
556 }
557 actconn++;
558 totalconn++;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100559 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200560 return 0;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100561
562 out_free_req:
563 pool_free2(pool2_buffer, s->req);
564 out_free_task:
Willy Tarreaua4613182009-03-21 18:13:21 +0100565 task_free(t);
Willy Tarreaua11e9762008-12-01 01:44:25 +0100566 out_free_session:
567 LIST_DEL(&s->list);
568 pool_free2(pool2_session, s);
569 out_close:
570 close(cfd);
571 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200572}
573
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100574/* Parses the request line in <cmd> and possibly starts dumping stats on
575 * s->rep with the hijack bit set. Returns 1 if OK, 0 in case of any error.
576 * The line is modified after parsing.
Willy Tarreau92fb9832007-10-16 17:34:28 +0200577 */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100578int unix_sock_parse_request(struct session *s, char *line)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200579{
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100580 char *args[MAX_UXST_ARGS + 1];
581 int arg;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200582
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100583 while (isspace((unsigned char)*line))
584 line++;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200585
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100586 arg = 0;
587 args[arg] = line;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200588
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100589 while (*line && arg < MAX_UXST_ARGS) {
590 if (isspace((unsigned char)*line)) {
591 *line++ = '\0';
Willy Tarreau92fb9832007-10-16 17:34:28 +0200592
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100593 while (isspace((unsigned char)*line))
594 line++;
595
596 args[++arg] = line;
597 continue;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200598 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100599
600 line++;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200601 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200602
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100603 while (++arg <= MAX_UXST_ARGS)
604 args[arg] = line;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200605
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100606 if (strcmp(args[0], "show") == 0) {
607 if (strcmp(args[1], "stat") == 0) {
608 if (*args[2] && *args[3] && *args[4]) {
609 s->data_ctx.stats.flags |= STAT_BOUND;
610 s->data_ctx.stats.iid = atoi(args[2]);
611 s->data_ctx.stats.type = atoi(args[3]);
612 s->data_ctx.stats.sid = atoi(args[4]);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200613 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100614
615 s->data_ctx.stats.flags |= STAT_SHOW_STAT;
616 s->data_ctx.stats.flags |= STAT_FMT_CSV;
617 s->ana_state = STATS_ST_REP;
Willy Tarreau01bf8672008-12-07 18:03:29 +0100618 buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200619 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100620 else if (strcmp(args[1], "info") == 0) {
621 s->data_ctx.stats.flags |= STAT_SHOW_INFO;
622 s->data_ctx.stats.flags |= STAT_FMT_CSV;
623 s->ana_state = STATS_ST_REP;
Willy Tarreau01bf8672008-12-07 18:03:29 +0100624 buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100625 }
Willy Tarreau3dfe6cd2008-12-07 22:29:48 +0100626 else if (strcmp(args[1], "sess") == 0) {
627 s->ana_state = STATS_ST_REP;
628 buffer_install_hijacker(s, s->rep, stats_dump_sess_to_buffer);
629 }
Willy Tarreau74808cb2009-03-04 15:53:18 +0100630 else if (strcmp(args[1], "errors") == 0) {
631 if (*args[2])
632 s->data_ctx.errors.iid = atoi(args[2]);
633 else
634 s->data_ctx.errors.iid = -1;
635 s->data_ctx.errors.px = NULL;
636 s->ana_state = STATS_ST_REP;
637 buffer_install_hijacker(s, s->rep, stats_dump_errors_to_buffer);
638 }
Willy Tarreau3dfe6cd2008-12-07 22:29:48 +0100639 else { /* neither "stat" nor "info" nor "sess" */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100640 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200641 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100642 }
643 else { /* not "show" */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200644 return 0;
645 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100646 return 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200647}
648
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100649/* Processes the stats interpreter on the statistics socket.
650 * In order to ease the transition, we simply simulate the server status
651 * for now. It only knows states STATS_ST_INIT, STATS_ST_REQ, STATS_ST_REP, and
652 * STATS_ST_CLOSE. It removes the AN_REQ_UNIX_STATS bit from req->analysers
653 * once done. It always returns 0.
Willy Tarreau92fb9832007-10-16 17:34:28 +0200654 */
Willy Tarreau3a816292009-07-07 10:55:49 +0200655int uxst_req_analyser_stats(struct session *s, struct buffer *req, int an_bit)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200656{
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100657 char *line, *p;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200658
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100659 switch (s->ana_state) {
660 case STATS_ST_INIT:
661 /* Stats output not initialized yet */
662 memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
663 s->data_source = DATA_SRC_STATS;
664 s->ana_state = STATS_ST_REQ;
Willy Tarreau38c99bc2009-02-22 15:58:45 +0100665 buffer_write_dis(s->req);
666 buffer_shutw_now(s->req);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100667 /* fall through */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200668
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100669 case STATS_ST_REQ:
670 /* Now, stats are initialized, hijack is not set, and
671 * we are waiting for a complete request line.
672 */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200673
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100674 line = s->req->data;
675 p = memchr(line, '\n', s->req->l);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200676
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100677 if (p) {
678 *p = '\0';
679 if (!unix_sock_parse_request(s, line)) {
680 /* invalid request */
Willy Tarreau43e0e392009-07-26 18:16:43 +0200681 stream_int_retnclose(s->req->prod, &unix_sock_usage);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100682 s->ana_state = 0;
683 req->analysers = 0;
684 return 0;
685 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200686 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200687
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100688 /* processing a valid or incomplete request */
689 if ((req->flags & BF_FULL) || /* invalid request */
690 (req->flags & BF_READ_ERROR) || /* input error */
691 (req->flags & BF_READ_TIMEOUT) || /* read timeout */
692 tick_is_expired(req->analyse_exp, now_ms) || /* request timeout */
693 (req->flags & BF_SHUTR)) { /* input closed */
Willy Tarreau38c99bc2009-02-22 15:58:45 +0100694 buffer_shutw_now(s->rep);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100695 s->ana_state = 0;
696 req->analysers = 0;
697 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200698 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100699 /* don't forward nor abort */
Willy Tarreau1b194fe2009-03-21 21:10:04 +0100700 req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100701 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200702
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100703 case STATS_ST_REP:
704 /* do nothing while response is being processed */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100705 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200706
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100707 case STATS_ST_CLOSE:
708 /* end of dump */
Willy Tarreau3a816292009-07-07 10:55:49 +0200709 s->req->analysers &= ~an_bit;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100710 s->ana_state = 0;
711 break;
712 }
713 return 0;
714}
Willy Tarreau92fb9832007-10-16 17:34:28 +0200715
Willy Tarreau92fb9832007-10-16 17:34:28 +0200716
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100717/* This function is the unix-stream equivalent of the global process_session().
718 * It is currently limited to unix-stream processing on control sockets such as
719 * stats, and has no server-side. The two functions should be merged into one
720 * once client and server sides are better delimited. Note that the server-side
721 * still exists but remains in SI_ST_INI state forever, so that any call is a
722 * NOP.
723 */
Willy Tarreau26c25062009-03-08 09:38:41 +0100724struct task *uxst_process_session(struct task *t)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100725{
726 struct session *s = t->context;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100727 int resync;
728 unsigned int rqf_last, rpf_last;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200729
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100730 /* 1a: Check for low level timeouts if needed. We just set a flag on
731 * stream interfaces when their timeouts have expired.
732 */
733 if (unlikely(t->state & TASK_WOKEN_TIMER)) {
734 stream_int_check_timeouts(&s->si[0]);
735 buffer_check_timeouts(s->req);
736 buffer_check_timeouts(s->rep);
737 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200738
Willy Tarreau86491c32008-12-14 09:04:47 +0100739 s->req->flags &= ~BF_READ_NOEXP;
740
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100741 /* copy req/rep flags so that we can detect shutdowns */
742 rqf_last = s->req->flags;
743 rpf_last = s->rep->flags;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200744
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100745 /* 1b: check for low-level errors reported at the stream interface. */
746 if (unlikely(s->si[0].flags & SI_FL_ERR)) {
747 if (s->si[0].state == SI_ST_EST || s->si[0].state == SI_ST_DIS) {
748 s->si[0].shutr(&s->si[0]);
749 s->si[0].shutw(&s->si[0]);
750 stream_int_report_error(&s->si[0]);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200751 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100752 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200753
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100754 /* check buffer timeouts, and close the corresponding stream interfaces
755 * for future reads or writes. Note: this will also concern upper layers
756 * but we do not touch any other flag. We must be careful and correctly
757 * detect state changes when calling them.
758 */
759 if (unlikely(s->req->flags & (BF_READ_TIMEOUT|BF_WRITE_TIMEOUT))) {
760 if (s->req->flags & BF_READ_TIMEOUT)
761 s->req->prod->shutr(s->req->prod);
762 if (s->req->flags & BF_WRITE_TIMEOUT)
763 s->req->cons->shutw(s->req->cons);
764 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200765
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100766 if (unlikely(s->rep->flags & (BF_READ_TIMEOUT|BF_WRITE_TIMEOUT))) {
767 if (s->rep->flags & BF_READ_TIMEOUT)
768 s->rep->prod->shutr(s->rep->prod);
769 if (s->rep->flags & BF_WRITE_TIMEOUT)
770 s->rep->cons->shutw(s->rep->cons);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200771 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200772
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100773 /* Check for connection closure */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200774
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100775 resync_stream_interface:
Willy Tarreau92fb9832007-10-16 17:34:28 +0200776
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100777 /* nothing special to be done on client side */
778 if (unlikely(s->req->prod->state == SI_ST_DIS))
779 s->req->prod->state = SI_ST_CLO;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200780
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100781 /*
782 * Note: of the transient states (REQ, CER, DIS), only REQ may remain
783 * at this point.
784 */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200785
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100786 resync_request:
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100787 /**** Process layer 7 below ****/
Willy Tarreau92fb9832007-10-16 17:34:28 +0200788
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100789 resync = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200790
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100791 /* Analyse request */
792 if ((s->req->flags & BF_MASK_ANALYSER) ||
793 (s->req->flags ^ rqf_last) & BF_MASK_STATIC) {
794 unsigned int flags = s->req->flags;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200795
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100796 if (s->req->prod->state >= SI_ST_EST) {
797 /* it's up to the analysers to reset write_ena */
798 buffer_write_ena(s->req);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200799
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100800 /* We will call all analysers for which a bit is set in
801 * s->req->analysers, following the bit order from LSB
802 * to MSB. The analysers must remove themselves from
803 * the list when not needed. This while() loop is in
804 * fact a cleaner if().
Willy Tarreau92fb9832007-10-16 17:34:28 +0200805 */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100806 while (s->req->analysers) {
807 if (s->req->analysers & AN_REQ_UNIX_STATS)
Willy Tarreau3a816292009-07-07 10:55:49 +0200808 if (!uxst_req_analyser_stats(s, s->req, AN_REQ_UNIX_STATS))
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100809 break;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200810
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100811 /* Just make sure that nobody set a wrong flag causing an endless loop */
812 s->req->analysers &= AN_REQ_UNIX_STATS;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200813
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100814 /* we don't want to loop anyway */
815 break;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200816 }
817 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100818 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
819 flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
Willy Tarreau06bea942009-03-21 22:09:29 +0100820 if ((s->req->flags ^ flags) & BF_MASK_STATIC)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100821 resync = 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200822 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200823
Willy Tarreauf890dc92008-12-13 21:12:26 +0100824 /* if noone is interested in analysing data, let's forward everything */
825 if (!s->req->analysers && !(s->req->flags & BF_HIJACK))
826 s->req->send_max = s->req->l;
827
Willy Tarreau7c84bab2009-03-08 21:38:23 +0100828 /* If noone is interested in analysing data, it's time to forward
829 * everything. We will wake up from time to time when either send_max
830 * or to_forward are reached.
Willy Tarreau6b66f3e2008-12-14 17:31:54 +0100831 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +0100832 if (!s->req->analysers &&
833 !(s->req->flags & (BF_HIJACK|BF_SHUTW)) &&
834 (s->req->prod->state >= SI_ST_EST)) {
835 /* This buffer is freewheeling, there's no analyser nor hijacker
836 * attached to it. If any data are left in, we'll permit them to
837 * move.
838 */
839 buffer_flush(s->req);
840
841 /* If the producer is still connected, we'll schedule large blocks
842 * of data to be forwarded from the producer to the consumer (which
843 * might possibly not be connected yet).
844 */
845 if (!(s->req->flags & BF_SHUTR) &&
846 s->req->to_forward < FORWARD_DEFAULT_SIZE)
Willy Tarreau0abebcc2009-01-08 00:09:41 +0100847 buffer_forward(s->req, FORWARD_DEFAULT_SIZE);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +0100848 }
849
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100850 /* reflect what the L7 analysers have seen last */
851 rqf_last = s->req->flags;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200852
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100853 /*
854 * Now forward all shutdown requests between both sides of the buffer
855 */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200856
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100857 /* first, let's check if the request buffer needs to shutdown(write) */
858 if (unlikely((s->req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
859 (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)))
860 buffer_shutw_now(s->req);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200861
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100862 /* shutdown(write) pending */
863 if (unlikely((s->req->flags & (BF_SHUTW|BF_SHUTW_NOW)) == BF_SHUTW_NOW))
864 s->req->cons->shutw(s->req->cons);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200865
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100866 /* shutdown(write) done on server side, we must stop the client too */
867 if (unlikely((s->req->flags & (BF_SHUTW|BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTW &&
868 !s->req->analysers))
869 buffer_shutr_now(s->req);
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100870
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100871 /* shutdown(read) pending */
872 if (unlikely((s->req->flags & (BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTR_NOW))
873 s->req->prod->shutr(s->req->prod);
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100874
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100875 /*
876 * Here we want to check if we need to resync or not.
877 */
878 if ((s->req->flags ^ rqf_last) & BF_MASK_STATIC)
879 resync = 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200880
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100881 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200882
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100883 /* according to benchmarks, it makes sense to resync now */
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100884 if (s->req->prod->state == SI_ST_DIS)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100885 goto resync_stream_interface;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200886
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100887 if (resync)
888 goto resync_request;
889
890 resync_response:
891 resync = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200892
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100893 /* Analyse response */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100894 if (unlikely(s->rep->flags & BF_HIJACK)) {
895 /* In inject mode, we wake up everytime something has
896 * happened on the write side of the buffer.
897 */
898 unsigned int flags = s->rep->flags;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200899
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100900 if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) &&
901 !(s->rep->flags & BF_FULL)) {
Willy Tarreau01bf8672008-12-07 18:03:29 +0100902 s->rep->hijacker(s, s->rep);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100903 }
904 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
905 flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
Willy Tarreau06bea942009-03-21 22:09:29 +0100906 if ((s->rep->flags ^ flags) & BF_MASK_STATIC)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100907 resync = 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200908 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100909 else if ((s->rep->flags & BF_MASK_ANALYSER) ||
910 (s->rep->flags ^ rpf_last) & BF_MASK_STATIC) {
911 unsigned int flags = s->rep->flags;
Willy Tarreau3e76e722007-10-17 18:57:38 +0200912
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100913 if (s->rep->prod->state >= SI_ST_EST) {
914 /* it's up to the analysers to reset write_ena */
915 buffer_write_ena(s->rep);
Willy Tarreau3e76e722007-10-17 18:57:38 +0200916 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100917 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
918 flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
Willy Tarreau06bea942009-03-21 22:09:29 +0100919 if ((s->rep->flags ^ flags) & BF_MASK_STATIC)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100920 resync = 1;
921 }
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100922
Willy Tarreau7c84bab2009-03-08 21:38:23 +0100923 /* If noone is interested in analysing data, it's time to forward
924 * everything. We will wake up from time to time when either send_max
925 * or to_forward are reached.
Willy Tarreau6b66f3e2008-12-14 17:31:54 +0100926 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +0100927 if (!s->rep->analysers &&
928 !(s->rep->flags & (BF_HIJACK|BF_SHUTW)) &&
929 (s->rep->prod->state >= SI_ST_EST)) {
930 /* This buffer is freewheeling, there's no analyser nor hijacker
931 * attached to it. If any data are left in, we'll permit them to
932 * move.
933 */
934 buffer_flush(s->rep);
935
936 /* If the producer is still connected, we'll schedule large blocks
937 * of data to be forwarded from the producer to the consumer (which
938 * might possibly not be connected yet).
939 */
940 if (!(s->rep->flags & BF_SHUTR) &&
941 s->rep->to_forward < FORWARD_DEFAULT_SIZE)
Willy Tarreau0abebcc2009-01-08 00:09:41 +0100942 buffer_forward(s->rep, FORWARD_DEFAULT_SIZE);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +0100943 }
Willy Tarreauf890dc92008-12-13 21:12:26 +0100944
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100945 /* reflect what the L7 analysers have seen last */
946 rpf_last = s->rep->flags;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100947
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100948 /*
949 * Now forward all shutdown requests between both sides of the buffer
950 */
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100951
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100952 /*
953 * FIXME: this is probably where we should produce error responses.
954 */
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100955
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100956 /* first, let's check if the request buffer needs to shutdown(write) */
957 if (unlikely((s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
958 (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)))
959 buffer_shutw_now(s->rep);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100960
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100961 /* shutdown(write) pending */
962 if (unlikely((s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW)) == BF_SHUTW_NOW))
963 s->rep->cons->shutw(s->rep->cons);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100964
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100965 /* shutdown(write) done on the client side, we must stop the server too */
966 if (unlikely((s->rep->flags & (BF_SHUTW|BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTW))
967 buffer_shutr_now(s->rep);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100968
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100969 /* shutdown(read) pending */
970 if (unlikely((s->rep->flags & (BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTR_NOW))
971 s->rep->prod->shutr(s->rep->prod);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100972
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100973 /*
974 * Here we want to check if we need to resync or not.
975 */
976 if ((s->rep->flags ^ rpf_last) & BF_MASK_STATIC)
977 resync = 1;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100978
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100979 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100980
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100981 if (s->req->prod->state == SI_ST_DIS)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100982 goto resync_stream_interface;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100983
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100984 if (s->req->flags != rqf_last)
985 goto resync_request;
986
987 if (resync)
988 goto resync_response;
989
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100990 if (likely(s->rep->cons->state != SI_ST_CLO)) {
991 if (s->rep->cons->state == SI_ST_EST)
992 stream_sock_data_finish(s->rep->cons);
Willy Tarreau3e76e722007-10-17 18:57:38 +0200993
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100994 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
995 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
996 s->si[0].prev_state = s->si[0].state;
Willy Tarreaub0ef7352008-12-14 13:26:20 +0100997 s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP);
Willy Tarreau3e76e722007-10-17 18:57:38 +0200998
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100999 /* Trick: if a request is being waiting for the server to respond,
1000 * and if we know the server can timeout, we don't want the timeout
1001 * to expire on the client side first, but we're still interested
1002 * in passing data from the client to the server (eg: POST). Thus,
1003 * we can cancel the client's request timeout if the server's
1004 * request timeout is set and the server has not yet sent a response.
1005 */
Willy Tarreau92fb9832007-10-16 17:34:28 +02001006
Willy Tarreaub1356cf2008-12-07 16:06:43 +01001007 if ((s->rep->flags & (BF_WRITE_ENA|BF_SHUTR)) == 0 &&
Willy Tarreau86491c32008-12-14 09:04:47 +01001008 (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) {
1009 s->req->flags |= BF_READ_NOEXP;
Willy Tarreaub1356cf2008-12-07 16:06:43 +01001010 s->req->rex = TICK_ETERNITY;
Willy Tarreau86491c32008-12-14 09:04:47 +01001011 }
Willy Tarreau92fb9832007-10-16 17:34:28 +02001012
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001013 t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
1014 tick_first(s->rep->rex, s->rep->wex));
Willy Tarreaub1356cf2008-12-07 16:06:43 +01001015 if (s->req->analysers)
1016 t->expire = tick_first(t->expire, s->req->analyse_exp);
1017
1018 if (s->si[0].exp)
1019 t->expire = tick_first(t->expire, s->si[0].exp);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001020
Willy Tarreau26c25062009-03-08 09:38:41 +01001021 return t;
Willy Tarreau92fb9832007-10-16 17:34:28 +02001022 }
1023
1024 actconn--;
Willy Tarreaub5654f62008-12-07 16:45:10 +01001025 if (s->listener) {
1026 s->listener->nbconn--;
1027 if (s->listener->state == LI_FULL &&
1028 s->listener->nbconn < s->listener->maxconn) {
Willy Tarreau92fb9832007-10-16 17:34:28 +02001029 /* we should reactivate the listener */
Willy Tarreaub5654f62008-12-07 16:45:10 +01001030 EV_FD_SET(s->listener->fd, DIR_RD);
1031 s->listener->state = LI_READY;
Willy Tarreau92fb9832007-10-16 17:34:28 +02001032 }
1033 }
1034
1035 /* the task MUST not be in the run queue anymore */
Willy Tarreau92fb9832007-10-16 17:34:28 +02001036 session_free(s);
Willy Tarreau26c25062009-03-08 09:38:41 +01001037 task_delete(t);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001038 task_free(t);
Willy Tarreau26c25062009-03-08 09:38:41 +01001039 return NULL;
Willy Tarreau92fb9832007-10-16 17:34:28 +02001040}
1041
Willy Tarreau92fb9832007-10-16 17:34:28 +02001042__attribute__((constructor))
1043static void __uxst_protocol_init(void)
1044{
1045 protocol_register(&proto_unix);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001046}
1047
1048
1049/*
1050 * Local variables:
1051 * c-indent-level: 8
1052 * c-basic-offset: 8
1053 * End:
1054 */