Optimize code for ssl

Signed-off-by: Jianhui Zhao <jianhuizhao329@gmail.com>
main
Jianhui Zhao 2017-11-12 12:56:52 +08:00
parent a393ce2b78
commit d6d2e86f76
4 changed files with 194 additions and 97 deletions

View File

@ -197,22 +197,27 @@ static void connection_read_cb(struct ev_loop *loop, ev_io *w, int revents)
char *base; char *base;
int len, parsered; int len, parsered;
#if (UHTTP_SSL_ENABLED)
if (con->flags & UH_CON_SSL_HANDSHAKE_DONE)
goto handshake_done;
uh_ssl_handshake(con);
if (con->flags & UH_CON_CLOSE)
uh_connection_destroy(con);
return;
handshake_done:
#endif
if (uh_buf_available(buf) < UH_BUFFER_SIZE) if (uh_buf_available(buf) < UH_BUFFER_SIZE)
uh_buf_grow(buf, UH_BUFFER_SIZE); uh_buf_grow(buf, UH_BUFFER_SIZE);
base = buf->base + buf->len; base = buf->base + buf->len;
len = uh_ssl_read(con, base, UH_BUFFER_SIZE); len = uh_ssl_read(con, base, UH_BUFFER_SIZE);
if (unlikely(len < 0)) { if (unlikely(len <= 0)) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) if (con->flags & UH_CON_CLOSE)
return; uh_connection_destroy(con);
uh_log_err("read");
uh_send_error(con, 500, NULL);
return;
}
if (len == 0) {
uh_connection_destroy(con);
return; return;
} }
@ -236,17 +241,18 @@ static void connection_write_cb(struct ev_loop *loop, ev_io *w, int revents)
if (buf->len > 0) { if (buf->len > 0) {
int len = uh_ssl_write(con, buf->base, buf->len); int len = uh_ssl_write(con, buf->base, buf->len);
uh_buf_remove(buf, len); if (len > 0)
uh_buf_remove(buf, len);
} }
if (buf->len == 0) { if (buf->len == 0) {
ev_io_stop(loop, w); ev_io_stop(loop, w);
if (!http_should_keep_alive(&con->parser)) if (!http_should_keep_alive(&con->parser))
con->flags |= UH_CONNECTION_CLOSE; con->flags |= UH_CON_CLOSE;
} }
if (con->flags & UH_CONNECTION_CLOSE) if (con->flags & UH_CON_CLOSE)
uh_connection_destroy(con); uh_connection_destroy(con);
} }
@ -267,12 +273,9 @@ static void uh_accept_cb(struct ev_loop *loop, ev_io *w, int revents)
con->srv = srv; con->srv = srv;
list_add(&con->list, &srv->connections); list_add(&con->list, &srv->connections);
sock = uh_ssl_accept(srv, con); sock = uh_ssl_accept(con);
if (unlikely(sock < 0)) { if (unlikely(sock < 0))
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
uh_log_err("accept");
goto err; goto err;
}
read_watcher = &con->read_watcher; read_watcher = &con->read_watcher;
ev_io_init(read_watcher, connection_read_cb, sock, EV_READ); ev_io_init(read_watcher, connection_read_cb, sock, EV_READ);
@ -443,7 +446,7 @@ void uh_send_error(struct uh_connection *con, int code, const char *reason)
if (parser->method != HTTP_HEAD) if (parser->method != HTTP_HEAD)
uh_send(con, reason, strlen(reason)); uh_send(con, reason, strlen(reason));
con->flags |= UH_CONNECTION_CLOSE; con->flags |= UH_CON_CLOSE;
} }
void uh_redirect(struct uh_connection *con, int code, const char *location) void uh_redirect(struct uh_connection *con, int code, const char *location)

View File

@ -10,7 +10,8 @@
#define UH_CONNECTION_TIMEOUT 30 #define UH_CONNECTION_TIMEOUT 30
#define UH_MAX_HTTP_HEADERS 20 #define UH_MAX_HTTP_HEADERS 20
#define UH_CONNECTION_CLOSE (1 << 0) #define UH_CON_CLOSE (1 << 0)
#define UH_CON_SSL_HANDSHAKE_DONE (1 << 1) /* SSL hanshake has completed */
#define likely(x) (__builtin_expect(!!(x), 1)) #define likely(x) (__builtin_expect(!!(x), 1))
#define unlikely(x) (__builtin_expect(!!(x), 0)) #define unlikely(x) (__builtin_expect(!!(x), 0))

View File

