varnish-cache/bin/varnishtest/vtc_tunnel.c
0
/*-
1
 * Copyright (c) 2020 Varnish Software
2
 * All rights reserved.
3
 *
4
 * Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
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/types.h>
34
#include <sys/stat.h>
35
36
#include <errno.h>
37
#include <poll.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <unistd.h>
42
43
#include "vtc.h"
44
45
#include "vsa.h"
46
#include "vtcp.h"
47
48
/* SECTION: tunnel tunnel
49
 *
50
 * The goal of a tunnel is to help control the data transfer between two
51
 * parties, for example to trigger socket timeouts in the middle of protocol
52
 * frames, without the need to change how both parties are implemented.
53
 *
54
 * A tunnel accepts a connection and then connects on behalf of the source to
55
 * the desired destination. Once both connections are established the tunnel
56
 * will transfer bytes unchanged between the source and destination. Transfer
57
 * can be interrupted, usually with the help of synchronization methods like
58
 * barriers. Once the transfer is paused, it is possible to let a specific
59
 * amount of bytes move in either direction.
60
 *
61
 * SECTION: tunnel.args Arguments
62
 *
63
 * \-start
64
 *        Start the tunnel in background, processing the last given
65
 *        specification.
66
 *
67
 * \-start+pause
68
 *        Start the tunnel, but already paused.
69
 *
70
 * \-wait
71
 *        Block until the thread finishes.
72
 *
73
 * \-listen STRING
74
 *        Dictate the listening socket for the server. STRING is of the form
75
 *        "IP PORT", or "HOST PORT".
76
 *
77
 *        Listens by defaults to a local random port.
78
 *
79
 * \-connect STRING
80
 *        Indicate the server to connect to. STRING is also of the form
81
 *        "IP PORT", or "HOST PORT".
82
 *
83
 *        Connects by default to a varnish instance called ``v1``.
84
 *
85
 * SECTION: tunnel.spec Specification
86
 *
87
 * The specification contains a list of tunnel commands that can be combined
88
 * with barriers and delays. For example::
89
 *
90
 *     tunnel t1 {
91
 *         barrier b1 sync
92
 *         pause
93
 *         delay 1
94
 *         send 42
95
 *         barrier b2 sync
96
 *         resume
97
 *     } -start
98
 *
99
 * If one end of the tunnel is closed before the end of the specification
100
 * the test case will fail. A specification that ends in a paused state will
101
 * implicitely resume the tunnel.
102
 */
103
104
enum tunnel_state_e {
105
        TUNNEL_ACCEPT,
106
        TUNNEL_RUNNING,
107
        TUNNEL_PAUSED,
108
        TUNNEL_SPEC_DONE,
109
        TUNNEL_POLL_DONE,
110
        TUNNEL_STOPPED,
111
};
112
113
struct tunnel_lane {
114
        char                    buf[1024];
115
        ssize_t                 buf_len;
116
        size_t                  wrk_len;
117
        int                     *rfd;
118
        int                     *wfd;
119
};
120
121
struct tunnel {
122
        unsigned                magic;
123
#define TUNNEL_MAGIC            0x7f59913d
124
        char                    *name;
125
        struct vtclog           *vl;
126
        VTAILQ_ENTRY(tunnel)    list;
127
        enum tunnel_state_e     state;
128
        unsigned                start_paused;
129
130
        char                    *spec;
131
132
        char                    connect[256];
133
        int                     csock;
134
135
        char                    listen[256];
136
        int                     lsock;
137
        char                    laddr[VTCP_ADDRBUFSIZE];
138
        char                    lport[VTCP_PORTBUFSIZE];
139
140
        int                     asock;
141
142
        struct tunnel_lane      send_lane[1];
143
        struct tunnel_lane      recv_lane[1];
144
145
        pthread_mutex_t         mtx;            /* state and lanes->*_len */
146
        pthread_cond_t          cond;
147
        pthread_t               tspec;
148
        pthread_t               tpoll;
149
};
150
151
static pthread_mutex_t          tunnel_mtx;
152
153
static VTAILQ_HEAD(, tunnel)    tunnels = VTAILQ_HEAD_INITIALIZER(tunnels);
154
155
/**********************************************************************
156
 * Is the tunnel still operating?
157
 */
