varnish-cache/bin/varnishtest/vtc_server.c
1
/*-
2
 * Copyright (c) 2008-2010 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include "config.h"
30
31
#include <sys/socket.h>
32
#include <sys/types.h>
33
#include <sys/stat.h>
34
35
#include <errno.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
41
#include "vtc.h"
42
43
#include "vtcp.h"
44
#include "vus.h"
45
46
struct server {
47
        unsigned                magic;
48
#define SERVER_MAGIC            0x55286619
49
        char                    *name;
50
        struct vtclog           *vl;
51
        VTAILQ_ENTRY(server)    list;
52
        char                    run;
53
54
        unsigned                repeat;
55
        unsigned                keepalive;
56
        char                    *spec;
57
58
        int                     depth;
59
        int                     sock;
60
        int                     fd;
61
        char                    listen[256];
62
        char                    aaddr[32];
63
        char                    aport[32];
64
65
        pthread_t               tp;
66
};
67
68
static pthread_mutex_t          server_mtx;
69
70
static VTAILQ_HEAD(, server)    servers =
71
    VTAILQ_HEAD_INITIALIZER(servers);
72
73
/**********************************************************************
74
 * Allocate and initialize a server
75
 */
76
77
static struct server *
78 1613
server_new(const char *name, struct vtclog *vl)
79
{
80
        struct server *s;
81
82 1613
        VTC_CHECK_NAME(vl, name, "Server", 's');
83 1613
        ALLOC_OBJ(s, SERVER_MAGIC);
84 1613
        AN(s);
85 1613
        REPLACE(s->name, name);
86 1613
        s->vl = vtc_logopen(s->name);
87 1613
        AN(s->vl);
88
89 1613
        bprintf(s->listen, "%s", "127.0.0.1 0");
90 1613
        s->repeat = 1;
91 1613
        s->depth = 10;
92 1613
        s->sock = -1;
93 1613
        s->fd = -1;
94 1613
        AZ(pthread_mutex_lock(&server_mtx));
95 1613
        VTAILQ_INSERT_TAIL(&servers, s, list);
96 1613
        AZ(pthread_mutex_unlock(&server_mtx));
97 1613
        return (s);
98
}
99
100
/**********************************************************************
101
 * Clean up a server
102
 */
103
104
static void
105 1613
server_delete(struct server *s)
106
{
107
108 1613
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
109 1613
        macro_undef(s->vl, s->name, "addr");
110 1613
        macro_undef(s->vl, s->name, "port");
111 1613
        macro_undef(s->vl, s->name, "sock");
112 1613
        vtc_logclose(s->vl);
113 1613
        free(s->name);
114
        /* XXX: MEMLEAK (?) (VSS ??) */
115 1613
        FREE_OBJ(s);
116 1613
}
117
118
/**********************************************************************
119
 * Server listen
120
 */
121
122
struct helper {
123
        int             depth;
124
        const char      **errp;
125
};
126
127
/* cf. VTCP_listen_on() */
128
static int v_matchproto_(vus_resolved_f)
129 114
uds_listen(void *priv, const struct sockaddr_un *uds)
130
{
131
        int sock, e;
132 114
        struct helper *hp = priv;
133
134 114
        sock = VUS_bind(uds, hp->errp);
135 114
        if (sock >= 0)   {
136 114
                if (listen(sock, hp->depth) != 0) {
137 0
                        e = errno;
138 0
                        closefd(&sock);
139 0
                        errno = e;
140 0
                        if (hp->errp != NULL)
141 0
                                *hp->errp = "listen(2)";
142 0
                        return (-1);
143
                }
144
        }
145 114
        if (sock > 0) {
146 114
                *hp->errp = NULL;
147 114
                return (sock);
148
        }
149 0
        AN(*hp->errp);
150 0
        return (0);
151
}
152
153
static void
154 114
server_listen_uds(struct server *s, const char **errp)
155
{
156
        mode_t m;
157
        struct helper h;
158
159 114
        h.depth = s->depth;
160 114
        h.errp = errp;
161
162 114
        errno = 0;
163 114
        if (unlink(s->listen) != 0 && errno != ENOENT)
164 0
                vtc_fatal(s->vl, "Could not unlink %s before bind: %s",
165 0
                          s->listen, strerror(errno));
166
        /*
167
         * Temporarily set the umask to 0 to avoid issues with
168
         * permissions.
169
         */
170 114
        m = umask(0);
171 114
        s->sock = VUS_resolver(s->listen, uds_listen, &h, errp);
172 114
        (void)umask(m);
173 114
        if (*errp != NULL)
174 0
                return;
175 114
        assert(s->sock > 0);
176 114
        macro_def(s->vl, s->name, "addr", "0.0.0.0");
177 114
        macro_def(s->vl, s->name, "port", "0");
178 114
        macro_def(s->vl, s->name, "sock", "%s", s->listen);
179
}
180
181
static void
182 1618
server_listen_tcp(struct server *s, const char **errp)
183
{
184 1618
        s->sock = VTCP_listen_on(s->listen, "0", s->depth, errp);
185 1618
        if (*errp != NULL)
186 0
                return;
187 1618
        assert(s->sock > 0);
188 1618
        VTCP_myname(s->sock, s->aaddr, sizeof s->aaddr,
189 1618
            s->aport, sizeof s->aport);
190 1618
        macro_def(s->vl, s->name, "addr", "%s", s->aaddr);
191 1618
        macro_def(s->vl, s->name, "port", "%s", s->aport);
192 1618
        macro_def(s->vl, s->name, "sock", "%s %s", s->aaddr, s->aport);
193
        /* Record the actual port, and reuse it on subsequent starts */
194 1618
        bprintf(s->listen, "%s %s", s->aaddr, s->aport);
195
}
196
197
static void
198 1732
server_listen(struct server *s)
199
{
200
        const char *err;
201
202 1732
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
203
204 1732
        if (s->sock >= 0)
205 142
                VTCP_close(&s->sock);
206 1732
        if (*s->listen != '/')
207 1618
                server_listen_tcp(s, &err);
208
        else
209 114
                server_listen_uds(s, &err);
210 1732
        if (err != NULL)
211 0
                vtc_fatal(s->vl,
212
                    "Server listen address (%s) cannot be resolved: %s",
213 0
                    s->listen, err);
214 1732
}
215
216
/**********************************************************************
217
 * Server thread
218
 */
219
220
static void *
221 1728
server_thread(void *priv)
222
{
223
        struct server *s;
224
        struct vtclog *vl;
225
        int i, j, fd;
226
        struct sockaddr_storage addr_s;
227
        struct sockaddr *addr;
228
        socklen_t l;
229
        char abuf[VTCP_ADDRBUFSIZE];
230
        char pbuf[VTCP_PORTBUFSIZE];
231
232 1728
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
233 1728
        assert(s->sock >= 0);
234
235 1728
        vl = vtc_logopen(s->name);
236 1728
        pthread_cleanup_push(vtc_logclose, vl);
237
238 1727
        vtc_log(vl, 2, "Started on %s (%u iterations%s)", s->listen,
239 1727
                s->repeat, s->keepalive ? " using keepalive" : "");
240 3880
        for (i = 0; i < s->repeat; i++) {
241 2348
                addr = (void*)&addr_s;
242 2348
                l = sizeof addr_s;
243 2348
                fd = accept(s->sock, addr, &l);
244 2192
                if (fd < 0)
245 0
                        vtc_fatal(vl, "Accept failed: %s", strerror(errno));
246 2192
                if (*s->listen != '/') {
247 1998
                        VTCP_hisname(fd, abuf, sizeof abuf, pbuf, sizeof pbuf);
248 1998
                        vtc_log(vl, 3, "accepted fd %d %s %s", fd, abuf, pbuf);
249
                } else
250 194
                        vtc_log(vl, 3, "accepted fd %d 0.0.0.0 0", fd);
251 2192
                if (! s->keepalive)
252 2186
                        fd = http_process(vl, s->spec, fd, &s->sock, s->listen);
253
                else
254 200
                        while (fd >= 0 && i++ < s->repeat)
255 188
                                fd = http_process(vl, s->spec, fd,
256 188
                                    &s->sock, s->listen);
257 2152
                vtc_log(vl, 3, "shutting fd %d", fd);
258 2152
                j = shutdown(fd, SHUT_WR);
259 2152
                if (!VTCP_Check(j))
260 0
                        vtc_fatal(vl, "Shutdown failed: %s", strerror(errno));
261 2152
                VTCP_close(&fd);
262
        }
263 1532
        vtc_log(vl, 2, "Ending");
264 1532
        pthread_cleanup_pop(0);
265 1532
        vtc_logclose(vl);
266 1532
        return (NULL);
267
}
268
269
270
/**********************************************************************
271
 * Start the server thread
272
 */
