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
33
#include <errno.h>
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <string.h>
37
38
#include "vtc.h"
39
40
#include "vtcp.h"
41
42
struct server {
43
        unsigned                magic;
44
#define SERVER_MAGIC            0x55286619
45
        char                    *name;
46
        struct vtclog           *vl;
47
        VTAILQ_ENTRY(server)    list;
48
        char                    run;
49
50
        unsigned                repeat;
51
        char                    *spec;
52
53
        int                     depth;
54
        int                     sock;
55
        int                     fd;
56
        char                    listen[256];
57
        char                    aaddr[32];
58
        char                    aport[32];
59
60
        pthread_t               tp;
61
};
62
63
static pthread_mutex_t          server_mtx;
64
65
static VTAILQ_HEAD(, server)    servers =
66
    VTAILQ_HEAD_INITIALIZER(servers);
67
68
/**********************************************************************
69
 * Allocate and initialize a server
70
 */
71
72
static struct server *
73 697
server_new(const char *name, struct vtclog *vl)
74
{
75
        struct server *s;
76
77 697
        VTC_CHECK_NAME(vl, name, "Server", 's');
78 697
        ALLOC_OBJ(s, SERVER_MAGIC);
79 697
        AN(s);
80 697
        REPLACE(s->name, name);
81 697
        s->vl = vtc_logopen(s->name);
82 697
        AN(s->vl);
83
84 697
        bprintf(s->listen, "%s", "127.0.0.1 0");
85 697
        s->repeat = 1;
86 697
        s->depth = 10;
87 697
        s->sock = -1;
88 697
        s->fd = -1;
89 697
        AZ(pthread_mutex_lock(&server_mtx));
90 697
        VTAILQ_INSERT_TAIL(&servers, s, list);
91 697
        AZ(pthread_mutex_unlock(&server_mtx));
92 697
        return (s);
93
}
94
95
/**********************************************************************
96
 * Clean up a server
97
 */
98
99
static void
100 697
server_delete(struct server *s)
101
{
102
103 697
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
104 697
        macro_undef(s->vl, s->name, "addr");
105 697
        macro_undef(s->vl, s->name, "port");
106 697
        macro_undef(s->vl, s->name, "sock");
107 697
        vtc_logclose(s->vl);
108 697
        free(s->name);
109
        /* XXX: MEMLEAK (?) (VSS ??) */
110 697
        FREE_OBJ(s);
111 697
}
112
113
/**********************************************************************
114
 * Server listen
115
 */
116
117
static void
118 747
server_listen(struct server *s)
119
{
120
        const char *err;
121
122 747
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
123
124 747
        if (s->sock >= 0)
125 56
                VTCP_close(&s->sock);
126 747
        s->sock = VTCP_listen_on(s->listen, "0", s->depth, &err);
127 747
        if (err != NULL)
128 0
                vtc_fatal(s->vl,
129
                    "Server listen address (%s) cannot be resolved: %s",
130 0
                    s->listen, err);
131 747
        assert(s->sock > 0);
132 747
        VTCP_myname(s->sock, s->aaddr, sizeof s->aaddr,
133 747
            s->aport, sizeof s->aport);
134 747
        macro_def(s->vl, s->name, "addr", "%s", s->aaddr);
135 747
        macro_def(s->vl, s->name, "port", "%s", s->aport);
136 747
        macro_def(s->vl, s->name, "sock", "%s %s", s->aaddr, s->aport);
137
        /* Record the actual port, and reuse it on subsequent starts */
138 747
        bprintf(s->listen, "%s %s", s->aaddr, s->aport);
139 747
}
140
141
/**********************************************************************
142
 * Server thread
143
 */
144
145
static void *
146 746
server_thread(void *priv)
147
{
148
        struct server *s;
149
        struct vtclog *vl;
150
        int i, j, fd;
151
        struct sockaddr_storage addr_s;
152
        struct sockaddr *addr;
153
        socklen_t l;
154
        char abuf[VTCP_ADDRBUFSIZE];
155
        char pbuf[VTCP_PORTBUFSIZE];
156
157 746
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
158 746
        assert(s->sock >= 0);
159
160 746
        vl = vtc_logopen(s->name);
161
162 746
        vtc_log(vl, 2, "Started on %s", s->listen);
163 1632
        for (i = 0; i < s->repeat; i++) {
164 973
                if (s->repeat > 1)
165 261
                        vtc_log(vl, 3, "Iteration %d", i);
166 973
                addr = (void*)&addr_s;
167 973
                l = sizeof addr_s;
168 973
                fd = accept(s->sock, addr, &l);
169 902
                if (fd < 0)
170 0
                        vtc_fatal(vl, "Accept failed: %s", strerror(errno));
171 902
                VTCP_hisname(fd, abuf, sizeof abuf, pbuf, sizeof pbuf);
172 902
                vtc_log(vl, 3, "accepted fd %d %s %s", fd, abuf, pbuf);
173 902
                fd = http_process(vl, s->spec, fd, &s->sock);
174 886
                vtc_log(vl, 3, "shutting fd %d", fd);
175 886
                j = shutdown(fd, SHUT_WR);
176 886
                if (!VTCP_Check(j))
177 0
                        vtc_fatal(vl, "Shutdown failed: %s", strerror(errno));
178 886
                VTCP_close(&fd);
179
        }
180 659
        vtc_log(vl, 2, "Ending");
181 659
        return (NULL);
182
}
183
184
185
/**********************************************************************
186
 * Start the server thread
187
 */
