parent
a393ce2b78
commit
d6d2e86f76
41
src/uhttp.c
41
src/uhttp.c
|
@ -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)
|
||||
|
|
|
@ -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
|
120
src/uhttp_ssl.c
120
src/uhttp_ssl.c
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue