blob: 8891149526daa31c97aaada5be2e724b93960316 [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
81
82/********************************
83 * 1) low-level socket functions
84 ********************************/
85
86
Willy Tarreau92fb9832007-10-16 17:34:28 +020087/* This function creates a named PF_UNIX stream socket at address <path>. Note
Willy Tarreaue6ad2b12007-10-18 12:45:54 +020088 * that the path cannot be NULL nor empty. <uid> and <gid> different of -1 will
89 * be used to change the socket owner. If <mode> is not 0, it will be used to
90 * restrict access to the socket. While it is known not to be portable on every
91 * OS, it's still useful where it works.
Willy Tarreau92fb9832007-10-16 17:34:28 +020092 * It returns the assigned file descriptor, or -1 in the event of an error.
93 */
Willy Tarreaue6ad2b12007-10-18 12:45:54 +020094static int create_uxst_socket(const char *path, uid_t uid, gid_t gid, mode_t mode)
Willy Tarreau92fb9832007-10-16 17:34:28 +020095{
96 char tempname[MAXPATHLEN];
97 char backname[MAXPATHLEN];
98 struct sockaddr_un addr;
99
100 int ret, sock;
101
102 /* 1. create socket names */
103 if (!path[0]) {
104 Alert("Invalid name for a UNIX socket. Aborting.\n");
105 goto err_return;
106 }
107
108 ret = snprintf(tempname, MAXPATHLEN, "%s.%d.tmp", path, pid);
109 if (ret < 0 || ret >= MAXPATHLEN) {
110 Alert("name too long for UNIX socket. Aborting.\n");
111 goto err_return;
112 }
113
114 ret = snprintf(backname, MAXPATHLEN, "%s.%d.bak", path, pid);
115 if (ret < 0 || ret >= MAXPATHLEN) {
116 Alert("name too long for UNIX socket. Aborting.\n");
117 goto err_return;
118 }
119
120 /* 2. clean existing orphaned entries */
121 if (unlink(tempname) < 0 && errno != ENOENT) {
122 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
123 goto err_return;
124 }
125
126 if (unlink(backname) < 0 && errno != ENOENT) {
127 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
128 goto err_return;
129 }
130
131 /* 3. backup existing socket */
132 if (link(path, backname) < 0 && errno != ENOENT) {
133 Alert("error when trying to preserve previous UNIX socket. Aborting.\n");
134 goto err_return;
135 }
136
137 /* 4. prepare new socket */
138 addr.sun_family = AF_UNIX;
139 strncpy(addr.sun_path, tempname, sizeof(addr.sun_path));
140 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
141
142 sock = socket(PF_UNIX, SOCK_STREAM, 0);
143 if (sock < 0) {
144 Alert("cannot create socket for UNIX listener. Aborting.\n");
145 goto err_unlink_back;
146 }
147
148 if (sock >= global.maxsock) {
149 Alert("socket(): not enough free sockets for UNIX listener. Raise -n argument. Aborting.\n");
150 goto err_unlink_temp;
151 }
152
153 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
154 Alert("cannot make UNIX socket non-blocking. Aborting.\n");
155 goto err_unlink_temp;
156 }
157
158 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
159 /* note that bind() creates the socket <tempname> on the file system */
160 Alert("cannot bind socket for UNIX listener. Aborting.\n");
161 goto err_unlink_temp;
162 }
163
Willy Tarreaue6ad2b12007-10-18 12:45:54 +0200164 if (((uid != -1 || gid != -1) && (chown(tempname, uid, gid) == -1)) ||
165 (mode != 0 && chmod(tempname, mode) == -1)) {
166 Alert("cannot change UNIX socket ownership. Aborting.\n");
167 goto err_unlink_temp;
168 }
169
Willy Tarreau92fb9832007-10-16 17:34:28 +0200170 if (listen(sock, 0) < 0) {
171 Alert("cannot listen to socket for UNIX listener. Aborting.\n");
172 goto err_unlink_temp;
173 }
174
175 /* 5. install.
176 * Point of no return: we are ready, we'll switch the sockets. We don't
177 * fear loosing the socket <path> because we have a copy of it in
178 * backname.
179 */
180 if (rename(tempname, path) < 0) {
181 Alert("cannot switch final and temporary sockets for UNIX listener. Aborting.\n");
182 goto err_rename;
183 }
184
185 /* 6. cleanup */
186 unlink(backname); /* no need to keep this one either */
187
188 return sock;
189
190 err_rename:
191 ret = rename(backname, path);
192 if (ret < 0 && errno == ENOENT)
193 unlink(path);
194 err_unlink_temp:
195 unlink(tempname);
196 close(sock);
197 err_unlink_back:
198 unlink(backname);
199 err_return:
200 return -1;
201}
202
203/* Tries to destroy the UNIX stream socket <path>. The socket must not be used
204 * anymore. It practises best effort, and no error is returned.
205 */
206static void destroy_uxst_socket(const char *path)
207{
208 struct sockaddr_un addr;
209 int sock, ret;
210
211 /* We might have been chrooted, so we may not be able to access the
212 * socket. In order to avoid bothering the other end, we connect with a
213 * wrong protocol, namely SOCK_DGRAM. The return code from connect()
214 * is enough to know if the socket is still live or not. If it's live
215 * in mode SOCK_STREAM, we get EPROTOTYPE or anything else but not
216 * ECONNREFUSED. In this case, we do not touch it because it's used
217 * by some other process.
218 */
219 sock = socket(PF_UNIX, SOCK_DGRAM, 0);
220 if (sock < 0)
221 return;
222
223 addr.sun_family = AF_UNIX;
224 strncpy(addr.sun_path, path, sizeof(addr.sun_path));
Willy Tarreau10ae5482007-10-18 16:15:52 +0200225 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200226 ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
227 if (ret < 0 && errno == ECONNREFUSED) {
228 /* Connect failed: the socket still exists but is not used
229 * anymore. Let's remove this socket now.
230 */
231 unlink(path);
232 }
233 close(sock);
234}
235
236
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100237/********************************
238 * 2) listener-oriented functions
239 ********************************/
240
241
242/* This function creates the UNIX socket associated to the listener. It changes
243 * the state from ASSIGNED to LISTEN. The socket is NOT enabled for polling.
244 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
245 */
246static int uxst_bind_listener(struct listener *listener)
247{
248 int fd;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100249
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100250 if (listener->state != LI_ASSIGNED)
251 return ERR_NONE; /* already bound */
252
253 fd = create_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path,
254 listener->perm.ux.uid,
255 listener->perm.ux.gid,
256 listener->perm.ux.mode);
257 if (fd == -1)
258 return ERR_FATAL;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100259
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100260 /* the socket is now listening */
261 listener->fd = fd;
262 listener->state = LI_LISTEN;
263
264 /* the function for the accept() event */
265 fd_insert(fd);
266 fdtab[fd].cb[DIR_RD].f = listener->accept;
267 fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
268 fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
Willy Tarreaueabf3132008-08-29 23:36:51 +0200269 fdtab[fd].owner = listener; /* reference the listener instead of a task */
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100270 fdtab[fd].state = FD_STLISTEN;
271 fdtab[fd].peeraddr = NULL;
272 fdtab[fd].peerlen = 0;
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100273 return ERR_NONE;
274}
275
276/* This function closes the UNIX sockets for the specified listener.
277 * The listener enters the LI_ASSIGNED state. It always returns ERR_NONE.
278 */
279static int uxst_unbind_listener(struct listener *listener)
280{
281 if (listener->state == LI_READY)
282 EV_FD_CLR(listener->fd, DIR_RD);
283
284 if (listener->state >= LI_LISTEN) {
Willy Tarreau8eebe5e2007-10-28 22:07:08 +0100285 fd_delete(listener->fd);
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100286 listener->state = LI_ASSIGNED;
287 destroy_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path);
288 }
289 return ERR_NONE;
290}
291
292/* Add a listener to the list of unix stream listeners. The listener's state
293 * is automatically updated from LI_INIT to LI_ASSIGNED. The number of
294 * listeners is updated. This is the function to use to add a new listener.
295 */
296void uxst_add_listener(struct listener *listener)
297{
298 if (listener->state != LI_INIT)
299 return;
300 listener->state = LI_ASSIGNED;
301 listener->proto = &proto_unix;
302 LIST_ADDQ(&proto_unix.listeners, &listener->proto_list);
303 proto_unix.nb_listeners++;
304}
305
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100306/********************************
307 * 3) protocol-oriented functions
308 ********************************/
309
310
Willy Tarreau92fb9832007-10-16 17:34:28 +0200311/* This function creates all UNIX sockets bound to the protocol entry <proto>.
312 * It is intended to be used as the protocol's bind_all() function.
313 * The sockets will be registered but not added to any fd_set, in order not to
314 * loose them across the fork(). A call to uxst_enable_listeners() is needed
315 * to complete initialization.
316 *
317 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
318 */
319static int uxst_bind_listeners(struct protocol *proto)
320{
321 struct listener *listener;
322 int err = ERR_NONE;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200323
324 list_for_each_entry(listener, &proto->listeners, proto_list) {
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100325 err |= uxst_bind_listener(listener);
326 if (err != ERR_NONE)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200327 continue;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200328 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200329 return err;
330}
331
Willy Tarreau92fb9832007-10-16 17:34:28 +0200332
333/* This function stops all listening UNIX sockets bound to the protocol
334 * <proto>. It does not detaches them from the protocol.
335 * It always returns ERR_NONE.
336 */
337static int uxst_unbind_listeners(struct protocol *proto)
338{
339 struct listener *listener;
340
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100341 list_for_each_entry(listener, &proto->listeners, proto_list)
342 uxst_unbind_listener(listener);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200343 return ERR_NONE;
344}
345
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100346
347/********************************
348 * 4) high-level functions
349 ********************************/
350
351
Willy Tarreau92fb9832007-10-16 17:34:28 +0200352/*
353 * This function is called on a read event from a listen socket, corresponding
354 * to an accept. It tries to accept as many connections as possible.
355 * It returns 0. Since we use UNIX sockets on the local system for monitoring
356 * purposes and other related things, we do not need to output as many messages
357 * as with TCP which can fall under attack.
358 */
359int uxst_event_accept(int fd) {
Willy Tarreaueabf3132008-08-29 23:36:51 +0200360 struct listener *l = fdtab[fd].owner;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200361 struct session *s;
362 struct task *t;
363 int cfd;
364 int max_accept;
365
366 if (global.nbproc > 1)
367 max_accept = 8; /* let other processes catch some connections too */
368 else
369 max_accept = -1;
370
371 while (max_accept--) {
372 struct sockaddr_storage addr;
373 socklen_t laddr = sizeof(addr);
374
375 if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) == -1) {
376 switch (errno) {
377 case EAGAIN:
378 case EINTR:
379 case ECONNABORTED:
380 return 0; /* nothing more to accept */
381 case ENFILE:
382 /* Process reached system FD limit. Check system tunables. */
383 return 0;
384 case EMFILE:
385 /* Process reached process FD limit. Check 'ulimit-n'. */
386 return 0;
387 case ENOBUFS:
388 case ENOMEM:
389 /* Process reached system memory limit. Check system tunables. */
390 return 0;
391 default:
392 return 0;
393 }
394 }
395
396 if (l->nbconn >= l->maxconn) {
397 /* too many connections, we shoot this one and return.
398 * FIXME: it would be better to simply switch the listener's
399 * state to LI_FULL and disable the FD. We could re-enable
400 * it upon fd_delete(), but this requires all protocols to
401 * be switched.
402 */
Willy Tarreaua11e9762008-12-01 01:44:25 +0100403 goto out_close;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200404 }
405
406 if ((s = pool_alloc2(pool2_session)) == NULL) {
407 Alert("out of memory in uxst_event_accept().\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100408 goto out_close;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200409 }
410
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100411 LIST_ADDQ(&sessions, &s->list);
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100412 LIST_INIT(&s->back_refs);
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100413
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100414 s->flags = 0;
Willy Tarreauf8533202008-08-16 14:55:08 +0200415 s->term_trace = 0;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100416
Willy Tarreau92fb9832007-10-16 17:34:28 +0200417 if ((t = pool_alloc2(pool2_task)) == NULL) {
418 Alert("out of memory in uxst_event_accept().\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100419 goto out_free_session;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200420 }
421
422 s->cli_addr = addr;
423
424 /* FIXME: should be checked earlier */
425 if (cfd >= global.maxsock) {
426 Alert("accept(): not enough free sockets. Raise -n argument. Giving up.\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100427 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200428 }
429
430 if (fcntl(cfd, F_SETFL, O_NONBLOCK) == -1) {
431 Alert("accept(): cannot set the socket in non blocking mode. Giving up\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100432 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200433 }
434
Willy Tarreau9789f7b2008-06-24 08:17:16 +0200435 task_init(t);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200436 t->process = l->handler;
437 t->context = s;
Willy Tarreau91e99932008-06-30 07:51:00 +0200438 t->nice = -64; /* we want to boost priority for local stats */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200439
440 s->task = t;
Willy Tarreaub5654f62008-12-07 16:45:10 +0100441 s->listener = l;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200442 s->fe = NULL;
443 s->be = NULL;
444
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100445 s->ana_state = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200446 s->req = s->rep = NULL; /* will be allocated later */
447
Willy Tarreaua11e9762008-12-01 01:44:25 +0100448 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
449 s->si[0].err_type = SI_ET_NONE;
450 s->si[0].err_loc = NULL;
451 s->si[0].owner = t;
452 s->si[0].shutr = stream_sock_shutr;
453 s->si[0].shutw = stream_sock_shutw;
Willy Tarreau3ffeba12008-12-14 14:42:35 +0100454 s->si[0].chk_rcv = stream_sock_chk_rcv;
455 s->si[0].chk_snd = stream_sock_chk_snd;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100456 s->si[0].fd = cfd;
457 s->si[0].flags = SI_FL_NONE;
458 s->si[0].exp = TICK_ETERNITY;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100459
460 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
461 s->si[1].err_type = SI_ET_NONE;
462 s->si[1].err_loc = NULL;
463 s->si[1].owner = t;
464 s->si[1].shutr = stream_sock_shutr;
465 s->si[1].shutw = stream_sock_shutw;
Willy Tarreau3ffeba12008-12-14 14:42:35 +0100466 s->si[1].chk_rcv = stream_sock_chk_rcv;
467 s->si[1].chk_snd = stream_sock_chk_snd;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100468 s->si[1].exp = TICK_ETERNITY;
469 s->si[1].fd = -1; /* just to help with debugging */
470 s->si[1].flags = SI_FL_NONE;
471
472 s->srv = s->prev_srv = s->srv_conn = NULL;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200473 s->pend_pos = NULL;
474
475 memset(&s->logs, 0, sizeof(s->logs));
476 memset(&s->txn, 0, sizeof(s->txn));
477
Willy Tarreau3dfe6cd2008-12-07 22:29:48 +0100478 s->logs.tv_accept = now; /* corrected date for internal use */
479
Willy Tarreau3e76e722007-10-17 18:57:38 +0200480 s->data_state = DATA_ST_INIT;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200481 s->data_source = DATA_SRC_NONE;
482 s->uniq_id = totalconn;
483
Willy Tarreaua11e9762008-12-01 01:44:25 +0100484 if ((s->req = pool_alloc2(pool2_buffer)) == NULL)
485 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200486
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100487 buffer_init(s->req);
Willy Tarreaua11e9762008-12-01 01:44:25 +0100488 s->req->prod = &s->si[0];
489 s->req->cons = &s->si[1];
490 s->si[0].ib = s->si[1].ob = s->req;
491 s->req->flags |= BF_READ_ATTACHED; /* the producer is already connected */
492
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100493 s->req->analysers = l->analysers;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100494
495 s->req->wto = TICK_ETERNITY;
496 s->req->cto = TICK_ETERNITY;
497 s->req->rto = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200498
Willy Tarreaua11e9762008-12-01 01:44:25 +0100499 if ((s->rep = pool_alloc2(pool2_buffer)) == NULL)
500 goto out_free_req;
501
Willy Tarreau92fb9832007-10-16 17:34:28 +0200502 buffer_init(s->rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200503
Willy Tarreaua11e9762008-12-01 01:44:25 +0100504 s->rep->prod = &s->si[1];
505 s->rep->cons = &s->si[0];
506 s->si[0].ob = s->si[1].ib = s->rep;
507
508 s->rep->rto = TICK_ETERNITY;
509 s->rep->cto = TICK_ETERNITY;
510 s->rep->wto = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200511
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200512 s->req->rex = TICK_ETERNITY;
513 s->req->wex = TICK_ETERNITY;
Willy Tarreauffab5b42008-08-17 18:03:28 +0200514 s->req->analyse_exp = TICK_ETERNITY;
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200515 s->rep->rex = TICK_ETERNITY;
516 s->rep->wex = TICK_ETERNITY;
Willy Tarreauffab5b42008-08-17 18:03:28 +0200517 s->rep->analyse_exp = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200518
Willy Tarreaua11e9762008-12-01 01:44:25 +0100519 t->expire = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200520
Willy Tarreaua11e9762008-12-01 01:44:25 +0100521 if (l->timeout) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200522 s->req->rto = *l->timeout;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200523 s->rep->wto = *l->timeout;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200524 }
525
Willy Tarreaua11e9762008-12-01 01:44:25 +0100526 fd_insert(cfd);
527 fdtab[cfd].owner = &s->si[0];
Willy Tarreaua11e9762008-12-01 01:44:25 +0100528 fdtab[cfd].state = FD_STREADY;
529 fdtab[cfd].cb[DIR_RD].f = l->proto->read;
530 fdtab[cfd].cb[DIR_RD].b = s->req;
531 fdtab[cfd].cb[DIR_WR].f = l->proto->write;
532 fdtab[cfd].cb[DIR_WR].b = s->rep;
533 fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
534 fdtab[cfd].peerlen = sizeof(s->cli_addr);
535
536 EV_FD_SET(cfd, DIR_RD);
537
Willy Tarreaufdccded2008-08-29 18:19:04 +0200538 task_wakeup(t, TASK_WOKEN_INIT);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200539
540 l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
541 if (l->nbconn >= l->maxconn) {
542 EV_FD_CLR(l->fd, DIR_RD);
543 l->state = LI_FULL;
544 }
545 actconn++;
546 totalconn++;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100547 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200548 return 0;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100549
550 out_free_req:
551 pool_free2(pool2_buffer, s->req);
552 out_free_task:
553 pool_free2(pool2_task, t);
554 out_free_session:
555 LIST_DEL(&s->list);
556 pool_free2(pool2_session, s);
557 out_close:
558 close(cfd);
559 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200560}
561
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100562/* Parses the request line in <cmd> and possibly starts dumping stats on
563 * s->rep with the hijack bit set. Returns 1 if OK, 0 in case of any error.
564 * The line is modified after parsing.
Willy Tarreau92fb9832007-10-16 17:34:28 +0200565 */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100566int unix_sock_parse_request(struct session *s, char *line)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200567{
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100568 char *args[MAX_UXST_ARGS + 1];
569 int arg;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200570
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100571 while (isspace((unsigned char)*line))
572 line++;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200573
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100574 arg = 0;
575 args[arg] = line;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200576
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100577 while (*line && arg < MAX_UXST_ARGS) {
578 if (isspace((unsigned char)*line)) {
579 *line++ = '\0';
Willy Tarreau92fb9832007-10-16 17:34:28 +0200580
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100581 while (isspace((unsigned char)*line))
582 line++;
583
584 args[++arg] = line;
585 continue;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200586 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100587
588 line++;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200589 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200590
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100591 while (++arg <= MAX_UXST_ARGS)
592 args[arg] = line;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200593
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100594 if (strcmp(args[0], "show") == 0) {
595 if (strcmp(args[1], "stat") == 0) {
596 if (*args[2] && *args[3] && *args[4]) {
597 s->data_ctx.stats.flags |= STAT_BOUND;
598 s->data_ctx.stats.iid = atoi(args[2]);
599 s->data_ctx.stats.type = atoi(args[3]);
600 s->data_ctx.stats.sid = atoi(args[4]);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200601 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100602
603 s->data_ctx.stats.flags |= STAT_SHOW_STAT;
604 s->data_ctx.stats.flags |= STAT_FMT_CSV;
605 s->ana_state = STATS_ST_REP;
Willy Tarreau01bf8672008-12-07 18:03:29 +0100606 buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200607 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100608 else if (strcmp(args[1], "info") == 0) {
609 s->data_ctx.stats.flags |= STAT_SHOW_INFO;
610 s->data_ctx.stats.flags |= STAT_FMT_CSV;
611 s->ana_state = STATS_ST_REP;
Willy Tarreau01bf8672008-12-07 18:03:29 +0100612 buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100613 }
Willy Tarreau3dfe6cd2008-12-07 22:29:48 +0100614 else if (strcmp(args[1], "sess") == 0) {
615 s->ana_state = STATS_ST_REP;
616 buffer_install_hijacker(s, s->rep, stats_dump_sess_to_buffer);
617 }
Willy Tarreau74808cb2009-03-04 15:53:18 +0100618 else if (strcmp(args[1], "errors") == 0) {
619 if (*args[2])
620 s->data_ctx.errors.iid = atoi(args[2]);
621 else
622 s->data_ctx.errors.iid = -1;
623 s->data_ctx.errors.px = NULL;
624 s->ana_state = STATS_ST_REP;
625 buffer_install_hijacker(s, s->rep, stats_dump_errors_to_buffer);
626 }
Willy Tarreau3dfe6cd2008-12-07 22:29:48 +0100627 else { /* neither "stat" nor "info" nor "sess" */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100628 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200629 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100630 }
631 else { /* not "show" */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200632 return 0;
633 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100634 return 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200635}
636
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100637/* Processes the stats interpreter on the statistics socket.
638 * In order to ease the transition, we simply simulate the server status
639 * for now. It only knows states STATS_ST_INIT, STATS_ST_REQ, STATS_ST_REP, and
640 * STATS_ST_CLOSE. It removes the AN_REQ_UNIX_STATS bit from req->analysers
641 * once done. It always returns 0.
Willy Tarreau92fb9832007-10-16 17:34:28 +0200642 */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100643int uxst_req_analyser_stats(struct session *s, struct buffer *req)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200644{
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100645 char *line, *p;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200646
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100647 switch (s->ana_state) {
648 case STATS_ST_INIT:
649 /* Stats output not initialized yet */
650 memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
651 s->data_source = DATA_SRC_STATS;
652 s->ana_state = STATS_ST_REQ;
Willy Tarreau38c99bc2009-02-22 15:58:45 +0100653 buffer_write_dis(s->req);
654 buffer_shutw_now(s->req);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100655 /* fall through */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200656
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100657 case STATS_ST_REQ:
658 /* Now, stats are initialized, hijack is not set, and
659 * we are waiting for a complete request line.
660 */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200661
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100662 line = s->req->data;
663 p = memchr(line, '\n', s->req->l);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200664
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100665 if (p) {
666 *p = '\0';
667 if (!unix_sock_parse_request(s, line)) {
668 /* invalid request */
Willy Tarreau38c99bc2009-02-22 15:58:45 +0100669 buffer_shutw_now(s->rep);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100670 s->ana_state = 0;
671 req->analysers = 0;
672 return 0;
673 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200674 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200675
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100676 /* processing a valid or incomplete request */
677 if ((req->flags & BF_FULL) || /* invalid request */
678 (req->flags & BF_READ_ERROR) || /* input error */
679 (req->flags & BF_READ_TIMEOUT) || /* read timeout */
680 tick_is_expired(req->analyse_exp, now_ms) || /* request timeout */
681 (req->flags & BF_SHUTR)) { /* input closed */
Willy Tarreau38c99bc2009-02-22 15:58:45 +0100682 buffer_shutw_now(s->rep);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100683 s->ana_state = 0;
684 req->analysers = 0;
685 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200686 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100687 /* don't forward nor abort */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100688 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200689
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100690 case STATS_ST_REP:
691 /* do nothing while response is being processed */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100692 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200693
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100694 case STATS_ST_CLOSE:
695 /* end of dump */
696 s->req->analysers &= ~AN_REQ_UNIX_STATS;
697 s->ana_state = 0;
698 break;
699 }
700 return 0;
701}
Willy Tarreau92fb9832007-10-16 17:34:28 +0200702
Willy Tarreau92fb9832007-10-16 17:34:28 +0200703
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100704/* This function is the unix-stream equivalent of the global process_session().
705 * It is currently limited to unix-stream processing on control sockets such as
706 * stats, and has no server-side. The two functions should be merged into one
707 * once client and server sides are better delimited. Note that the server-side
708 * still exists but remains in SI_ST_INI state forever, so that any call is a
709 * NOP.
710 */
Willy Tarreau26c25062009-03-08 09:38:41 +0100711struct task *uxst_process_session(struct task *t)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100712{
713 struct session *s = t->context;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100714 int resync;
715 unsigned int rqf_last, rpf_last;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200716
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100717 /* 1a: Check for low level timeouts if needed. We just set a flag on
718 * stream interfaces when their timeouts have expired.
719 */
720 if (unlikely(t->state & TASK_WOKEN_TIMER)) {
721 stream_int_check_timeouts(&s->si[0]);
722 buffer_check_timeouts(s->req);
723 buffer_check_timeouts(s->rep);
724 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200725
Willy Tarreau86491c32008-12-14 09:04:47 +0100726 s->req->flags &= ~BF_READ_NOEXP;
727
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100728 /* copy req/rep flags so that we can detect shutdowns */
729 rqf_last = s->req->flags;
730 rpf_last = s->rep->flags;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200731
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100732 /* 1b: check for low-level errors reported at the stream interface. */
733 if (unlikely(s->si[0].flags & SI_FL_ERR)) {
734 if (s->si[0].state == SI_ST_EST || s->si[0].state == SI_ST_DIS) {
735 s->si[0].shutr(&s->si[0]);
736 s->si[0].shutw(&s->si[0]);
737 stream_int_report_error(&s->si[0]);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200738 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100739 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200740
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100741 /* check buffer timeouts, and close the corresponding stream interfaces
742 * for future reads or writes. Note: this will also concern upper layers
743 * but we do not touch any other flag. We must be careful and correctly
744 * detect state changes when calling them.
745 */
746 if (unlikely(s->req->flags & (BF_READ_TIMEOUT|BF_WRITE_TIMEOUT))) {
747 if (s->req->flags & BF_READ_TIMEOUT)
748 s->req->prod->shutr(s->req->prod);
749 if (s->req->flags & BF_WRITE_TIMEOUT)
750 s->req->cons->shutw(s->req->cons);
751 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200752
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100753 if (unlikely(s->rep->flags & (BF_READ_TIMEOUT|BF_WRITE_TIMEOUT))) {
754 if (s->rep->flags & BF_READ_TIMEOUT)
755 s->rep->prod->shutr(s->rep->prod);
756 if (s->rep->flags & BF_WRITE_TIMEOUT)
757 s->rep->cons->shutw(s->rep->cons);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200758 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200759
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100760 /* Check for connection closure */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200761
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100762 resync_stream_interface:
Willy Tarreau92fb9832007-10-16 17:34:28 +0200763
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100764 /* nothing special to be done on client side */
765 if (unlikely(s->req->prod->state == SI_ST_DIS))
766 s->req->prod->state = SI_ST_CLO;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200767
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100768 /*
769 * Note: of the transient states (REQ, CER, DIS), only REQ may remain
770 * at this point.
771 */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200772
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100773 resync_request:
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100774 /**** Process layer 7 below ****/
Willy Tarreau92fb9832007-10-16 17:34:28 +0200775
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100776 resync = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200777
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100778 /* Analyse request */
779 if ((s->req->flags & BF_MASK_ANALYSER) ||
780 (s->req->flags ^ rqf_last) & BF_MASK_STATIC) {
781 unsigned int flags = s->req->flags;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200782
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100783 if (s->req->prod->state >= SI_ST_EST) {
784 /* it's up to the analysers to reset write_ena */
785 buffer_write_ena(s->req);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200786
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100787 /* We will call all analysers for which a bit is set in
788 * s->req->analysers, following the bit order from LSB
789 * to MSB. The analysers must remove themselves from
790 * the list when not needed. This while() loop is in
791 * fact a cleaner if().
Willy Tarreau92fb9832007-10-16 17:34:28 +0200792 */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100793 while (s->req->analysers) {
794 if (s->req->analysers & AN_REQ_UNIX_STATS)
795 if (!uxst_req_analyser_stats(s, s->req))
796 break;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200797
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100798 /* Just make sure that nobody set a wrong flag causing an endless loop */
799 s->req->analysers &= AN_REQ_UNIX_STATS;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200800
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100801 /* we don't want to loop anyway */
802 break;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200803 }
804 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100805 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
806 flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
807 if (s->req->flags != flags)
808 resync = 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200809 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200810
Willy Tarreauf890dc92008-12-13 21:12:26 +0100811 /* if noone is interested in analysing data, let's forward everything */
812 if (!s->req->analysers && !(s->req->flags & BF_HIJACK))
813 s->req->send_max = s->req->l;
814
Willy Tarreau6b66f3e2008-12-14 17:31:54 +0100815 /* if noone is interested in analysing data, let's forward everything
816 * and only wake up every 1-2 MB. We still wake up when send_max is
817 * reached though.
818 */
819 if (!s->req->send_max && s->req->prod->state >= SI_ST_EST &&
820 !s->req->analysers && !(s->req->flags & BF_HIJACK)) {
821 if (s->req->to_forward < FORWARD_DEFAULT_SIZE)
Willy Tarreau0abebcc2009-01-08 00:09:41 +0100822 buffer_forward(s->req, FORWARD_DEFAULT_SIZE);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +0100823 }
824
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100825 /* reflect what the L7 analysers have seen last */
826 rqf_last = s->req->flags;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200827
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100828 /*
829 * Now forward all shutdown requests between both sides of the buffer
830 */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200831
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100832 /* first, let's check if the request buffer needs to shutdown(write) */
833 if (unlikely((s->req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
834 (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)))
835 buffer_shutw_now(s->req);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200836
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100837 /* shutdown(write) pending */
838 if (unlikely((s->req->flags & (BF_SHUTW|BF_SHUTW_NOW)) == BF_SHUTW_NOW))
839 s->req->cons->shutw(s->req->cons);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200840
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100841 /* shutdown(write) done on server side, we must stop the client too */
842 if (unlikely((s->req->flags & (BF_SHUTW|BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTW &&
843 !s->req->analysers))
844 buffer_shutr_now(s->req);
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100845
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100846 /* shutdown(read) pending */
847 if (unlikely((s->req->flags & (BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTR_NOW))
848 s->req->prod->shutr(s->req->prod);
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100849
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100850 /*
851 * Here we want to check if we need to resync or not.
852 */
853 if ((s->req->flags ^ rqf_last) & BF_MASK_STATIC)
854 resync = 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200855
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100856 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200857
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100858 /* according to benchmarks, it makes sense to resync now */
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100859 if (s->req->prod->state == SI_ST_DIS)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100860 goto resync_stream_interface;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200861
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100862 if (resync)
863 goto resync_request;
864
865 resync_response:
866 resync = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200867
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100868 /* Analyse response */
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100869 if (unlikely(s->rep->flags & BF_HIJACK)) {
870 /* In inject mode, we wake up everytime something has
871 * happened on the write side of the buffer.
872 */
873 unsigned int flags = s->rep->flags;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200874
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100875 if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) &&
876 !(s->rep->flags & BF_FULL)) {
Willy Tarreau01bf8672008-12-07 18:03:29 +0100877 s->rep->hijacker(s, s->rep);
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100878 }
879 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
880 flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
881 if (s->rep->flags != flags)
882 resync = 1;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200883 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100884 else if ((s->rep->flags & BF_MASK_ANALYSER) ||
885 (s->rep->flags ^ rpf_last) & BF_MASK_STATIC) {
886 unsigned int flags = s->rep->flags;
Willy Tarreau3e76e722007-10-17 18:57:38 +0200887
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100888 if (s->rep->prod->state >= SI_ST_EST) {
889 /* it's up to the analysers to reset write_ena */
890 buffer_write_ena(s->rep);
Willy Tarreau3e76e722007-10-17 18:57:38 +0200891 }
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100892 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
893 flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
894 if (s->rep->flags != flags)
895 resync = 1;
896 }
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100897
Willy Tarreau6b66f3e2008-12-14 17:31:54 +0100898 /* if noone is interested in analysing data, let's forward everything
899 * and only wake up every 1-2 MB. We still wake up when send_max is
900 * reached though.
901 */
902 if (!s->rep->send_max && s->rep->prod->state >= SI_ST_EST &&
903 !s->rep->analysers && !(s->rep->flags & BF_HIJACK)) {
Willy Tarreau0abebcc2009-01-08 00:09:41 +0100904 if (s->rep->to_forward < FORWARD_DEFAULT_SIZE)
905 buffer_forward(s->rep, FORWARD_DEFAULT_SIZE);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +0100906 }
Willy Tarreauf890dc92008-12-13 21:12:26 +0100907
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100908 /* reflect what the L7 analysers have seen last */
909 rpf_last = s->rep->flags;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100910
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100911 /*
912 * Now forward all shutdown requests between both sides of the buffer
913 */
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100914
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100915 /*
916 * FIXME: this is probably where we should produce error responses.
917 */
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100918
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100919 /* first, let's check if the request buffer needs to shutdown(write) */
920 if (unlikely((s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
921 (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)))
922 buffer_shutw_now(s->rep);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100923
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100924 /* shutdown(write) pending */
925 if (unlikely((s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW)) == BF_SHUTW_NOW))
926 s->rep->cons->shutw(s->rep->cons);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100927
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100928 /* shutdown(write) done on the client side, we must stop the server too */
929 if (unlikely((s->rep->flags & (BF_SHUTW|BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTW))
930 buffer_shutr_now(s->rep);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100931
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100932 /* shutdown(read) pending */
933 if (unlikely((s->rep->flags & (BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTR_NOW))
934 s->rep->prod->shutr(s->rep->prod);
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100935
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100936 /*
937 * Here we want to check if we need to resync or not.
938 */
939 if ((s->rep->flags ^ rpf_last) & BF_MASK_STATIC)
940 resync = 1;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100941
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100942 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100943
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100944 if (s->req->prod->state == SI_ST_DIS)
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100945 goto resync_stream_interface;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100946
Willy Tarreau0be0ef92009-03-08 19:20:25 +0100947 if (s->req->flags != rqf_last)
948 goto resync_request;
949
950 if (resync)
951 goto resync_response;
952
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100953 if (likely(s->rep->cons->state != SI_ST_CLO)) {
954 if (s->rep->cons->state == SI_ST_EST)
955 stream_sock_data_finish(s->rep->cons);
Willy Tarreau3e76e722007-10-17 18:57:38 +0200956
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100957 s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
958 s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
959 s->si[0].prev_state = s->si[0].state;
Willy Tarreaub0ef7352008-12-14 13:26:20 +0100960 s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP);
Willy Tarreau3e76e722007-10-17 18:57:38 +0200961
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100962 /* Trick: if a request is being waiting for the server to respond,
963 * and if we know the server can timeout, we don't want the timeout
964 * to expire on the client side first, but we're still interested
965 * in passing data from the client to the server (eg: POST). Thus,
966 * we can cancel the client's request timeout if the server's
967 * request timeout is set and the server has not yet sent a response.
968 */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200969
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100970 if ((s->rep->flags & (BF_WRITE_ENA|BF_SHUTR)) == 0 &&
Willy Tarreau86491c32008-12-14 09:04:47 +0100971 (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) {
972 s->req->flags |= BF_READ_NOEXP;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100973 s->req->rex = TICK_ETERNITY;
Willy Tarreau86491c32008-12-14 09:04:47 +0100974 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200975
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200976 t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
977 tick_first(s->rep->rex, s->rep->wex));
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100978 if (s->req->analysers)
979 t->expire = tick_first(t->expire, s->req->analyse_exp);
980
981 if (s->si[0].exp)
982 t->expire = tick_first(t->expire, s->si[0].exp);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200983
Willy Tarreau26c25062009-03-08 09:38:41 +0100984 return t;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200985 }
986
987 actconn--;
Willy Tarreaub5654f62008-12-07 16:45:10 +0100988 if (s->listener) {
989 s->listener->nbconn--;
990 if (s->listener->state == LI_FULL &&
991 s->listener->nbconn < s->listener->maxconn) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200992 /* we should reactivate the listener */
Willy Tarreaub5654f62008-12-07 16:45:10 +0100993 EV_FD_SET(s->listener->fd, DIR_RD);
994 s->listener->state = LI_READY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200995 }
996 }
997
998 /* the task MUST not be in the run queue anymore */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200999 session_free(s);
Willy Tarreau26c25062009-03-08 09:38:41 +01001000 task_delete(t);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001001 task_free(t);
Willy Tarreau26c25062009-03-08 09:38:41 +01001002 return NULL;
Willy Tarreau92fb9832007-10-16 17:34:28 +02001003}
1004
Willy Tarreau92fb9832007-10-16 17:34:28 +02001005__attribute__((constructor))
1006static void __uxst_protocol_init(void)
1007{
1008 protocol_register(&proto_unix);
Willy Tarreau92fb9832007-10-16 17:34:28 +02001009}
1010
1011
1012/*
1013 * Local variables:
1014 * c-indent-level: 8
1015 * c-basic-offset: 8
1016 * End:
1017 */