2 * Copyright (C) 2017 Andy Spencer <andy753421@gmail.com>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include <openssl/bio.h>
29 #include <openssl/ssl.h>
35 static int flush(net_t *net)
37 static char buf[NET_BUFFER];
41 if (net->state == NET_READY) {
42 if (net->out_len > 0) {
43 debug("net: flush plain");
44 len = send(net->poll.fd, &net->out_buf[net->out_pos],
45 net->out_len-net->out_pos, 0);
48 if (net->out_pos == net->out_len) {
54 if (net->state == NET_ENCRYPTED) {
55 if (net->out_len > 0) {
56 debug("net: flush crypto");
57 len = SSL_write(net->ssl,
58 &net->out_buf[net->out_pos],
59 net->out_len-net->out_pos);
62 if (net->out_pos == net->out_len) {
68 while ((len = BIO_read(net->out, buf, sizeof(buf))) > 0)
69 send(net->poll.fd, buf, len, 0);
72 /* Enable output poll */
73 if ((net->out_len > 0) &&
74 (net->state == NET_READY ||
75 net->state == NET_ENCRYPTED))
76 poll_ctl(&net->poll, 1, 1, 1);
78 poll_ctl(&net->poll, 1, 0, 1);
83 static void on_poll(void *_net)
85 static char buf[NET_BUFFER];
91 socklen_t elen = sizeof(err);
92 if (getsockopt(net->poll.fd, SOL_SOCKET, SO_ERROR, &err, &elen))
93 error("Error getting socket opt");
98 if (net->state == NET_CONNECT) {
99 debug("net: connect");
100 net->state = NET_READY;
102 if (net->state == NET_READY) {
104 len = recv(net->poll.fd, buf, sizeof(buf), 0);
107 net->recv(net->data, buf, len);
109 if (net->state == NET_HANDSHAKE) {
110 debug("net: handshake");
111 len = recv(net->poll.fd, buf, sizeof(buf), 0);
115 BIO_write(net->in, buf, len);
117 SSL_do_handshake(net->ssl);
119 while ((len = BIO_read(net->out, buf, sizeof(buf))) > 0)
120 send(net->poll.fd, buf, len, 0);
122 if (SSL_is_init_finished(net->ssl))
123 net->state = NET_ENCRYPTED;
126 if (net->state == NET_ENCRYPTED) {
127 debug("net: encrypted");
128 len = recv(net->poll.fd, buf, sizeof(buf), 0);
132 BIO_write(net->in, buf, len);
134 while ((len = SSL_read(net->ssl, buf, sizeof(buf))) > 0)
135 net->recv(net->data, buf, len);
139 /* Networking functions */
140 const char *get_hostname(void)
142 static char hostname[512];
144 if (gethostname(hostname, sizeof(hostname)))
145 error("Error getting hostname");
153 SSL_load_error_strings();
154 ERR_load_BIO_strings();
155 OpenSSL_add_all_algorithms();
158 void net_open(net_t *net, const char *host, int port)
161 struct addrinfo *addrs = NULL;
162 struct addrinfo hints = {};
165 net->host = strcopy(host);
168 snprintf(service, sizeof(service), "%d", net->port);
169 hints.ai_family = AF_INET;
170 hints.ai_socktype = SOCK_STREAM;
173 if (getaddrinfo(net->host, service, &hints, &addrs))
174 error("Error getting net address info");
176 if ((sock = socket(addrs->ai_family,
178 addrs->ai_protocol)) < 0)
179 error("Error opening net socket");
181 if ((flags = fcntl(sock, F_GETFL, 0)) < 0)
182 error("Error getting net socket flags");
184 if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
185 error("Error setting net socket non-blocking");
187 if (connect(sock, addrs->ai_addr, addrs->ai_addrlen) < 0)
188 if (errno != EINPROGRESS)
189 error("Error connecting socket");
194 net->state = NET_CONNECT;
195 poll_add(&net->poll, sock, on_poll, net);
198 void net_encrypt(net_t *net)
200 debug("net: encrypt");
202 net->ctx = SSL_CTX_new(TLSv1_2_client_method());
203 net->ssl = SSL_new(net->ctx);
205 net->in = BIO_new(BIO_s_mem());
206 net->out = BIO_new(BIO_s_mem());
208 BIO_set_mem_eof_return(net->in, -1);
209 BIO_set_mem_eof_return(net->out, -1);
211 SSL_set_bio(net->ssl, net->in, net->out);
212 SSL_set_connect_state(net->ssl);
214 net->state = NET_HANDSHAKE;
217 int net_send(net_t *net, const char *buf, int len)
226 if (len > NET_BUFFER)
228 memcpy(net->out_buf, buf, len);
236 int net_print(net_t *net, const char *fmt, ...)
244 len = vsnprintf(net->out_buf, NET_BUFFER, fmt, ap);
248 if (len > NET_BUFFER)
251 if (net->out_buf[len-1] == '\n')
252 debug("net: print [%.*s]", len-1, net->out_buf);
254 debug("net: print [%.*s]", len, net->out_buf);
262 void net_close(net_t *net)
264 debug("net_close: %s:%d",
265 net->host, net->port);
266 net->state = NET_CLOSED;
267 poll_del(&net->poll);