158
159
static unsigned
160 1641
tunnel_is_open(struct tunnel *t)
161
{
162
        unsigned is_open;
163
164 1641
        PTOK(pthread_mutex_lock(&t->mtx));
165 1641
        is_open = (t->send_lane->buf_len >= 0 && t->recv_lane->buf_len >= 0);
166 1641
        PTOK(pthread_mutex_unlock(&t->mtx));
167 1641
        return (is_open);
168
}
169
170
/**********************************************************************
171
 * SECTION: tunnel.spec.pause
172
 *
173
 * pause
174
 *         Wait for in-flight bytes to be transferred and pause the tunnel.
175
 *
176
 *         The tunnel must be running.
177
 */
178
179
static void
180 150
cmd_tunnel_pause(CMD_ARGS)
181
{
182
        struct tunnel *t;
183
184 150
        CAST_OBJ_NOTNULL(t, priv, TUNNEL_MAGIC);
185 150
        AZ(av[1]);
186
187 150
        if (!tunnel_is_open(t))
188 0
                vtc_fatal(vl, "Tunnel already closed");
189
190 150
        PTOK(pthread_mutex_lock(&t->mtx));
191 150
        if (t->state == TUNNEL_PAUSED) {
192 0
                PTOK(pthread_mutex_unlock(&t->mtx));
193 0
                vtc_fatal(vl, "Tunnel already paused");
194
        }
195 150
        assert(t->state == TUNNEL_RUNNING);
196 150
        t->state = TUNNEL_PAUSED;
197 150
        PTOK(pthread_cond_signal(&t->cond));
198 150
        PTOK(pthread_cond_wait(&t->cond, &t->mtx));
199 150
        PTOK(pthread_mutex_unlock(&t->mtx));
200 150
}
201
202
/**********************************************************************
203
 * SECTION: tunnel.spec.send
204
 *
205
 * send NUMBER
206
 *         Wait until NUMBER bytes are transferred from source to
207
 *         destination.
208
 *
209
 *         The tunnel must be paused, it remains paused afterwards.
210
 */
211
212
static void
213 250
cmd_tunnel_send(CMD_ARGS)
214
{
215
        struct tunnel *t;
216
        unsigned len;
217
218 250
        CAST_OBJ_NOTNULL(t, priv, TUNNEL_MAGIC);
219 250
        AN(av[1]);
220 250
        AZ(av[2]);
221
222 250
        len = atoi(av[1]);
223
224 250
        if (!tunnel_is_open(t))
225 0
                vtc_fatal(vl, "Tunnel already closed");
226
227 250
        PTOK(pthread_mutex_lock(&t->mtx));
228 250
        if (t->state == TUNNEL_RUNNING) {
229 0
                PTOK(pthread_mutex_unlock(&t->mtx));
230 0
                vtc_fatal(vl, "Tunnel still running");
231
        }
232 250
        assert(t->state == TUNNEL_PAUSED);
233 250
        AZ(t->send_lane->wrk_len);
234 250
        AZ(t->recv_lane->wrk_len);
235 250
        if (!strcmp(av[0], "send"))
236 125
                t->send_lane->wrk_len = len;
237
        else
238 125
                t->recv_lane->wrk_len = len;
239 250
        PTOK(pthread_cond_signal(&t->cond));
240 250
        PTOK(pthread_cond_wait(&t->cond, &t->mtx));
241 250
        PTOK(pthread_mutex_unlock(&t->mtx));
242 250
}
243
244
/**********************************************************************
245
 * SECTION: tunnel.spec.recv
246
 *
247
 * recv NUMBER
248
 *         Wait until NUMBER bytes are transferred from destination to
249
 *         source.
250
 *
251
 *         The tunnel must be paused, it remains paused afterwards.
252
 */
253
254
static void
255 125
cmd_tunnel_recv(CMD_ARGS)
256
{
257
258 125
        cmd_tunnel_send(av, priv, vl);
259 125
}
260
261
/**********************************************************************
262
 * SECTION: tunnel.spec.resume
263
 *
264
 * resume
265
 *         Resume the transfer of bytes in both directions.
266
 *
267
 *         The tunnel must be paused.
268
 */