@ -20,6 +20,9 @@ int uh_ssl_init(struct uh_server *srv, const char *cert, const char *key)
#if (UHTTP_USE_OPENSSL) #if (UHTTP_USE_OPENSSL)
SSL_library_init(); SSL_library_init();
/* registers the error strings for all libssl functions */
SSL_load_error_strings();
/* creates a new SSL_CTX object */ /* creates a new SSL_CTX object */
ctx = SSL_CTX_new(SSLv23_server_method()); ctx = SSL_CTX_new(SSLv23_server_method());
if (!ctx) { if (!ctx) {
@ -115,45 +118,115 @@ void uh_ssl_free(struct uh_connection *con)
#endif #endif
} }
#if (UHTTP_SSL_ENABLED)
static int uh_ssl_err(struct uh_connection *con, int ret, const char *fun)
{
int err;
#if (UHTTP_USE_OPENSSL)
err = SSL_get_error(con->ssl, ret);
if (err == SSL_ERROR_ZERO_RETURN || ERR_peek_error()) {
con->flags |= UH_CON_CLOSE;
return 0;
}
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
return -1;
if (err == SSL_ERROR_SYSCALL) {
if (errno > 0)
uh_log_err("%s", fun);
con->flags |= UH_CON_CLOSE;
return -1;
}
con->flags |= UH_CON_CLOSE;
uh_log_err("%s() Error: %s", fun, ERR_reason_error_string(err));
return -1;
#elif (UHTTP_USE_CYASSL)
#endif
}
#endif
int uh_ssl_read(struct uh_connection *con, void *buf, int count) int uh_ssl_read(struct uh_connection *con, void *buf, int count)
{ {
int ret = -1;
#if (UHTTP_SSL_ENABLED) #if (UHTTP_SSL_ENABLED)
if (!con->ssl) if (!con->ssl)
return read(con->sock, buf, count); goto no_ssl;
#endif #endif
#if (UHTTP_USE_OPENSSL) #if (UHTTP_USE_OPENSSL)
return SSL_read(con->ssl, buf, count); ret = SSL_read(con->ssl, buf, count);
if (ret > 0)
return ret;
return uh_ssl_err(con, ret, "SSL_read");
#elif (UHTTP_USE_CYASSL) #elif (UHTTP_USE_CYASSL)
return wolfSSL_read(con->ssl, buf, count); return wolfSSL_read(con->ssl, buf, count);
#endif #endif
return read(con->sock, buf, count); #if (UHTTP_SSL_ENABLED)
no_ssl:
#endif
ret = read(con->sock, buf, count);
if (ret <= 0) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
return ret;
if (ret != 0) {
con->flags |= UH_CON_CLOSE;
uh_log_err("read");
}
}
return ret;
} }
int uh_ssl_write(struct uh_connection *con, void *buf, int count) int uh_ssl_write(struct uh_connection *con, void *buf, int count)
{ {
int ret = -1;
#if (UHTTP_SSL_ENABLED) #if (UHTTP_SSL_ENABLED)
if (!con->ssl) if (!con->ssl)
return write(con->sock, buf, count); goto no_ssl;
#endif #endif
#if (UHTTP_USE_OPENSSL) #if (UHTTP_USE_OPENSSL)
return SSL_write(con->ssl, buf, count); ret = SSL_write(con->ssl, buf, count);
if (ret > 0)
return ret;
return uh_ssl_err(con, ret, "SSL_write");
#elif (UHTTP_USE_CYASSL) #elif (UHTTP_USE_CYASSL)
return wolfSSL_write(con->ssl, buf, count); return wolfSSL_write(con->ssl, buf, count);
#endif #endif
return write(con->sock, buf, count); #if (UHTTP_SSL_ENABLED)
no_ssl:
#endif
ret = write(con->sock, buf, count);
if (ret <= 0) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
return ret;
if (ret != 0) {
con->flags |= UH_CON_CLOSE;
uh_log_err("write");
}
}
return ret;
} }
int uh_ssl_accept(struct uh_server *srv, struct uh_connection *con) int uh_ssl_accept(struct uh_connection *con)
{ {
int sock = -1; int sock = -1;
struct uh_server *srv = con->srv;
sock = accept4(srv->sock, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC); sock = accept4(srv->sock, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (sock < 0) if (unlikely(sock < 0)) {
return sock; if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)
uh_log_err("accept4");
return -1;
}
con->sock = sock; con->sock = sock;
@ -167,12 +240,13 @@ int uh_ssl_accept(struct uh_server *srv, struct uh_connection *con)
if (!con->ssl) if (!con->ssl)
return -1; return -1;
SSL_set_fd(con->ssl, sock); if (!SSL_set_fd(con->ssl, sock)) {
uh_log_err("SSL_set_fd() failed");
if (!SSL_accept(con->ssl)) {
uh_log_err("SSL_accept Error: %s", ERR_reason_error_string(ERR_get_error()));
return -1; return -1;
} }
SSL_set_accept_state(con->ssl);
#elif (UHTTP_USE_CYASSL) #elif (UHTTP_USE_CYASSL)
con->ssl = wolfSSL_new(srv->ssl_ctx); con->ssl = wolfSSL_new(srv->ssl_ctx);
if (!con->ssl) if (!con->ssl)
@ -184,3 +258,21 @@ int uh_ssl_accept(struct uh_server *srv, struct uh_connection *con)
return sock; return sock;
} }
void uh_ssl_handshake(struct uh_connection *con)
{
#if (UHTTP_SSL_ENABLED)
int ret;
#if (UHTTP_USE_OPENSSL)
ret = SSL_do_handshake(con->ssl);
if (ret == 1) {
con->flags |= UH_CON_SSL_HANDSHAKE_DONE;
return;
}
uh_ssl_err(con, ret, "SSL_do_handshake");
#elif (UHTTP_USE_CYASSL)
#endif
#endif
}

View File

@ -7,6 +7,7 @@ void uh_ssl_ctx_free(struct uh_server *srv);
void uh_ssl_free(struct uh_connection *con); void uh_ssl_free(struct uh_connection *con);
int uh_ssl_read(struct uh_connection *con, void *buf, int count); int uh_ssl_read(struct uh_connection *con, void *buf, int count);
int uh_ssl_write(struct uh_connection *con, void *buf, int count); int uh_ssl_write(struct uh_connection *con, void *buf, int count);
int uh_ssl_accept(struct uh_server *srv, struct uh_connection *con); int uh_ssl_accept(struct uh_connection *con);
void uh_ssl_handshake(struct uh_connection *con);
#endif #endif