fix
[libexssl.git] / src / libexssl / sslwnet.c
blob3481d8a4f0f199b66b1ba30f8483453751c2d304
1 #include "sslnet.h"
3 static __thread str_t *errmsg = NULL;
4 __thread int ssl_errno = 0;
6 __attribute__ ((destructor))
7 static void sslw_free_err () {
8 if (errmsg)
9 free(errmsg);
12 static int adderr (const char *str, size_t len, void *userdata) {
13 if (errmsg)
14 strnadd(&errmsg, str, len);
15 else
16 errmsg = mkstr(str, len, 64);
17 return 0;
20 cstr_t *ssl_error () {
21 if (errmsg)
22 return mkcstr(errmsg->ptr, errmsg->len);
23 return NULL;
26 SSL_CTX *ssl_create (int kind) {
27 const SSL_METHOD *m;
28 switch (kind) {
29 case SSL_CLIENT:
30 m = SSLv23_client_method();
31 break;
32 case SSL_SERVER:
33 m = SSLv23_server_method();
34 break;
35 default:
36 m = SSLv23_method();
37 break;
39 SSL_CTX *ctx = SSL_CTX_new(m);
40 if (!ctx) {
41 if (errmsg) {
42 free(errmsg);
43 errmsg = NULL;
45 ERR_print_errors_cb(adderr, NULL);
47 return ctx;
50 int ssl_config (SSL_CTX *ctx, const char *cert_file, const char *key_file) {
51 int rc;
52 SSL_CTX_set_ecdh_auto(ctx, 1);
53 if ((rc = SSL_CTX_use_certificate_chain_file(ctx, cert_file)) > 0)
54 rc = SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM);
55 if (rc <= 0) {
56 if (errmsg) {
57 free(errmsg);
58 errmsg = NULL;
60 ERR_print_errors_cb(adderr, NULL);
62 return rc > 0 ? 0 : -1;
65 int ssl_accept (SSL_CTX *ctx, int fd, SSL **ssl) {
66 int rc;
67 if (!*ssl) {
68 *ssl = SSL_new(ctx);
69 SSL_set_fd(*ssl, fd);
70 } else
71 if (SSL_is_init_finished(*ssl))
72 return NET_WAIT;
73 rc = SSL_accept(*ssl);
74 if (1 == rc)
75 return 1;
76 switch (SSL_get_error(*ssl, rc)) {
77 case SSL_ERROR_NONE:
78 return 1;
79 case SSL_ERROR_WANT_WRITE:
80 case SSL_ERROR_WANT_READ:
81 return 0;
82 default:
83 if (errmsg) {
84 free(errmsg);
85 errmsg = NULL;
87 ERR_print_errors_cb(adderr, NULL);
88 SSL_shutdown(*ssl);
89 SSL_free(*ssl);
90 *ssl = NULL;
92 return -1;
95 int ssl_connect (SSL_CTX *ctx, int fd, SSL **ssl) {
96 int rc;
97 if (!*ssl) {
98 *ssl = SSL_new(ctx);
99 SSL_set_fd(*ssl, fd);
101 if (SSL_is_init_finished(*ssl))
102 return 0;
103 rc = SSL_connect(*ssl);
104 if (1 == rc)
105 return 1;
106 switch (SSL_get_error(*ssl, rc)) {
107 case SSL_ERROR_NONE:
108 return 1;
109 case SSL_ERROR_WANT_WRITE:
110 case SSL_ERROR_WANT_READ:
111 return 0;
112 default:
113 if (errmsg) {
114 free(errmsg);
115 errmsg = NULL;
117 ERR_print_errors_cb(adderr, NULL);
118 SSL_shutdown(*ssl);
119 SSL_free(*ssl);
120 *ssl = NULL;
122 return -1;
125 ssize_t ssl_recv (SSL *ssl, strbuf_t *buf) {
126 ssize_t readed = -1;
127 int rc;
128 ssl_errno = 0;
129 if (-1 == strbufsize(buf, buf->len + buf->chunk_size, STR_KEEPLEN | STR_REDUCE))
130 return -1;
131 rc = SSL_read_ex(ssl, buf->ptr + buf->len, buf->chunk_size, (size_t*)&readed);
132 if (rc > 0) {
133 buf->len += readed;
134 return readed;
136 switch ((ssl_errno = SSL_get_error(ssl, rc))) {
137 case SSL_ERROR_WANT_READ:
138 case SSL_ERROR_NONE:
139 if (0 == rc)
140 ssl_errno = 0;
141 return 0;
142 case SSL_ERROR_ZERO_RETURN:
143 case SSL_ERROR_SYSCALL:
144 SSL_shutdown(ssl);
145 return -1;
146 default:
147 if (errmsg) {
148 free(errmsg);
149 errmsg = NULL;
151 ERR_print_errors_cb(adderr, NULL);
152 break;
154 return -1;
157 ssize_t ssl_send (SSL *ssl, const void *buf, size_t size) {
158 ssize_t sent = 0, wrote = 0;
159 int rc;
160 ssl_errno = 0;
161 while (sent < size) {
162 rc = SSL_write_ex(ssl, buf, size - sent, (size_t*)&wrote);
163 if (rc > 0) {
164 sent += wrote;
165 buf += wrote;
166 continue;
168 if (0 == rc)
169 continue;
170 if (errmsg) {
171 free(errmsg);
172 errmsg = NULL;
174 ssl_errno = SSL_get_error(ssl, rc);
175 if (SSL_ERROR_WANT_WRITE == ssl_errno)
176 continue;
177 if (SSL_ERROR_ZERO_RETURN == ssl_errno)
178 SSL_shutdown(ssl);
179 ERR_print_errors_cb(adderr, NULL);
180 sent = -1;
182 return sent;
185 int sslws_handshake (SSL *ssl, strbuf_t *buf, strptr_t *url) {
186 int rc = WS_ERROR;
187 ssize_t readed;
188 while ((readed = ssl_recv(ssl, buf)) > 0);
189 if (0 == readed && SSL_ERROR_WANT_READ == ssl_errno)
190 return WS_WAIT;
191 if (-1 == readed)
192 return WS_ERROR;
193 http_request_t req;
194 ws_handshake_t wsh;
195 memset(&req, 0, sizeof req);
196 memset(&wsh, 0, sizeof wsh);
197 switch ((rc = ws_handshake(&req, buf->ptr, buf->len, &wsh))) {
198 case HTTP_LOADED:
199 if (url) {
200 url->ptr = strndup(req.url.ptr, req.url.len);
201 url->len = req.url.len;
203 ws_make_response(buf, &wsh);
204 if ((readed = ssl_send(ssl, buf->ptr, buf->len)) > 0) {
205 rc = WS_OK;
206 buf->len = 0;
207 return rc;
209 rc = WS_ERROR;
210 buf->len = 0;
211 if (url) {
212 if (url->ptr) {
213 free(url->ptr);
214 url->ptr = NULL;
216 url->len = 0;
218 break;
219 case HTTP_ERROR:
220 rc = WS_ERROR;
221 break;
222 default:
223 rc = WS_WAIT;
224 break;
226 return rc;
229 int sslws_recv (SSL *ssl, netbuf_t *nbuf, ws_t *result) {
230 int rc = 0;
231 ssize_t nbytes, ntotal = 0;
232 if ((nbytes = ws_buflen((const uint8_t*)nbuf->buf.ptr, nbuf->buf.len)) > 0) {
233 rc = ws_parse(nbuf->buf.ptr, nbytes, result);
234 wsnet_save_tail(nbuf, nbytes);
235 if (WS_OK == rc)
236 return WS_OK;
237 return WS_WAIT;
239 while ((nbytes = ssl_recv(ssl, &nbuf->buf)) > 0)
240 ntotal += nbytes;
241 if (0 == nbytes && SSL_ERROR_WANT_READ == ssl_errno)
242 return WS_WAIT;
243 if (-1 == nbytes)
244 return WS_ERROR;
245 if (-1 == (nbytes = ws_buflen((const uint8_t*)nbuf->buf.ptr, nbuf->buf.len)))
246 return WS_WAIT;
247 rc = ws_parse(nbuf->buf.ptr, nbytes, result);
248 wsnet_save_tail(nbuf, nbytes);
249 if (WS_OK == rc)
250 return WS_OK;
251 return WS_WAIT;
254 // WS SRV
256 static int sslws_ev_open (int fd, ssl_srv_t *srv, uint32_t flags, http_url_t *h_url) {
257 int rc = NET_ERROR;
258 ssize_t rd;
259 ssl_ev_t *ev = (ssl_ev_t*)&srv->fd_info[fd];
260 str_t *req;
261 strbuf_t buf;
262 if (!(flags & NF_CLIENT))
263 return NET_OK;
264 switch (ssl_connect(srv->ctx_cli, fd, &ev->ssl)) {
265 case -1:
266 return NET_ERROR;
267 case 0:
268 return NET_ERROR;
269 case 1:
270 ev->nf_flags |= NF_SSLACCEPTED;
271 break;
273 req = create_ws_request(h_url);
274 strbufalloc(&buf, SRV_BUF_SIZE, SRV_BUF_SIZE);
275 if (req->len == ssl_send(ev->ssl, req->ptr, req->len)) {
276 while ((rd = ssl_recv(ev->ssl, &buf)) > 0) {
277 if (buf.len > 4 && 0 == cmpstr(buf.ptr+buf.len-4, 4, CONST_STR_LEN("\r\n\r\n"))) { // FIXME : parse response, save tail
278 rc = NET_WAIT;
279 srv->fd_info[fd].nf_flags |= NF_WSCONNECTED;
280 break;
284 free(buf.ptr);
285 free(req);
286 return rc;
289 static int sslws_ev_recv (int fd, ssl_srv_t *srv) {
290 ssl_ev_t *ev = (ssl_ev_t*)&srv->fd_info[fd];
291 if (!(ev->nf_flags & NF_SSLACCEPTED)) {
292 switch (ssl_accept(srv->ctx_srv, fd, &ev->ssl)) {
293 case -1:
294 return NET_ERROR;
295 case 0:
296 return NET_WAIT;
297 case 1:
298 ev->nf_flags |= NF_SSLACCEPTED;
299 //return NET_WAIT;
300 break;
303 if (!(ev->nf_flags & NF_WSCONNECTED)) {
304 strptr_t url = CONST_STR_INIT_NULL;
305 switch (sslws_handshake(ev->ssl, &ev->rd_buf.buf, &url)) {
306 case WS_WAIT:
307 return NET_WAIT;
308 case WS_ERROR:
309 return NET_ERROR;
311 ticket_lock(&ev->locker);
312 ev->nf_flags |= NF_WSCONNECTED;
313 if (ev->rd_buf.buf.ptr) {
314 free(ev->rd_buf.buf.ptr);
315 ev->rd_buf.buf.ptr = NULL;
317 if (url.ptr) {
318 if (srv->on_check_url) {
319 int ver;
320 if (NET_ERROR == (ver = srv->on_check_url(fd, (net_srv_t*)srv, &url))) {
321 ticket_unlock(&ev->locker);
322 free(url.ptr);
323 return NET_ERROR;
325 srv->fd_info[fd].ver = ver;
327 free(url.ptr);
329 ticket_unlock(&ev->locker);
330 return NET_OK;
332 switch (sslws_recv(ev->ssl, &ev->rd_buf, &ev->ws)) {
333 case WS_WAIT:
334 return NET_WAIT;
335 case WS_ERROR:
336 return NET_ERROR;
338 return NET_OK;
341 static int ssl_ev_send (int fd, ssl_srv_t *srv) {
342 ssize_t rc;
343 cstr_t *buf;
344 ssl_ev_t *ev = (ssl_ev_t*)&srv->fd_info[fd];
345 if (!ev->ssl)
346 return NET_OK;
347 ticket_lock(&ev->locker);
348 buf = mkcstr(ev->wr_buf.ptr + ev->wrote, ev->wr_buf.len - ev->wrote);
349 ticket_unlock(&ev->locker);
350 if ((rc = ssl_send(ev->ssl, buf->ptr, buf->len)) > 0)
351 ev->wrote += rc;
352 free(buf);
353 return rc;
356 static int ssl_close_ev (int fd, ssl_srv_t *srv) {
357 ssl_ev_t *ev = (ssl_ev_t*)&srv->fd_info[fd];
358 if (ev->ssl) {
359 SSL_shutdown(ev->ssl);
360 SSL_free(ev->ssl);
361 ev->ssl = NULL;
363 return NET_OK;
366 net_srv_t *sslws_srv_init_ex (const char *svc, size_t srv_size, size_t ev_size, const char *cert_file, const char *key_file) {
367 net_srv_t *srv = net_srv_init(svc, srv_size, ev_size);
368 SSL_CTX *ctx_cli = NULL, *ctx_srv = NULL;
369 if (!srv) return NULL;
370 if (!(ctx_cli = ssl_create(SSL_CLIENT)) ||
371 !(ctx_srv = ssl_create(SSL_SERVER)) ||
372 -1 == ssl_config(ctx_cli, cert_file, key_file) ||
373 -1 == ssl_config(ctx_srv, cert_file, key_file))
374 goto err;
375 ((ssl_srv_t*)srv)->ctx_cli = ctx_cli;
376 ((ssl_srv_t*)srv)->ctx_srv = ctx_srv;
377 srv->on_open = (net_ev_open_h)sslws_ev_open;
378 srv->on_recv = (net_ev_h)sslws_ev_recv;
379 srv->on_send = (net_ev_h)ssl_ev_send;
380 srv->on_recvd = ws_ev_recvd;
381 srv->ev_bufsize = sizeof(ev_buf_t);
382 srv->on_evbuf_set = ws_evbuf_set;
383 srv->on_evbuf_free = ws_rpc_evbuf_free;
384 srv->on_event = ws_rpc_srv_event;
385 srv->on_close_ev = (net_ev_h)ssl_close_ev;
386 srv->msg_info = ws_create_msg_info();
387 return srv;
388 err:
389 if (ctx_srv) SSL_CTX_free(ctx_srv);
390 if (ctx_cli) SSL_CTX_free(ctx_cli);
391 net_srv_done(srv);
392 return NULL;
395 void sslws_srv_done (net_srv_t *srv) {
396 SSL_CTX *ctx;
397 if ((ctx = ((ssl_srv_t*)srv)->ctx_srv))
398 SSL_CTX_free(ctx);
399 if ((ctx = ((ssl_srv_t*)srv)->ctx_cli))
400 SSL_CTX_free(ctx);
401 rbtree_free(srv->msg_info);
402 ws_srv_done(srv);
405 // WS JSONRPC SRV
407 net_srv_t *sslws_jsonrpc_srv_init_ex (const char *svc, size_t srv_size, size_t ev_size, const char *cert_file, const char *key_file) {
408 net_srv_t *srv = sslws_srv_init_ex(svc, srv_size, ev_size, cert_file, key_file);
409 if (srv) {
410 srv->on_evbuf_free = ws_jsonrpc_evbuf_free;
411 srv->on_event = ws_jsonrpc_srv_event;
412 srv->on_check_url = check_api_ver;
414 return srv;