Commit 5825e3ea authored by Sergey Lyubka's avatar Sergey Lyubka

Adding use_ssl to mg_connect()

parent 061ba991
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
// See the GNU General Public License for more details. // See the GNU General Public License for more details.
// //
// Alternatively, you can license this library under a commercial // Alternatively, you can license this library under a commercial
// license, as set out in <http://cesanta.com/products.html>. // license, as set out in <http://cesanta.com/>.
#undef UNICODE // Use ANSI WinAPI functions #undef UNICODE // Use ANSI WinAPI functions
#undef _UNICODE // Use multibyte encoding on Windows #undef _UNICODE // Use multibyte encoding on Windows
...@@ -117,31 +117,10 @@ typedef struct stat file_stat_t; ...@@ -117,31 +117,10 @@ typedef struct stat file_stat_t;
#endif #endif
#ifdef USE_SSL #ifdef USE_SSL
// Following define gets rid of openssl deprecation messages #ifdef __APPLE__
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#ifdef USE_CYASSL
#include <openssl/ssl.h>
#else
typedef struct ssl_ctx_st SSL_CTX;
typedef struct ssl_st SSL;
typedef struct ssl_method_st SSL_METHOD;
extern void __cdecl SSL_free(SSL *);
extern int __cdecl SSL_accept(SSL *);
extern int __cdecl SSL_connect(SSL *);
extern int __cdecl SSL_read(SSL *, void *, int);
extern int __cdecl SSL_write(SSL *, const void *, int);
extern int __cdecl SSL_set_fd(SSL *, int);
extern SSL * __cdecl SSL_new(SSL_CTX *);
extern SSL_CTX * __cdecl SSL_CTX_new(SSL_METHOD *);
extern SSL_METHOD * __cdecl SSLv23_server_method(void);
extern int __cdecl SSL_library_init(void);
extern int __cdecl SSL_CTX_use_PrivateKey_file(SSL_CTX *, const char *, int);
extern int __cdecl SSL_CTX_use_certificate_file(SSL_CTX *, const char *, int);
extern int __cdecl SSL_CTX_use_certificate_chain_file(SSL_CTX *, const char *);
extern void __cdecl SSL_CTX_free(SSL_CTX *);
#endif #endif
#include <openssl/ssl.h>
#endif #endif
#include "mongoose.h" #include "mongoose.h"
...@@ -291,7 +270,10 @@ struct mg_server { ...@@ -291,7 +270,10 @@ struct mg_server {
mg_handler_t error_handler; mg_handler_t error_handler;
char *config_options[NUM_OPTIONS]; char *config_options[NUM_OPTIONS];
void *server_data; void *server_data;
void *ssl_ctx; // SSL context #ifdef USE_SSL
SSL_CTX *ssl_ctx; // Server SSL context
SSL_CTX *client_ssl_ctx; // Client SSL context
#endif
sock_t ctl[2]; // Control socketpair. Used to wake up from select() call sock_t ctl[2]; // Control socketpair. Used to wake up from select() call
}; };
...@@ -339,8 +321,10 @@ struct connection { ...@@ -339,8 +321,10 @@ struct connection {
int64_t cl; // Reply content length, for Range support int64_t cl; // Reply content length, for Range support
int request_len; // Request length, including last \r\n after last header int request_len; // Request length, including last \r\n after last header
int flags; // CONN_* flags: CONN_CLOSE, CONN_SPOOL_DONE, etc int flags; // CONN_* flags: CONN_CLOSE, CONN_SPOOL_DONE, etc
void *ssl; // SSL descriptor
mg_handler_t handler; // Callback for HTTP client mg_handler_t handler; // Callback for HTTP client
#ifdef USE_SSL
SSL *ssl; // SSL descriptor
#endif
}; };
static void close_local_endpoint(struct connection *conn); static void close_local_endpoint(struct connection *conn);
...@@ -3523,11 +3507,20 @@ static void callback_http_client_on_connect(struct connection *conn) { ...@@ -3523,11 +3507,20 @@ static void callback_http_client_on_connect(struct connection *conn) {
int ok; int ok;
socklen_t len = sizeof(ok); socklen_t len = sizeof(ok);
conn->flags &= ~CONN_CONNECTING;
if (getsockopt(conn->client_sock, SOL_SOCKET, SO_ERROR, (char *) &ok, if (getsockopt(conn->client_sock, SOL_SOCKET, SO_ERROR, (char *) &ok,
&len) == 0 && ok == 0) { &len) == 0 && ok == 0) {
conn->mg_conn.status_code = MG_CONNECT_SUCCESS; conn->mg_conn.status_code = MG_CONNECT_SUCCESS;
#ifdef USE_SSL
if (conn->ssl != NULL) {
switch (SSL_connect(conn->ssl)) {
case 1: conn->flags = CONN_SSL_HANDS_SHAKEN; break;
case 0: conn->flags &= ~CONN_CONNECTING; // Call this function again
default: ok = 1; break;
}
}
#endif
} }
conn->flags &= ~CONN_CONNECTING;
if (conn->handler(&conn->mg_conn) || ok != 0) { if (conn->handler(&conn->mg_conn) || ok != 0) {
conn->flags |= CONN_CLOSE; conn->flags |= CONN_CLOSE;
} }
...@@ -3575,7 +3568,7 @@ static void read_from_socket(struct connection *conn) { ...@@ -3575,7 +3568,7 @@ static void read_from_socket(struct connection *conn) {
} }
int mg_connect(struct mg_server *server, const char *host, int port, int mg_connect(struct mg_server *server, const char *host, int port,
mg_handler_t handler, void *param) { int use_ssl, mg_handler_t handler, void *param) {
sock_t sock = INVALID_SOCKET; sock_t sock = INVALID_SOCKET;
struct sockaddr_in sin; struct sockaddr_in sin;
struct hostent *he = NULL; struct hostent *he = NULL;
...@@ -3584,6 +3577,9 @@ int mg_connect(struct mg_server *server, const char *host, int port, ...@@ -3584,6 +3577,9 @@ int mg_connect(struct mg_server *server, const char *host, int port,
if (host == NULL || (he = gethostbyname(host)) == NULL || if (host == NULL || (he = gethostbyname(host)) == NULL ||
(sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) return 0; (sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) return 0;
#ifndef USE_SSL
if (use_ssl) return 0;
#endif
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_port = htons((uint16_t) port); sin.sin_port = htons((uint16_t) port);
...@@ -3606,6 +3602,11 @@ int mg_connect(struct mg_server *server, const char *host, int port, ...@@ -3606,6 +3602,11 @@ int mg_connect(struct mg_server *server, const char *host, int port,
conn->birth_time = conn->last_activity_time = time(NULL); conn->birth_time = conn->last_activity_time = time(NULL);
conn->flags = CONN_CONNECTING; conn->flags = CONN_CONNECTING;
conn->mg_conn.status_code = MG_CONNECT_FAILURE; conn->mg_conn.status_code = MG_CONNECT_FAILURE;
#ifdef USE_SSL
if (use_ssl && (conn->ssl = SSL_new(server->client_ssl_ctx)) != NULL) {
SSL_set_fd(conn->ssl, sock);
}
#endif
LINKED_LIST_ADD_TO_FRONT(&server->active_connections, &conn->link); LINKED_LIST_ADD_TO_FRONT(&server->active_connections, &conn->link);
DBG(("%p %s:%d", conn, host, port)); DBG(("%p %s:%d", conn, host, port));
...@@ -3826,25 +3827,27 @@ void mg_destroy_server(struct mg_server **server) { ...@@ -3826,25 +3827,27 @@ void mg_destroy_server(struct mg_server **server) {
struct ll *lp, *tmp; struct ll *lp, *tmp;
if (server != NULL && *server != NULL) { if (server != NULL && *server != NULL) {
struct mg_server *s = *server;
// Do one last poll, see https://github.com/cesanta/mongoose/issues/286 // Do one last poll, see https://github.com/cesanta/mongoose/issues/286
mg_poll_server(*server, 0); mg_poll_server(s, 0);
closesocket((*server)->listening_sock); closesocket(s->listening_sock);
closesocket((*server)->ctl[0]); closesocket(s->ctl[0]);
closesocket((*server)->ctl[1]); closesocket(s->ctl[1]);
LINKED_LIST_FOREACH(&(*server)->active_connections, lp, tmp) { LINKED_LIST_FOREACH(&s->active_connections, lp, tmp) {
close_conn(LINKED_LIST_ENTRY(lp, struct connection, link)); close_conn(LINKED_LIST_ENTRY(lp, struct connection, link));
} }
LINKED_LIST_FOREACH(&(*server)->uri_handlers, lp, tmp) { LINKED_LIST_FOREACH(&s->uri_handlers, lp, tmp) {
free(LINKED_LIST_ENTRY(lp, struct uri_handler, link)->uri); free(LINKED_LIST_ENTRY(lp, struct uri_handler, link)->uri);
free(LINKED_LIST_ENTRY(lp, struct uri_handler, link)); free(LINKED_LIST_ENTRY(lp, struct uri_handler, link));
} }
for (i = 0; i < (int) ARRAY_SIZE((*server)->config_options); i++) { for (i = 0; i < (int) ARRAY_SIZE(s->config_options); i++) {
free((*server)->config_options[i]); // It is OK to free(NULL) free(s->config_options[i]); // It is OK to free(NULL)
} }
#ifdef USE_SSL #ifdef USE_SSL
if ((*server)->ssl_ctx != NULL) SSL_CTX_free((*server)->ssl_ctx); if (s->ssl_ctx != NULL) SSL_CTX_free((*server)->ssl_ctx);
if (s->client_ssl_ctx != NULL) SSL_CTX_free(s->client_ssl_ctx);
#endif #endif
free(*server); free(s);
*server = NULL; *server = NULL;
} }
} }
...@@ -4130,6 +4133,10 @@ struct mg_server *mg_create_server(void *server_data) { ...@@ -4130,6 +4133,10 @@ struct mg_server *mg_create_server(void *server_data) {
mg_socketpair(server->ctl); mg_socketpair(server->ctl);
} while (server->ctl[0] == INVALID_SOCKET); } while (server->ctl[0] == INVALID_SOCKET);
#ifdef USE_SSL
server->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method());
#endif
server->server_data = server_data; server->server_data = server_data;
server->listening_sock = INVALID_SOCKET; server->listening_sock = INVALID_SOCKET;
set_default_option_values(server->config_options); set_default_option_values(server->config_options);
......
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
// See the GNU General Public License for more details. // See the GNU General Public License for more details.
// //
// Alternatively, you can license this library under a commercial // Alternatively, you can license this library under a commercial
// license, as set out in <http://cesanta.com/products.html>. // license, as set out in <http://cesanta.com/>.
// //
// NOTE: Detailed API documentation is at http://cesanta.com/docs.html // NOTE: Detailed API documentation is at http://cesanta.com/#docs
#ifndef MONGOOSE_HEADER_INCLUDED #ifndef MONGOOSE_HEADER_INCLUDED
#define MONGOOSE_HEADER_INCLUDED #define MONGOOSE_HEADER_INCLUDED
...@@ -106,7 +106,7 @@ enum { ...@@ -106,7 +106,7 @@ enum {
MG_CONNECT_SUCCESS, MG_CONNECT_FAILURE, MG_CONNECT_SUCCESS, MG_CONNECT_FAILURE,
MG_DOWNLOAD_SUCCESS, MG_DOWNLOAD_FAILURE MG_DOWNLOAD_SUCCESS, MG_DOWNLOAD_FAILURE
}; };
int mg_connect(struct mg_server *server, const char *host, int port, int mg_connect(struct mg_server *, const char *host, int port, int use_ssl,
mg_handler_t handler, void *param); mg_handler_t handler, void *param);
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -407,8 +407,8 @@ static const char *test_server(void) { ...@@ -407,8 +407,8 @@ static const char *test_server(void) {
mg_add_uri_handler(server, "/cb1", cb1); mg_add_uri_handler(server, "/cb1", cb1);
mg_set_http_error_handler(server, error_handler); mg_set_http_error_handler(server, error_handler);
ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), ts1, buf1) == 1); ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, ts1, buf1) == 1);
ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), ts2, buf2) == 1); ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, ts2, buf2) == 1);
{ int i; for (i = 0; i < 50; i++) mg_poll_server(server, 0); } { int i; for (i = 0; i < 50; i++) mg_poll_server(server, 0); }
ASSERT(strcmp(buf1, "foo ? 127.0.0.1") == 0); ASSERT(strcmp(buf1, "foo ? 127.0.0.1") == 0);
...@@ -468,9 +468,9 @@ static const char *test_mg_connect(void) { ...@@ -468,9 +468,9 @@ static const char *test_mg_connect(void) {
ASSERT(mg_set_option(server, "listening_port", LISTENING_ADDR) == NULL); ASSERT(mg_set_option(server, "listening_port", LISTENING_ADDR) == NULL);
ASSERT(mg_set_option(server, "document_root", ".") == NULL); ASSERT(mg_set_option(server, "document_root", ".") == NULL);
ASSERT(mg_connect(server, "", 0, NULL, NULL) == 0); ASSERT(mg_connect(server, "", 0, 0, NULL, NULL) == 0);
ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), cb2, buf2) == 1); ASSERT(mg_connect(server, "127.0.0.1", atoi(HTTP_PORT), 0, cb2, buf2) == 1);
ASSERT(mg_connect(server, "127.0.0.1", 1, cb3, buf3) == 1); ASSERT(mg_connect(server, "127.0.0.1", 1, 0, cb3, buf3) == 1);
{ int i; for (i = 0; i < 50; i++) mg_poll_server(server, 0); } { int i; for (i = 0; i < 50; i++) mg_poll_server(server, 0); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment