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
        char                    *spec;
56
57
        int                     depth;
58
        int                     sock;
59
        int                     fd;
60
        char                    listen[256];
61
        char                    aaddr[32];
62
        char                    aport[32];
63
64
        pthread_t               tp;
65
};
66
67
static pthread_mutex_t          server_mtx;
68
69
static VTAILQ_HEAD(, server)    servers =
70
    VTAILQ_HEAD_INITIALIZER(servers);
71
72
/**********************************************************************
73
 * Allocate and initialize a server
74
 */
75
76
static struct server *
77 801
server_new(const char *name, struct vtclog *vl)
78
{
79
        struct server *s;
80
81 801
        VTC_CHECK_NAME(vl, name, "Server", 's');
82 801
        ALLOC_OBJ(s, SERVER_MAGIC);
83 801
        AN(s);
84 801
        REPLACE(s->name, name);
85 801
        s->vl = vtc_logopen(s->name);
86 801
        AN(s->vl);
87
88 801
        bprintf(s->listen, "%s", "127.0.0.1 0");
89 801
        s->repeat = 1;
90 801
        s->depth = 10;
91 801
        s->sock = -1;
92 801
        s->fd = -1;
93 801
        AZ(pthread_mutex_lock(&server_mtx));
94 801
        VTAILQ_INSERT_TAIL(&servers, s, list);
95 801
        AZ(pthread_mutex_unlock(&server_mtx));
96 801
        return (s);
97
}
98
99
/**********************************************************************
100
 * Clean up a server
101
 */
102
103
static void
104 801
server_delete(struct server *s)
105
{
106
107 801
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
108 801
        macro_undef(s->vl, s->name, "addr");
109 801
        macro_undef(s->vl, s->name, "port");
110 801
        macro_undef(s->vl, s->name, "sock");
111 801
        vtc_logclose(s->vl);
112 801
        free(s->name);
113
        /* XXX: MEMLEAK (?) (VSS ??) */
114 801
        FREE_OBJ(s);
115 801
}
116
117
/**********************************************************************
118
 * Server listen
119
 */
120
121
struct helper {
122
        int             depth;
123
        const char      **errp;
124
};
125
126
/* cf. VTCP_listen_on() */
127
static int v_matchproto_(vus_resolved_f)
128 57
uds_listen(void *priv, const struct sockaddr_un *uds)
129
{
130
        int sock, e;
131 57
        struct helper *hp = priv;
132
133 57
        sock = VUS_bind(uds, hp->errp);
134 57
        if (sock >= 0)   {
135 57
                if (listen(sock, hp->depth) != 0) {
136 0
                        e = errno;
137 0
                        closefd(&sock);
138 0
                        errno = e;
139 0
                        if (hp->errp != NULL)
140 0
                                *hp->errp = "listen(2)";
141 0
                        return (-1);
142
                }
143
        }
144 57
        if (sock > 0) {
145 57
                *hp->errp = NULL;
146 57
                return (sock);
147
        }
148 0
        AN(*hp->errp);
149 0
        return (0);
150
}
151
152
static void
153 57
server_listen_uds(struct server *s, const char **errp)
154
{
155
        mode_t m;
156
        struct helper h;
157
158 57
        h.depth = s->depth;
159 57
        h.errp = errp;
160
161 57
        errno = 0;
162 57
        if (unlink(s->listen) != 0 && errno != ENOENT)
163 0
                vtc_fatal(s->vl, "Could not unlink %s before bind: %s",
164 0
                          s->listen, strerror(errno));
165
        /*
166
         * Temporarily set the umask to 0 to avoid issues with
167
         * permissions.
168
         */
169 57
        m = umask(0);
170 57
        s->sock = VUS_resolver(s->listen, uds_listen, &h, errp);
171 57
        (void)umask(m);
172 57
        if (*errp != NULL)
173 0
                return;
174 57
        assert(s->sock > 0);
175 57
        macro_def(s->vl, s->name, "addr", "0.0.0.0");
176 57
        macro_def(s->vl, s->name, "port", "0");
177 57
        macro_def(s->vl, s->name, "sock", "%s", s->listen);
178
}
179
180
static void
181 799
server_listen_tcp(struct server *s, const char **errp)
182
{
183 799
        s->sock = VTCP_listen_on(s->listen, "0", s->depth, errp);
184 799
        if (*errp != NULL)
185 0
                return;
186 799
        assert(s->sock > 0);
187 799
        VTCP_myname(s->sock, s->aaddr, sizeof s->aaddr,
188 799
            s->aport, sizeof s->aport);
189 799
        macro_def(s->vl, s->name, "addr", "%s", s->aaddr);
190 799
        macro_def(s->vl, s->name, "port", "%s", s->aport);
191 799
        macro_def(s->vl, s->name, "sock", "%s %s", s->aaddr, s->aport);
192
        /* Record the actual port, and reuse it on subsequent starts */
193 799
        bprintf(s->listen, "%s %s", s->aaddr, s->aport);
194
}
195
196
static void
197 856
server_listen(struct server *s)
198
{
199
        const char *err;
200
201 856
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
202
203 856
        if (s->sock >= 0)
204 66
                VTCP_close(&s->sock);
205 856
        if (*s->listen != '/')
206 799
                server_listen_tcp(s, &err);
207
        else
208 57
                server_listen_uds(s, &err);
209 856
        if (err != NULL)
210 0
                vtc_fatal(s->vl,
211
                    "Server listen address (%s) cannot be resolved: %s",
212 0
                    s->listen, err);
213 856
}
214
215
/**********************************************************************
216
 * Server thread
217
 */
