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