test.c revision 296465
1/* test.c */
2/* $Id: test.c,v 1.1 2001/09/17 19:06:59 bodo Exp $ */
3
4#define L_PORT 9999
5#define C_PORT 443
6
7#include <arpa/inet.h>
8#include <assert.h>
9#include <errno.h>
10#include <fcntl.h>
11#include <netinet/in.h>
12#include <netinet/tcp.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <sys/select.h>
17#include <sys/socket.h>
18#include <unistd.h>
19
20#include "test.h"
21#include "easy-tls.h"
22
23void test_process_init(int fd, int client_p, void *apparg)
24{
25    fprintf(stderr,
26            "test_process_init(fd = %d, client_p = %d, apparg = %p)\n", fd,
27            client_p, apparg);
28}
29
30void test_errflush(int child_p, char *errbuf, size_t num, void *apparg)
31{
32    fputs(errbuf, stderr);
33}
34
35int main(int argc, char *argv[])
36{
37    int s, fd, r;
38    FILE *conn_in;
39    FILE *conn_out;
40    char buf[256];
41    SSL_CTX *ctx;
42    int client_p = 0;
43    int port;
44    int tls = 0;
45    char infobuf[TLS_INFO_SIZE + 1];
46
47    if (argc > 1 && argv[1][0] == '-') {
48        fputs("Usage: test [port]                   -- server\n"
49              "       test num.num.num.num [port]   -- client\n", stderr);
50        exit(1);
51    }
52
53    if (argc > 1) {
54        if (strchr(argv[1], '.')) {
55            client_p = 1;
56        }
57    }
58
59    fputs(client_p ? "Client\n" : "Server\n", stderr);
60
61    {
62        struct tls_create_ctx_args a = tls_create_ctx_defaultargs();
63        a.client_p = client_p;
64        a.certificate_file = "cert.pem";
65        a.key_file = "cert.pem";
66        a.ca_file = "cacerts.pem";
67
68        ctx = tls_create_ctx(a, NULL);
69        if (ctx == NULL)
70            exit(1);
71    }
72
73    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
74    if (s == -1) {
75        perror("socket");
76        exit(1);
77    }
78
79    if (client_p) {
80        struct sockaddr_in addr;
81        size_t addr_len = sizeof addr;
82
83        addr.sin_family = AF_INET;
84        assert(argc > 1);
85        if (argc > 2)
86            sscanf(argv[2], "%d", &port);
87        else
88            port = C_PORT;
89        addr.sin_port = htons(port);
90        addr.sin_addr.s_addr = inet_addr(argv[1]);
91
92        r = connect(s, &addr, addr_len);
93        if (r != 0) {
94            perror("connect");
95            exit(1);
96        }
97        fd = s;
98        fprintf(stderr, "Connect (fd = %d).\n", fd);
99    } else {
100        /* server */
101        {
102            int i = 1;
103
104            r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof i);
105            if (r == -1) {
106                perror("setsockopt");
107                exit(1);
108            }
109        }
110
111        {
112            struct sockaddr_in addr;
113            size_t addr_len = sizeof addr;
114
115            if (argc > 1)
116                sscanf(argv[1], "%d", &port);
117            else
118                port = L_PORT;
119            addr.sin_family = AF_INET;
120            addr.sin_port = htons(port);
121            addr.sin_addr.s_addr = INADDR_ANY;
122
123            r = bind(s, &addr, addr_len);
124            if (r != 0) {
125                perror("bind");
126                exit(1);
127            }
128        }
129
130        r = listen(s, 1);
131        if (r == -1) {
132            perror("listen");
133            exit(1);
134        }
135
136        fprintf(stderr, "Listening at port %i.\n", port);
137
138        fd = accept(s, NULL, 0);
139        if (fd == -1) {
140            perror("accept");
141            exit(1);
142        }
143
144        fprintf(stderr, "Accept (fd = %d).\n", fd);
145    }
146
147    conn_in = fdopen(fd, "r");
148    if (conn_in == NULL) {
149        perror("fdopen");
150        exit(1);
151    }
152    conn_out = fdopen(fd, "w");
153    if (conn_out == NULL) {
154        perror("fdopen");
155        exit(1);
156    }
157
158    setvbuf(conn_in, NULL, _IOLBF, 256);
159    setvbuf(conn_out, NULL, _IOLBF, 256);
160
161    while (fgets(buf, sizeof buf, stdin) != NULL) {
162        if (buf[0] == 'W') {
163            fprintf(conn_out, "%.*s\r\n", (int)(strlen(buf + 1) - 1),
164                    buf + 1);
165            fprintf(stderr, ">>> %.*s\n", (int)(strlen(buf + 1) - 1),
166                    buf + 1);
167        } else if (buf[0] == 'C') {
168            fprintf(stderr, "Closing.\n");
169            fclose(conn_in);
170            fclose(conn_out);
171            exit(0);
172        } else if (buf[0] == 'R') {
173            int lines = 0;
174
175            sscanf(buf + 1, "%d", &lines);
176            do {
177                if (fgets(buf, sizeof buf, conn_in) == NULL) {
178                    if (ferror(conn_in)) {
179                        fprintf(stderr, "ERROR\n");
180                        exit(1);
181                    }
182                    fprintf(stderr, "CLOSED\n");
183                    return 0;
184                }
185                fprintf(stderr, "<<< %s", buf);
186            } while (--lines > 0);
187        } else if (buf[0] == 'T') {
188            int infofd;
189
190            tls++;
191            {
192                struct tls_start_proxy_args a = tls_start_proxy_defaultargs();
193                a.fd = fd;
194                a.client_p = client_p;
195                a.ctx = ctx;
196                a.infofd = &infofd;
197                r = tls_start_proxy(a, NULL);
198            }
199            assert(r != 1);
200            if (r != 0) {
201                fprintf(stderr, "tls_start_proxy failed: %d\n", r);
202                switch (r) {
203                case -1:
204                    fputs("socketpair", stderr);
205                    break;
206                case 2:
207                    fputs("FD_SETSIZE exceeded", stderr);
208                    break;
209                case -3:
210                    fputs("pipe", stderr);
211                    break;
212                case -4:
213                    fputs("fork", stderr);
214                    break;
215                case -5:
216                    fputs("dup2", stderr);
217                    break;
218                default:
219                    fputs("?", stderr);
220                }
221                if (r < 0)
222                    perror("");
223                else
224                    fputc('\n', stderr);
225                exit(1);
226            }
227
228            r = read(infofd, infobuf, sizeof infobuf - 1);
229            if (r > 0) {
230                const char *info = infobuf;
231                const char *eol;
232
233                infobuf[r] = '\0';
234                while ((eol = strchr(info, '\n')) != NULL) {
235                    fprintf(stderr, "+++ `%.*s'\n", eol - info, info);
236                    info = eol + 1;
237                }
238                close(infofd);
239            }
240        } else {
241            fprintf(stderr, "W...  write line to network\n"
242                    "R[n]  read line (n lines) from network\n"
243                    "C     close\n"
244                    "T     start %sTLS proxy\n", tls ? "another " : "");
245        }
246    }
247    return 0;
248}
249