218
219
static void *
220 854
server_thread(void *priv)
221
{
222
        struct server *s;
223
        struct vtclog *vl;
224
        int i, j, fd;
225
        struct sockaddr_storage addr_s;
226
        struct sockaddr *addr;
227
        socklen_t l;
228
        char abuf[VTCP_ADDRBUFSIZE];
229
        char pbuf[VTCP_PORTBUFSIZE];
230
231 854
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
232 854
        assert(s->sock >= 0);
233
234 854
        vl = vtc_logopen(s->name);
235 854
        pthread_cleanup_push(vtc_logclose, vl);
236
237 854
        vtc_log(vl, 2, "Started on %s", s->listen);
238 2010
        for (i = 0; i < s->repeat; i++) {
239 1255
                if (s->repeat > 1)
240 449
                        vtc_log(vl, 3, "Iteration %d", i);
241 1255
                addr = (void*)&addr_s;
242 1255
                l = sizeof addr_s;
243 1255
                fd = accept(s->sock, addr, &l);
244 1176
                if (fd < 0)
245 0
                        vtc_fatal(vl, "Accept failed: %s", strerror(errno));
246 1176
                if (*s->listen != '/') {
247 1079
                        VTCP_hisname(fd, abuf, sizeof abuf, pbuf, sizeof pbuf);
248 1079
                        vtc_log(vl, 3, "accepted fd %d %s %s", fd, abuf, pbuf);
249
                } else
250 97
                        vtc_log(vl, 3, "accepted fd %d 0.0.0.0 0", fd);
251 1176
                fd = http_process(vl, s->spec, fd, &s->sock, s->listen);
252 1156
                vtc_log(vl, 3, "shutting fd %d", fd);
253 1156
                j = shutdown(fd, SHUT_WR);
254 1156
                if (!VTCP_Check(j))
255 0
                        vtc_fatal(vl, "Shutdown failed: %s", strerror(errno));
256 1156
                VTCP_close(&fd);
257
        }
258 755
        vtc_log(vl, 2, "Ending");
259 755
        pthread_cleanup_pop(0);
260 755
        vtc_logclose(vl);
261 755
        return (NULL);
262
}
263
264
265
/**********************************************************************
266
 * Start the server thread
267
 */
268
269
static void
270 854
server_start(struct server *s)
271
{
272 854
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
273 854
        vtc_log(s->vl, 2, "Starting server");
274 854
        server_listen(s);
275 854
        vtc_log(s->vl, 1, "Listen on %s", s->listen);
276 854
        s->run = 1;
277 854
        AZ(pthread_create(&s->tp, NULL, server_thread, s));
278 854
}
279
280
/**********************************************************************
281
 */
