3 static __thread str_t
*errmsg
= NULL
;
4 __thread
int ssl_errno
= 0;
6 __attribute__ ((destructor
))
7 static void sslw_free_err () {
12 static int adderr (const char *str
, size_t len
, void *userdata
) {
14 strnadd(&errmsg
, str
, len
);
16 errmsg
= mkstr(str
, len
, 64);
20 cstr_t
*ssl_error () {
22 return mkcstr(errmsg
->ptr
, errmsg
->len
);
26 SSL_CTX
*ssl_create (int kind
) {
30 m
= SSLv23_client_method();
33 m
= SSLv23_server_method();
39 SSL_CTX
*ctx
= SSL_CTX_new(m
);
45 ERR_print_errors_cb(adderr
, NULL
);
50 int ssl_config (SSL_CTX
*ctx
, const char *cert_file
, const char *key_file
) {
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
);
60 ERR_print_errors_cb(adderr
, NULL
);
62 return rc
> 0 ? 0 : -1;
65 int ssl_accept (SSL_CTX
*ctx
, int fd
, SSL
**ssl
) {
71 if (SSL_is_init_finished(*ssl
))
73 rc
= SSL_accept(*ssl
);
76 switch (SSL_get_error(*ssl
, rc
)) {
79 case SSL_ERROR_WANT_WRITE
:
80 case SSL_ERROR_WANT_READ
:
87 ERR_print_errors_cb(adderr
, NULL
);
95 int ssl_connect (SSL_CTX
*ctx
, int fd
, SSL
**ssl
) {
101 if (SSL_is_init_finished(*ssl
))
103 rc
= SSL_connect(*ssl
);
106 switch (SSL_get_error(*ssl
, rc
)) {
109 case SSL_ERROR_WANT_WRITE
:
110 case SSL_ERROR_WANT_READ
:
117 ERR_print_errors_cb(adderr
, NULL
);
125 ssize_t
ssl_recv (SSL
*ssl
, strbuf_t
*buf
) {
129 if (-1 == strbufsize(buf
, buf
->len
+ buf
->chunk_size
, STR_KEEPLEN
| STR_REDUCE
))
131 rc
= SSL_read_ex(ssl
, buf
->ptr
+ buf
->len
, buf
->chunk_size
, (size_t*)&readed
);
136 switch ((ssl_errno
= SSL_get_error(ssl
, rc
))) {
137 case SSL_ERROR_WANT_READ
:
142 case SSL_ERROR_ZERO_RETURN
:
143 case SSL_ERROR_SYSCALL
:
151 ERR_print_errors_cb(adderr
, NULL
);
157 ssize_t
ssl_send (SSL
*ssl
, const void *buf
, size_t size
) {
158 ssize_t sent
= 0, wrote
= 0;
161 while (sent
< size
) {
162 rc
= SSL_write_ex(ssl
, buf
, size
- sent
, (size_t*)&wrote
);
174 ssl_errno
= SSL_get_error(ssl
, rc
);
175 if (SSL_ERROR_WANT_WRITE
== ssl_errno
)
177 if (SSL_ERROR_ZERO_RETURN
== ssl_errno
)
179 ERR_print_errors_cb(adderr
, NULL
);
185 int sslws_handshake (SSL
*ssl
, strbuf_t
*buf
, strptr_t
*url
) {
188 while ((readed
= ssl_recv(ssl
, buf
)) > 0);
189 if (0 == readed
&& SSL_ERROR_WANT_READ
== ssl_errno
)
195 memset(&req
, 0, sizeof req
);
196 memset(&wsh
, 0, sizeof wsh
);
197 switch ((rc
= ws_handshake(&req
, buf
->ptr
, buf
->len
, &wsh
))) {
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) {
229 int sslws_recv (SSL
*ssl
, netbuf_t
*nbuf
, ws_t
*result
) {
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
);
239 while ((nbytes
= ssl_recv(ssl
, &nbuf
->buf
)) > 0)
241 if (0 == nbytes
&& SSL_ERROR_WANT_READ
== ssl_errno
)
245 if (-1 == (nbytes
= ws_buflen((const uint8_t*)nbuf
->buf
.ptr
, nbuf
->buf
.len
)))
247 rc
= ws_parse(nbuf
->buf
.ptr
, nbytes
, result
);
248 wsnet_save_tail(nbuf
, nbytes
);
256 static int sslws_ev_open (int fd
, ssl_srv_t
*srv
, uint32_t flags
, http_url_t
*h_url
) {
259 ssl_ev_t
*ev
= (ssl_ev_t
*)&srv
->fd_info
[fd
];
262 if (!(flags
& NF_CLIENT
))
264 switch (ssl_connect(srv
->ctx_cli
, fd
, &ev
->ssl
)) {
270 ev
->nf_flags
|= NF_SSLACCEPTED
;
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
279 srv
->fd_info
[fd
].nf_flags
|= NF_WSCONNECTED
;
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
)) {
298 ev
->nf_flags
|= NF_SSLACCEPTED
;
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
)) {
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
;
318 if (srv
->on_check_url
) {
320 if (NET_ERROR
== (ver
= srv
->on_check_url(fd
, (net_srv_t
*)srv
, &url
))) {
321 ticket_unlock(&ev
->locker
);
325 srv
->fd_info
[fd
].ver
= ver
;
329 ticket_unlock(&ev
->locker
);
332 switch (sslws_recv(ev
->ssl
, &ev
->rd_buf
, &ev
->ws
)) {
341 static int ssl_ev_send (int fd
, ssl_srv_t
*srv
) {
344 ssl_ev_t
*ev
= (ssl_ev_t
*)&srv
->fd_info
[fd
];
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)
356 static int ssl_close_ev (int fd
, ssl_srv_t
*srv
) {
357 ssl_ev_t
*ev
= (ssl_ev_t
*)&srv
->fd_info
[fd
];
359 SSL_shutdown(ev
->ssl
);
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
))
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();
389 if (ctx_srv
) SSL_CTX_free(ctx_srv
);
390 if (ctx_cli
) SSL_CTX_free(ctx_cli
);
395 void sslws_srv_done (net_srv_t
*srv
) {
397 if ((ctx
= ((ssl_srv_t
*)srv
)->ctx_srv
))
399 if ((ctx
= ((ssl_srv_t
*)srv
)->ctx_cli
))
401 rbtree_free(srv
->msg_info
);
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
);
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
;