269
270
static void
271 175
cmd_tunnel_resume(CMD_ARGS)
272
{
273
        struct tunnel *t;
274
275 175
        CAST_OBJ_NOTNULL(t, priv, TUNNEL_MAGIC);
276 175
        AZ(av[1]);
277
278 175
        if (!tunnel_is_open(t))
279 0
                vtc_fatal(vl, "Tunnel already closed");
280
281 175
        PTOK(pthread_mutex_lock(&t->mtx));
282 175
        if (t->state == TUNNEL_RUNNING) {
283 0
                PTOK(pthread_mutex_unlock(&t->mtx));
284 0
                vtc_fatal(vl, "Tunnel already running");
285
        }
286 175
        assert(t->state == TUNNEL_PAUSED);
287 175
        t->state = TUNNEL_RUNNING;
288 175
        PTOK(pthread_cond_signal(&t->cond));
289 175
        PTOK(pthread_mutex_unlock(&t->mtx));
290 175
}
291
292
static const struct cmds tunnel_cmds[] = {
293
#define CMD_TUNNEL(n) { #n, cmd_tunnel_##n },
294
        CMD_TUNNEL(pause)
295
        CMD_TUNNEL(send)
296
        CMD_TUNNEL(recv)
297
        CMD_TUNNEL(resume)
298
#undef CMD_TUNNEL
299
        { NULL, NULL }
300
};
301
302
/**********************************************************************
303
 * Tunnel poll thread
304
 */
305
306
static void
307 1932
tunnel_read(struct tunnel *t, struct vtclog *vl, const struct pollfd *pfd,
308
    struct tunnel_lane *lane)
309
{
310
        size_t len;
311
        ssize_t res;
312
        enum tunnel_state_e state;
313
314 1932
        assert(pfd->fd == *lane->rfd);
315 1932
        if (!(pfd->revents & POLLIN))
316 1132
                return;
317
318 800
        PTOK(pthread_mutex_lock(&t->mtx));
319 800
        AZ(lane->buf_len);
320 800
        len = lane->wrk_len;
321 800
        state = t->state;
322 800
        PTOK(pthread_mutex_unlock(&t->mtx));
323
324 800
        if (len == 0 && state == TUNNEL_PAUSED)
325 250
                return;
326
327 550
        if (len == 0 || len > sizeof lane->buf)
328 300
                len = sizeof lane->buf;
329
330 550
        res = read(pfd->fd, lane->buf, len);
331 550
        if (res < 0)
332 0
                vtc_fatal(vl, "Read failed: %s", strerror(errno));
333
334 550
        PTOK(pthread_mutex_lock(&t->mtx));
335 550
        lane->buf_len = (res == 0) ? -1 : res;
336 550
        PTOK(pthread_mutex_unlock(&t->mtx));
337 1932
}
338
339
static void
340 1932
tunnel_write(struct tunnel *t, struct vtclog *vl, struct tunnel_lane *lane,
341
    const char *action)