273
274
static void
275 1728
server_start(struct server *s)
276
{
277 1728
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
278 1728
        vtc_log(s->vl, 2, "Starting server");
279 1728
        server_listen(s);
280 1728
        vtc_log(s->vl, 1, "Listen on %s", s->listen);
281 1728
        s->run = 1;
282 1728
        AZ(pthread_create(&s->tp, NULL, server_thread, s));
283 1728
}
284
285
/**********************************************************************
286
 */
287
288
static void *
289 25
server_dispatch_wrk(void *priv)
290
{
291
        struct server *s;
292
        struct vtclog *vl;
293
        int j, fd;
294
295 25
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
296 25
        assert(s->sock < 0);
297
298 25
        vl = vtc_logopen(s->name);
299 25
        pthread_cleanup_push(vtc_logclose, vl);
300
301 25
        fd = s->fd;
302
303 25
        vtc_log(vl, 3, "start with fd %d", fd);
304 25
        fd = http_process(vl, s->spec, fd, &s->sock, s->listen);
305 14
        vtc_log(vl, 3, "shutting fd %d", fd);
306 14
        j = shutdown(fd, SHUT_WR);
307 14
        if (!VTCP_Check(j))
308 0
                vtc_fatal(vl, "Shutdown failed: %s", strerror(errno));
309 14
        VTCP_close(&s->fd);
310 14
        vtc_log(vl, 2, "Ending");
311 14
        pthread_cleanup_pop(0);
312 14
        vtc_logclose(vl);
313 14
        return (NULL);
314
}
315
316
static void *
317 4
server_dispatch_thread(void *priv)
318
{
319
        struct server *s, *s2;
320 4
        int sn = 1, fd;
321
        char snbuf[8];
322
        struct vtclog *vl;
323
        struct sockaddr_storage addr_s;
324
        struct sockaddr *addr;
325
        socklen_t l;
326
327 4
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
328 4
        assert(s->sock >= 0);
329
330 4
        vl = vtc_logopen(s->name);
331 4
        pthread_cleanup_push(vtc_logclose, vl);
332
333 4
        vtc_log(vl, 2, "Dispatch started on %s", s->listen);
334
335 4
        while (!vtc_stop) {
336 29
                addr = (void*)&addr_s;
337 29
                l = sizeof addr_s;
338 29
                fd = accept(s->sock, addr, &l);
339 25
                if (fd < 0)
340 0
                        vtc_fatal(vl, "Accepted failed: %s", strerror(errno));
341 25
                bprintf(snbuf, "s%d", sn++);
342 25
                vtc_log(vl, 3, "dispatch fd %d -> %s", fd, snbuf);
343 25
                s2 = server_new(snbuf, vl);
344 25
                s2->spec = s->spec;
345 25
                strcpy(s2->listen, s->listen);
346 25
                s2->fd = fd;
347 25
                s2->run = 1;
348 25
                AZ(pthread_create(&s2->tp, NULL, server_dispatch_wrk, s2));
349
        }
350 0
        pthread_cleanup_pop(0);
351 0
        vtc_logclose(vl);
352 0
        NEEDLESS(return(NULL));
353
}
354
355
static void
356 4
server_dispatch(struct server *s)
357
{
358 4
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
359 4
        server_listen(s);
360 4
        vtc_log(s->vl, 2, "Starting dispatch server");
361 4
        s->run = 1;
362 4
        AZ(pthread_create(&s->tp, NULL, server_dispatch_thread, s));
363 4
}
364
365
/**********************************************************************
366
 * Force stop the server thread
367
 */
