Update civetweb
This commit is contained in:
@@ -10,4 +10,5 @@ set(LIBRARY_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/build/lib")
|
|||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-modules/")
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-modules/")
|
||||||
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../nats.c ${CMAKE_CURRENT_BINARY_DIR}/nats.c)
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../nats.c ${CMAKE_CURRENT_BINARY_DIR}/nats.c)
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../civetweb ${CMAKE_CURRENT_BINARY_DIR}/civetweb)
|
||||||
add_subdirectory (src)
|
add_subdirectory (src)
|
||||||
|
|||||||
@@ -4,6 +4,21 @@ echo "Clean"
|
|||||||
rm -rf build/*
|
rm -rf build/*
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
CMAKE_OPTS=""
|
||||||
|
|
||||||
|
# Options for CIVETWEB
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DCIVETWEB_ENABLE_SERVER_EXECUTABLE=OFF"
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DCIVETWEB_ENABLE_CXX=ON"
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DCIVETWEB_ENABLE_WEBSOCKETS=ON"
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DCIVETWEB_BUILD_TESTING=OFF"
|
||||||
|
|
||||||
|
# Options for NATS.c
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DNATS_BUILD_EXAMPLES=OFF"
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DNATS_BUILD_STREAMING=OFF"
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DNATS_BUILD_TLS_USE_OPENSSL_1_1_API=ON"
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DNATS_BUILD_WITH_TLS=OFF"
|
||||||
|
CMAKE_OPTS="$CMAKE_OPTS -DNATS_BUILD_LIB_SHARED=OFF"
|
||||||
|
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DNATS_BUILD_WITH_TLS=OFF -DNATS_BUILD_TLS_USE_OPENSSL_1_1_API=ON -DNATS_BUILD_STREAMING=OFF ..
|
cmake .. $CMAKE_OPTS ..
|
||||||
make
|
make
|
||||||
|
|||||||
@@ -12,14 +12,18 @@ include_directories(${CMAKE_SOURCE_DIR}/../nats.c/src)
|
|||||||
file(
|
file(
|
||||||
GLOB_RECURSE
|
GLOB_RECURSE
|
||||||
source_files
|
source_files
|
||||||
domo-iot.c
|
domo-iot.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable (domo-iot ${source_files})
|
add_executable (domo-iot ${source_files})
|
||||||
|
|
||||||
target_link_libraries (domo-iot
|
target_link_libraries (domo-iot
|
||||||
LINK_PUBLIC
|
LINK_PUBLIC
|
||||||
nats
|
nats_static
|
||||||
|
event
|
||||||
|
pthread
|
||||||
|
event_pthreads
|
||||||
|
civetweb-cpp
|
||||||
rt
|
rt
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
445
src/domo-iot.cpp
Normal file
445
src/domo-iot.cpp
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
/* Copyright (c) 2013-2018 the Civetweb developers
|
||||||
|
* Copyright (c) 2013 No Face Press, LLC
|
||||||
|
* License http://opensource.org/licenses/mit-license.php MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Simple example program on how to use Embedded C++ interface.
|
||||||
|
|
||||||
|
#include "CivetServer.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DOCUMENT_ROOT "."
|
||||||
|
#define PORT "8081"
|
||||||
|
#define EXAMPLE_URI "/example"
|
||||||
|
#define EXIT_URI "/exit"
|
||||||
|
|
||||||
|
|
||||||
|
#define USE_WEBSOCKET 1
|
||||||
|
|
||||||
|
/* Exit flag for main loop */
|
||||||
|
volatile bool exitNow = false;
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
mg_printf(conn, "<html><body>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<h2>This is an example text from a C++ handler</h2>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To see a page from the A handler <a "
|
||||||
|
"href=\"a\">click here</a></p>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<form action=\"a\" method=\"get\">"
|
||||||
|
"To see a page from the A handler with a parameter "
|
||||||
|
"<input type=\"submit\" value=\"click here\" "
|
||||||
|
"name=\"param\" \\> (GET)</form>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<form action=\"a\" method=\"post\">"
|
||||||
|
"To see a page from the A handler with a parameter "
|
||||||
|
"<input type=\"submit\" value=\"click here\" "
|
||||||
|
"name=\"param\" \\> (POST)</form>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To see a page from the A/B handler <a "
|
||||||
|
"href=\"a/b\">click here</a></p>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To see a page from the *.foo handler <a "
|
||||||
|
"href=\"xy.foo\">click here</a></p>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To see a page from the WebSocket handler <a "
|
||||||
|
"href=\"ws\">click here</a></p>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To exit <a href=\"%s\">click here</a></p>\r\n",
|
||||||
|
EXIT_URI);
|
||||||
|
mg_printf(conn, "</body></html>\r\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExitHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/plain\r\nConnection: close\r\n\r\n");
|
||||||
|
mg_printf(conn, "Bye!\n");
|
||||||
|
exitNow = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool
|
||||||
|
handleAll(const char *method,
|
||||||
|
CivetServer *server,
|
||||||
|
struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
std::string s = "";
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
mg_printf(conn, "<html><body>");
|
||||||
|
mg_printf(conn, "<h2>This is the A handler for \"%s\" !</h2>", method);
|
||||||
|
if (CivetServer::getParam(conn, "param", s)) {
|
||||||
|
mg_printf(conn, "<p>param set to %s</p>", s.c_str());
|
||||||
|
} else {
|
||||||
|
mg_printf(conn, "<p>param not set</p>");
|
||||||
|
}
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
return handleAll("GET", server, conn);
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
handlePost(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
return handleAll("POST", server, conn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ABHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
mg_printf(conn, "<html><body>");
|
||||||
|
mg_printf(conn, "<h2>This is the AB handler!!!</h2>");
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FooHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
|
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
|
||||||
|
mg_printf(conn, "<html><body>\n");
|
||||||
|
mg_printf(conn, "<h2>This is the Foo GET handler!!!</h2>\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n",
|
||||||
|
req_info->request_method,
|
||||||
|
req_info->request_uri,
|
||||||
|
req_info->http_version);
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
handlePost(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
|
long long rlen, wlen;
|
||||||
|
long long nlen = 0;
|
||||||
|
long long tlen = req_info->content_length;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
|
||||||
|
mg_printf(conn, "<html><body>\n");
|
||||||
|
mg_printf(conn, "<h2>This is the Foo POST handler!!!</h2>\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n",
|
||||||
|
req_info->request_method,
|
||||||
|
req_info->request_uri,
|
||||||
|
req_info->http_version);
|
||||||
|
mg_printf(conn, "<p>Content Length: %li</p>\n", (long)tlen);
|
||||||
|
mg_printf(conn, "<pre>\n");
|
||||||
|
|
||||||
|
while (nlen < tlen) {
|
||||||
|
rlen = tlen - nlen;
|
||||||
|
if (rlen > sizeof(buf)) {
|
||||||
|
rlen = sizeof(buf);
|
||||||
|
}
|
||||||
|
rlen = mg_read(conn, buf, (size_t)rlen);
|
||||||
|
if (rlen <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wlen = mg_write(conn, buf, (size_t)rlen);
|
||||||
|
if (wlen != rlen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nlen += wlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_printf(conn, "\n</pre>\n");
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fopen_recursive fopen
|
||||||
|
|
||||||
|
bool
|
||||||
|
handlePut(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
|
long long rlen, wlen;
|
||||||
|
long long nlen = 0;
|
||||||
|
long long tlen = req_info->content_length;
|
||||||
|
FILE * f;
|
||||||
|
char buf[1024];
|
||||||
|
int fail = 0;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
_snprintf(buf, sizeof(buf), "D:\\somewhere\\%s\\%s", req_info->remote_user, req_info->local_uri);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
if (strlen(buf)>255) {
|
||||||
|
/* Windows will not work with path > 260 (MAX_PATH), unless we use
|
||||||
|
* the unicode API. However, this is just an example code: A real
|
||||||
|
* code will probably never store anything to D:\\somewhere and
|
||||||
|
* must be adapted to the specific needs anyhow. */
|
||||||
|
fail = 1;
|
||||||
|
f = NULL;
|
||||||
|
} else {
|
||||||
|
f = fopen_recursive(buf, "wb");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
snprintf(buf, sizeof(buf), "~/somewhere/%s/%s", req_info->remote_user, req_info->local_uri);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
if (strlen(buf)>1020) {
|
||||||
|
/* The string is too long and probably truncated. Make sure an
|
||||||
|
* UTF-8 string is never truncated between the UTF-8 code bytes.
|
||||||
|
* This example code must be adapted to the specific needs. */
|
||||||
|
fail = 1;
|
||||||
|
f = NULL;
|
||||||
|
} else {
|
||||||
|
f = fopen_recursive(buf, "w");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!f) {
|
||||||
|
fail = 1;
|
||||||
|
} else {
|
||||||
|
while (nlen < tlen) {
|
||||||
|
rlen = tlen - nlen;
|
||||||
|
if (rlen > sizeof(buf)) {
|
||||||
|
rlen = sizeof(buf);
|
||||||
|
}
|
||||||
|
rlen = mg_read(conn, buf, (size_t)rlen);
|
||||||
|
if (rlen <= 0) {
|
||||||
|
fail = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wlen = fwrite(buf, 1, (size_t)rlen, f);
|
||||||
|
if (wlen != rlen) {
|
||||||
|
fail = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nlen += wlen;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail) {
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 409 Conflict\r\n"
|
||||||
|
"Content-Type: text/plain\r\n"
|
||||||
|
"Connection: close\r\n\r\n");
|
||||||
|
} else {
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 201 Created\r\n"
|
||||||
|
"Content-Type: text/plain\r\n"
|
||||||
|
"Connection: close\r\n\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WsStartHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
|
||||||
|
"close\r\n\r\n");
|
||||||
|
|
||||||
|
mg_printf(conn, "<!DOCTYPE html>\n");
|
||||||
|
mg_printf(conn, "<html>\n<head>\n");
|
||||||
|
mg_printf(conn, "<meta charset=\"UTF-8\">\n");
|
||||||
|
mg_printf(conn, "<title>Embedded websocket example</title>\n");
|
||||||
|
|
||||||
|
#ifdef USE_WEBSOCKET
|
||||||
|
/* mg_printf(conn, "<script type=\"text/javascript\"><![CDATA[\n"); ...
|
||||||
|
* xhtml style */
|
||||||
|
mg_printf(conn, "<script>\n");
|
||||||
|
mg_printf(
|
||||||
|
conn,
|
||||||
|
"var i=0\n"
|
||||||
|
"function load() {\n"
|
||||||
|
" var wsproto = (location.protocol === 'https:') ? 'wss:' : 'ws:';\n"
|
||||||
|
" connection = new WebSocket(wsproto + '//' + window.location.host + "
|
||||||
|
"'/websocket');\n"
|
||||||
|
" websock_text_field = "
|
||||||
|
"document.getElementById('websock_text_field');\n"
|
||||||
|
" connection.onmessage = function (e) {\n"
|
||||||
|
" websock_text_field.innerHTML=e.data;\n"
|
||||||
|
" i=i+1;"
|
||||||
|
" connection.send(i);\n"
|
||||||
|
" }\n"
|
||||||
|
" connection.onerror = function (error) {\n"
|
||||||
|
" alert('WebSocket error');\n"
|
||||||
|
" connection.close();\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
/* mg_printf(conn, "]]></script>\n"); ... xhtml style */
|
||||||
|
mg_printf(conn, "</script>\n");
|
||||||
|
mg_printf(conn, "</head>\n<body onload=\"load()\">\n");
|
||||||
|
mg_printf(
|
||||||
|
conn,
|
||||||
|
"<div id='websock_text_field'>No websocket connection yet</div>\n");
|
||||||
|
#else
|
||||||
|
mg_printf(conn, "</head>\n<body>\n");
|
||||||
|
mg_printf(conn, "Example not compiled with USE_WEBSOCKET\n");
|
||||||
|
#endif
|
||||||
|
mg_printf(conn, "</body>\n</html>\n");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_WEBSOCKET
|
||||||
|
class WebSocketHandler : public CivetWebSocketHandler {
|
||||||
|
|
||||||
|
virtual bool handleConnection(CivetServer *server,
|
||||||
|
const struct mg_connection *conn) {
|
||||||
|
printf("WS connected\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void handleReadyState(CivetServer *server,
|
||||||
|
struct mg_connection *conn) {
|
||||||
|
printf("WS ready\n");
|
||||||
|
|
||||||
|
const char *text = "Hello from the websocket ready handler";
|
||||||
|
mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_TEXT, text, strlen(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool handleData(CivetServer *server,
|
||||||
|
struct mg_connection *conn,
|
||||||
|
int bits,
|
||||||
|
char *data,
|
||||||
|
size_t data_len) {
|
||||||
|
printf("WS got %lu bytes: ", (long unsigned)data_len);
|
||||||
|
fwrite(data, 1, data_len, stdout);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_TEXT, data, data_len);
|
||||||
|
return (data_len<4);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void handleClose(CivetServer *server,
|
||||||
|
const struct mg_connection *conn) {
|
||||||
|
printf("WS closed\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const char *options[] = {
|
||||||
|
"document_root", DOCUMENT_ROOT, "listening_ports", PORT, 0};
|
||||||
|
|
||||||
|
std::vector<std::string> cpp_options;
|
||||||
|
for (int i=0; i<(sizeof(options)/sizeof(options[0])-1); i++) {
|
||||||
|
cpp_options.push_back(options[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CivetServer server(options); // <-- C style start
|
||||||
|
CivetServer server(cpp_options); // <-- C++ style start
|
||||||
|
|
||||||
|
ExampleHandler h_ex;
|
||||||
|
server.addHandler(EXAMPLE_URI, h_ex);
|
||||||
|
|
||||||
|
ExitHandler h_exit;
|
||||||
|
server.addHandler(EXIT_URI, h_exit);
|
||||||
|
|
||||||
|
AHandler h_a;
|
||||||
|
server.addHandler("/a", h_a);
|
||||||
|
|
||||||
|
ABHandler h_ab;
|
||||||
|
server.addHandler("/a/b", h_ab);
|
||||||
|
|
||||||
|
WsStartHandler h_ws;
|
||||||
|
server.addHandler("/ws", h_ws);
|
||||||
|
|
||||||
|
#ifdef NO_FILES
|
||||||
|
/* This handler will handle "everything else", including
|
||||||
|
* requests to files. If this handler is installed,
|
||||||
|
* NO_FILES should be set. */
|
||||||
|
FooHandler h_foo;
|
||||||
|
server.addHandler("", h_foo);
|
||||||
|
|
||||||
|
printf("See a page from the \"all\" handler at http://localhost:%s/\n", PORT);
|
||||||
|
#else
|
||||||
|
FooHandler h_foo;
|
||||||
|
server.addHandler("**.foo", h_foo);
|
||||||
|
printf("Browse files at http://localhost:%s/\n", PORT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_WEBSOCKET
|
||||||
|
WebSocketHandler h_websocket;
|
||||||
|
server.addWebSocketHandler("/websocket", h_websocket);
|
||||||
|
printf("Run websocket example at http://localhost:%s/ws\n", PORT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI);
|
||||||
|
printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI);
|
||||||
|
|
||||||
|
while (!exitNow) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
Sleep(1000);
|
||||||
|
#else
|
||||||
|
sleep(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Bye!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -25,10 +25,12 @@
|
|||||||
|
|
||||||
/*-------------------------------- INCLUDES ---------------------------------*/
|
/*-------------------------------- INCLUDES ---------------------------------*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <adapters/libevent.h>
|
||||||
#include <nats.h>
|
#include <nats.h>
|
||||||
|
|
||||||
static void
|
static void onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
|
||||||
{
|
{
|
||||||
printf("Received msg: %s - %.*s\n",
|
printf("Received msg: %s - %.*s\n",
|
||||||
natsMsg_GetSubject(msg),
|
natsMsg_GetSubject(msg),
|
||||||
@@ -37,9 +39,6 @@ onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
|||||||
|
|
||||||
// Need to destroy the message!
|
// Need to destroy the message!
|
||||||
natsMsg_Destroy(msg);
|
natsMsg_Destroy(msg);
|
||||||
|
|
||||||
// Notify the main thread that we are done.
|
|
||||||
*(bool *)(closure) = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! ----------------------------------------------------------------------------
|
/*! ----------------------------------------------------------------------------
|
||||||
@@ -50,33 +49,54 @@ onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
natsConnection *conn = NULL;
|
natsConnection *conn = NULL;
|
||||||
|
natsOptions *opts = NULL;
|
||||||
natsSubscription *sub = NULL;
|
natsSubscription *sub = NULL;
|
||||||
natsStatus s;
|
natsStatus s;
|
||||||
volatile bool done = false;
|
struct event_base *evLoop = NULL;
|
||||||
|
nats_Open(-1);
|
||||||
|
|
||||||
printf("Listening on subject 'foo'\n");
|
printf("Listening on subject 'foo'\n");
|
||||||
|
|
||||||
// Creates a connection to the default NATS URL
|
// One time initialization of things that we need.
|
||||||
s = natsConnection_ConnectTo(&conn, "nats.nadal-fr.com");
|
natsLibevent_Init();
|
||||||
if (s == NATS_OK)
|
|
||||||
{
|
|
||||||
// Creates an asynchronous subscription on subject "foo".
|
|
||||||
// When a message is sent on subject "foo", the callback
|
|
||||||
// onMsg() will be invoked by the client library.
|
|
||||||
// You can pass a closure as the last argument.
|
|
||||||
s = natsConnection_Subscribe(&sub, conn, "foo", onMsg, (void *)&done);
|
|
||||||
}
|
|
||||||
if (s == NATS_OK)
|
|
||||||
{
|
|
||||||
for (; !done;)
|
|
||||||
{
|
|
||||||
nats_Sleep(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anything that is created need to be destroyed
|
// Create a loop.
|
||||||
natsSubscription_Destroy(sub);
|
evLoop = event_base_new();
|
||||||
natsConnection_Destroy(conn);
|
if (evLoop == NULL)
|
||||||
|
s = NATS_ERR;
|
||||||
|
|
||||||
|
if (natsOptions_Create(&opts) != NATS_OK)
|
||||||
|
s = NATS_NO_MEMORY;
|
||||||
|
|
||||||
|
s = natsOptions_UseGlobalMessageDelivery(opts, true);
|
||||||
|
|
||||||
|
// Indicate which loop and callbacks to use once connected.
|
||||||
|
if (s == NATS_OK)
|
||||||
|
s = natsOptions_SetEventLoop(opts, (void *)evLoop,
|
||||||
|
natsLibevent_Attach,
|
||||||
|
natsLibevent_Read,
|
||||||
|
natsLibevent_Write,
|
||||||
|
natsLibevent_Detach);
|
||||||
|
|
||||||
|
s = natsOptions_SetURL(opts, "nats.nadal-fr.com");
|
||||||
|
|
||||||
|
if (s == NATS_OK)
|
||||||
|
s = natsConnection_Connect(&conn, opts);
|
||||||
|
|
||||||
|
if (s == NATS_OK)
|
||||||
|
s = natsConnection_Subscribe(&sub, conn, "foo", onMsg, NULL);
|
||||||
|
|
||||||
|
// For maximum performance, set no limit on the number of pending messages.
|
||||||
|
if (s == NATS_OK)
|
||||||
|
s = natsSubscription_SetPendingLimits(sub, -1, -1);
|
||||||
|
|
||||||
|
// Run the event loop.
|
||||||
|
// This call will return when the connection is closed (either after
|
||||||
|
// receiving all messages, or disconnected and unable to reconnect).
|
||||||
|
if (s == NATS_OK)
|
||||||
|
{
|
||||||
|
event_base_dispatch(evLoop);
|
||||||
|
}
|
||||||
|
|
||||||
// If there was an error, print a stack trace and exit
|
// If there was an error, print a stack trace and exit
|
||||||
if (s != NATS_OK)
|
if (s != NATS_OK)
|
||||||
@@ -85,5 +105,18 @@ int main(int argc, char *argv[])
|
|||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Anything that is created need to be destroyed
|
||||||
|
natsSubscription_Destroy(sub);
|
||||||
|
natsConnection_Destroy(conn);
|
||||||
|
natsOptions_Destroy(opts);
|
||||||
|
|
||||||
|
if (evLoop != NULL)
|
||||||
|
event_base_free(evLoop);
|
||||||
|
|
||||||
|
// To silence reports of memory still in used with valgrind
|
||||||
|
nats_Close();
|
||||||
|
libevent_global_shutdown();
|
||||||
|
|
||||||
|
printf("done\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user