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

@ -196,6 +196,18 @@ static void connection_read_cb(struct ev_loop *loop, ev_io *w, int revents)
struct uh_buf *buf = &con->read_buf;
char *base;
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)
uh_buf_grow(buf, UH_BUFFER_SIZE);
@ -203,16 +215,9 @@ static void connection_read_cb(struct ev_loop *loop, ev_io *w, int revents)
base = buf->base + buf->len;
len = uh_ssl_read(con, base, UH_BUFFER_SIZE);
if (unlikely(len < 0)) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
return;
uh_log_err("read");
uh_send_error(con, 500, NULL);
return;
}
if (len == 0) {
uh_connection_destroy(con);
if (unlikely(len <= 0)) {
if (con->flags & UH_CON_CLOSE)
uh_connection_destroy(con);
return;
}
@ -236,17 +241,18 @@ static void connection_write_cb(struct ev_loop *loop, ev_io *w, int revents)
if (buf->len > 0) {
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) {
ev_io_stop(loop, w);
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);
}
@ -267,12 +273,9 @@ static void uh_accept_cb(struct ev_loop *loop, ev_io *w, int revents)
con->srv = srv;
list_add(&con->list, &srv->connections);
sock = uh_ssl_accept(srv, con);
if (unlikely(sock < 0)) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
uh_log_err("accept");
sock = uh_ssl_accept(con);
if (unlikely(sock < 0))
goto err;
}
read_watcher = &con->read_watcher;
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)
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)

View File

@ -1,64 +1,65 @@
#ifndef _UHTTP_INTERNAL_H
#define _UHTTP_INTERNAL_H
#include <http_parser.h>
#include "list.h"
#include "uhttp.h"
#define UH_BUFFER_SIZE 2048
#define UH_CONNECTION_TIMEOUT 30
#define UH_MAX_HTTP_HEADERS 20
#define UH_CONNECTION_CLOSE (1 << 0)
#define likely(x) (__builtin_expect(!!(x), 1))
#define unlikely(x) (__builtin_expect(!!(x), 0))
struct uh_route {
char *path;
uh_route_handler_t cb;
struct list_head list;
};
struct uh_server {
int sock;
#if (UHTTP_SSL_ENABLED)
void *ssl_ctx;
#endif
ev_io read_watcher;
struct ev_loop *loop;
struct list_head routes;
struct list_head connections;
};
struct uh_header {
struct uh_value field;
struct uh_value value;
};
struct uh_request {
struct uh_value url;
struct uh_value body;
int header_num;
struct uh_header header[UH_MAX_HTTP_HEADERS];
};
struct uh_connection {
int sock;
#if (UHTTP_SSL_ENABLED)
void *ssl;
#endif
unsigned char flags;
struct uh_buf read_buf;
struct uh_buf write_buf;
ev_io read_watcher;
ev_io write_watcher;
ev_timer timer_watcher;
struct uh_request req;
http_parser parser;
struct list_head list;
struct uh_server *srv;
};
#ifndef _UHTTP_INTERNAL_H
#define _UHTTP_INTERNAL_H
#include <http_parser.h>
#include "list.h"
#include "uhttp.h"
#define UH_BUFFER_SIZE 2048
#define UH_CONNECTION_TIMEOUT 30
#define UH_MAX_HTTP_HEADERS 20
#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 unlikely(x) (__builtin_expect(!!(x), 0))
struct uh_route {
char *path;
uh_route_handler_t cb;
struct list_head list;
};
struct uh_server {
int sock;
#if (UHTTP_SSL_ENABLED)
void *ssl_ctx;
#endif
ev_io read_watcher;
struct ev_loop *loop;
struct list_head routes;
struct list_head connections;
};
struct uh_header {
struct uh_value field;
struct uh_value value;
};
struct uh_request {
struct uh_value url;
struct uh_value body;
int header_num;
struct uh_header header[UH_MAX_HTTP_HEADERS];
};
struct uh_connection {
int sock;
#if (UHTTP_SSL_ENABLED)
void *ssl;
#endif
unsigned char flags;
struct uh_buf read_buf;
struct uh_buf write_buf;
ev_io read_watcher;
ev_io write_watcher;
ev_timer timer_watcher;
struct uh_request req;
http_parser parser;
struct list_head list;
struct uh_server *srv;
};
#endif

View File

@ -20,6 +20,9 @@ int uh_ssl_init(struct uh_server *srv, const char *cert, const char *key)
#if (UHTTP_USE_OPENSSL)
SSL_library_init();
/* registers the error strings for all libssl functions */
SSL_load_error_strings();
/* creates a new SSL_CTX object */
ctx = SSL_CTX_new(SSLv23_server_method());
if (!ctx) {
@ -115,45 +118,115 @@ void uh_ssl_free(struct uh_connection *con)
#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 ret = -1;
#if (UHTTP_SSL_ENABLED)
if (!con->ssl)
return read(con->sock, buf, count);
goto no_ssl;
#endif
#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)
return wolfSSL_read(con->ssl, buf, count);
#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 ret = -1;
#if (UHTTP_SSL_ENABLED)
if (!con->ssl)
return write(con->sock, buf, count);
goto no_ssl;
#endif
#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)
return wolfSSL_write(con->ssl, buf, count);
#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;
struct uh_server *srv = con->srv;
sock = accept4(srv->sock, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (sock < 0)
return sock;
if (unlikely(sock < 0)) {
if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)
uh_log_err("accept4");
return -1;
}
con->sock = sock;
@ -162,17 +235,18 @@ int uh_ssl_accept(struct uh_server *srv, struct uh_connection *con)
return sock;
#endif
#if (UHTTP_USE_OPENSSL)
#if (UHTTP_USE_OPENSSL)
con->ssl = SSL_new(srv->ssl_ctx);
if (!con->ssl)
return -1;
SSL_set_fd(con->ssl, sock);
if (!SSL_accept(con->ssl)) {
uh_log_err("SSL_accept Error: %s", ERR_reason_error_string(ERR_get_error()));
if (!SSL_set_fd(con->ssl, sock)) {
uh_log_err("SSL_set_fd() failed");
return -1;
}
SSL_set_accept_state(con->ssl);
#elif (UHTTP_USE_CYASSL)
con->ssl = wolfSSL_new(srv->ssl_ctx);
if (!con->ssl)
@ -184,3 +258,21 @@ int uh_ssl_accept(struct uh_server *srv, struct uh_connection *con)
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);
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_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