282
283
static void *
284 12
server_dispatch_wrk(void *priv)
285
{
286
        struct server *s;
287
        struct vtclog *vl;
288
        int j, fd;
289
290 12
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
291 12
        assert(s->sock < 0);
292
293 12
        vl = vtc_logopen(s->name);
294 12
        pthread_cleanup_push(vtc_logclose, vl);
295
296 12
        fd = s->fd;
297
298 12
        vtc_log(vl, 3, "start with fd %d", fd);
299 12
        fd = http_process(vl, s->spec, fd, &s->sock, s->listen);
300 6
        vtc_log(vl, 3, "shutting fd %d", fd);
301 6
        j = shutdown(fd, SHUT_WR);
302 6
        if (!VTCP_Check(j))
303 0
                vtc_fatal(vl, "Shutdown failed: %s", strerror(errno));
304 6
        VTCP_close(&s->fd);
305 6
        vtc_log(vl, 2, "Ending");
306 6
        pthread_cleanup_pop(0);
307 6
        vtc_logclose(vl);
308 6
        return (NULL);
309
}
310
311
static void *
312 2
server_dispatch_thread(void *priv)
313
{
314
        struct server *s, *s2;
315 2
        int sn = 1, fd;
316
        char snbuf[8];
317
        struct vtclog *vl;
318
        struct sockaddr_storage addr_s;
319
        struct sockaddr *addr;
320
        socklen_t l;
321
322 2
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
323 2
        assert(s->sock >= 0);
324
325 2
        vl = vtc_logopen(s->name);
326 2
        pthread_cleanup_push(vtc_logclose, vl);
327
328 2
        vtc_log(vl, 2, "Dispatch started on %s", s->listen);
329
330 2
        while (!vtc_stop) {
331 14
                addr = (void*)&addr_s;
332 14
                l = sizeof addr_s;
333 14
                fd = accept(s->sock, addr, &l);
334 12
                if (fd < 0)
335 0
                        vtc_fatal(vl, "Accepted failed: %s", strerror(errno));
336 12
                bprintf(snbuf, "s%d", sn++);
337 12
                vtc_log(vl, 3, "dispatch fd %d -> %s", fd, snbuf);
338 12
                s2 = server_new(snbuf, vl);
339 12
                s2->spec = s->spec;
340 12
                strcpy(s2->listen, s->listen);
341 12
                s2->fd = fd;
342 12
                s2->run = 1;
343 12
                AZ(pthread_create(&s2->tp, NULL, server_dispatch_wrk, s2));
344
        }
345 0
        pthread_cleanup_pop(0);
346 0
        vtc_logclose(vl);
347 0
        NEEDLESS(return(NULL));
348
}
349
350
static void
351 2
server_dispatch(struct server *s)
352
{
353 2
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
354 2
        server_listen(s);
355 2
        vtc_log(s->vl, 2, "Starting dispatch server");
356 2
        s->run = 1;
357 2
        AZ(pthread_create(&s->tp, NULL, server_dispatch_thread, s));
358 2
}
359
360
/**********************************************************************
361
 * Force stop the server thread
362
 */
363
364
static void
365 2
server_break(struct server *s)
366
{
367
        void *res;
368
369 2
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
370 2
        vtc_log(s->vl, 2, "Breaking for server");
371 2
        (void)pthread_cancel(s->tp);
372 2
        AZ(pthread_join(s->tp, &res));
373 2
        s->tp = 0;
374 2
        s->run = 0;
375 2
}
376
377
/**********************************************************************
378
 * Wait for server thread to stop
379
 */
380
381
static void
382 866
server_wait(struct server *s)
383
{
384
        void *res;
385
386 866
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
387 866
        vtc_log(s->vl, 2, "Waiting for server (%d/%d)", s->sock, s->fd);
388 866
        AZ(pthread_join(s->tp, &res));
389 866
        if (res != NULL && !vtc_stop)
390 0
                vtc_fatal(s->vl, "Server returned \"%p\"",
391
                    (char *)res);
392 866
        s->tp = 0;
393 866
        s->run = 0;
394 866
}
395
396
/**********************************************************************
397
 * Generate VCL backend decls for our servers
398
 */
399
400
void
401 676
cmd_server_gen_vcl(struct vsb *vsb)
402
{
403
        struct server *s;
404
405 676
        AZ(pthread_mutex_lock(&server_mtx));
406 1420
        VTAILQ_FOREACH(s, &servers, list) {
407 744
                if (*s->listen != '/')
408 726
                        VSB_printf(vsb,
409
                                   "backend %s { .host = \"%s\"; "
410
                                   ".port = \"%s\"; }\n",
411 726
                                   s->name, s->aaddr, s->aport);
412
                else
413 18
                        VSB_printf(vsb,
414
                                   "backend %s { .path = \"%s\"; }\n",
415 18
                                   s->name, s->listen);
416
        }
417 676
        AZ(pthread_mutex_unlock(&server_mtx));
418 676
}
419
420
421
/**********************************************************************
422
 * Generate VCL backend decls for our servers
423
 */