342
{
343
        const char *p;
344
        ssize_t res, l;
345
346 1932
        p = lane->buf;
347 1932
        l = lane->buf_len;
348
349 1932
        if (l > 0)
350 450
                vtc_log(vl, 3, "%s %zd bytes", action, l);
351 2382
        while (l > 0) {
352 450
                res = write(*lane->wfd, p, l);
353 450
                if (res <= 0)
354 0
                        vtc_fatal(vl, "Write failed: %s", strerror(errno));
355 450
                l -= res;
356 450
                p += res;
357
        }
358
359 1932
        PTOK(pthread_mutex_lock(&t->mtx));
360 1932
        if (lane->wrk_len > 0 && lane->buf_len != -1) {
361 500
                assert(lane->buf_len >= 0);
362 500
                assert(lane->wrk_len >= (size_t)lane->buf_len);
363 500
                lane->wrk_len -= lane->buf_len;
364 500
        }
365 1932
        lane->buf_len = l;
366 1932
        PTOK(pthread_mutex_unlock(&t->mtx));
367 1932
}
368
369
static void *
370 100
tunnel_poll_thread(void *priv)
371
{
372
        struct tunnel *t;
373
        struct vtclog *vl;
374
        struct pollfd pfd[2];
375
        enum tunnel_state_e state;
376
        int res;
377
378 100
        CAST_OBJ_NOTNULL(t, priv, TUNNEL_MAGIC);
379
380 100
        vl = vtc_logopen("%s", t->name);
381 100
        pthread_cleanup_push(vtc_logclose, vl);
382
383 1066
        while (tunnel_is_open(t) && !vtc_stop) {
384 966
                PTOK(pthread_mutex_lock(&t->mtx));
385
                /* NB: can be woken up by `tunnel tX -wait` */
386 1076
                while (t->state == TUNNEL_ACCEPT && !vtc_stop)
387 110
                        PTOK(pthread_cond_wait(&t->cond, &t->mtx));
388 966
                state = t->state;
389 966
                PTOK(pthread_mutex_unlock(&t->mtx));
390
391 966
                if (vtc_stop)
392 0
                        break;
393
394 966
                assert(state < TUNNEL_POLL_DONE);
395
396 966
                memset(pfd, 0, sizeof pfd);
397 966
                pfd[0].fd = *t->send_lane->rfd;
398 966
                pfd[1].fd = *t->recv_lane->rfd;
399 966
                pfd[0].events = POLLIN;
400 966
                pfd[1].events = POLLIN;
401 966
                res = poll(pfd, 2, 100);
402 966
                if (res == -1)
403 0
                        vtc_fatal(vl, "Poll failed: %s", strerror(errno));
404
405 966
                tunnel_read(t, vl, &pfd[0], t->send_lane);
406 966
                tunnel_read(t, vl, &pfd[1], t->recv_lane);
407
408 966
                PTOK(pthread_mutex_lock(&t->mtx));
409 966
                if (t->state == TUNNEL_PAUSED && t->send_lane->wrk_len == 0 &&
410 525
                    t->recv_lane->wrk_len == 0) {
411 400
                        AZ(t->send_lane->buf_len);
412 400
                        AZ(t->recv_lane->buf_len);
413 400
                        PTOK(pthread_cond_signal(&t->cond));
414 400
                        PTOK(pthread_cond_wait(&t->cond, &t->mtx));
415 400
                }
416 966
                PTOK(pthread_mutex_unlock(&t->mtx));
417
418 966
                if (vtc_stop)
419 0
                        break;
420
421 966
                tunnel_write(t, vl, t->send_lane, "Sending");
422 966
                tunnel_write(t, vl, t->recv_lane, "Receiving");
423
        }
424
425 100
        PTOK(pthread_mutex_lock(&t->mtx));
426 100
        if (t->state != TUNNEL_SPEC_DONE && !vtc_stop) {
427 0
                PTOK(pthread_cond_signal(&t->cond));
428 0
                PTOK(pthread_cond_wait(&t->cond, &t->mtx));
429 0
        }
430 100
        PTOK(pthread_mutex_unlock(&t->mtx));
431
432 100
        pthread_cleanup_pop(0);
433 100
        vtc_logclose(vl);
434 100
        t->state = TUNNEL_POLL_DONE;
435 100
        return (NULL);
436
}
437
438
/**********************************************************************
439
 * Tunnel spec thread
440
 */
