aboutsummaryrefslogtreecommitdiff
path: root/src/forward.c
blob: d81f24c0c651a6dde8153770256f8729d2538407 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "forward.h"
#include "log.h"


int fwd_init_ctx(forward_ctx **ctx, init_cb init_fn)
{
    assert(ctx || init_fn);
    if (!*ctx)
        *ctx = (forward_ctx *) malloc(sizeof(**ctx));
    assert(*ctx);

    memset(*ctx, 0, sizeof(**ctx));
    if (init_fn(*ctx))
        return 1;

    return 0;
}

int fwd_setup_client(forward_ctx *ctx, const char *host, const char *port)
{
    int s;
    struct addrinfo *fwd_addr = NULL;

    assert(ctx);
    ctx->fwd_type = FT_CLIENT;

    s = socket_init_in(host, port, &fwd_addr);
    if (s) {
        E_GAIERR(s, "Could not initialise client forward socket");
        return 1;
    }

    if (!ctx->fwd_cbs.on_listen)
        return 1;
    if (ctx->fwd_cbs.on_listen(ctx, host, port))
        return 1;

    if (socket_connect_in(&ctx->sock, &fwd_addr)) {
        E_STRERR("Connection to forward socket %s:%s", host, port);
        return 1;
    }
    s = socket_addrtostr_in(&ctx->sock, ctx->host_buf, ctx->service_buf);
    if (s) {
        E_GAIERR(s, "Convert forward socket address to string");
        return 1;
    }
    if (socket_close(&ctx->sock)) {
        E_STRERR("Forward socket to %s:%s close",
            ctx->host_buf, ctx->service_buf);
        return 1;
    }

    return 0;
}

int fwd_setup_server(forward_ctx *ctx, const char *listen_addr,
                                       const char *listen_port)
{
    int s;
    struct addrinfo *fwd_addr = NULL;

    assert(ctx);
    ctx->fwd_type = FT_SERVER;

    s = socket_init_in(listen_addr, listen_port, &fwd_addr);
    if (s) {
        E_GAIERR(s, "Could not initialise server forward socket");
        return 1;
    }
    if (socket_bind_in(&ctx->sock, &fwd_addr)) {
        E_STRERR("Could not bind forward server socket to %s:%s",
            listen_addr, listen_port);
        return 1;
    }

    return 0;
}

int fwd_validate_ctx(const forward_ctx *ctx)
{
    assert(ctx);
    assert(ctx->fwd_type == FT_CLIENT ||
           ctx->fwd_type == FT_SERVER);
    assert(ctx->fwd_cbs.on_listen && ctx->fwd_cbs.on_shutdown);
    assert(ctx->sock.addr_len > 0);
    assert(strnlen(ctx->host_buf, NI_MAXHOST) > 0);
    assert(strnlen(ctx->service_buf, NI_MAXSERV) > 0);

    return 0;
}

int fwd_connect_sock(forward_ctx *ctx, psocket *fwd_client)
{
    psocket *dst;

    assert(ctx);
    assert(ctx->fwd_type == FT_CLIENT);
    if (fwd_client) {
        dst = fwd_client;
        socket_clone(&ctx->sock, fwd_client);
    } else {
        dst = &ctx->sock;
    }

    return socket_reconnect_in(dst);
}

int fwd_listen_sock(forward_ctx *ctx, psocket *fwd_server)
{
    psocket *dst;

    assert(ctx);
    assert(ctx->fwd_type == FT_SERVER);
    if (fwd_server) {
        dst = fwd_server;
        socket_clone(&ctx->sock, fwd_server);
    } else {
        dst = &ctx->sock;
    }

    if (socket_listen_in(dst)) {
        E_STRERR("Could not listen on forward server socket on %s:%s",
            ctx->host_buf, ctx->service_buf);
        return 1;
    }

    return 0;
}