add client example code
[project/ustream-ssl.git] / ustream-example-client.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4
5 #include <libubox/usock.h>
6 #include <libubox/uloop.h>
7 #include "ustream-ssl.h"
8
9 static struct uloop_fd fd;
10
11 static struct ustream_fd stream, s_input;
12 static struct ustream_ssl ssl;
13
14 static void *ctx;
15
16 static void client_teardown(void)
17 {
18         if (s_input.fd.registered)
19                 ustream_free(&s_input.stream);
20
21         ustream_free(&ssl.stream);
22         ustream_free(&stream.stream);
23         close(stream.fd.fd);
24         uloop_end();
25 }
26
27 static void client_input_notify_read(struct ustream *s, int bytes)
28 {
29         char *buf;
30         int len;
31
32         buf = ustream_get_read_buf(s, &len);
33         ustream_write(&ssl.stream, buf, len, false);
34         ustream_consume(s, len);
35 }
36
37 static void client_ssl_notify_read(struct ustream *s, int bytes)
38 {
39         char *buf;
40         int len;
41
42         buf = ustream_get_read_buf(s, &len);
43         fwrite(buf, len, 1, stdout);
44         fflush(stdout);
45         ustream_consume(s, len);
46 }
47
48 static void client_notify_connected(struct ustream_ssl *ssl)
49 {
50         fprintf(stderr, "SSL connection established\n");
51         s_input.stream.notify_read = client_input_notify_read;
52         ustream_fd_init(&s_input, 0);
53 }
54
55 static void client_notify_error(struct ustream_ssl *ssl, int error, const char *str)
56 {
57         fprintf(stderr, "SSL connection error(%d): %s\n", error, str);
58         client_teardown();
59 }
60
61 static void client_notify_state(struct ustream *us)
62 {
63         if (!us->write_error && !us->eof)
64                 return;
65
66         fprintf(stderr, "Connection closed\n");
67         client_teardown();
68 }
69
70 static void example_connect_ssl(int fd)
71 {
72         fprintf(stderr, "Starting SSL negnotiation\n");
73
74         ssl.notify_error = client_notify_error;
75         ssl.notify_connected = client_notify_connected;
76         ssl.stream.notify_read = client_ssl_notify_read;
77         ssl.stream.notify_state = client_notify_state;
78
79         ustream_fd_init(&stream, fd);
80         ustream_ssl_init(&ssl, &stream.stream, ctx, false);
81 }
82
83 static void example_connect_cb(struct uloop_fd *f, unsigned int events)
84 {
85         if (fd.eof || fd.error) {
86                 fprintf(stderr, "Connection failed\n");
87                 uloop_end();
88                 return;
89         }
90
91         fprintf(stderr, "Connection established\n");
92         uloop_fd_delete(&fd);
93         example_connect_ssl(fd.fd);
94 }
95
96 static void connect_client(const char *host, const char *port)
97 {
98         fd.fd = usock(USOCK_TCP | USOCK_NONBLOCK, host, port);
99         fd.cb = example_connect_cb;
100         uloop_fd_add(&fd, ULOOP_WRITE | ULOOP_EDGE_TRIGGER);
101 }
102
103 int main(int argc, char **argv)
104 {
105         if (argc != 3) {
106                 fprintf(stderr, "Usage: %s <hostname> <port>\n", argv[0]);
107                 return 1;
108         }
109
110         ctx = ustream_ssl_context_new(false);
111         uloop_init();
112         connect_client(argv[1], argv[2]);
113         uloop_run();
114
115         close(fd.fd);
116         uloop_done();
117         return 0;
118 }