441
442
static void
443 100
tunnel_accept(struct tunnel *t, struct vtclog *vl)
444
{
445
        struct vsb *vsb;
446
        const char *addr, *err;
447
        int afd, cfd;
448
449 100
        CHECK_OBJ_NOTNULL(t, TUNNEL_MAGIC);
450 100
        assert(t->lsock >= 0);
451 100
        assert(t->asock < 0);
452 100
        assert(t->csock < 0);
453 100
        assert(t->state == TUNNEL_ACCEPT);
454
455 100
        vtc_log(vl, 4, "Accepting");
456 100
        afd = accept(t->lsock, NULL, NULL);
457 100
        if (afd < 0)
458 0
                vtc_fatal(vl, "Accept failed: %s", strerror(errno));
459 100
        vtc_log(vl, 3, "Accepted socket fd is %d", afd);
460
461 100
        vsb = macro_expand(vl, t->connect);
462 100
        AN(vsb);
463 100
        addr = VSB_data(vsb);
464
465 100
        cfd = VTCP_open(addr, NULL, 10., &err);
466 100
        if (cfd < 0)
467 0
                vtc_fatal(vl, "Failed to open %s: %s", addr, err);
468 100
        vtc_log(vl, 3, "Connected socket fd is %d", cfd);
469 100
        VSB_destroy(&vsb);
470
471 100
        VTCP_blocking(afd);
472 100
        VTCP_blocking(cfd);
473
474 100
        PTOK(pthread_mutex_lock(&t->mtx));
475 100
        t->asock = afd;
476 100
        t->csock = cfd;
477 100
        t->send_lane->buf_len = 0;
478 100
        t->send_lane->wrk_len = 0;
479 100
        t->recv_lane->buf_len = 0;
480 100
        t->recv_lane->wrk_len = 0;
481 100
        if (t->start_paused) {
482 25
                t->state = TUNNEL_PAUSED;
483 25
                t->start_paused = 0;
484 25
        } else
485 75
                t->state = TUNNEL_RUNNING;
486 100
        PTOK(pthread_cond_signal(&t->cond));
487 100
        PTOK(pthread_mutex_unlock(&t->mtx));
488 100
}
489
490
static void *
491 100
tunnel_spec_thread(void *priv)
492
{
493
        struct tunnel *t;
494
        struct vtclog *vl;
495
        enum tunnel_state_e state;
496
497 100
        CAST_OBJ_NOTNULL(t, priv, TUNNEL_MAGIC);
498 100
        AN(*t->connect);
499
500 100
        vl = vtc_logopen("%s", t->name);
501 100
        vtc_log_set_cmd(vl, tunnel_cmds);
502 100
        pthread_cleanup_push(vtc_logclose, vl);
503
504 100
        tunnel_accept(t, vl);
505 100
        parse_string(vl, t, t->spec);
506
507 100
        PTOK(pthread_mutex_lock(&t->mtx));
508 100
        state = t->state;
509 100
        PTOK(pthread_mutex_unlock(&t->mtx));
510
511 100
        if (state == TUNNEL_PAUSED && !vtc_stop)
512 50
                parse_string(vl, t, "resume");
513
514 100
        PTOK(pthread_mutex_lock(&t->mtx));
515 100
        t->state = TUNNEL_SPEC_DONE;
516 100
        PTOK(pthread_cond_signal(&t->cond));
517 100
        PTOK(pthread_mutex_unlock(&t->mtx));
518
519 100
        vtc_log(vl, 2, "Ending");
520 100
        pthread_cleanup_pop(0);
521 100
        vtc_logclose(vl);
522 100
        return (NULL);
523
}
524
525
/**********************************************************************
526
 * Tunnel management
527
 */
528
529
static struct tunnel *
530 75
tunnel_new(const char *name)
531
{
532
        struct tunnel *t;
533
534 75
        ALLOC_OBJ(t, TUNNEL_MAGIC);
535 75
        AN(t);
536 75
        REPLACE(t->name, name);
537 75
        t->vl = vtc_logopen("%s", name);
538 75
        AN(t->vl);
539
540 75
        t->state = TUNNEL_STOPPED;
541 75
        bprintf(t->connect, "%s", "${v1_sock}");
542 75
        bprintf(t->listen, "%s", default_listen_addr);
543 75
        t->csock = -1;
544 75
        t->lsock = -1;
545 75
        t->asock = -1;
546 75
        t->send_lane->rfd = &t->asock;
547 75
        t->send_lane->wfd = &t->csock;
548 75
        t->recv_lane->rfd = &t->csock;
549 75
        t->recv_lane->wfd = &t->asock;
550 75
        PTOK(pthread_mutex_init(&t->mtx, NULL));
551 75
        PTOK(pthread_cond_init(&t->cond, NULL));
552 75
        PTOK(pthread_mutex_lock(&tunnel_mtx));
553 75
        VTAILQ_INSERT_TAIL(&tunnels, t, list);
554 75
        PTOK(pthread_mutex_unlock(&tunnel_mtx));
555 75
        return (t);
556
}
557
558
static void
559 75
tunnel_delete(struct tunnel *t)
560
{
561
562 75
        CHECK_OBJ_NOTNULL(t, TUNNEL_MAGIC);
563 75
        assert(t->asock < 0);
564 75
        assert(t->csock < 0);
565 75
        if (t->lsock >= 0)
566 75
                VTCP_close(&t->lsock);
567 75
        macro_undef(t->vl, t->name, "addr");
568 75
        macro_undef(t->vl, t->name, "port");
569 75
        macro_undef(t->vl, t->name, "sock");
570 75
        vtc_logclose(t->vl);
571 75
        (void)pthread_mutex_destroy(&t->mtx);
572 75
        (void)pthread_cond_destroy(&t->cond);
573 75
        free(t->name);
574 75
        FREE_OBJ(t);
575 75
}
576
577
/**********************************************************************
578
 * Tunnel listen
579
 */