424
425
void
426 1
cmd_server_gen_haproxy_conf(struct vsb *vsb)
427
{
428
        struct server *s;
429
430 1
        AZ(pthread_mutex_lock(&server_mtx));
431 2
        VTAILQ_FOREACH(s, &servers, list) {
432 1
                if (*s->listen != '/')
433 2
                        VSB_printf(vsb,
434
                           "\n    backend be%s\n"
435
                           "\tserver srv%s %s:%s\n",
436 2
                           s->name + 1, s->name + 1, s->aaddr, s->aport);
437
                else
438 0
                        INCOMPL();
439
        }
440 2
        VTAILQ_FOREACH(s, &servers, list) {
441 1
                if (*s->listen != '/')
442 3
                        VSB_printf(vsb,
443
                           "\n    frontend http%s\n"
444
                           "\tuse_backend be%s\n"
445
                           "\tbind \"fd@${fe%s}\"\n",
446 3
                           s->name + 1, s->name + 1, s->name + 1);
447
                else
448 0
                        INCOMPL();
449
        }
450 1
        AZ(pthread_mutex_unlock(&server_mtx));
451 1
}
452
453
454
/**********************************************************************
455
 * Server command dispatch
456
 */
457
458
void
459 1723
cmd_server(CMD_ARGS)
460
{
461
        struct server *s;
462
463
        (void)priv;
464
        (void)cmd;
465
466 1723
        if (av == NULL) {
467
                /* Reset and free */
468
                while (1) {
469 2365
                        AZ(pthread_mutex_lock(&server_mtx));
470 1564
                        s = VTAILQ_FIRST(&servers);
471 1564
                        CHECK_OBJ_ORNULL(s, SERVER_MAGIC);
472 1564
                        if (s != NULL)
473 801
                                VTAILQ_REMOVE(&servers, s, list);
474 1564
                        AZ(pthread_mutex_unlock(&server_mtx));
475 1564
                        if (s == NULL)
476 763
                                break;
477 801
                        if (s->run) {
478 739
                                (void)pthread_cancel(s->tp);
479 739
                                server_wait(s);
480
                        }
481 801
                        if (s->sock >= 0)
482 789
                                VTCP_close(&s->sock);
483 801
                        server_delete(s);
484
                }
485 763
                return;
486
        }
487
488 960
        AZ(strcmp(av[0], "server"));
489 960
        av++;
490
491 960
        AZ(pthread_mutex_lock(&server_mtx));
492 1202
        VTAILQ_FOREACH(s, &servers, list)
493 413
                if (!strcmp(s->name, av[0]))
494 171
                        break;
495 960
        AZ(pthread_mutex_unlock(&server_mtx));
496 960
        if (s == NULL)
497 789
                s = server_new(av[0], vl);
498 960
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
499 960
        av++;
500
501 2832
        for (; *av != NULL; av++) {
502 1872
                if (vtc_error)
503 0
                        break;
504 1872
                if (!strcmp(*av, "-wait")) {
505 74
                        if (!s->run)
506 0
                                vtc_fatal(s->vl, "Server not -started");
507 74
                        server_wait(s);
508 74
                        continue;
509
                }
510
511 1798
                if (!strcmp(*av, "-break")) {
512 2
                        server_break(s);
513 2
                        continue;
514
                }
515
516
                /*
517
                 * We do an implict -wait if people muck about with a
518
                 * running server.
519
                 */
520 1796
                if (s->run)
521 53
                        server_wait(s);
522
523 1796
                AZ(s->run);
524 1796
                if (!strcmp(*av, "-repeat")) {
525 50
                        s->repeat = atoi(av[1]);
526 50
                        av++;
527 50
                        continue;
528
                }
529 1746
                if (!strcmp(*av, "-listen")) {
530 52
                        if (s->sock >= 0)
531 1
                                VTCP_close(&s->sock);
532 52
                        bprintf(s->listen, "%s", av[1]);
533 52
                        av++;
534 52
                        continue;
535
                }
536 1694
                if (!strcmp(*av, "-start")) {
537 854
                        server_start(s);
538 854
                        continue;
539
                }
540 840
                if (!strcmp(*av, "-dispatch")) {
541 2
                        if (strcmp(s->name, "s0"))
542 0
                                vtc_fatal(s->vl,
543
                                    "server -dispatch only works on s0");
544 2
                        server_dispatch(s);
545 2
                        continue;
546
                }
547 838
                if (**av == '-')
548 0
                        vtc_fatal(s->vl, "Unknown server argument: %s", *av);
549 838
                s->spec = *av;
550
        }
551
}
552
553
void
554 763
init_server(void)
555
{
556 763
        AZ(pthread_mutex_init(&server_mtx, NULL));
557 763
}