Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright (c) 2014 Cesanta Software Limited
// All rights reserved
//
// To build and run this example:
// git clone https://github.com/cesanta/net_skeleton.git
// git clone https://github.com/cesanta/mongoose.git
// cd mongoose/examples
// make proxy
// ./proxy # (then point your browser at http://localhost:2014)
#include "net_skeleton.h"
#include "mongoose.h"
static int s_received_signal = 0;
static const char *s_ca_cert = NULL;
static const char *s_cert = NULL;
static const char *s_sse_port = "2014";
static const char *s_proxy_port = "2015";
static struct mg_server *s_sse_server = NULL;
static struct mg_server *s_proxy_server = NULL;
static void elog(int do_exit, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fputc('\n', stderr);
if (do_exit) exit(EXIT_FAILURE);
}
static void signal_handler(int sig_num) {
signal(sig_num, signal_handler);
s_received_signal = sig_num;
}
static int sse_push(struct mg_connection *conn, enum mg_event ev) {
const char *str = (const char *) conn->connection_param;
if (ev == MG_POLL && str != NULL && strcmp(str, "sse") == 0) {
mg_printf(conn, "data: %s\r\n\r\n", (const char *) conn->callback_param);
}
return MG_TRUE;
}
static void *sse_pusher_thread_func(void *param) {
while (s_received_signal == 0) {
mg_wakeup_server_ex(s_sse_server, sse_push, "%lu %s",
(unsigned long) time(NULL), (const char *) param);
sleep(1);
}
return NULL;
}
static int sse_handler(struct mg_connection *conn, enum mg_event ev) {
switch (ev) {
case MG_REQUEST:
if (strcmp(conn->uri, "/") == 0) {
mg_printf(conn, "%s", "HTTP/1.1 302 Moved\r\n"
"Location: /sse.html\r\n\r\n");
return MG_TRUE;
}
if (strcmp(conn->uri, "/api/sse") == 0) {
conn->connection_param = (void *) "sse";
mg_printf(conn, "%s",
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/event-stream\r\n"
"Cache-Control: no-cache\r\n"
"\r\n");
return MG_MORE;
}
return MG_FALSE;
case MG_AUTH:
return MG_TRUE;
case MG_POLL:
return MG_FALSE;
default:
return MG_FALSE;
}
}
static void *serve_thread_func(void *param) {
struct mg_server *server = (struct mg_server *) param;
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
while (s_received_signal == 0) {
mg_poll_server(server, 1000);
}
return NULL;
}
static void show_usage_and_exit(const char *prog) {
elog(1, "Usage: %s [-ca_cert FILE] [-sse_port PORT] [-proxy_port PORT]",
prog);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
int i;
// Parse command line options
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-ca_cert") == 0 && i + 1 < argc) {
s_ca_cert = argv[++i];
} else if (strcmp(argv[i], "-cert") == 0 && i + 1 < argc) {
s_cert = argv[++i];
} else if (strcmp(argv[i], "-sse_port") == 0 && i + 1 < argc) {
s_sse_port = argv[++i];
} else if (strcmp(argv[i], "-proxy_port") == 0 && i + 1 < argc) {
s_proxy_port = argv[++i];
} else {
show_usage_and_exit(argv[0]);
}
}
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
// Create, configure and start proxy server in a separate thread
s_proxy_server = mg_create_server(NULL, &sse_handler);
mg_set_option(s_proxy_server, "listening_port", s_proxy_port);
mg_set_option(s_proxy_server, "ssl_certificate", s_cert);
mg_set_option(s_proxy_server, "ssl_ca_certificate", s_ca_cert);
mg_start_thread(serve_thread_func, s_proxy_server);
// Create, configure and start SSE server and SSE pusher threads
// Start two SSE pushing threads
// Serve SSE server in the main thread
s_sse_server = mg_create_server(NULL, &sse_handler);
mg_set_option(s_sse_server, "listening_port", s_sse_port);
mg_set_option(s_sse_server, "document_root", ".");
mg_start_thread(sse_pusher_thread_func, (void *) "sse_pusher_thread_1");
mg_start_thread(sse_pusher_thread_func, (void *) "sse_pusher_thread_2");
serve_thread_func(s_sse_server);
printf("Existing on signal %d\n", s_received_signal);
mg_destroy_server(&s_sse_server);
mg_destroy_server(&s_proxy_server);
return EXIT_SUCCESS;
}