580
581
static void
582 100
tunnel_listen(struct tunnel *t)
583
{
584 100
        char buf[vsa_suckaddr_len];
585
        const struct suckaddr *sua;
586
        const char *err;
587
588 100
        if (t->lsock >= 0)
589 25
                VTCP_close(&t->lsock);
590 100
        t->lsock = VTCP_listen_on(t->listen, "0", 1, &err);
591 100
        if (err != NULL)
592 0
                vtc_fatal(t->vl,
593
                    "Tunnel listen address (%s) cannot be resolved: %s",
594 0
                    t->listen, err);
595 100
        assert(t->lsock > 0);
596 100
        sua = VSA_getsockname(t->lsock, buf, sizeof buf);
597 100
        AN(sua);
598 100
        VTCP_name(sua, t->laddr, sizeof t->laddr, t->lport, sizeof t->lport);
599
600
        /* Record the actual port, and reuse it on subsequent starts */
601 100
        if (VSA_Get_Proto(sua) == AF_INET)
602 100
                bprintf(t->listen, "%s:%s", t->laddr, t->lport);
603
        else
604 0
                bprintf(t->listen, "[%s]:%s", t->laddr, t->lport);
605
606 100
        macro_def(t->vl, t->name, "addr", "%s", t->laddr);
607 100
        macro_def(t->vl, t->name, "port", "%s", t->lport);
608 100
        macro_def(t->vl, t->name, "sock", "%s %s", t->laddr, t->lport);
609 100
}
610
611
/**********************************************************************
612
 * Start the tunnel thread
613
 */
614
615
static void
616 100
tunnel_start(struct tunnel *t)
617
{
618
619 100
        CHECK_OBJ_NOTNULL(t, TUNNEL_MAGIC);
620 100
        vtc_log(t->vl, 2, "Starting tunnel");
621 100
        tunnel_listen(t);
622 100
        vtc_log(t->vl, 1, "Listen on %s", t->listen);
623 100
        assert(t->state == TUNNEL_STOPPED);
624 100
        t->state = TUNNEL_ACCEPT;
625 100
        t->send_lane->buf_len = 0;
626 100
        t->send_lane->wrk_len = 0;
627 100
        t->recv_lane->buf_len = 0;
628 100
        t->recv_lane->wrk_len = 0;
629 100
        PTOK(pthread_create(&t->tpoll, NULL, tunnel_poll_thread, t));
630 100
        PTOK(pthread_create(&t->tspec, NULL, tunnel_spec_thread, t));
631 100
}
632
633
static void
634 25
tunnel_start_pause(struct tunnel *t)
635
{
636
637 25
        CHECK_OBJ_NOTNULL(t, TUNNEL_MAGIC);
638 25
        t->start_paused = 1;
639 25
        tunnel_start(t);
640 25
}
641
642
/**********************************************************************
643
 * Wait for tunnel thread to stop
644
 */
