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