mirror of
https://github.com/cesanta/mongoose.git
synced 2025-06-10 19:33:06 +08:00
Overload mg_bind
to bind to tunnel
PUBLISHED_FROM=f554cc63dfea12455fe5e428c6ce5f3152774f8e
This commit is contained in:
parent
296affc6e4
commit
e1a9ad7f82
@ -10,11 +10,14 @@ signature: |
|
|||||||
struct mg_iface *iface; /* Interface instance */
|
struct mg_iface *iface; /* Interface instance */
|
||||||
#if MG_ENABLE_SSL
|
#if MG_ENABLE_SSL
|
||||||
/* SSL settings. */
|
/* SSL settings. */
|
||||||
const char *ssl_cert; /* Server certificate to present to clients */
|
const char *ssl_cert; /* Server certificate to present to clients
|
||||||
|
* Or client certificate to present to tunnel
|
||||||
|
* dispatcher. */
|
||||||
const char *ssl_key; /* Private key corresponding to the certificate.
|
const char *ssl_key; /* Private key corresponding to the certificate.
|
||||||
If ssl_cert is set but ssl_key is not, ssl_cert
|
If ssl_cert is set but ssl_key is not, ssl_cert
|
||||||
is used. */
|
is used. */
|
||||||
const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
|
const char *ssl_ca_cert; /* CA bundle used to verify client certificates or
|
||||||
|
* tunnel dispatchers. */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
|
||||||
static const char *s_local_port = ":8001";
|
static const char *s_local_port = ":8001";
|
||||||
static const char *s_dispatcher = "ws://localhost:8000";
|
static const char *s_dispatcher = "ws://foo:bar@localhost:8000";
|
||||||
static const char *s_user = "foo";
|
|
||||||
static const char *s_pass = "bar";
|
|
||||||
|
|
||||||
void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
struct http_message *hm = (struct http_message *) ev_data;
|
struct http_message *hm = (struct http_message *) ev_data;
|
||||||
@ -41,15 +39,10 @@ int main(int argc, char **argv) {
|
|||||||
s_local_port = argv[++i];
|
s_local_port = argv[++i];
|
||||||
} else if (strcmp(argv[i], "-d") == 0) {
|
} else if (strcmp(argv[i], "-d") == 0) {
|
||||||
s_dispatcher = argv[++i];
|
s_dispatcher = argv[++i];
|
||||||
} else if (strcmp(argv[i], "-u") == 0) {
|
|
||||||
s_user = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-p") == 0) {
|
|
||||||
s_pass = argv[++i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((nc = mg_tuna_bind(&mgr, ev_handler, s_dispatcher, s_user, s_pass)) ==
|
if ((nc = mg_bind(&mgr, s_dispatcher, ev_handler)) == NULL) {
|
||||||
NULL) {
|
|
||||||
fprintf(stderr, "Cannot create tunneled listening socket on [%s]\n",
|
fprintf(stderr, "Cannot create tunneled listening socket on [%s]\n",
|
||||||
s_dispatcher);
|
s_dispatcher);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
154
mongoose.c
154
mongoose.c
@ -1796,6 +1796,87 @@ int64_t cs_to64(const char *s) {
|
|||||||
|
|
||||||
#endif /* EXCLUDE_COMMON */
|
#endif /* EXCLUDE_COMMON */
|
||||||
#ifdef MG_MODULE_LINES
|
#ifdef MG_MODULE_LINES
|
||||||
|
#line 1 "mongoose/src/tun.h"
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CS_MONGOOSE_SRC_TUN_H_
|
||||||
|
#define CS_MONGOOSE_SRC_TUN_H_
|
||||||
|
|
||||||
|
#if MG_ENABLE_TUN
|
||||||
|
|
||||||
|
/* Amalgamated: #include "mongoose/src/net.h" */
|
||||||
|
/* Amalgamated: #include "common/mg_str.h" */
|
||||||
|
|
||||||
|
#ifndef MG_TUN_RECONNECT_INTERVAL
|
||||||
|
#define MG_TUN_RECONNECT_INTERVAL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MG_TUN_DATA_FRAME 0x0
|
||||||
|
#define MG_TUN_F_END_STREAM 0x1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MG TUN frame format is loosely based on HTTP/2.
|
||||||
|
* However since the communication happens via WebSocket
|
||||||
|
* there is no need to encode the frame length, since that's
|
||||||
|
* solved by WebSocket framing.
|
||||||
|
*
|
||||||
|
* TODO(mkm): Detailed description of the protocol.
|
||||||
|
*/
|
||||||
|
struct mg_tun_frame {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t flags;
|
||||||
|
uint32_t stream_id; /* opaque stream identifier */
|
||||||
|
struct mg_str body;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mg_tun_ssl_opts {
|
||||||
|
#if MG_ENABLE_SSL
|
||||||
|
const char *ssl_cert;
|
||||||
|
const char *ssl_key;
|
||||||
|
const char *ssl_ca_cert;
|
||||||
|
#else
|
||||||
|
int dummy; /* some compilers don't like empty structs */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mg_tun_client {
|
||||||
|
struct mg_mgr *mgr;
|
||||||
|
struct mg_iface *iface;
|
||||||
|
const char *disp_url;
|
||||||
|
struct mg_tun_ssl_opts ssl;
|
||||||
|
|
||||||
|
uint32_t last_stream_id; /* stream id of most recently accepted connection */
|
||||||
|
|
||||||
|
struct mg_connection *disp;
|
||||||
|
struct mg_connection *listener;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
struct mg_connection *mg_tun_bind_opt(struct mg_mgr *mgr,
|
||||||
|
const char *dispatcher,
|
||||||
|
mg_event_handler_t handler,
|
||||||
|
struct mg_bind_opts opts);
|
||||||
|
|
||||||
|
int mg_tun_parse_frame(void *data, size_t len, struct mg_tun_frame *frame);
|
||||||
|
|
||||||
|
void mg_tun_send_frame(struct mg_connection *ws, uint32_t stream_id,
|
||||||
|
uint8_t type, uint8_t flags, struct mg_str msg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* MG_ENABLE_TUN */
|
||||||
|
|
||||||
|
#endif /* CS_MONGOOSE_SRC_TUN_H_ */
|
||||||
|
#ifdef MG_MODULE_LINES
|
||||||
#line 1 "mongoose/src/net.c"
|
#line 1 "mongoose/src/net.c"
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
@ -1821,6 +1902,7 @@ int64_t cs_to64(const char *s) {
|
|||||||
/* Amalgamated: #include "mongoose/src/internal.h" */
|
/* Amalgamated: #include "mongoose/src/internal.h" */
|
||||||
/* Amalgamated: #include "mongoose/src/resolv.h" */
|
/* Amalgamated: #include "mongoose/src/resolv.h" */
|
||||||
/* Amalgamated: #include "mongoose/src/util.h" */
|
/* Amalgamated: #include "mongoose/src/util.h" */
|
||||||
|
/* Amalgamated: #include "mongoose/src/tun.h" */
|
||||||
|
|
||||||
#define MG_MAX_HOST_LEN 200
|
#define MG_MAX_HOST_LEN 200
|
||||||
|
|
||||||
@ -2797,6 +2879,13 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
|
|||||||
|
|
||||||
MG_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts);
|
MG_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts);
|
||||||
|
|
||||||
|
#if MG_ENABLE_TUN
|
||||||
|
if (mg_strncmp(mg_mk_str(address), mg_mk_str("ws://"), 5) == 0 ||
|
||||||
|
mg_strncmp(mg_mk_str(address), mg_mk_str("wss://"), 6) == 0) {
|
||||||
|
return mg_tun_bind_opt(mgr, address, callback, opts);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mg_parse_address(address, &sa, &proto, host, sizeof(host)) <= 0) {
|
if (mg_parse_address(address, &sa, &proto, host, sizeof(host)) <= 0) {
|
||||||
MG_SET_PTRPTR(opts.error_string, "cannot parse address");
|
MG_SET_PTRPTR(opts.error_string, "cannot parse address");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -10676,13 +10765,12 @@ static void mg_tun_reconnect(struct mg_tun_client *client);
|
|||||||
|
|
||||||
static void mg_tun_init_client(struct mg_tun_client *client, struct mg_mgr *mgr,
|
static void mg_tun_init_client(struct mg_tun_client *client, struct mg_mgr *mgr,
|
||||||
struct mg_iface *iface, const char *dispatcher,
|
struct mg_iface *iface, const char *dispatcher,
|
||||||
const char *user, const char *pass) {
|
struct mg_tun_ssl_opts ssl) {
|
||||||
client->mgr = mgr;
|
client->mgr = mgr;
|
||||||
client->iface = iface;
|
client->iface = iface;
|
||||||
client->disp_url = dispatcher;
|
client->disp_url = dispatcher;
|
||||||
client->user = user;
|
|
||||||
client->pass = pass;
|
|
||||||
client->last_stream_id = 0;
|
client->last_stream_id = 0;
|
||||||
|
client->ssl = ssl;
|
||||||
|
|
||||||
client->disp = NULL; /* will be set by mg_tun_reconnect */
|
client->disp = NULL; /* will be set by mg_tun_reconnect */
|
||||||
client->listener = NULL; /* will be set by mg_do_bind */
|
client->listener = NULL; /* will be set by mg_do_bind */
|
||||||
@ -10787,24 +10875,23 @@ static void mg_tun_client_handler(struct mg_connection *nc, int ev,
|
|||||||
|
|
||||||
static void mg_tun_do_reconnect(struct mg_tun_client *client) {
|
static void mg_tun_do_reconnect(struct mg_tun_client *client) {
|
||||||
struct mg_connection *dc;
|
struct mg_connection *dc;
|
||||||
struct mbuf headers;
|
struct mg_connect_opts opts;
|
||||||
mbuf_init(&headers, 0);
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
#if MG_ENABLE_SSL
|
||||||
|
opts.ssl_cert = client->ssl.ssl_cert;
|
||||||
|
opts.ssl_key = client->ssl.ssl_key;
|
||||||
|
opts.ssl_ca_cert = client->ssl.ssl_ca_cert;
|
||||||
|
#endif
|
||||||
/* HTTP/Websocket listener */
|
/* HTTP/Websocket listener */
|
||||||
mg_basic_auth_header(client->user, client->pass, &headers);
|
if ((dc = mg_connect_ws_opt(client->mgr, mg_tun_client_handler, opts,
|
||||||
mbuf_append(&headers, "", 1); /* nul terminate */
|
client->disp_url, "mg_tun", NULL)) == NULL) {
|
||||||
if ((dc = mg_connect_ws(client->mgr, mg_tun_client_handler, client->disp_url,
|
|
||||||
"mg_tun", headers.buf)) == NULL) {
|
|
||||||
LOG(LL_ERROR,
|
LOG(LL_ERROR,
|
||||||
("Cannot connect to WS server on addr [%s]\n", client->disp_url));
|
("Cannot connect to WS server on addr [%s]\n", client->disp_url));
|
||||||
goto clean;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->disp = dc;
|
client->disp = dc;
|
||||||
dc->user_data = client;
|
dc->user_data = client;
|
||||||
|
|
||||||
clean:
|
|
||||||
mbuf_free(&headers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_tun_reconnect_ev_handler(struct mg_connection *nc, int ev,
|
void mg_tun_reconnect_ev_handler(struct mg_connection *nc, int ev,
|
||||||
@ -10829,8 +10916,7 @@ static void mg_tun_reconnect(struct mg_tun_client *client) {
|
|||||||
|
|
||||||
static struct mg_tun_client *mg_tun_create_client(struct mg_mgr *mgr,
|
static struct mg_tun_client *mg_tun_create_client(struct mg_mgr *mgr,
|
||||||
const char *dispatcher,
|
const char *dispatcher,
|
||||||
const char *user,
|
struct mg_tun_ssl_opts ssl) {
|
||||||
const char *pass) {
|
|
||||||
struct mg_tun_client *client = NULL;
|
struct mg_tun_client *client = NULL;
|
||||||
struct mg_iface *iface = mg_find_iface(mgr, &mg_tun_iface_vtable, NULL);
|
struct mg_iface *iface = mg_find_iface(mgr, &mg_tun_iface_vtable, NULL);
|
||||||
if (iface == NULL) {
|
if (iface == NULL) {
|
||||||
@ -10840,39 +10926,43 @@ static struct mg_tun_client *mg_tun_create_client(struct mg_mgr *mgr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
client = (struct mg_tun_client *) MG_MALLOC(sizeof(*client));
|
client = (struct mg_tun_client *) MG_MALLOC(sizeof(*client));
|
||||||
mg_tun_init_client(client, mgr, iface, dispatcher, user, pass);
|
mg_tun_init_client(client, mgr, iface, dispatcher, ssl);
|
||||||
iface->data = client;
|
iface->data = client;
|
||||||
|
|
||||||
mg_tun_do_reconnect(client);
|
mg_tun_do_reconnect(client);
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mg_connection *mg_tuna_do_bind(struct mg_tun_client *client,
|
static struct mg_connection *mg_tun_do_bind(struct mg_tun_client *client,
|
||||||
mg_event_handler_t handler) {
|
mg_event_handler_t handler,
|
||||||
|
struct mg_bind_opts opts) {
|
||||||
struct mg_connection *lc;
|
struct mg_connection *lc;
|
||||||
struct mg_bind_opts opts;
|
|
||||||
const char *err;
|
|
||||||
memset(&opts, 0, sizeof(opts));
|
|
||||||
opts.iface = client->iface;
|
opts.iface = client->iface;
|
||||||
opts.error_string = &err;
|
|
||||||
lc = mg_bind_opt(client->mgr, ":1234" /* dummy port */, handler, opts);
|
lc = mg_bind_opt(client->mgr, ":1234" /* dummy port */, handler, opts);
|
||||||
if (lc == NULL) {
|
|
||||||
LOG(LL_ERROR, ("Cannot bind: %s", err));
|
|
||||||
}
|
|
||||||
client->listener = lc;
|
client->listener = lc;
|
||||||
return lc;
|
return lc;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mg_connection *mg_tuna_bind(struct mg_mgr *mgr,
|
struct mg_connection *mg_tun_bind_opt(struct mg_mgr *mgr,
|
||||||
|
const char *dispatcher,
|
||||||
mg_event_handler_t handler,
|
mg_event_handler_t handler,
|
||||||
const char *dispatcher, const char *user,
|
struct mg_bind_opts opts) {
|
||||||
const char *pass) {
|
#if MG_ENABLE_SSL
|
||||||
struct mg_tun_client *client =
|
struct mg_tun_ssl_opts ssl = {opts.ssl_cert, opts.ssl_key, opts.ssl_ca_cert};
|
||||||
mg_tun_create_client(mgr, dispatcher, user, pass);
|
#else
|
||||||
|
struct mg_tun_ssl_opts ssl = {0};
|
||||||
|
#endif
|
||||||
|
struct mg_tun_client *client = mg_tun_create_client(mgr, dispatcher, ssl);
|
||||||
if (client == NULL) {
|
if (client == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return mg_tuna_do_bind(client, handler);
|
#if MG_ENABLE_SSL
|
||||||
|
/* these options don't make sense in the local mouth of the tunnel */
|
||||||
|
opts.ssl_cert = NULL;
|
||||||
|
opts.ssl_key = NULL;
|
||||||
|
opts.ssl_ca_cert = NULL;
|
||||||
|
#endif
|
||||||
|
return mg_tun_do_bind(client, handler, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_tun_parse_frame(void *data, size_t len, struct mg_tun_frame *frame) {
|
int mg_tun_parse_frame(void *data, size_t len, struct mg_tun_frame *frame) {
|
||||||
|
79
mongoose.h
79
mongoose.h
@ -3221,11 +3221,14 @@ struct mg_bind_opts {
|
|||||||
struct mg_iface *iface; /* Interface instance */
|
struct mg_iface *iface; /* Interface instance */
|
||||||
#if MG_ENABLE_SSL
|
#if MG_ENABLE_SSL
|
||||||
/* SSL settings. */
|
/* SSL settings. */
|
||||||
const char *ssl_cert; /* Server certificate to present to clients */
|
const char *ssl_cert; /* Server certificate to present to clients
|
||||||
|
* Or client certificate to present to tunnel
|
||||||
|
* dispatcher. */
|
||||||
const char *ssl_key; /* Private key corresponding to the certificate.
|
const char *ssl_key; /* Private key corresponding to the certificate.
|
||||||
If ssl_cert is set but ssl_key is not, ssl_cert
|
If ssl_cert is set but ssl_key is not, ssl_cert
|
||||||
is used. */
|
is used. */
|
||||||
const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
|
const char *ssl_ca_cert; /* CA bundle used to verify client certificates or
|
||||||
|
* tunnel dispatchers. */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5540,75 +5543,3 @@ uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);
|
|||||||
#endif /* MG_ENABLE_COAP */
|
#endif /* MG_ENABLE_COAP */
|
||||||
|
|
||||||
#endif /* CS_MONGOOSE_SRC_COAP_H_ */
|
#endif /* CS_MONGOOSE_SRC_COAP_H_ */
|
||||||
#ifdef MG_MODULE_LINES
|
|
||||||
#line 1 "mongoose/src/tun.h"
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
|
||||||
* All rights reserved
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CS_MONGOOSE_SRC_TUN_H_
|
|
||||||
#define CS_MONGOOSE_SRC_TUN_H_
|
|
||||||
|
|
||||||
#if MG_ENABLE_TUN
|
|
||||||
|
|
||||||
/* Amalgamated: #include "mongoose/src/net.h" */
|
|
||||||
/* Amalgamated: #include "common/mg_str.h" */
|
|
||||||
|
|
||||||
#ifndef MG_TUN_RECONNECT_INTERVAL
|
|
||||||
#define MG_TUN_RECONNECT_INTERVAL 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MG_TUN_DATA_FRAME 0x0
|
|
||||||
#define MG_TUN_F_END_STREAM 0x1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MG TUN frame format is loosely based on HTTP/2.
|
|
||||||
* However since the communication happens via WebSocket
|
|
||||||
* there is no need to encode the frame length, since that's
|
|
||||||
* solved by WebSocket framing.
|
|
||||||
*
|
|
||||||
* TODO(mkm): Detailed description of the protocol.
|
|
||||||
*/
|
|
||||||
struct mg_tun_frame {
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t flags;
|
|
||||||
uint32_t stream_id; /* opaque stream identifier */
|
|
||||||
struct mg_str body;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mg_tun_client {
|
|
||||||
struct mg_mgr *mgr;
|
|
||||||
struct mg_iface *iface;
|
|
||||||
const char *disp_url;
|
|
||||||
const char *user;
|
|
||||||
const char *pass;
|
|
||||||
|
|
||||||
uint32_t last_stream_id; /* stream id of most recently accepted connection */
|
|
||||||
|
|
||||||
struct mg_connection *disp;
|
|
||||||
struct mg_connection *listener;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
struct mg_connection *mg_tuna_bind(struct mg_mgr *mgr,
|
|
||||||
mg_event_handler_t handler,
|
|
||||||
const char *dispatcher, const char *user,
|
|
||||||
const char *pass);
|
|
||||||
|
|
||||||
int mg_tun_parse_frame(void *data, size_t len, struct mg_tun_frame *frame);
|
|
||||||
|
|
||||||
void mg_tun_send_frame(struct mg_connection *ws, uint32_t stream_id,
|
|
||||||
uint8_t type, uint8_t flags, struct mg_str msg);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#endif /* MG_ENABLE_TUN */
|
|
||||||
|
|
||||||
#endif /* CS_MONGOOSE_SRC_TUN_H_ */
|
|
||||||
|
Loading…
Reference in New Issue
Block a user