645
646
static void
647 100
tunnel_wait(struct tunnel *t)
648
{
649
        void *res;
650
651 100
        CHECK_OBJ_NOTNULL(t, TUNNEL_MAGIC);
652 100
        vtc_log(t->vl, 2, "Waiting for tunnel");
653
654 100
        PTOK(pthread_cond_signal(&t->cond));
655
656 100
        PTOK(pthread_join(t->tspec, &res));
657 100
        if (res != NULL && !vtc_stop)
658 0
                vtc_fatal(t->vl, "Tunnel spec returned \"%p\"", res);
659
660 100
        PTOK(pthread_join(t->tpoll, &res));
661 100
        if (res != NULL && !vtc_stop)
662 0
                vtc_fatal(t->vl, "Tunnel poll returned \"%p\"", res);
663
664 100
        if (t->csock >= 0)
665 100
                VTCP_close(&t->csock);
666 100
        if (t->asock >= 0)
667 100
                VTCP_close(&t->asock);
668 100
        t->tspec = 0;
669 100
        t->tpoll = 0;
670 100
        t->state = TUNNEL_STOPPED;
671 100
}
672
673
/**********************************************************************
674
 * Reap tunnel
675
 */
676
677
static void
678 24425
tunnel_reset(void)
679
{
680
        struct tunnel *t;
681
682 24500
        while (1) {
683 24500
                PTOK(pthread_mutex_lock(&tunnel_mtx));
684 24500
                t = VTAILQ_FIRST(&tunnels);
685 24500
                CHECK_OBJ_ORNULL(t, TUNNEL_MAGIC);
686 24500
                if (t != NULL)
687 75
                        VTAILQ_REMOVE(&tunnels, t, list);
688 24500
                PTOK(pthread_mutex_unlock(&tunnel_mtx));
689 24500
                if (t == NULL)
690 24425
                        break;
691
692 75
                if (t->state != TUNNEL_STOPPED)
693 25
                        tunnel_wait(t);
694 75
                tunnel_delete(t);
695
        }
696 24425
}
697
698
/**********************************************************************
699
 * Tunnel command dispatch
700
 */
701
702
void
703 24600
cmd_tunnel(CMD_ARGS)
704
{
705
        struct tunnel *t;
706
707 24600
        (void)priv;
708
709 24600
        if (av == NULL) {
710
                /* Reset and free */
711 24425
                tunnel_reset();
712 24425
                return;
713
        }
714
715 175
        AZ(strcmp(av[0], "tunnel"));
716 175
        av++;
717
718 175
        VTC_CHECK_NAME(vl, av[0], "Tunnel", 't');
719
720 175
        PTOK(pthread_mutex_lock(&tunnel_mtx));
721 200
        VTAILQ_FOREACH(t, &tunnels, list)
722 125
                if (!strcmp(t->name, av[0]))
723 100
                        break;
724 175
        PTOK(pthread_mutex_unlock(&tunnel_mtx));
725 175
        if (t == NULL)
726 75
                t = tunnel_new(av[0]);
727 175
        CHECK_OBJ_NOTNULL(t, TUNNEL_MAGIC);
728 175
        av++;
729
730 475
        for (; *av != NULL; av++) {
731 300
                if (vtc_error)
732 0
                        break;
733 300
                if (!strcmp(*av, "-wait")) {
734 75
                        if (t->state == TUNNEL_STOPPED)
735 0
                                vtc_fatal(t->vl, "Tunnel not -started");
736 75
                        tunnel_wait(t);
737 75
                        continue;
738
                }
739
740
                /* Don't mess with a running tunnel */
741 225
                if (t->state != TUNNEL_STOPPED)
742 0
                        tunnel_wait(t);
743
744 225
                assert(t->state == TUNNEL_STOPPED);
745 225
                if (!strcmp(*av, "-connect")) {
746 50
                        bprintf(t->connect, "%s", av[1]);
747 50
                        av++;
748 50
                        continue;
749
                }
750 175
                if (!strcmp(*av, "-listen")) {
751 0
                        bprintf(t->listen, "%s", av[1]);
752 0
                        av++;
753 0
                        continue;
754
                }
755 175
                if (!strcmp(*av, "-start")) {
756 75
                        tunnel_start(t);
757 75
                        continue;
758
                }
759 100
                if (!strcmp(*av, "-start+pause")) {
760 25
                        tunnel_start_pause(t);
761 25
                        continue;
762
                }
763 75
                if (**av == '-')
764 0
                        vtc_fatal(t->vl, "Unknown tunnel argument: %s", *av);
765 75
                t->spec = *av;
766 75
        }
767 24600
}
768
769
void
770 24425
init_tunnel(void)
771
{
772
773 24425
        PTOK(pthread_mutex_init(&tunnel_mtx, NULL));
774 24425
}