188
189
static void
190 746
server_start(struct server *s)
191
{
192 746
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
193 746
        vtc_log(s->vl, 2, "Starting server");
194 746
        server_listen(s);
195 746
        vtc_log(s->vl, 1, "Listen on %s", s->listen);
196 746
        s->run = 1;
197 746
        AZ(pthread_create(&s->tp, NULL, server_thread, s));
198 746
}
199
200
/**********************************************************************
201
 */
202
203
static void *
204 6
server_dispatch_wrk(void *priv)
205
{
206
        struct server *s;
207
        struct vtclog *vl;
208
        int j, fd;
209
210 6
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
211 6
        assert(s->sock < 0);
212
213 6
        vl = vtc_logopen(s->name);
214
215 6
        fd = s->fd;
216
217 6
        vtc_log(vl, 3, "start with fd %d", fd);
218 6
        fd = http_process(vl, s->spec, fd, &s->sock);
219 3
        vtc_log(vl, 3, "shutting fd %d", fd);
220 3
        j = shutdown(fd, SHUT_WR);
221 3
        if (!VTCP_Check(j))
222 0
                vtc_fatal(vl, "Shutdown failed: %s", strerror(errno));
223 3
        VTCP_close(&s->fd);
224 3
        vtc_log(vl, 2, "Ending");
225 3
        return (NULL);
226
}
227
228
static void *
229 1
server_dispatch_thread(void *priv)
230
{
231
        struct server *s, *s2;
232 1
        int sn = 1, fd;
233
        char snbuf[8];
234
        struct vtclog *vl;
235
        struct sockaddr_storage addr_s;
236
        struct sockaddr *addr;
237
        socklen_t l;
238
239 1
        CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
240 1
        assert(s->sock >= 0);
241
242 1
        vl = vtc_logopen(s->name);
243 1
        AN(vl);
244 1
        vtc_log(vl, 2, "Dispatch started on %s", s->listen);
245
246
        while (1) {
247 7
                addr = (void*)&addr_s;
248 7
                l = sizeof addr_s;
249 7
                fd = accept(s->sock, addr, &l);
250 6
                if (fd < 0)
251 0
                        vtc_fatal(vl, "Accepted failed: %s", strerror(errno));
252 6
                bprintf(snbuf, "s%d", sn++);
253 6
                vtc_log(vl, 3, "dispatch fd %d -> %s", fd, snbuf);
254 6
                s2 = server_new(snbuf, vl);
255 6
                s2->spec = s->spec;
256 6
                strcpy(s2->listen, s->listen);
257 6
                s2->fd = fd;
258 6
                s2->run = 1;
259 6
                AZ(pthread_create(&s2->tp, NULL, server_dispatch_wrk, s2));
260 6
        }
261
        NEEDLESS(return(NULL));
262
}
263
264
static void
265 1
server_dispatch(struct server *s)
266
{
267 1
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
268 1
        server_listen(s);
269 1
        vtc_log(s->vl, 2, "Starting dispatch server");
270 1
        s->run = 1;
271 1
        AZ(pthread_create(&s->tp, NULL, server_dispatch_thread, s));
272 1
}
273
274
/**********************************************************************
275
 * Force stop the server thread
276
 */
277
278
static void
279 1
server_break(struct server *s)
280
{
281
        void *res;
282
283 1
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
284 1
        vtc_log(s->vl, 2, "Breaking for server");
285 1
        (void)pthread_cancel(s->tp);
286 1
        AZ(pthread_join(s->tp, &res));
287 1
        s->tp = 0;
288 1
        s->run = 0;
289 1
}
290
291
/**********************************************************************
292
 * Wait for server thread to stop
293
 */