368
369
static void
370 4
server_break(struct server *s)
371
{
372
        void *res;
373
374 4
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
375 4
        vtc_log(s->vl, 2, "Breaking for server");
376 4
        (void)pthread_cancel(s->tp);
377 4
        AZ(pthread_join(s->tp, &res));
378 4
        s->tp = 0;
379 4
        s->run = 0;
380 4
}
381
382
/**********************************************************************
383
 * Wait for server thread to stop
384
 */
385
386
static void
387 1753
server_wait(struct server *s)
388
{
389
        void *res;
390
391 1753
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
392 1753
        vtc_log(s->vl, 2, "Waiting for server (%d/%d)", s->sock, s->fd);
393 1753
        AZ(pthread_join(s->tp, &res));
394 1753
        if (res != NULL && !vtc_stop)
395 0
                vtc_fatal(s->vl, "Server returned \"%p\"",
396
                    (char *)res);
397 1753
        s->tp = 0;
398 1753
        s->run = 0;
399 1753
}
400
401
/**********************************************************************
402
 * Generate VCL backend decls for our servers
403
 */
404
405
void
406 1366
cmd_server_gen_vcl(struct vsb *vsb)
407
{
408
        struct server *s;
409
410 1366
        AZ(pthread_mutex_lock(&server_mtx));
411 2866
        VTAILQ_FOREACH(s, &servers, list) {
412 1500
                if (*s->listen != '/')
413 1464
                        VSB_printf(vsb,
414
                                   "backend %s { .host = \"%s\"; "
415
                                   ".port = \"%s\"; }\n",
416 1464
                                   s->name, s->aaddr, s->aport);
417
                else
418 36
                        VSB_printf(vsb,
419
                                   "backend %s { .path = \"%s\"; }\n",
420 36
                                   s->name, s->listen);
421
        }
422 1366
        AZ(pthread_mutex_unlock(&server_mtx));
423 1366
}
424
425
426
/**********************************************************************
427
 * Generate VCL backend decls for our servers
428
 */
429
430
void
431 2
cmd_server_gen_haproxy_conf(struct vsb *vsb)
432
{
433
        struct server *s;
434
435 2
        AZ(pthread_mutex_lock(&server_mtx));
436 4
        VTAILQ_FOREACH(s, &servers, list) {
437 2
                if (*s->listen != '/')
438 4
                        VSB_printf(vsb,
439
                           "\n    backend be%s\n"
440
                           "\tserver srv%s %s:%s\n",
441 4
                           s->name + 1, s->name + 1, s->aaddr, s->aport);
442
                else
443 0
                        INCOMPL();
444
        }
445 4
        VTAILQ_FOREACH(s, &servers, list) {
446 2
                if (*s->listen != '/')
447 6
                        VSB_printf(vsb,
448
                           "\n    frontend http%s\n"
449
                           "\tuse_backend be%s\n"
450
                           "\tbind \"fd@${fe%s}\"\n",
451 6
                           s->name + 1, s->name + 1, s->name + 1);
452
                else
453 0
                        INCOMPL();
454
        }
455 2
        AZ(pthread_mutex_unlock(&server_mtx));
456 2
}
457
458
459
/**********************************************************************
460
 * Server command dispatch
461
 */
