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