294
295
static void
296 752
server_wait(struct server *s)
297
{
298
        void *res;
299
300 752
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
301 752
        vtc_log(s->vl, 2, "Waiting for server (%d/%d)", s->sock, s->fd);
302 752
        AZ(pthread_join(s->tp, &res));
303 752
        if (res != NULL && !vtc_stop)
304 0
                vtc_fatal(s->vl, "Server returned \"%p\"",
305
                    (char *)res);
306 752
        s->tp = 0;
307 752
        s->run = 0;
308 752
}
309
310
/**********************************************************************
311
 * Generate VCL backend decls for our servers
312
 */
313
314
void
315 607
cmd_server_genvcl(struct vsb *vsb)
316
{
317
        struct server *s;
318
319 607
        AZ(pthread_mutex_lock(&server_mtx));
320 1278
        VTAILQ_FOREACH(s, &servers, list) {
321 671
                VSB_printf(vsb,
322
                    "backend %s { .host = \"%s\"; .port = \"%s\"; }\n",
323 671
                    s->name, s->aaddr, s->aport);
324
        }
325 607
        AZ(pthread_mutex_unlock(&server_mtx));
326 607
}
327
328
329
/**********************************************************************
330
 * Server command dispatch
331
 */
332
333
void
334 1504
cmd_server(CMD_ARGS)
335
{
336
        struct server *s;
337
338
        (void)priv;
339
        (void)cmd;
340
341 1504
        if (av == NULL) {
342
                /* Reset and free */
343
                while (1) {
344 1375
                        AZ(pthread_mutex_lock(&server_mtx));
345 1375
                        s = VTAILQ_FIRST(&servers);
346 1375
                        CHECK_OBJ_ORNULL(s, SERVER_MAGIC);
347 1375
                        if (s != NULL)
348 697
                                VTAILQ_REMOVE(&servers, s, list);
349 1375
                        AZ(pthread_mutex_unlock(&server_mtx));
350 1375
                        if (s == NULL)
351 678
                                break;
352 697
                        if (s->run) {
353 648
                                (void)pthread_cancel(s->tp);
354 648
                                server_wait(s);
355
                        }
356 697
                        if (s->sock >= 0)
357 691
                                VTCP_close(&s->sock);
358 697
                        server_delete(s);
359 697
                }
360 2182
                return;
361
        }
362
363 826
        AZ(strcmp(av[0], "server"));
364 826
        av++;
365
366 826
        AZ(pthread_mutex_lock(&server_mtx));
367 973
        VTAILQ_FOREACH(s, &servers, list)
368 282
                if (!strcmp(s->name, av[0]))
369 135
                        break;
370 826
        AZ(pthread_mutex_unlock(&server_mtx));
371 826
        if (s == NULL)
372 691
                s = server_new(av[0], vl);
373 826
        CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
374 826
        av++;
375
376 2403
        for (; *av != NULL; av++) {
377 1577
                if (vtc_error)
378 0
                        break;
379 1577
                if (!strcmp(*av, "-wait")) {
380 59
                        if (!s->run)
381 0
                                vtc_fatal(s->vl, "Server not -started");
382 59
                        server_wait(s);
383 59
                        continue;
384
                }
385
386 1518
                if (!strcmp(*av, "-break")) {
387 1
                        server_break(s);
388 1
                        continue;
389
                }
390
391
                /*
392
                 * We do an implict -wait if people muck about with a
393
                 * running server.
394
                 */
395 1517
                if (s->run)
396 45
                        server_wait(s);
397
398 1517
                AZ(s->run);
399 1517
                if (!strcmp(*av, "-repeat")) {
400 36
                        s->repeat = atoi(av[1]);
401 36
                        av++;
402 36
                        continue;
403
                }
404 1481
                if (!strcmp(*av, "-listen")) {
405 0
                        if (s->sock >= 0)
406 0
                                VTCP_close(&s->sock);
407 0
                        bprintf(s->listen, "%s", av[1]);
408 0
                        av++;
409 0
                        continue;
410
                }
411 1481
                if (!strcmp(*av, "-start")) {
412 746
                        server_start(s);
413 746
                        continue;
414
                }
415 735
                if (!strcmp(*av, "-dispatch")) {
416 1
                        if (strcmp(s->name, "s0"))
417 0
                                vtc_fatal(s->vl,
418
                                    "server -dispatch only works on s0");
419 1
                        server_dispatch(s);
420 1
                        continue;
421
                }
422 734
                if (**av == '-')
423 0
                        vtc_fatal(s->vl, "Unknown server argument: %s", *av);
424 734
                s->spec = *av;
425
        }
426
}
427
428
void
429 678
init_server(void)
430
{
431 678
        AZ(pthread_mutex_init(&server_mtx, NULL));
432 678
}