462
463
void
464 3466
cmd_server(CMD_ARGS)
465
{
466
        struct server *s;
467
468
        (void)priv;
469
        (void)cmd;
470
471 3466
        if (av == NULL) {
472
                /* Reset and free */
473
                while (1) {
474 4752
                        AZ(pthread_mutex_lock(&server_mtx));
475 3139
                        s = VTAILQ_FIRST(&servers);
476 3139
                        CHECK_OBJ_ORNULL(s, SERVER_MAGIC);
477 3139
                        if (s != NULL)
478 1613
                                VTAILQ_REMOVE(&servers, s, list);
479 3139
                        AZ(pthread_mutex_unlock(&server_mtx));
480 3139
                        if (s == NULL)
481 1526
                                break;
482 1613
                        if (s->run) {
483 1489
                                (void)pthread_cancel(s->tp);
484 1489
                                server_wait(s);
485
                        }
486 1613
                        if (s->sock >= 0)
487 1588
                                VTCP_close(&s->sock);
488 1613
                        server_delete(s);
489
                }
490 1526
                return;
491
        }
492
493 1940
        AZ(strcmp(av[0], "server"));
494 1940
        av++;
495
496 1940
        AZ(pthread_mutex_lock(&server_mtx));
497 2422
        VTAILQ_FOREACH(s, &servers, list)
498 834
                if (!strcmp(s->name, av[0]))
499 352
                        break;
500 1940
        AZ(pthread_mutex_unlock(&server_mtx));
501 1940
        if (s == NULL)
502 1588
                s = server_new(av[0], vl);
503 1940
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
504 1940
        av++;
505
506 5730
        for (; *av != NULL; av++) {
507 3790
                if (vtc_error)
508 0
                        break;
509 3790
                if (!strcmp(*av, "-wait")) {
510 148
                        if (!s->run)
511 0
                                vtc_fatal(s->vl, "Server not -started");
512 148
                        server_wait(s);
513 148
                        continue;
514
                }
515
516 3642
                if (!strcmp(*av, "-break")) {
517 4
                        server_break(s);
518 4
                        continue;
519
                }
520
521
                /*
522
                 * We do an implict -wait if people muck about with a
523
                 * running server.
524
                 */
525 3638
                if (s->run)
526 116
                        server_wait(s);
527
528 3638
                AZ(s->run);
529 3638
                if (!strcmp(*av, "-repeat")) {
530 100
                        s->repeat = atoi(av[1]);
531 100
                        av++;
532 100
                        continue;
533
                }
534 3538
                if (!strcmp(*av, "-keepalive")) {
535 6
                        s->keepalive = 1;
536 6
                        continue;
537
                }
538 3532
                if (!strcmp(*av, "-listen")) {
539 104
                        if (s->sock >= 0)
540 2
                                VTCP_close(&s->sock);
541 104
                        bprintf(s->listen, "%s", av[1]);
542 104
                        av++;
543 104
                        continue;
544
                }
545 3428
                if (!strcmp(*av, "-start")) {
546 1728
                        server_start(s);
547 1728
                        continue;
548
                }
549 1700
                if (!strcmp(*av, "-dispatch")) {
550 4
                        if (strcmp(s->name, "s0"))
551 0
                                vtc_fatal(s->vl,
552
                                    "server -dispatch only works on s0");
553 4
                        server_dispatch(s);
554 4
                        continue;
555
                }
556 1696
                if (**av == '-')
557 0
                        vtc_fatal(s->vl, "Unknown server argument: %s", *av);
558 1696
                s->spec = *av;
559
        }
560
}
561
562
void
563 1526
init_server(void)
564
{
565 1526
        AZ(pthread_mutex_init(&server_mtx, NULL));
566 1526
}