blob: 84a38c6aa4d86ce7c746ba0e5b13c1aa2c8527f9 [file] [log] [blame]
Willy Tarreau92fb9832007-10-16 17:34:28 +02001/*
2 * UNIX SOCK_STREAM protocol layer (uxst)
3 *
Willy Tarreau2c9f5b12009-08-16 19:12:36 +02004 * Copyright 2000-2009 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 Tarreau9a42c0d2009-09-22 19:31:03 +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 Tarreaudabf2e22007-10-28 21:59:24 +010081/********************************
82 * 1) low-level socket functions
83 ********************************/
84
85
Willy Tarreau92fb9832007-10-16 17:34:28 +020086/* This function creates a named PF_UNIX stream socket at address <path>. Note
Willy Tarreaue6ad2b12007-10-18 12:45:54 +020087 * that the path cannot be NULL nor empty. <uid> and <gid> different of -1 will
88 * be used to change the socket owner. If <mode> is not 0, it will be used to
89 * restrict access to the socket. While it is known not to be portable on every
90 * OS, it's still useful where it works.
Willy Tarreau92fb9832007-10-16 17:34:28 +020091 * It returns the assigned file descriptor, or -1 in the event of an error.
92 */
Willy Tarreaue6ad2b12007-10-18 12:45:54 +020093static int create_uxst_socket(const char *path, uid_t uid, gid_t gid, mode_t mode)
Willy Tarreau92fb9832007-10-16 17:34:28 +020094{
95 char tempname[MAXPATHLEN];
96 char backname[MAXPATHLEN];
97 struct sockaddr_un addr;
98
99 int ret, sock;
100
101 /* 1. create socket names */
102 if (!path[0]) {
103 Alert("Invalid name for a UNIX socket. Aborting.\n");
104 goto err_return;
105 }
106
107 ret = snprintf(tempname, MAXPATHLEN, "%s.%d.tmp", path, pid);
108 if (ret < 0 || ret >= MAXPATHLEN) {
109 Alert("name too long for UNIX socket. Aborting.\n");
110 goto err_return;
111 }
112
113 ret = snprintf(backname, MAXPATHLEN, "%s.%d.bak", path, pid);
114 if (ret < 0 || ret >= MAXPATHLEN) {
115 Alert("name too long for UNIX socket. Aborting.\n");
116 goto err_return;
117 }
118
119 /* 2. clean existing orphaned entries */
120 if (unlink(tempname) < 0 && errno != ENOENT) {
121 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
122 goto err_return;
123 }
124
125 if (unlink(backname) < 0 && errno != ENOENT) {
126 Alert("error when trying to unlink previous UNIX socket. Aborting.\n");
127 goto err_return;
128 }
129
130 /* 3. backup existing socket */
131 if (link(path, backname) < 0 && errno != ENOENT) {
132 Alert("error when trying to preserve previous UNIX socket. Aborting.\n");
133 goto err_return;
134 }
135
136 /* 4. prepare new socket */
137 addr.sun_family = AF_UNIX;
138 strncpy(addr.sun_path, tempname, sizeof(addr.sun_path));
139 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
140
141 sock = socket(PF_UNIX, SOCK_STREAM, 0);
142 if (sock < 0) {
143 Alert("cannot create socket for UNIX listener. Aborting.\n");
144 goto err_unlink_back;
145 }
146
147 if (sock >= global.maxsock) {
148 Alert("socket(): not enough free sockets for UNIX listener. Raise -n argument. Aborting.\n");
149 goto err_unlink_temp;
150 }
151
152 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
153 Alert("cannot make UNIX socket non-blocking. Aborting.\n");
154 goto err_unlink_temp;
155 }
156
157 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
158 /* note that bind() creates the socket <tempname> on the file system */
159 Alert("cannot bind socket for UNIX listener. Aborting.\n");
160 goto err_unlink_temp;
161 }
162
Willy Tarreaue6ad2b12007-10-18 12:45:54 +0200163 if (((uid != -1 || gid != -1) && (chown(tempname, uid, gid) == -1)) ||
164 (mode != 0 && chmod(tempname, mode) == -1)) {
165 Alert("cannot change UNIX socket ownership. Aborting.\n");
166 goto err_unlink_temp;
167 }
168
Willy Tarreau92fb9832007-10-16 17:34:28 +0200169 if (listen(sock, 0) < 0) {
170 Alert("cannot listen to socket for UNIX listener. Aborting.\n");
171 goto err_unlink_temp;
172 }
173
174 /* 5. install.
175 * Point of no return: we are ready, we'll switch the sockets. We don't
176 * fear loosing the socket <path> because we have a copy of it in
177 * backname.
178 */
179 if (rename(tempname, path) < 0) {
180 Alert("cannot switch final and temporary sockets for UNIX listener. Aborting.\n");
181 goto err_rename;
182 }
183
184 /* 6. cleanup */
185 unlink(backname); /* no need to keep this one either */
186
187 return sock;
188
189 err_rename:
190 ret = rename(backname, path);
191 if (ret < 0 && errno == ENOENT)
192 unlink(path);
193 err_unlink_temp:
194 unlink(tempname);
195 close(sock);
196 err_unlink_back:
197 unlink(backname);
198 err_return:
199 return -1;
200}
201
202/* Tries to destroy the UNIX stream socket <path>. The socket must not be used
203 * anymore. It practises best effort, and no error is returned.
204 */
205static void destroy_uxst_socket(const char *path)
206{
207 struct sockaddr_un addr;
208 int sock, ret;
209
210 /* We might have been chrooted, so we may not be able to access the
211 * socket. In order to avoid bothering the other end, we connect with a
212 * wrong protocol, namely SOCK_DGRAM. The return code from connect()
213 * is enough to know if the socket is still live or not. If it's live
214 * in mode SOCK_STREAM, we get EPROTOTYPE or anything else but not
215 * ECONNREFUSED. In this case, we do not touch it because it's used
216 * by some other process.
217 */
218 sock = socket(PF_UNIX, SOCK_DGRAM, 0);
219 if (sock < 0)
220 return;
221
222 addr.sun_family = AF_UNIX;
223 strncpy(addr.sun_path, path, sizeof(addr.sun_path));
Willy Tarreau10ae5482007-10-18 16:15:52 +0200224 addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200225 ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
226 if (ret < 0 && errno == ECONNREFUSED) {
227 /* Connect failed: the socket still exists but is not used
228 * anymore. Let's remove this socket now.
229 */
230 unlink(path);
231 }
232 close(sock);
233}
234
235
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100236/********************************
237 * 2) listener-oriented functions
238 ********************************/
239
240
241/* This function creates the UNIX socket associated to the listener. It changes
242 * the state from ASSIGNED to LISTEN. The socket is NOT enabled for polling.
243 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
244 */
245static int uxst_bind_listener(struct listener *listener)
246{
247 int fd;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100248
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100249 if (listener->state != LI_ASSIGNED)
250 return ERR_NONE; /* already bound */
251
252 fd = create_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path,
253 listener->perm.ux.uid,
254 listener->perm.ux.gid,
255 listener->perm.ux.mode);
256 if (fd == -1)
257 return ERR_FATAL;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100258
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100259 /* the socket is now listening */
260 listener->fd = fd;
261 listener->state = LI_LISTEN;
262
263 /* the function for the accept() event */
264 fd_insert(fd);
265 fdtab[fd].cb[DIR_RD].f = listener->accept;
266 fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
267 fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
Willy Tarreaueabf3132008-08-29 23:36:51 +0200268 fdtab[fd].owner = listener; /* reference the listener instead of a task */
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100269 fdtab[fd].state = FD_STLISTEN;
270 fdtab[fd].peeraddr = NULL;
271 fdtab[fd].peerlen = 0;
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100272 return ERR_NONE;
273}
274
275/* This function closes the UNIX sockets for the specified listener.
276 * The listener enters the LI_ASSIGNED state. It always returns ERR_NONE.
277 */
278static int uxst_unbind_listener(struct listener *listener)
279{
280 if (listener->state == LI_READY)
281 EV_FD_CLR(listener->fd, DIR_RD);
282
283 if (listener->state >= LI_LISTEN) {
Willy Tarreau8eebe5e2007-10-28 22:07:08 +0100284 fd_delete(listener->fd);
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100285 listener->state = LI_ASSIGNED;
286 destroy_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path);
287 }
288 return ERR_NONE;
289}
290
291/* Add a listener to the list of unix stream listeners. The listener's state
292 * is automatically updated from LI_INIT to LI_ASSIGNED. The number of
293 * listeners is updated. This is the function to use to add a new listener.
294 */
295void uxst_add_listener(struct listener *listener)
296{
297 if (listener->state != LI_INIT)
298 return;
299 listener->state = LI_ASSIGNED;
300 listener->proto = &proto_unix;
301 LIST_ADDQ(&proto_unix.listeners, &listener->proto_list);
302 proto_unix.nb_listeners++;
303}
304
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100305/********************************
306 * 3) protocol-oriented functions
307 ********************************/
308
309
Willy Tarreau92fb9832007-10-16 17:34:28 +0200310/* This function creates all UNIX sockets bound to the protocol entry <proto>.
311 * It is intended to be used as the protocol's bind_all() function.
312 * The sockets will be registered but not added to any fd_set, in order not to
313 * loose them across the fork(). A call to uxst_enable_listeners() is needed
314 * to complete initialization.
315 *
316 * The return value is composed from ERR_NONE, ERR_RETRYABLE and ERR_FATAL.
317 */
318static int uxst_bind_listeners(struct protocol *proto)
319{
320 struct listener *listener;
321 int err = ERR_NONE;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200322
323 list_for_each_entry(listener, &proto->listeners, proto_list) {
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100324 err |= uxst_bind_listener(listener);
325 if (err != ERR_NONE)
Willy Tarreau92fb9832007-10-16 17:34:28 +0200326 continue;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200327 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200328 return err;
329}
330
Willy Tarreau92fb9832007-10-16 17:34:28 +0200331
332/* This function stops all listening UNIX sockets bound to the protocol
333 * <proto>. It does not detaches them from the protocol.
334 * It always returns ERR_NONE.
335 */
336static int uxst_unbind_listeners(struct protocol *proto)
337{
338 struct listener *listener;
339
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100340 list_for_each_entry(listener, &proto->listeners, proto_list)
341 uxst_unbind_listener(listener);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200342 return ERR_NONE;
343}
344
Willy Tarreaudabf2e22007-10-28 21:59:24 +0100345
346/********************************
347 * 4) high-level functions
348 ********************************/
349
350
Willy Tarreau92fb9832007-10-16 17:34:28 +0200351/*
352 * This function is called on a read event from a listen socket, corresponding
353 * to an accept. It tries to accept as many connections as possible.
354 * It returns 0. Since we use UNIX sockets on the local system for monitoring
355 * purposes and other related things, we do not need to output as many messages
356 * as with TCP which can fall under attack.
357 */
358int uxst_event_accept(int fd) {
Willy Tarreaueabf3132008-08-29 23:36:51 +0200359 struct listener *l = fdtab[fd].owner;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200360 struct session *s;
361 struct task *t;
362 int cfd;
363 int max_accept;
364
365 if (global.nbproc > 1)
366 max_accept = 8; /* let other processes catch some connections too */
367 else
368 max_accept = -1;
369
Willy Tarreau2d045592009-03-28 11:02:18 +0100370 while (max_accept--) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200371 struct sockaddr_storage addr;
372 socklen_t laddr = sizeof(addr);
373
374 if ((cfd = accept(fd, (struct sockaddr *)&addr, &laddr)) == -1) {
375 switch (errno) {
376 case EAGAIN:
377 case EINTR:
378 case ECONNABORTED:
379 return 0; /* nothing more to accept */
380 case ENFILE:
381 /* Process reached system FD limit. Check system tunables. */
382 return 0;
383 case EMFILE:
384 /* Process reached process FD limit. Check 'ulimit-n'. */
385 return 0;
386 case ENOBUFS:
387 case ENOMEM:
388 /* Process reached system memory limit. Check system tunables. */
389 return 0;
390 default:
391 return 0;
392 }
393 }
394
Willy Tarreau2d045592009-03-28 11:02:18 +0100395 if (l->nbconn >= l->maxconn || actconn >= global.maxconn) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200396 /* too many connections, we shoot this one and return.
397 * FIXME: it would be better to simply switch the listener's
398 * state to LI_FULL and disable the FD. We could re-enable
399 * it upon fd_delete(), but this requires all protocols to
400 * be switched.
401 */
Willy Tarreaua11e9762008-12-01 01:44:25 +0100402 goto out_close;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200403 }
404
405 if ((s = pool_alloc2(pool2_session)) == NULL) {
406 Alert("out of memory in uxst_event_accept().\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100407 goto out_close;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200408 }
409
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100410 LIST_ADDQ(&sessions, &s->list);
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100411 LIST_INIT(&s->back_refs);
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100412
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100413 s->flags = 0;
Willy Tarreauf8533202008-08-16 14:55:08 +0200414 s->term_trace = 0;
Krzysztof Piotr Oledzki2c6962c2008-03-02 02:42:14 +0100415
Willy Tarreaua4613182009-03-21 18:13:21 +0100416 if ((t = task_new()) == NULL) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200417 Alert("out of memory in uxst_event_accept().\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100418 goto out_free_session;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200419 }
420
421 s->cli_addr = addr;
422
423 /* FIXME: should be checked earlier */
424 if (cfd >= global.maxsock) {
425 Alert("accept(): not enough free sockets. Raise -n argument. Giving up.\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100426 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200427 }
428
429 if (fcntl(cfd, F_SETFL, O_NONBLOCK) == -1) {
430 Alert("accept(): cannot set the socket in non blocking mode. Giving up\n");
Willy Tarreaua11e9762008-12-01 01:44:25 +0100431 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200432 }
433
Willy Tarreau92fb9832007-10-16 17:34:28 +0200434 t->process = l->handler;
435 t->context = s;
Willy Tarreau2c9f5b12009-08-16 19:12:36 +0200436 t->nice = l->nice;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200437
438 s->task = t;
Willy Tarreaub5654f62008-12-07 16:45:10 +0100439 s->listener = l;
Willy Tarreau89a63132009-08-16 17:41:45 +0200440 s->fe = s->be = l->private;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200441
Willy Tarreau92fb9832007-10-16 17:34:28 +0200442 s->req = s->rep = NULL; /* will be allocated later */
443
Willy Tarreaua11e9762008-12-01 01:44:25 +0100444 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
445 s->si[0].err_type = SI_ET_NONE;
446 s->si[0].err_loc = NULL;
447 s->si[0].owner = t;
Willy Tarreaudc85b392009-08-18 07:38:19 +0200448 s->si[0].update = stream_sock_data_finish;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100449 s->si[0].shutr = stream_sock_shutr;
450 s->si[0].shutw = stream_sock_shutw;
Willy Tarreau3ffeba12008-12-14 14:42:35 +0100451 s->si[0].chk_rcv = stream_sock_chk_rcv;
452 s->si[0].chk_snd = stream_sock_chk_snd;
Willy Tarreaudc85b392009-08-18 07:38:19 +0200453 s->si[0].connect = NULL;
Willy Tarreaub029f8c2009-09-05 20:57:35 +0200454 s->si[0].iohandler = NULL;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100455 s->si[0].fd = cfd;
456 s->si[0].flags = SI_FL_NONE;
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200457 if (s->fe->options2 & PR_O2_INDEPSTR)
458 s->si[0].flags |= SI_FL_INDEP_STR;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100459 s->si[0].exp = TICK_ETERNITY;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100460
461 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
462 s->si[1].err_type = SI_ET_NONE;
463 s->si[1].err_loc = NULL;
464 s->si[1].owner = t;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100465 s->si[1].exp = TICK_ETERNITY;
466 s->si[1].fd = -1; /* just to help with debugging */
467 s->si[1].flags = SI_FL_NONE;
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200468 if (s->be->options2 & PR_O2_INDEPSTR)
469 s->si[1].flags |= SI_FL_INDEP_STR;
470
Willy Tarreau9a42c0d2009-09-22 19:31:03 +0200471 stream_int_register_handler(&s->si[1], stats_io_handler);
472 s->si[1].private = s;
Willy Tarreauf5a885f2009-10-04 14:22:18 +0200473 s->si[1].st1 = 0;
474 s->si[1].st0 = STAT_CLI_INIT;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100475
476 s->srv = s->prev_srv = s->srv_conn = NULL;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200477 s->pend_pos = NULL;
478
479 memset(&s->logs, 0, sizeof(s->logs));
480 memset(&s->txn, 0, sizeof(s->txn));
481
Willy Tarreau3dfe6cd2008-12-07 22:29:48 +0100482 s->logs.tv_accept = now; /* corrected date for internal use */
483
Willy Tarreau3e76e722007-10-17 18:57:38 +0200484 s->data_state = DATA_ST_INIT;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200485 s->data_source = DATA_SRC_NONE;
486 s->uniq_id = totalconn;
487
Willy Tarreaua11e9762008-12-01 01:44:25 +0100488 if ((s->req = pool_alloc2(pool2_buffer)) == NULL)
489 goto out_free_task;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200490
Willy Tarreau27a674e2009-08-17 07:23:33 +0200491 s->req->size = global.tune.bufsize;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100492 buffer_init(s->req);
Willy Tarreaua11e9762008-12-01 01:44:25 +0100493 s->req->prod = &s->si[0];
494 s->req->cons = &s->si[1];
495 s->si[0].ib = s->si[1].ob = s->req;
496 s->req->flags |= BF_READ_ATTACHED; /* the producer is already connected */
Willy Tarreau1b194fe2009-03-21 21:10:04 +0100497 s->req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
Willy Tarreaua11e9762008-12-01 01:44:25 +0100498
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100499 s->req->analysers = l->analysers;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100500
501 s->req->wto = TICK_ETERNITY;
502 s->req->cto = TICK_ETERNITY;
503 s->req->rto = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200504
Willy Tarreaua11e9762008-12-01 01:44:25 +0100505 if ((s->rep = pool_alloc2(pool2_buffer)) == NULL)
506 goto out_free_req;
507
Willy Tarreau27a674e2009-08-17 07:23:33 +0200508 s->rep->size = global.tune.bufsize;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200509 buffer_init(s->rep);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200510
Willy Tarreaua11e9762008-12-01 01:44:25 +0100511 s->rep->prod = &s->si[1];
512 s->rep->cons = &s->si[0];
513 s->si[0].ob = s->si[1].ib = s->rep;
514
515 s->rep->rto = TICK_ETERNITY;
516 s->rep->cto = TICK_ETERNITY;
517 s->rep->wto = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200518
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200519 s->req->rex = TICK_ETERNITY;
520 s->req->wex = TICK_ETERNITY;
Willy Tarreauffab5b42008-08-17 18:03:28 +0200521 s->req->analyse_exp = TICK_ETERNITY;
Willy Tarreau0c303ee2008-07-07 00:09:58 +0200522 s->rep->rex = TICK_ETERNITY;
523 s->rep->wex = TICK_ETERNITY;
Willy Tarreauffab5b42008-08-17 18:03:28 +0200524 s->rep->analyse_exp = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200525
Willy Tarreaua11e9762008-12-01 01:44:25 +0100526 t->expire = TICK_ETERNITY;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200527
Willy Tarreaua11e9762008-12-01 01:44:25 +0100528 if (l->timeout) {
Willy Tarreau92fb9832007-10-16 17:34:28 +0200529 s->req->rto = *l->timeout;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200530 s->rep->wto = *l->timeout;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200531 }
532
Willy Tarreaua11e9762008-12-01 01:44:25 +0100533 fd_insert(cfd);
534 fdtab[cfd].owner = &s->si[0];
Willy Tarreaua11e9762008-12-01 01:44:25 +0100535 fdtab[cfd].state = FD_STREADY;
536 fdtab[cfd].cb[DIR_RD].f = l->proto->read;
537 fdtab[cfd].cb[DIR_RD].b = s->req;
538 fdtab[cfd].cb[DIR_WR].f = l->proto->write;
539 fdtab[cfd].cb[DIR_WR].b = s->rep;
540 fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
541 fdtab[cfd].peerlen = sizeof(s->cli_addr);
542
543 EV_FD_SET(cfd, DIR_RD);
544
Willy Tarreaufdccded2008-08-29 18:19:04 +0200545 task_wakeup(t, TASK_WOKEN_INIT);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200546
547 l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
548 if (l->nbconn >= l->maxconn) {
549 EV_FD_CLR(l->fd, DIR_RD);
550 l->state = LI_FULL;
551 }
552 actconn++;
553 totalconn++;
Willy Tarreaub1356cf2008-12-07 16:06:43 +0100554 }
Willy Tarreau92fb9832007-10-16 17:34:28 +0200555 return 0;
Willy Tarreaua11e9762008-12-01 01:44:25 +0100556
557 out_free_req:
558 pool_free2(pool2_buffer, s->req);
559 out_free_task:
Willy Tarreaua4613182009-03-21 18:13:21 +0100560 task_free(t);
Willy Tarreaua11e9762008-12-01 01:44:25 +0100561 out_free_session:
562 LIST_DEL(&s->list);
563 pool_free2(pool2_session, s);
564 out_close:
565 close(cfd);
566 return 0;
Willy Tarreau92fb9832007-10-16 17:34:28 +0200567}
568
Willy Tarreau92fb9832007-10-16 17:34:28 +0200569__attribute__((constructor))
570static void __uxst_protocol_init(void)
571{
572 protocol_register(&proto_unix);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200573}
574
575
576/*
577 * Local variables:
578 * c-indent-level: 8
579 * c-basic-offset: 8
580 * End:
581 */