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 <sys/socket.h>
29 #include <netinet/in.h>
30 #include <netinet/tcp.h>
32 #include <openssl/bio.h>
33 #include <openssl/ssl.h>
39 static int flush(net_t *net)
41 static char buf[NET_BUFFER];
45 if (net->state == NET_READY) {
46 if (net->out_len > 0) {
47 debug("net: flush plain");
48 len = send(net->poll.fd, &net->out_buf[net->out_pos],
49 net->out_len-net->out_pos, 0);
52 if (net->out_pos == net->out_len) {
58 if (net->state == NET_ENCRYPTED) {
59 if (net->out_len > 0) {
60 debug("net: flush crypto");
61 len = SSL_write(net->ssl,
62 &net->out_buf[net->out_pos],
63 net->out_len-net->out_pos);
66 if (net->out_pos == net->out_len) {
72 while ((len = BIO_read(net->out, buf, sizeof(buf))) > 0)
73 send(net->poll.fd, buf, len, 0);
79 static void on_poll(void *_net)
81 static char buf[NET_BUFFER];
83 int len, err = 0, done = 0;
87 socklen_t elen = sizeof(err);
88 if (getsockopt(net->poll.fd, SOL_SOCKET, SO_ERROR, &err, &elen))
89 error("Error getting socket opt");
91 debug("Socket error: %s", strerror(err));
96 if (net->state == NET_CONNECT) {
97 debug("net: connect");
98 net->state = NET_READY;
101 if (net->state == NET_READY) {
103 len = recv(net->poll.fd, buf, sizeof(buf), 0);
108 net->recv(net->data, buf, len);
110 if (net->state == NET_ENCRYPT) {
111 debug("net: encrypt");
112 net->state = NET_HANDSHAKE;
114 if (net->state == NET_HANDSHAKE) {
115 debug("net: handshake");
116 len = recv(net->poll.fd, buf, sizeof(buf), 0);
122 BIO_write(net->in, buf, len);
124 SSL_do_handshake(net->ssl);
126 while ((len = BIO_read(net->out, buf, sizeof(buf))) > 0)
127 send(net->poll.fd, buf, len, 0);
129 if (SSL_is_init_finished(net->ssl))
130 net->state = NET_ENCRYPTED;
133 if (net->state == NET_ENCRYPTED) {
134 debug("net: encrypted");
135 len = recv(net->poll.fd, buf, sizeof(buf), 0);
141 BIO_write(net->in, buf, len);
143 while ((len = SSL_read(net->ssl, buf, sizeof(buf))) > 0)
144 net->recv(net->data, buf, len);
149 /* Networking functions */
150 const char *get_hostname(void)
152 static char hostname[512];
154 if (gethostname(hostname, sizeof(hostname)))
155 error("Error getting hostname");
163 SSL_load_error_strings();
164 ERR_load_BIO_strings();
165 OpenSSL_add_all_algorithms();
168 void net_open(net_t *net, const char *host, int port)
171 struct addrinfo *addrs = NULL;
172 struct addrinfo hints = {};
174 int yes = 1, idle = 120;
176 net->host = strcopy(host);
179 snprintf(service, sizeof(service), "%d", net->port);
180 hints.ai_family = AF_INET;
181 hints.ai_socktype = SOCK_STREAM;
184 if (getaddrinfo(net->host, service, &hints, &addrs))
185 error("Error getting net address info");
187 if ((sock = socket(addrs->ai_family,
189 addrs->ai_protocol)) < 0)
190 error("Error opening net socket");
192 if ((flags = fcntl(sock, F_GETFL, 0)) < 0)
193 error("Error getting net socket flags");
195 if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
196 error("Error setting net socket non-blocking");
198 if (setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)) < 0)
199 error("Error setting net socket keepidle");
201 if (setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &yes, sizeof(yes)) < 0)
202 error("Error setting net socket keepintvl");
204 if (setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &yes, sizeof(yes)) < 0)
205 error("Error setting net socket keepcnt");
207 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) < 0)
208 error("Error setting net socket keepalive");
210 if (connect(sock, addrs->ai_addr, addrs->ai_addrlen) < 0)
211 if (errno != EINPROGRESS)
212 error("Error connecting socket");
217 net->state = NET_CONNECT;
218 poll_add(&net->poll, sock, on_poll, net);
221 void net_encrypt(net_t *net)
223 debug("net: encrypt");
225 net->ctx = SSL_CTX_new(TLSv1_2_client_method());
226 net->ssl = SSL_new(net->ctx);
228 net->in = BIO_new(BIO_s_mem());
229 net->out = BIO_new(BIO_s_mem());
231 BIO_set_mem_eof_return(net->in, -1);
232 BIO_set_mem_eof_return(net->out, -1);
234 SSL_set_bio(net->ssl, net->in, net->out);
235 SSL_set_connect_state(net->ssl);
237 net->state = NET_ENCRYPT;
240 int net_send(net_t *net, const char *buf, int len)
249 if (len > NET_BUFFER)
251 memcpy(net->out_buf, buf, len);
259 int net_print(net_t *net, const char *fmt, ...)
267 len = vsnprintf(net->out_buf, NET_BUFFER, fmt, ap);
271 if (len > NET_BUFFER)
274 if (net->out_buf[len-1] == '\n')
275 debug("net: print [%.*s]", len-1, net->out_buf);
277 debug("net: print [%.*s]", len, net->out_buf);
285 void net_close(net_t *net)
287 debug("net_close: %s:%d",
288 net->host, net->port);
289 net->state = NET_CLOSED;
290 poll_del(&net->poll);