ws_ssl.c
Go to the documentation of this file.
1 // Copyright (c) 2014 Cesanta Software
2 // All rights reserved
3 //
4 // This example demostrates proxying of WebSocket traffic, regardless of the
5 // protocol (ws:// or wss://).
6 // To use this example:
7 // 1. configure your browser to use a proxy on port 2014
8 // 2. import certs/ws1_ca.pem and certs/ws2_ca.pem into the trusted
9 // certificates list on your browser
10 // 3. make && ./ws_ssl
11 // 4. Point your browser to http://ws_ssl.com
12 // A page with 4 sections should appear, showing websocket echoes
13 
14 #include "net_skeleton.h"
15 #include "mongoose.h"
16 #include "ssl_wrapper.h"
17 
18 #define S1_PEM "certs/ws1_server.pem"
19 #define C1_PEM "certs/ws1_client.pem"
20 #define CA1_PEM "certs/ws1_ca.pem"
21 #define S2_PEM "certs/ws2_server.pem"
22 #define C2_PEM "certs/ws2_client.pem"
23 #define CA2_PEM "certs/ws2_ca.pem"
24 
25 struct config {
26  const char *uri;
27  const char *wrapper_server_addr;
28  const char *wrapper_client_addr;
29  const char *target_addr;
30 };
31 
32 static struct config s_wrappers[] = {
33  {
34  "ws1:80",
35  "tcp://127.0.0.1:7001",
36  "tcp://127.0.0.1:7001",
37  "tcp://127.0.0.1:9001"
38  },
39  {
40  "ws1:443",
41  "ssl://127.0.0.1:7002:" S1_PEM,
42  "tcp://127.0.0.1:7002",
43  "tcp://127.0.0.1:9001"
44  },
45  {
46  "ws2:80",
47  "tcp://127.0.0.1:7003",
48  "tcp://127.0.0.1:7003",
49  "ssl://127.0.0.1:9002:" C2_PEM ":" CA2_PEM
50  },
51  {
52  "ws2:443",
53  "ssl://127.0.0.1:7004:" S2_PEM,
54  "tcp://127.0.0.1:7004",
55  "ssl://127.0.0.1:9002:" C2_PEM ":" CA2_PEM
56  },
57 };
58 
59 static int s_received_signal = 0;
60 
61 static void signal_handler(int sig_num) {
62  signal(sig_num, signal_handler);
63  s_received_signal = sig_num;
64 }
65 
66 static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
67  int i;
68 
69  switch (ev) {
70  case MG_AUTH:
71  return MG_TRUE;
72 
73  case MG_REQUEST:
74  printf("==> [%s] [%s]\n", conn->request_method, conn->uri);
75 
76  if (strcmp(conn->request_method, "CONNECT") == 0) {
77  // Iterate over configured wrappers, see if we can use one of them
78  for (i = 0; i < (int) ARRAY_SIZE(s_wrappers); i++) {
79  if (strcmp(conn->uri, s_wrappers[i].uri) == 0) {
80  mg_forward(conn, s_wrappers[i].wrapper_client_addr);
81  return MG_MORE;
82  }
83  }
84 
85  // No suitable wrappers found. Disallow that CONNECT request.
86  mg_send_status(conn, 405);
87  return MG_TRUE;
88  }
89 
90  // Not a CONNECT request, serve HTML file.
91  mg_send_file(conn, "ws_ssl.html", NULL);
92  return MG_MORE;
93 
94  default:
95  return MG_FALSE;
96  }
97 }
98 
99 static int ws_handler(struct mg_connection *conn, enum mg_event ev) {
100  switch (ev) {
101  case MG_AUTH:
102  return MG_TRUE;
103  case MG_REQUEST:
104  if (conn->is_websocket) {
105  // Simple websocket echo server
107  conn->content, conn->content_len);
108  } else {
109  mg_printf_data(conn, "%s", "websocket connection expected");
110  }
111  return MG_TRUE;
112  default:
113  return MG_FALSE;
114  }
115 }
116 
117 static void *serve_thread_func(void *param) {
118  struct mg_server *server = (struct mg_server *) param;
119  printf("Listening on port %s\n", mg_get_option(server, "listening_port"));
120  while (s_received_signal == 0) {
121  mg_poll_server(server, 1000);
122  }
123  mg_destroy_server(&server);
124  return NULL;
125 }
126 
127 static void *wrapper_thread_func(void *param) {
128  struct config *c = (struct config *) param;
129  const char *err_msg;
130  void *wrapper;
131 
132  wrapper = ssl_wrapper_init(c->wrapper_server_addr, c->target_addr, &err_msg);
133  if (wrapper == NULL) {
134  fprintf(stderr, "Error: %s\n", err_msg);
135  exit(EXIT_FAILURE);
136  }
137  //((struct ns_mgr *) wrapper)->hexdump_file = "/dev/stderr";
139 
140  return NULL;
141 }
142 
143 int main(void) {
144  struct mg_server *proxy_server = mg_create_server(NULL, ev_handler);
145  struct mg_server *ws1_server = mg_create_server(NULL, ws_handler);
146  struct mg_server *ws2_server = mg_create_server(NULL, ws_handler);
147  size_t i;
148 
149  ((struct ns_mgr *) proxy_server)->hexdump_file = "/dev/stderr";
150 
151  // Configure proxy server to listen on port 2014
152  mg_set_option(proxy_server, "listening_port", "2014");
153  //mg_set_option(proxy_server, "enable_proxy", "yes");
154 
155  // Configure two websocket echo servers:
156  // ws1 is WS, listening on 9001
157  // ws2 is WSS, listening on 9002
158  // Note that HTML page thinks that ws1 is WSS, and ws2 is WS,
159  // where in reality it is vice versa and proxy server makes the decision.
160  mg_set_option(ws1_server, "listening_port", "tcp://127.0.0.1:9001");
161  mg_set_option(ws2_server, "listening_port",
162  "ssl://127.0.0.1:9002:" S2_PEM ":" CA2_PEM);
163 
164  // Setup signal handlers
165  signal(SIGTERM, signal_handler);
166  signal(SIGINT, signal_handler);
167 
168  // Start SSL wrappers, each in it's own thread
169  for (i = 0; i < ARRAY_SIZE(s_wrappers); i++) {
170  ns_start_thread(wrapper_thread_func, &s_wrappers[i]);
171  }
172 
173  // Start websocket servers in separate threads
174  mg_start_thread(serve_thread_func, ws1_server);
175  mg_start_thread(serve_thread_func, ws2_server);
176 
177  // Finally, start proxy server in this thread: this call blocks
178  serve_thread_func(proxy_server);
179 
180  printf("Existing on signal %d\n", s_received_signal);
181  return EXIT_SUCCESS;
182 }
const char * target_addr
Definition: ws_ssl.c:29
int is_websocket
Definition: mongoose.h:52
int main(void)
Definition: ws_ssl.c:143
Definition: ws_ssl.c:25
static int ev_handler(struct mg_connection *conn, enum mg_event ev)
Definition: ws_ssl.c:66
void * mg_start_thread(void *(*func)(void *), void *param)
void * ssl_wrapper_init(const char *local_addr, const char *target_addr, const char **err_msg)
Definition: ssl_wrapper.c:59
#define S1_PEM
Definition: ws_ssl.c:18
size_t mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
Definition: mongoose.c:3045
const char * uri
Definition: mongoose.h:34
void * ns_start_thread(void *(*f)(void *), void *p)
struct mg_server * mg_create_server(void *server_data, mg_handler_t handler)
Definition: mongoose.c:5431
#define S2_PEM
Definition: ws_ssl.c:21
const char * mg_get_option(const struct mg_server *server, const char *name)
Definition: mongoose.c:5425
void mg_send_status(struct mg_connection *c, int status)
Definition: mongoose.c:2750
void ssl_wrapper_serve(void *param, volatile int *quit)
Definition: ssl_wrapper.c:79
static int ws_handler(struct mg_connection *conn, enum mg_event ev)
Definition: ws_ssl.c:99
static void signal_handler(int sig_num)
Definition: ws_ssl.c:61
unsigned int i
Definition: unit1303.c:79
time_t mg_poll_server(struct mg_server *server, int milliseconds)
Definition: mongoose.c:4965
#define C2_PEM
Definition: ws_ssl.c:22
static int s_received_signal
Definition: ws_ssl.c:59
size_t mg_printf_data(struct mg_connection *c, const char *fmt,...)
Definition: mongoose.c:2785
#define printf
Definition: curl_printf.h:40
mg_event
Definition: mongoose.h:62
static struct mg_server * server
Definition: web_server.c:72
static void * wrapper_thread_func(void *param)
Definition: ws_ssl.c:127
#define CA2_PEM
Definition: ws_ssl.c:23
int mg_forward(struct mg_connection *c, const char *addr)
Definition: mongoose.c:4474
const char * mg_set_option(struct mg_server *server, const char *name, const char *value)
Definition: mongoose.c:5143
const char * uri
Definition: ws_ssl.c:26
void mg_send_file(struct mg_connection *c, const char *file_name, const char *extra_headers)
Definition: mongoose.c:4585
const char * wrapper_client_addr
Definition: ws_ssl.c:28
#define fprintf
Definition: curl_printf.h:41
const char * request_method
Definition: mongoose.h:33
const char * wrapper_server_addr
Definition: ws_ssl.c:27
#define ARRAY_SIZE(array)
Definition: net_skeleton.h:119
void mg_destroy_server(struct mg_server **server)
Definition: mongoose.c:4969
static void * serve_thread_func(void *param)
Definition: ws_ssl.c:117
static struct config s_wrappers[]
Definition: ws_ssl.c:32
size_t content_len
Definition: mongoose.h:50
char * content
Definition: mongoose.h:49


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:17