mirror of
https://github.com/lammertb/libhttp.git
synced 2025-07-31 08:24:23 +03:00
Apply revised clang-format (#207) to all actively maintained source files
This commit is contained in:
@ -28,7 +28,8 @@
|
|||||||
int exitNow = 0;
|
int exitNow = 0;
|
||||||
|
|
||||||
|
|
||||||
int ExampleHandler(struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
ExampleHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||||
mg_printf(conn, "<html><body>");
|
mg_printf(conn, "<html><body>");
|
||||||
@ -65,7 +66,8 @@ int ExampleHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ExitHandler(struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
ExitHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n");
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n");
|
||||||
mg_printf(conn, "Server will shut down.\n");
|
mg_printf(conn, "Server will shut down.\n");
|
||||||
@ -75,7 +77,8 @@ int ExitHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int AHandler(struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
AHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||||
mg_printf(conn, "<html><body>");
|
mg_printf(conn, "<html><body>");
|
||||||
@ -85,7 +88,8 @@ int AHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ABHandler(struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
ABHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||||
mg_printf(conn, "<html><body>");
|
mg_printf(conn, "<html><body>");
|
||||||
@ -95,7 +99,8 @@ int ABHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int BXHandler(struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
BXHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
/* Handler may access the request info using mg_get_request_info */
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
@ -109,7 +114,8 @@ int BXHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int FooHandler(struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
FooHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
/* Handler may access the request info using mg_get_request_info */
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
@ -127,7 +133,8 @@ int FooHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int WebSocketStartHandler(struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
WebSocketStartHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||||
|
|
||||||
@ -190,13 +197,15 @@ struct t_ws_client {
|
|||||||
#define ASSERT(x) \
|
#define ASSERT(x) \
|
||||||
{ \
|
{ \
|
||||||
if (!(x)) { \
|
if (!(x)) { \
|
||||||
fprintf( \
|
fprintf(stderr, \
|
||||||
stderr, "Assertion failed in line %u\n", (unsigned)__LINE__); \
|
"Assertion failed in line %u\n", \
|
||||||
|
(unsigned)__LINE__); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int WebSocketConnectHandler(const struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
WebSocketConnectHandler(const struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
int reject = 1;
|
int reject = 1;
|
||||||
@ -221,7 +230,8 @@ int WebSocketConnectHandler(const struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WebSocketReadyHandler(struct mg_connection *conn, void *cbdata)
|
void
|
||||||
|
WebSocketReadyHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
const char *text = "Hello from the websocket ready handler";
|
const char *text = "Hello from the websocket ready handler";
|
||||||
struct t_ws_client *client = mg_get_user_connection_data(conn);
|
struct t_ws_client *client = mg_get_user_connection_data(conn);
|
||||||
@ -235,11 +245,12 @@ void WebSocketReadyHandler(struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int WebsocketDataHandler(struct mg_connection *conn,
|
int
|
||||||
int bits,
|
WebsocketDataHandler(struct mg_connection *conn,
|
||||||
char *data,
|
int bits,
|
||||||
size_t len,
|
char *data,
|
||||||
void *cbdata)
|
size_t len,
|
||||||
|
void *cbdata)
|
||||||
{
|
{
|
||||||
struct t_ws_client *client = mg_get_user_connection_data(conn);
|
struct t_ws_client *client = mg_get_user_connection_data(conn);
|
||||||
ASSERT(client->conn == conn);
|
ASSERT(client->conn == conn);
|
||||||
@ -253,7 +264,8 @@ int WebsocketDataHandler(struct mg_connection *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WebSocketCloseHandler(const struct mg_connection *conn, void *cbdata)
|
void
|
||||||
|
WebSocketCloseHandler(const struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
struct t_ws_client *client = mg_get_user_connection_data(conn);
|
struct t_ws_client *client = mg_get_user_connection_data(conn);
|
||||||
@ -270,7 +282,8 @@ void WebSocketCloseHandler(const struct mg_connection *conn, void *cbdata)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InformWebsockets(struct mg_context *ctx)
|
void
|
||||||
|
InformWebsockets(struct mg_context *ctx)
|
||||||
{
|
{
|
||||||
static unsigned long cnt = 0;
|
static unsigned long cnt = 0;
|
||||||
char text[32];
|
char text[32];
|
||||||
@ -281,8 +294,10 @@ void InformWebsockets(struct mg_context *ctx)
|
|||||||
mg_lock_context(ctx);
|
mg_lock_context(ctx);
|
||||||
for (i = 0; i < MAX_WS_CLIENTS; i++) {
|
for (i = 0; i < MAX_WS_CLIENTS; i++) {
|
||||||
if (ws_clients[i].state == 2) {
|
if (ws_clients[i].state == 2) {
|
||||||
mg_websocket_write(
|
mg_websocket_write(ws_clients[i].conn,
|
||||||
ws_clients[i].conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text));
|
WEBSOCKET_OPCODE_TEXT,
|
||||||
|
text,
|
||||||
|
strlen(text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mg_unlock_context(ctx);
|
mg_unlock_context(ctx);
|
||||||
@ -290,7 +305,8 @@ void InformWebsockets(struct mg_context *ctx)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const char *options[] = {"document_root",
|
const char *options[] = {"document_root",
|
||||||
DOCUMENT_ROOT,
|
DOCUMENT_ROOT,
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -19,126 +19,153 @@
|
|||||||
#define EXIT_URI "/exit"
|
#define EXIT_URI "/exit"
|
||||||
bool exitNow = false;
|
bool exitNow = false;
|
||||||
|
|
||||||
class ExampleHandler: public CivetHandler
|
class ExampleHandler : public CivetHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool handleGet(CivetServer *server, struct mg_connection *conn) {
|
bool
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
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, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\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, "<html><body>\r\n");
|
||||||
mg_printf(conn, "<p>To see a page from the A handler with a parameter <a href=\"a?param=1\">click here</a></p>\r\n");
|
mg_printf(conn,
|
||||||
mg_printf(conn, "<p>To see a page from the A/B handler <a href=\"a/b\">click here</a></p>\r\n");
|
"<h2>This is an example text from a C++ handler</h2>\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 A handler <a "
|
||||||
mg_printf(conn, "<p>To exit <a href=\"%s\">click here</a></p>\r\n", EXIT_URI);
|
"href=\"a\">click here</a></p>\r\n");
|
||||||
mg_printf(conn, "</body></html>\r\n");
|
mg_printf(conn, "<p>To see a page from the A handler with a parameter "
|
||||||
return true;
|
"<a href=\"a?param=1\">click here</a></p>\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 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
|
class ExitHandler : public CivetHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool handleGet(CivetServer *server, struct mg_connection *conn) {
|
bool
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n");
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
mg_printf(conn, "Bye!\n");
|
{
|
||||||
exitNow = true;
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n");
|
||||||
return true;
|
mg_printf(conn, "Bye!\n");
|
||||||
}
|
exitNow = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AHandler: public CivetHandler
|
class AHandler : public CivetHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool handleAll(const char * method, CivetServer *server, struct mg_connection *conn) {
|
bool
|
||||||
std::string s = "";
|
handleAll(const char *method,
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
CivetServer *server,
|
||||||
mg_printf(conn, "<html><body>");
|
struct mg_connection *conn)
|
||||||
mg_printf(conn, "<h2>This is the A handler for \"%s\" !</h2>", method);
|
{
|
||||||
if (CivetServer::getParam(conn, "param", s)) {
|
std::string s = "";
|
||||||
mg_printf(conn, "<p>param set to %s</p>", s.c_str());
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||||
} else {
|
mg_printf(conn, "<html><body>");
|
||||||
mg_printf(conn, "<p>param not set</p>");
|
mg_printf(conn, "<h2>This is the A handler for \"%s\" !</h2>", method);
|
||||||
}
|
if (CivetServer::getParam(conn, "param", s)) {
|
||||||
mg_printf(conn, "</body></html>\n");
|
mg_printf(conn, "<p>param set to %s</p>", s.c_str());
|
||||||
return true;
|
} else {
|
||||||
}
|
mg_printf(conn, "<p>param not set</p>");
|
||||||
public:
|
}
|
||||||
bool handleGet(CivetServer *server, struct mg_connection *conn) {
|
mg_printf(conn, "</body></html>\n");
|
||||||
return handleAll("GET", server, conn);
|
return true;
|
||||||
}
|
}
|
||||||
bool handlePost(CivetServer *server, struct mg_connection *conn) {
|
|
||||||
return handleAll("POST", server, conn);
|
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
|
class ABHandler : public CivetHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool handleGet(CivetServer *server, struct mg_connection *conn) {
|
bool
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
mg_printf(conn, "<html><body>");
|
{
|
||||||
mg_printf(conn, "<h2>This is the AB handler!!!</h2>");
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||||
mg_printf(conn, "</body></html>\n");
|
mg_printf(conn, "<html><body>");
|
||||||
return true;
|
mg_printf(conn, "<h2>This is the AB handler!!!</h2>");
|
||||||
}
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FooHandler: public CivetHandler
|
class FooHandler : public CivetHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool handleGet(CivetServer *server, struct mg_connection *conn) {
|
bool
|
||||||
/* Handler may access the request info using mg_get_request_info */
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
const struct mg_request_info * req_info = mg_get_request_info(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\n\r\n");
|
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||||
mg_printf(conn, "<html><body>");
|
mg_printf(conn, "<html><body>");
|
||||||
mg_printf(conn, "<h2>This is the Foo handler!!!</h2>");
|
mg_printf(conn, "<h2>This is the Foo handler!!!</h2>");
|
||||||
mg_printf(conn, "<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>",
|
mg_printf(conn,
|
||||||
req_info->request_method, req_info->uri, req_info->http_version);
|
"<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>",
|
||||||
mg_printf(conn, "</body></html>\n");
|
req_info->request_method,
|
||||||
return true;
|
req_info->uri,
|
||||||
}
|
req_info->http_version);
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
const char * options[] = { "document_root", DOCUMENT_ROOT,
|
const char *options[] = {
|
||||||
"listening_ports", PORT, 0
|
"document_root", DOCUMENT_ROOT, "listening_ports", PORT, 0};
|
||||||
};
|
|
||||||
|
|
||||||
CivetServer server(options);
|
CivetServer server(options);
|
||||||
|
|
||||||
ExampleHandler h_ex;
|
ExampleHandler h_ex;
|
||||||
server.addHandler(EXAMPLE_URI, h_ex);
|
server.addHandler(EXAMPLE_URI, h_ex);
|
||||||
|
|
||||||
ExitHandler h_exit;
|
ExitHandler h_exit;
|
||||||
server.addHandler(EXIT_URI, h_exit);
|
server.addHandler(EXIT_URI, h_exit);
|
||||||
|
|
||||||
AHandler h_a;
|
AHandler h_a;
|
||||||
server.addHandler("/a", h_a);
|
server.addHandler("/a", h_a);
|
||||||
|
|
||||||
ABHandler h_ab;
|
ABHandler h_ab;
|
||||||
server.addHandler("/a/b", h_ab);
|
server.addHandler("/a/b", h_ab);
|
||||||
|
|
||||||
FooHandler h_foo;
|
FooHandler h_foo;
|
||||||
server.addHandler("**.foo$", h_foo);
|
server.addHandler("**.foo$", h_foo);
|
||||||
|
|
||||||
printf("Browse files at http://localhost:%s/\n", PORT);
|
printf("Browse files at http://localhost:%s/\n", PORT);
|
||||||
printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI);
|
printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI);
|
||||||
printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI);
|
printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI);
|
||||||
|
|
||||||
while (!exitNow) {
|
while (!exitNow) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Sleep(1000);
|
Sleep(1000);
|
||||||
#else
|
#else
|
||||||
sleep(1);
|
sleep(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Bye!\n");
|
printf("Bye!\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -15,180 +15,211 @@
|
|||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#define mg_sleep(x) usleep((x) * 1000)
|
#define mg_sleep(x) usleep((x)*1000)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void send_to_all_websockets(struct mg_context *ctx, const char * data, int data_len) {
|
static void
|
||||||
|
send_to_all_websockets(struct mg_context *ctx, const char *data, int data_len)
|
||||||
|
{
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
|
tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
|
||||||
|
|
||||||
mg_lock_context(ctx);
|
mg_lock_context(ctx);
|
||||||
for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
|
for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) {
|
||||||
if (ws_ctx->socketList[i] && (ws_ctx->socketList[i]->webSockState==2)) {
|
if (ws_ctx->socketList[i]
|
||||||
mg_websocket_write(ws_ctx->socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
|
&& (ws_ctx->socketList[i]->webSockState == 2)) {
|
||||||
}
|
mg_websocket_write(ws_ctx->socketList[i]->conn,
|
||||||
}
|
WEBSOCKET_OPCODE_TEXT,
|
||||||
mg_unlock_context(ctx);
|
data,
|
||||||
|
data_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mg_unlock_context(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void websocket_ready_handler(struct mg_connection *conn, void *_ignored) {
|
void
|
||||||
|
websocket_ready_handler(struct mg_connection *conn, void *_ignored)
|
||||||
|
{
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
const struct mg_request_info * rq = mg_get_request_info(conn);
|
const struct mg_request_info *rq = mg_get_request_info(conn);
|
||||||
struct mg_context * ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
|
tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
|
||||||
tWebSockInfo * wsock = malloc(sizeof(tWebSockInfo));
|
tWebSockInfo *wsock = malloc(sizeof(tWebSockInfo));
|
||||||
assert(wsock);
|
assert(wsock);
|
||||||
wsock->webSockState = 0;
|
wsock->webSockState = 0;
|
||||||
mg_set_user_connection_data(conn, wsock);
|
mg_set_user_connection_data(conn, wsock);
|
||||||
|
|
||||||
mg_lock_context(ctx);
|
mg_lock_context(ctx);
|
||||||
for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
|
for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) {
|
||||||
if (0==ws_ctx->socketList[i]) {
|
if (0 == ws_ctx->socketList[i]) {
|
||||||
ws_ctx->socketList[i] = wsock;
|
ws_ctx->socketList[i] = wsock;
|
||||||
wsock->conn = conn;
|
wsock->conn = conn;
|
||||||
wsock->webSockState = 1;
|
wsock->webSockState = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\nNew websocket attached: %s:%u\n", rq->remote_addr, rq->remote_port);
|
printf("\nNew websocket attached: %s:%u\n",
|
||||||
mg_unlock_context(ctx);
|
rq->remote_addr,
|
||||||
|
rq->remote_port);
|
||||||
|
mg_unlock_context(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void websocket_done(tWebSockContext *ws_ctx, tWebSockInfo * wsock) {
|
static void
|
||||||
|
websocket_done(tWebSockContext *ws_ctx, tWebSockInfo *wsock)
|
||||||
|
{
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (wsock) {
|
if (wsock) {
|
||||||
wsock->webSockState = 99;
|
wsock->webSockState = 99;
|
||||||
for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
|
for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) {
|
||||||
if (wsock==ws_ctx->socketList[i]) {
|
if (wsock == ws_ctx->socketList[i]) {
|
||||||
ws_ctx->socketList[i] = 0;
|
ws_ctx->socketList[i] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\nClose websocket attached: %s:%u\n", mg_get_request_info(wsock->conn)->remote_addr, mg_get_request_info(wsock->conn)->remote_port);
|
printf("\nClose websocket attached: %s:%u\n",
|
||||||
free(wsock);
|
mg_get_request_info(wsock->conn)->remote_addr,
|
||||||
}
|
mg_get_request_info(wsock->conn)->remote_port);
|
||||||
|
free(wsock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len, void *_ignored) {
|
int
|
||||||
|
websocket_data_handler(struct mg_connection *conn,
|
||||||
|
int flags,
|
||||||
|
char *data,
|
||||||
|
size_t data_len,
|
||||||
|
void *_ignored)
|
||||||
|
{
|
||||||
|
|
||||||
const struct mg_request_info * rq = mg_get_request_info(conn);
|
const struct mg_request_info *rq = mg_get_request_info(conn);
|
||||||
tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
|
tWebSockInfo *wsock = (tWebSockInfo *)rq->conn_data;
|
||||||
struct mg_context * ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
|
tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
|
||||||
char msg[128];
|
char msg[128];
|
||||||
|
|
||||||
mg_lock_context(ctx);
|
mg_lock_context(ctx);
|
||||||
if (flags==136) {
|
if (flags == 136) {
|
||||||
// close websock
|
// close websock
|
||||||
websocket_done(ws_ctx, wsock);
|
websocket_done(ws_ctx, wsock);
|
||||||
mg_set_user_connection_data(conn, NULL);
|
mg_set_user_connection_data(conn, NULL);
|
||||||
mg_unlock_context(ctx);
|
mg_unlock_context(ctx);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (((data_len>=5) && (data_len<100) && (flags==129)) || (flags==130)) {
|
if (((data_len >= 5) && (data_len < 100) && (flags == 129))
|
||||||
|
|| (flags == 130)) {
|
||||||
|
|
||||||
// init command
|
// init command
|
||||||
if ((wsock->webSockState==1) && (!memcmp(data,"init ",5))) {
|
if ((wsock->webSockState == 1) && (!memcmp(data, "init ", 5))) {
|
||||||
char * chk;
|
char *chk;
|
||||||
unsigned long gid;
|
unsigned long gid;
|
||||||
memcpy(msg,data+5,data_len-5);
|
memcpy(msg, data + 5, data_len - 5);
|
||||||
msg[data_len-5]=0;
|
msg[data_len - 5] = 0;
|
||||||
gid = strtoul(msg,&chk,10);
|
gid = strtoul(msg, &chk, 10);
|
||||||
wsock->initId = gid;
|
wsock->initId = gid;
|
||||||
if (gid>0 && chk!=NULL && *chk==0) {
|
if (gid > 0 && chk != NULL && *chk == 0) {
|
||||||
wsock->webSockState = 2;
|
wsock->webSockState = 2;
|
||||||
}
|
}
|
||||||
mg_unlock_context(ctx);
|
mg_unlock_context(ctx);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chat message
|
// chat message
|
||||||
if ((wsock->webSockState==2) && (!memcmp(data,"msg ",4))) {
|
if ((wsock->webSockState == 2) && (!memcmp(data, "msg ", 4))) {
|
||||||
send_to_all_websockets(ctx, data, data_len);
|
send_to_all_websockets(ctx, data, data_len);
|
||||||
mg_unlock_context(ctx);
|
mg_unlock_context(ctx);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep alive
|
// keep alive
|
||||||
if ((data_len==4) && !memcmp(data,"ping",4)) {
|
if ((data_len == 4) && !memcmp(data, "ping", 4)) {
|
||||||
mg_unlock_context(ctx);
|
mg_unlock_context(ctx);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_unlock_context(ctx);
|
mg_unlock_context(ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void connection_close_handler(const struct mg_connection *conn, void *_ignored) {
|
void
|
||||||
|
connection_close_handler(const struct mg_connection *conn, void *_ignored)
|
||||||
|
{
|
||||||
|
|
||||||
const struct mg_request_info * rq = mg_get_request_info(conn);
|
const struct mg_request_info *rq = mg_get_request_info(conn);
|
||||||
tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
|
tWebSockInfo *wsock = (tWebSockInfo *)rq->conn_data;
|
||||||
struct mg_context * ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
|
tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
|
||||||
|
|
||||||
mg_lock_context(ctx);
|
mg_lock_context(ctx);
|
||||||
websocket_done(ws_ctx, wsock);
|
websocket_done(ws_ctx, wsock);
|
||||||
mg_set_user_connection_data(conn, NULL);
|
mg_set_user_connection_data(conn, NULL);
|
||||||
mg_unlock_context(ctx);
|
mg_unlock_context(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void * eventMain(void * arg) {
|
static void *
|
||||||
|
eventMain(void *arg)
|
||||||
|
{
|
||||||
|
|
||||||
char msg[256];
|
char msg[256];
|
||||||
struct mg_context *ctx = (struct mg_context *)arg;
|
struct mg_context *ctx = (struct mg_context *)arg;
|
||||||
tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
|
tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
|
||||||
|
|
||||||
ws_ctx->runLoop = 1;
|
ws_ctx->runLoop = 1;
|
||||||
while (ws_ctx->runLoop) {
|
while (ws_ctx->runLoop) {
|
||||||
time_t t = time(0);
|
time_t t = time(0);
|
||||||
struct tm * timestr = localtime(&t);
|
struct tm *timestr = localtime(&t);
|
||||||
strftime(msg, sizeof(msg), "title %c", timestr);
|
strftime(msg, sizeof(msg), "title %c", timestr);
|
||||||
send_to_all_websockets(ctx, msg, strlen(msg));
|
send_to_all_websockets(ctx, msg, strlen(msg));
|
||||||
|
|
||||||
mg_sleep(1000);
|
mg_sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void websock_send_broadcast(struct mg_context *ctx, const char * data, int data_len) {
|
void
|
||||||
|
websock_send_broadcast(struct mg_context *ctx, const char *data, int data_len)
|
||||||
|
{
|
||||||
|
|
||||||
char buffer[260];
|
char buffer[260];
|
||||||
|
|
||||||
if (data_len<=256) {
|
if (data_len <= 256) {
|
||||||
strcpy(buffer, "msg ");
|
strcpy(buffer, "msg ");
|
||||||
memcpy(buffer+4, data, data_len);
|
memcpy(buffer + 4, data, data_len);
|
||||||
|
|
||||||
send_to_all_websockets(ctx, buffer, data_len+4);
|
send_to_all_websockets(ctx, buffer, data_len + 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void websock_init_lib(const struct mg_context *ctx) {
|
void
|
||||||
|
websock_init_lib(const struct mg_context *ctx)
|
||||||
|
{
|
||||||
|
|
||||||
tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
|
tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
|
||||||
memset(ws_ctx, 0, sizeof(*ws_ctx));
|
memset(ws_ctx, 0, sizeof(*ws_ctx));
|
||||||
/* todo: use mg_start_thread_id instead of mg_start_thread */
|
/* todo: use mg_start_thread_id instead of mg_start_thread */
|
||||||
mg_start_thread(eventMain, (void*)ctx);
|
mg_start_thread(eventMain, (void *)ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void websock_exit_lib(const struct mg_context *ctx) {
|
void
|
||||||
|
websock_exit_lib(const struct mg_context *ctx)
|
||||||
|
{
|
||||||
|
|
||||||
tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
|
tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
|
||||||
ws_ctx->runLoop = 0;
|
ws_ctx->runLoop = 0;
|
||||||
/* todo: wait for the thread instead of a timeout */
|
/* todo: wait for the thread instead of a timeout */
|
||||||
mg_sleep(2000);
|
mg_sleep(2000);
|
||||||
}
|
}
|
||||||
|
@ -9,26 +9,31 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct tWebSockInfo {
|
typedef struct tWebSockInfo {
|
||||||
int webSockState;
|
int webSockState;
|
||||||
unsigned long initId;
|
unsigned long initId;
|
||||||
struct mg_connection *conn;
|
struct mg_connection *conn;
|
||||||
} tWebSockInfo;
|
} tWebSockInfo;
|
||||||
|
|
||||||
#define MAX_NUM_OF_WEBSOCKS (256)
|
#define MAX_NUM_OF_WEBSOCKS (256)
|
||||||
typedef struct tWebSockContext {
|
typedef struct tWebSockContext {
|
||||||
int runLoop;
|
int runLoop;
|
||||||
void * thread_id;
|
void *thread_id;
|
||||||
tWebSockInfo *socketList[MAX_NUM_OF_WEBSOCKS];
|
tWebSockInfo *socketList[MAX_NUM_OF_WEBSOCKS];
|
||||||
} tWebSockContext;
|
} tWebSockContext;
|
||||||
|
|
||||||
|
|
||||||
void websock_init_lib(const struct mg_context *ctx);
|
void websock_init_lib(const struct mg_context *ctx);
|
||||||
void websock_exit_lib(const struct mg_context *ctx);
|
void websock_exit_lib(const struct mg_context *ctx);
|
||||||
|
|
||||||
void websock_send_broadcast(struct mg_context *ctx, const char * data, int data_len);
|
void
|
||||||
|
websock_send_broadcast(struct mg_context *ctx, const char *data, int data_len);
|
||||||
|
|
||||||
void websocket_ready_handler(struct mg_connection *conn, void *_ignored);
|
void websocket_ready_handler(struct mg_connection *conn, void *_ignored);
|
||||||
int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len, void *_ignored);
|
int websocket_data_handler(struct mg_connection *conn,
|
||||||
|
int flags,
|
||||||
|
char *data,
|
||||||
|
size_t data_len,
|
||||||
|
void *_ignored);
|
||||||
void connection_close_handler(const struct mg_connection *conn, void *_ignored);
|
void connection_close_handler(const struct mg_connection *conn, void *_ignored);
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,50 +10,56 @@
|
|||||||
#include "civetweb.h"
|
#include "civetweb.h"
|
||||||
#include "WebSockCallbacks.h"
|
#include "WebSockCallbacks.h"
|
||||||
|
|
||||||
int main(void)
|
int
|
||||||
|
main(void)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = 0;
|
struct mg_context *ctx = 0;
|
||||||
struct mg_callbacks callback_funcs = {0};
|
struct mg_callbacks callback_funcs = {0};
|
||||||
tWebSockContext ws_ctx;
|
tWebSockContext ws_ctx;
|
||||||
char inbuf[4];
|
char inbuf[4];
|
||||||
|
|
||||||
const char *server_options[] = {
|
const char *server_options[] = {
|
||||||
/* document_root: The path to the test function websock.htm */
|
/* document_root: The path to the test function websock.htm */
|
||||||
"document_root", "../../examples/websocket",
|
"document_root",
|
||||||
|
"../../examples/websocket",
|
||||||
|
|
||||||
/* port: use http standard to match websocket url in websock.htm: ws://127.0.0.1/MyWebSock */
|
/* port: use http standard to match websocket url in websock.htm:
|
||||||
/* if the port is changed here, it needs to be changed in websock.htm as well */
|
ws://127.0.0.1/MyWebSock */
|
||||||
"listening_ports", "80",
|
/* if the port is changed here, it needs to be changed in
|
||||||
|
websock.htm as well */
|
||||||
|
"listening_ports",
|
||||||
|
"80",
|
||||||
|
|
||||||
NULL
|
NULL};
|
||||||
};
|
|
||||||
|
|
||||||
callback_funcs.init_context = websock_init_lib;
|
callback_funcs.init_context = websock_init_lib;
|
||||||
callback_funcs.exit_context = websock_exit_lib;
|
callback_funcs.exit_context = websock_exit_lib;
|
||||||
|
|
||||||
ctx = mg_start(&callback_funcs, &ws_ctx, server_options);
|
ctx = mg_start(&callback_funcs, &ws_ctx, server_options);
|
||||||
|
|
||||||
mg_set_websocket_handler(ctx, "/MyWebSock",
|
mg_set_websocket_handler(ctx,
|
||||||
NULL,
|
"/MyWebSock",
|
||||||
websocket_ready_handler,
|
NULL,
|
||||||
websocket_data_handler,
|
websocket_ready_handler,
|
||||||
connection_close_handler,
|
websocket_data_handler,
|
||||||
NULL);
|
connection_close_handler,
|
||||||
|
NULL);
|
||||||
|
|
||||||
printf("Connect to localhost:%s/websock.htm\n", mg_get_option(ctx, "listening_ports"));
|
printf("Connect to localhost:%s/websock.htm\n",
|
||||||
|
mg_get_option(ctx, "listening_ports"));
|
||||||
|
|
||||||
puts("Enter an (ASCII) character or * to exit:");
|
puts("Enter an (ASCII) character or * to exit:");
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fgets(inbuf, sizeof(inbuf), stdin);
|
fgets(inbuf, sizeof(inbuf), stdin);
|
||||||
|
|
||||||
if (inbuf[0]=='*') {
|
if (inbuf[0] == '*') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
inbuf[0] = toupper(inbuf[0]);
|
inbuf[0] = toupper(inbuf[0]);
|
||||||
websock_send_broadcast(ctx, inbuf, 1);
|
websock_send_broadcast(ctx, inbuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_stop(ctx);
|
mg_stop(ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// Simple example program on how to use websocket client embedded C interface.
|
// Simple example program on how to use websocket client embedded C interface.
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#define sleep(x) Sleep(1000*(x))
|
#define sleep(x) Sleep(1000 * (x))
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
@ -21,318 +21,393 @@
|
|||||||
#define PORT "8888"
|
#define PORT "8888"
|
||||||
#define SSL_CERT "./ssl/server.pem"
|
#define SSL_CERT "./ssl/server.pem"
|
||||||
|
|
||||||
const char * websocket_welcome_msg = "websocket welcome\n";
|
const char *websocket_welcome_msg = "websocket welcome\n";
|
||||||
const size_t websocket_welcome_msg_len = 18 /* strlen(websocket_welcome_msg) */ ;
|
const size_t websocket_welcome_msg_len = 18 /* strlen(websocket_welcome_msg) */;
|
||||||
const char * websocket_acknowledge_msg = "websocket msg ok\n";
|
const char *websocket_acknowledge_msg = "websocket msg ok\n";
|
||||||
const size_t websocket_acknowledge_msg_len = 17 /* strlen(websocket_acknowledge_msg) */ ;
|
const size_t websocket_acknowledge_msg_len =
|
||||||
const char * websocket_goodbye_msg = "websocket bye\n";
|
17 /* strlen(websocket_acknowledge_msg) */;
|
||||||
const size_t websocket_goodbye_msg_len = 14 /* strlen(websocket_goodbye_msg) */ ;
|
const char *websocket_goodbye_msg = "websocket bye\n";
|
||||||
|
const size_t websocket_goodbye_msg_len = 14 /* strlen(websocket_goodbye_msg) */;
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************************/
|
/*************************************************************************************/
|
||||||
/* WEBSOCKET SERVER */
|
/* WEBSOCKET SERVER */
|
||||||
/*************************************************************************************/
|
/*************************************************************************************/
|
||||||
#if defined(MG_LEGACY_INTERFACE)
|
#if defined(MG_LEGACY_INTERFACE)
|
||||||
int websock_server_connect(const struct mg_connection * conn)
|
int
|
||||||
|
websock_server_connect(const struct mg_connection *conn)
|
||||||
#else
|
#else
|
||||||
int websocket_server_connect(const struct mg_connection * conn, void * _ignored)
|
int
|
||||||
|
websocket_server_connect(const struct mg_connection *conn, void *_ignored)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
printf("Server: Websocket connected\n");
|
printf("Server: Websocket connected\n");
|
||||||
return 0; /* return 0 to accept every connection */
|
return 0; /* return 0 to accept every connection */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(MG_LEGACY_INTERFACE)
|
#if defined(MG_LEGACY_INTERFACE)
|
||||||
void websocket_server_ready(struct mg_connection * conn)
|
void
|
||||||
|
websocket_server_ready(struct mg_connection *conn)
|
||||||
#else
|
#else
|
||||||
void websocket_server_ready(struct mg_connection * conn, void * _ignored)
|
void
|
||||||
|
websocket_server_ready(struct mg_connection *conn, void *_ignored)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
printf("Server: Websocket ready\n");
|
printf("Server: Websocket ready\n");
|
||||||
|
|
||||||
/* Send websocket welcome message */
|
/* Send websocket welcome message */
|
||||||
mg_lock_connection(conn);
|
mg_lock_connection(conn);
|
||||||
mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, websocket_welcome_msg, websocket_welcome_msg_len);
|
mg_websocket_write(conn,
|
||||||
mg_unlock_connection(conn);
|
WEBSOCKET_OPCODE_TEXT,
|
||||||
|
websocket_welcome_msg,
|
||||||
|
websocket_welcome_msg_len);
|
||||||
|
mg_unlock_connection(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(MG_LEGACY_INTERFACE)
|
#if defined(MG_LEGACY_INTERFACE)
|
||||||
int websocket_server_data(struct mg_connection * conn, int bits, char *data, size_t data_len)
|
int
|
||||||
|
websocket_server_data(struct mg_connection *conn,
|
||||||
|
int bits,
|
||||||
|
char *data,
|
||||||
|
size_t data_len)
|
||||||
#else
|
#else
|
||||||
int websocket_server_data(struct mg_connection * conn, int bits, char *data, size_t data_len, void *_ignored)
|
int
|
||||||
|
websocket_server_data(struct mg_connection *conn,
|
||||||
|
int bits,
|
||||||
|
char *data,
|
||||||
|
size_t data_len,
|
||||||
|
void *_ignored)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
printf("Server: Got %u bytes from the client\n", data_len);
|
printf("Server: Got %u bytes from the client\n", data_len);
|
||||||
|
|
||||||
if (data_len<3 || 0!=memcmp(data, "bye", 3)) {
|
if (data_len < 3 || 0 != memcmp(data, "bye", 3)) {
|
||||||
/* Send websocket acknowledge message */
|
/* Send websocket acknowledge message */
|
||||||
mg_lock_connection(conn);
|
mg_lock_connection(conn);
|
||||||
mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, websocket_acknowledge_msg, websocket_acknowledge_msg_len);
|
mg_websocket_write(conn,
|
||||||
mg_unlock_connection(conn);
|
WEBSOCKET_OPCODE_TEXT,
|
||||||
} else {
|
websocket_acknowledge_msg,
|
||||||
/* Send websocket acknowledge message */
|
websocket_acknowledge_msg_len);
|
||||||
mg_lock_connection(conn);
|
mg_unlock_connection(conn);
|
||||||
mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, websocket_goodbye_msg, websocket_goodbye_msg_len);
|
} else {
|
||||||
mg_unlock_connection(conn);
|
/* Send websocket acknowledge message */
|
||||||
}
|
mg_lock_connection(conn);
|
||||||
|
mg_websocket_write(conn,
|
||||||
|
WEBSOCKET_OPCODE_TEXT,
|
||||||
|
websocket_goodbye_msg,
|
||||||
|
websocket_goodbye_msg_len);
|
||||||
|
mg_unlock_connection(conn);
|
||||||
|
}
|
||||||
|
|
||||||
return 1; /* return 1 to keep the connetion open */
|
return 1; /* return 1 to keep the connetion open */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(MG_LEGACY_INTERFACE)
|
#if defined(MG_LEGACY_INTERFACE)
|
||||||
void websocket_server_connection_close(const struct mg_connection * conn)
|
void
|
||||||
|
websocket_server_connection_close(const struct mg_connection *conn)
|
||||||
#else
|
#else
|
||||||
void websocket_server_connection_close(const struct mg_connection * conn, void *_ignored)
|
void
|
||||||
|
websocket_server_connection_close(const struct mg_connection *conn,
|
||||||
|
void *_ignored)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
printf("Server: Close connection\n");
|
printf("Server: Close connection\n");
|
||||||
|
|
||||||
/* Can not send a websocket goodbye message here - the connection is already closed */
|
/* Can not send a websocket goodbye message here - the connection is already
|
||||||
|
* closed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct mg_context * start_websocket_server()
|
struct mg_context *
|
||||||
|
start_websocket_server()
|
||||||
{
|
{
|
||||||
const char * options[] = { "document_root", DOCUMENT_ROOT,
|
const char *options[] = {"document_root",
|
||||||
"ssl_certificate", SSL_CERT,
|
DOCUMENT_ROOT,
|
||||||
"listening_ports", PORT,
|
"ssl_certificate",
|
||||||
"request_timeout_ms", "5000",
|
SSL_CERT,
|
||||||
0
|
"listening_ports",
|
||||||
};
|
PORT,
|
||||||
struct mg_callbacks callbacks;
|
"request_timeout_ms",
|
||||||
struct mg_context *ctx;
|
"5000",
|
||||||
|
0};
|
||||||
|
struct mg_callbacks callbacks;
|
||||||
|
struct mg_context *ctx;
|
||||||
|
|
||||||
memset(&callbacks, 0, sizeof(callbacks));
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
|
||||||
#if defined(MG_LEGACY_INTERFACE)
|
#if defined(MG_LEGACY_INTERFACE)
|
||||||
/* Obsolete: */
|
/* Obsolete: */
|
||||||
callbacks.websocket_connect = websock_server_connect;
|
callbacks.websocket_connect = websock_server_connect;
|
||||||
callbacks.websocket_ready = websocket_server_ready;
|
callbacks.websocket_ready = websocket_server_ready;
|
||||||
callbacks.websocket_data = websocket_server_data;
|
callbacks.websocket_data = websocket_server_data;
|
||||||
callbacks.connection_close = websocket_server_connection_close;
|
callbacks.connection_close = websocket_server_connection_close;
|
||||||
|
|
||||||
ctx = mg_start(&callbacks, 0, options);
|
ctx = mg_start(&callbacks, 0, options);
|
||||||
#else
|
#else
|
||||||
/* New interface: */
|
/* New interface: */
|
||||||
ctx = mg_start(&callbacks, 0, options);
|
ctx = mg_start(&callbacks, 0, options);
|
||||||
|
|
||||||
mg_set_websocket_handler(ctx, "/websocket",
|
mg_set_websocket_handler(ctx,
|
||||||
websocket_server_connect,
|
"/websocket",
|
||||||
websocket_server_ready,
|
websocket_server_connect,
|
||||||
websocket_server_data,
|
websocket_server_ready,
|
||||||
websocket_server_connection_close,
|
websocket_server_data,
|
||||||
NULL);
|
websocket_server_connection_close,
|
||||||
|
NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************************/
|
/*************************************************************************************/
|
||||||
/* WEBSOCKET CLIENT */
|
/* WEBSOCKET CLIENT */
|
||||||
/*************************************************************************************/
|
/*************************************************************************************/
|
||||||
struct tclient_data {
|
struct tclient_data {
|
||||||
void * data;
|
void *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
int closed;
|
int closed;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int websocket_client_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len, void * user_data)
|
static int
|
||||||
|
websocket_client_data_handler(struct mg_connection *conn,
|
||||||
|
int flags,
|
||||||
|
char *data,
|
||||||
|
size_t data_len,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
struct tclient_data *pclient_data = (struct tclient_data *) mg_get_user_data(ctx);
|
struct tclient_data *pclient_data =
|
||||||
|
(struct tclient_data *)mg_get_user_data(ctx);
|
||||||
|
|
||||||
printf("Client received data from server: ");
|
printf("Client received data from server: ");
|
||||||
fwrite(data, 1, data_len, stdout);
|
fwrite(data, 1, data_len, stdout);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
pclient_data->data = malloc(data_len);
|
pclient_data->data = malloc(data_len);
|
||||||
assert(pclient_data->data != NULL);
|
assert(pclient_data->data != NULL);
|
||||||
memcpy(pclient_data->data, data, data_len);
|
memcpy(pclient_data->data, data, data_len);
|
||||||
pclient_data->len = data_len;
|
pclient_data->len = data_len;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void websocket_client_close_handler(const struct mg_connection *conn, void * user_data)
|
static void
|
||||||
|
websocket_client_close_handler(const struct mg_connection *conn,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
struct tclient_data *pclient_data = (struct tclient_data *) mg_get_user_data(ctx);
|
struct tclient_data *pclient_data =
|
||||||
|
(struct tclient_data *)mg_get_user_data(ctx);
|
||||||
|
|
||||||
printf("Client: Close handler\n");
|
printf("Client: Close handler\n");
|
||||||
pclient_data->closed++;
|
pclient_data->closed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = NULL;
|
struct mg_context *ctx = NULL;
|
||||||
struct tclient_data client1_data = {NULL, 0, 0};
|
struct tclient_data client1_data = {NULL, 0, 0};
|
||||||
struct tclient_data client2_data = {NULL, 0, 0};
|
struct tclient_data client2_data = {NULL, 0, 0};
|
||||||
struct tclient_data client3_data = {NULL, 0, 0};
|
struct tclient_data client3_data = {NULL, 0, 0};
|
||||||
struct mg_connection* newconn1 = NULL;
|
struct mg_connection *newconn1 = NULL;
|
||||||
struct mg_connection* newconn2 = NULL;
|
struct mg_connection *newconn2 = NULL;
|
||||||
struct mg_connection* newconn3 = NULL;
|
struct mg_connection *newconn3 = NULL;
|
||||||
char ebuf[100] = {0};
|
char ebuf[100] = {0};
|
||||||
|
|
||||||
assert(websocket_welcome_msg_len == strlen(websocket_welcome_msg));
|
assert(websocket_welcome_msg_len == strlen(websocket_welcome_msg));
|
||||||
|
|
||||||
/* First set up a websocket server */
|
/* First set up a websocket server */
|
||||||
ctx = start_websocket_server();
|
ctx = start_websocket_server();
|
||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
printf("Server init\n\n");
|
printf("Server init\n\n");
|
||||||
|
|
||||||
/* Then connect a first client */
|
/* Then connect a first client */
|
||||||
newconn1 = mg_connect_websocket_client("localhost", atoi(PORT), 0, ebuf, sizeof(ebuf),
|
newconn1 = mg_connect_websocket_client("localhost",
|
||||||
"/websocket", NULL, websocket_client_data_handler, websocket_client_close_handler,
|
atoi(PORT),
|
||||||
&client1_data);
|
0,
|
||||||
|
ebuf,
|
||||||
|
sizeof(ebuf),
|
||||||
|
"/websocket",
|
||||||
|
NULL,
|
||||||
|
websocket_client_data_handler,
|
||||||
|
websocket_client_close_handler,
|
||||||
|
&client1_data);
|
||||||
|
|
||||||
if (newconn1 == NULL)
|
if (newconn1 == NULL) {
|
||||||
{
|
printf("Error: %s", ebuf);
|
||||||
printf("Error: %s", ebuf);
|
return 1;
|
||||||
return 1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sleep(1); /* Should get the websocket welcome message */
|
sleep(1); /* Should get the websocket welcome message */
|
||||||
assert(client1_data.closed == 0);
|
assert(client1_data.closed == 0);
|
||||||
assert(client2_data.closed == 0);
|
assert(client2_data.closed == 0);
|
||||||
assert(client2_data.data == NULL);
|
assert(client2_data.data == NULL);
|
||||||
assert(client2_data.len == 0);
|
assert(client2_data.len == 0);
|
||||||
assert(client1_data.data != NULL);
|
assert(client1_data.data != NULL);
|
||||||
assert(client1_data.len == websocket_welcome_msg_len);
|
assert(client1_data.len == websocket_welcome_msg_len);
|
||||||
assert(!memcmp(client1_data.data, websocket_welcome_msg, websocket_welcome_msg_len));
|
assert(!memcmp(client1_data.data,
|
||||||
free(client1_data.data);
|
websocket_welcome_msg,
|
||||||
client1_data.data = NULL;
|
websocket_welcome_msg_len));
|
||||||
client1_data.len = 0;
|
free(client1_data.data);
|
||||||
|
client1_data.data = NULL;
|
||||||
|
client1_data.len = 0;
|
||||||
|
|
||||||
mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data1", 5);
|
mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data1", 5);
|
||||||
|
|
||||||
sleep(1); /* Should get the acknowledge message */
|
sleep(1); /* Should get the acknowledge message */
|
||||||
assert(client1_data.closed == 0);
|
assert(client1_data.closed == 0);
|
||||||
assert(client2_data.closed == 0);
|
assert(client2_data.closed == 0);
|
||||||
assert(client2_data.data == NULL);
|
assert(client2_data.data == NULL);
|
||||||
assert(client2_data.len == 0);
|
assert(client2_data.len == 0);
|
||||||
assert(client1_data.data != NULL);
|
assert(client1_data.data != NULL);
|
||||||
assert(client1_data.len == websocket_acknowledge_msg_len);
|
assert(client1_data.len == websocket_acknowledge_msg_len);
|
||||||
assert(!memcmp(client1_data.data, websocket_acknowledge_msg, websocket_acknowledge_msg_len));
|
assert(!memcmp(client1_data.data,
|
||||||
free(client1_data.data);
|
websocket_acknowledge_msg,
|
||||||
client1_data.data = NULL;
|
websocket_acknowledge_msg_len));
|
||||||
client1_data.len = 0;
|
free(client1_data.data);
|
||||||
|
client1_data.data = NULL;
|
||||||
|
client1_data.len = 0;
|
||||||
|
|
||||||
/* Now connect a second client */
|
/* Now connect a second client */
|
||||||
newconn2 = mg_connect_websocket_client("localhost", atoi(PORT), 0, ebuf, sizeof(ebuf),
|
newconn2 = mg_connect_websocket_client("localhost",
|
||||||
"/websocket", NULL, websocket_client_data_handler, websocket_client_close_handler,
|
atoi(PORT),
|
||||||
&client2_data);
|
0,
|
||||||
|
ebuf,
|
||||||
|
sizeof(ebuf),
|
||||||
|
"/websocket",
|
||||||
|
NULL,
|
||||||
|
websocket_client_data_handler,
|
||||||
|
websocket_client_close_handler,
|
||||||
|
&client2_data);
|
||||||
|
|
||||||
if (newconn2 == NULL)
|
if (newconn2 == NULL) {
|
||||||
{
|
printf("Error: %s", ebuf);
|
||||||
printf("Error: %s", ebuf);
|
return 1;
|
||||||
return 1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sleep(1); /* Client 2 should get the websocket welcome message */
|
sleep(1); /* Client 2 should get the websocket welcome message */
|
||||||
assert(client1_data.closed == 0);
|
assert(client1_data.closed == 0);
|
||||||
assert(client2_data.closed == 0);
|
assert(client2_data.closed == 0);
|
||||||
assert(client1_data.data == NULL);
|
assert(client1_data.data == NULL);
|
||||||
assert(client1_data.len == 0);
|
assert(client1_data.len == 0);
|
||||||
assert(client2_data.data != NULL);
|
assert(client2_data.data != NULL);
|
||||||
assert(client2_data.len == websocket_welcome_msg_len);
|
assert(client2_data.len == websocket_welcome_msg_len);
|
||||||
assert(!memcmp(client2_data.data, websocket_welcome_msg, websocket_welcome_msg_len));
|
assert(!memcmp(client2_data.data,
|
||||||
free(client2_data.data);
|
websocket_welcome_msg,
|
||||||
client2_data.data = NULL;
|
websocket_welcome_msg_len));
|
||||||
client2_data.len = 0;
|
free(client2_data.data);
|
||||||
|
client2_data.data = NULL;
|
||||||
|
client2_data.len = 0;
|
||||||
|
|
||||||
mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data2", 5);
|
mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data2", 5);
|
||||||
|
|
||||||
sleep(1); /* Should get the acknowledge message */
|
sleep(1); /* Should get the acknowledge message */
|
||||||
assert(client1_data.closed == 0);
|
assert(client1_data.closed == 0);
|
||||||
assert(client2_data.closed == 0);
|
assert(client2_data.closed == 0);
|
||||||
assert(client2_data.data == NULL);
|
assert(client2_data.data == NULL);
|
||||||
assert(client2_data.len == 0);
|
assert(client2_data.len == 0);
|
||||||
assert(client1_data.data != NULL);
|
assert(client1_data.data != NULL);
|
||||||
assert(client1_data.len == websocket_acknowledge_msg_len);
|
assert(client1_data.len == websocket_acknowledge_msg_len);
|
||||||
assert(!memcmp(client1_data.data, websocket_acknowledge_msg, websocket_acknowledge_msg_len));
|
assert(!memcmp(client1_data.data,
|
||||||
free(client1_data.data);
|
websocket_acknowledge_msg,
|
||||||
client1_data.data = NULL;
|
websocket_acknowledge_msg_len));
|
||||||
client1_data.len = 0;
|
free(client1_data.data);
|
||||||
|
client1_data.data = NULL;
|
||||||
|
client1_data.len = 0;
|
||||||
|
|
||||||
mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "bye", 3);
|
mg_websocket_write(newconn1, WEBSOCKET_OPCODE_TEXT, "bye", 3);
|
||||||
|
|
||||||
sleep(1); /* Should get the goodbye message */
|
sleep(1); /* Should get the goodbye message */
|
||||||
assert(client1_data.closed == 0);
|
assert(client1_data.closed == 0);
|
||||||
assert(client2_data.closed == 0);
|
assert(client2_data.closed == 0);
|
||||||
assert(client2_data.data == NULL);
|
assert(client2_data.data == NULL);
|
||||||
assert(client2_data.len == 0);
|
assert(client2_data.len == 0);
|
||||||
assert(client1_data.data != NULL);
|
assert(client1_data.data != NULL);
|
||||||
assert(client1_data.len == websocket_goodbye_msg_len);
|
assert(client1_data.len == websocket_goodbye_msg_len);
|
||||||
assert(!memcmp(client1_data.data, websocket_goodbye_msg, websocket_goodbye_msg_len));
|
assert(!memcmp(client1_data.data,
|
||||||
free(client1_data.data);
|
websocket_goodbye_msg,
|
||||||
client1_data.data = NULL;
|
websocket_goodbye_msg_len));
|
||||||
client1_data.len = 0;
|
free(client1_data.data);
|
||||||
|
client1_data.data = NULL;
|
||||||
|
client1_data.len = 0;
|
||||||
|
|
||||||
mg_close_connection(newconn1);
|
mg_close_connection(newconn1);
|
||||||
|
|
||||||
sleep(1); /* Won't get any message */
|
sleep(1); /* Won't get any message */
|
||||||
assert(client1_data.closed == 1);
|
assert(client1_data.closed == 1);
|
||||||
assert(client2_data.closed == 0);
|
assert(client2_data.closed == 0);
|
||||||
assert(client1_data.data == NULL);
|
assert(client1_data.data == NULL);
|
||||||
assert(client1_data.len == 0);
|
assert(client1_data.len == 0);
|
||||||
assert(client2_data.data == NULL);
|
assert(client2_data.data == NULL);
|
||||||
assert(client2_data.len == 0);
|
assert(client2_data.len == 0);
|
||||||
|
|
||||||
mg_websocket_write(newconn2, WEBSOCKET_OPCODE_TEXT, "bye", 3);
|
mg_websocket_write(newconn2, WEBSOCKET_OPCODE_TEXT, "bye", 3);
|
||||||
|
|
||||||
sleep(1); /* Should get the goodbye message */
|
sleep(1); /* Should get the goodbye message */
|
||||||
assert(client1_data.closed == 1);
|
assert(client1_data.closed == 1);
|
||||||
assert(client2_data.closed == 0);
|
assert(client2_data.closed == 0);
|
||||||
assert(client1_data.data == NULL);
|
assert(client1_data.data == NULL);
|
||||||
assert(client1_data.len == 0);
|
assert(client1_data.len == 0);
|
||||||
assert(client2_data.data != NULL);
|
assert(client2_data.data != NULL);
|
||||||
assert(client2_data.len == websocket_goodbye_msg_len);
|
assert(client2_data.len == websocket_goodbye_msg_len);
|
||||||
assert(!memcmp(client2_data.data, websocket_goodbye_msg, websocket_goodbye_msg_len));
|
assert(!memcmp(client2_data.data,
|
||||||
free(client2_data.data);
|
websocket_goodbye_msg,
|
||||||
client2_data.data = NULL;
|
websocket_goodbye_msg_len));
|
||||||
client2_data.len = 0;
|
free(client2_data.data);
|
||||||
|
client2_data.data = NULL;
|
||||||
|
client2_data.len = 0;
|
||||||
|
|
||||||
mg_close_connection(newconn2);
|
mg_close_connection(newconn2);
|
||||||
|
|
||||||
sleep(1); /* Won't get any message */
|
sleep(1); /* Won't get any message */
|
||||||
assert(client1_data.closed == 1);
|
assert(client1_data.closed == 1);
|
||||||
assert(client2_data.closed == 1);
|
assert(client2_data.closed == 1);
|
||||||
assert(client1_data.data == NULL);
|
assert(client1_data.data == NULL);
|
||||||
assert(client1_data.len == 0);
|
assert(client1_data.len == 0);
|
||||||
assert(client2_data.data == NULL);
|
assert(client2_data.data == NULL);
|
||||||
assert(client2_data.len == 0);
|
assert(client2_data.len == 0);
|
||||||
|
|
||||||
/* Connect client 3 */
|
/* Connect client 3 */
|
||||||
newconn3 = mg_connect_websocket_client("localhost", atoi(PORT), 0, ebuf, sizeof(ebuf),
|
newconn3 = mg_connect_websocket_client("localhost",
|
||||||
"/websocket", NULL, websocket_client_data_handler, websocket_client_close_handler,
|
atoi(PORT),
|
||||||
&client3_data);
|
0,
|
||||||
|
ebuf,
|
||||||
|
sizeof(ebuf),
|
||||||
|
"/websocket",
|
||||||
|
NULL,
|
||||||
|
websocket_client_data_handler,
|
||||||
|
websocket_client_close_handler,
|
||||||
|
&client3_data);
|
||||||
|
|
||||||
sleep(1); /* Client 3 should get the websocket welcome message */
|
sleep(1); /* Client 3 should get the websocket welcome message */
|
||||||
assert(client1_data.closed == 1);
|
assert(client1_data.closed == 1);
|
||||||
assert(client2_data.closed == 1);
|
assert(client2_data.closed == 1);
|
||||||
assert(client3_data.closed == 0);
|
assert(client3_data.closed == 0);
|
||||||
assert(client1_data.data == NULL);
|
assert(client1_data.data == NULL);
|
||||||
assert(client1_data.len == 0);
|
assert(client1_data.len == 0);
|
||||||
assert(client2_data.data == NULL);
|
assert(client2_data.data == NULL);
|
||||||
assert(client2_data.len == 0);
|
assert(client2_data.len == 0);
|
||||||
assert(client3_data.data != NULL);
|
assert(client3_data.data != NULL);
|
||||||
assert(client3_data.len == websocket_welcome_msg_len);
|
assert(client3_data.len == websocket_welcome_msg_len);
|
||||||
assert(!memcmp(client3_data.data, websocket_welcome_msg, websocket_welcome_msg_len));
|
assert(!memcmp(client3_data.data,
|
||||||
free(client3_data.data);
|
websocket_welcome_msg,
|
||||||
client3_data.data = NULL;
|
websocket_welcome_msg_len));
|
||||||
client3_data.len = 0;
|
free(client3_data.data);
|
||||||
|
client3_data.data = NULL;
|
||||||
|
client3_data.len = 0;
|
||||||
|
|
||||||
mg_stop(ctx);
|
mg_stop(ctx);
|
||||||
printf("Server shutdown\n");
|
printf("Server shutdown\n");
|
||||||
|
|
||||||
sleep(10);
|
sleep(10);
|
||||||
|
|
||||||
assert(client3_data.closed == 1);
|
assert(client3_data.closed == 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ class CivetServer;
|
|||||||
*/
|
*/
|
||||||
class CIVETWEB_API CivetException : public std::runtime_error
|
class CIVETWEB_API CivetException : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CivetException(const std::string &msg) : std::runtime_error(msg)
|
CivetException(const std::string &msg) : std::runtime_error(msg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ class CIVETWEB_API CivetException : public std::runtime_error
|
|||||||
*/
|
*/
|
||||||
class CIVETWEB_API CivetHandler
|
class CIVETWEB_API CivetHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* Destructor
|
||||||
*/
|
*/
|
||||||
@ -95,7 +95,7 @@ class CIVETWEB_API CivetHandler
|
|||||||
*/
|
*/
|
||||||
class CIVETWEB_API CivetServer
|
class CIVETWEB_API CivetServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -127,7 +127,8 @@ class CIVETWEB_API CivetServer
|
|||||||
*
|
*
|
||||||
* @return the context or 0 if not running.
|
* @return the context or 0 if not running.
|
||||||
*/
|
*/
|
||||||
const struct mg_context *getContext() const
|
const struct mg_context *
|
||||||
|
getContext() const
|
||||||
{
|
{
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
@ -145,7 +146,8 @@ class CIVETWEB_API CivetServer
|
|||||||
*/
|
*/
|
||||||
void addHandler(const std::string &uri, CivetHandler *handler);
|
void addHandler(const std::string &uri, CivetHandler *handler);
|
||||||
|
|
||||||
void addHandler(const std::string &uri, CivetHandler &handler)
|
void
|
||||||
|
addHandler(const std::string &uri, CivetHandler &handler)
|
||||||
{
|
{
|
||||||
addHandler(uri, &handler);
|
addHandler(uri, &handler);
|
||||||
}
|
}
|
||||||
@ -236,10 +238,11 @@ class CIVETWEB_API CivetServer
|
|||||||
*based).
|
*based).
|
||||||
* @return true if key was found
|
* @return true if key was found
|
||||||
*/
|
*/
|
||||||
static bool getParam(const std::string &data,
|
static bool
|
||||||
const char *name,
|
getParam(const std::string &data,
|
||||||
std::string &dst,
|
const char *name,
|
||||||
size_t occurrence = 0)
|
std::string &dst,
|
||||||
|
size_t occurrence = 0)
|
||||||
{
|
{
|
||||||
return getParam(data.c_str(), data.length(), name, dst, occurrence);
|
return getParam(data.c_str(), data.length(), name, dst, occurrence);
|
||||||
}
|
}
|
||||||
@ -275,9 +278,10 @@ class CIVETWEB_API CivetServer
|
|||||||
* uses '+' as character for space, see RFC 1866 section 8.2.1
|
* uses '+' as character for space, see RFC 1866 section 8.2.1
|
||||||
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
|
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
|
||||||
*/
|
*/
|
||||||
static void urlDecode(const std::string &src,
|
static void
|
||||||
std::string &dst,
|
urlDecode(const std::string &src,
|
||||||
bool is_form_url_encoded = true)
|
std::string &dst,
|
||||||
|
bool is_form_url_encoded = true)
|
||||||
{
|
{
|
||||||
urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
|
urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
|
||||||
}
|
}
|
||||||
@ -348,10 +352,10 @@ class CIVETWEB_API CivetServer
|
|||||||
std::string &dst,
|
std::string &dst,
|
||||||
bool append = false);
|
bool append = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class CivetConnection
|
class CivetConnection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
char *postData;
|
char *postData;
|
||||||
unsigned long postDataLen;
|
unsigned long postDataLen;
|
||||||
|
|
||||||
@ -362,7 +366,7 @@ class CIVETWEB_API CivetServer
|
|||||||
struct mg_context *context;
|
struct mg_context *context;
|
||||||
std::map<struct mg_connection *, class CivetConnection> connections;
|
std::map<struct mg_connection *, class CivetConnection> connections;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* requestHandler(struct mg_connection *, void *cbdata)
|
* requestHandler(struct mg_connection *, void *cbdata)
|
||||||
*
|
*
|
||||||
|
@ -388,7 +388,6 @@ enum {
|
|||||||
The array is terminated by a NULL name option. */
|
The array is terminated by a NULL name option. */
|
||||||
CIVETWEB_API const struct mg_option *mg_get_valid_options(void);
|
CIVETWEB_API const struct mg_option *mg_get_valid_options(void);
|
||||||
|
|
||||||
|
|
||||||
struct mg_server_ports {
|
struct mg_server_ports {
|
||||||
int protocol; /* 1 = IPv4, 2 = IPv6, 3 = both */
|
int protocol; /* 1 = IPv4, 2 = IPv6, 3 = both */
|
||||||
int port; /* port number */
|
int port; /* port number */
|
||||||
@ -409,12 +408,10 @@ CIVETWEB_API int mg_get_server_ports(const struct mg_context *ctx,
|
|||||||
int size,
|
int size,
|
||||||
struct mg_server_ports *ports);
|
struct mg_server_ports *ports);
|
||||||
|
|
||||||
|
|
||||||
/* Deprecated. Use mg_get_server_ports instead. */
|
/* Deprecated. Use mg_get_server_ports instead. */
|
||||||
CIVETWEB_API size_t
|
CIVETWEB_API size_t
|
||||||
mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl);
|
mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl);
|
||||||
|
|
||||||
|
|
||||||
/* Add, edit or delete the entry in the passwords file.
|
/* Add, edit or delete the entry in the passwords file.
|
||||||
|
|
||||||
This function allows an application to manipulate .htpasswd files on the
|
This function allows an application to manipulate .htpasswd files on the
|
||||||
@ -755,7 +752,6 @@ CIVETWEB_API int mg_get_response(struct mg_connection *conn,
|
|||||||
size_t ebuf_len,
|
size_t ebuf_len,
|
||||||
int timeout);
|
int timeout);
|
||||||
|
|
||||||
|
|
||||||
/* Check which features where set when civetweb has been compiled.
|
/* Check which features where set when civetweb has been compiled.
|
||||||
Parameters:
|
Parameters:
|
||||||
feature: specifies which feature should be checked
|
feature: specifies which feature should be checked
|
||||||
@ -774,7 +770,6 @@ CIVETWEB_API int mg_get_response(struct mg_connection *conn,
|
|||||||
*/
|
*/
|
||||||
CIVETWEB_API unsigned mg_check_feature(unsigned feature);
|
CIVETWEB_API unsigned mg_check_feature(unsigned feature);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
@ -15,43 +15,48 @@
|
|||||||
#define UNUSED_PARAMETER(x) (void)(x)
|
#define UNUSED_PARAMETER(x) (void)(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool CivetHandler::handleGet(CivetServer *server, struct mg_connection *conn)
|
bool
|
||||||
|
CivetHandler::handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
{
|
{
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn)
|
bool
|
||||||
|
CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn)
|
||||||
{
|
{
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn)
|
bool
|
||||||
|
CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn)
|
||||||
{
|
{
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetHandler::handleDelete(CivetServer *server, struct mg_connection *conn)
|
bool
|
||||||
|
CivetHandler::handleDelete(CivetServer *server, struct mg_connection *conn)
|
||||||
{
|
{
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetHandler::handleOptions(CivetServer *server,
|
bool
|
||||||
struct mg_connection *conn)
|
CivetHandler::handleOptions(CivetServer *server, struct mg_connection *conn)
|
||||||
{
|
{
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CivetServer::requestHandler(struct mg_connection *conn, void *cbdata)
|
int
|
||||||
|
CivetServer::requestHandler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
assert(request_info != NULL);
|
assert(request_info != NULL);
|
||||||
@ -110,7 +115,8 @@ CivetServer::~CivetServer()
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::closeHandler(const struct mg_connection *conn)
|
void
|
||||||
|
CivetServer::closeHandler(const struct mg_connection *conn)
|
||||||
{
|
{
|
||||||
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
assert(request_info != NULL);
|
assert(request_info != NULL);
|
||||||
@ -128,17 +134,20 @@ void CivetServer::closeHandler(const struct mg_connection *conn)
|
|||||||
mg_unlock_context(me->context);
|
mg_unlock_context(me->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::addHandler(const std::string &uri, CivetHandler *handler)
|
void
|
||||||
|
CivetServer::addHandler(const std::string &uri, CivetHandler *handler)
|
||||||
{
|
{
|
||||||
mg_set_request_handler(context, uri.c_str(), requestHandler, handler);
|
mg_set_request_handler(context, uri.c_str(), requestHandler, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::removeHandler(const std::string &uri)
|
void
|
||||||
|
CivetServer::removeHandler(const std::string &uri)
|
||||||
{
|
{
|
||||||
mg_set_request_handler(context, uri.c_str(), NULL, NULL);
|
mg_set_request_handler(context, uri.c_str(), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::close()
|
void
|
||||||
|
CivetServer::close()
|
||||||
{
|
{
|
||||||
if (context) {
|
if (context) {
|
||||||
mg_stop(context);
|
mg_stop(context);
|
||||||
@ -146,47 +155,53 @@ void CivetServer::close()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CivetServer::getCookie(struct mg_connection *conn,
|
int
|
||||||
const std::string &cookieName,
|
CivetServer::getCookie(struct mg_connection *conn,
|
||||||
std::string &cookieValue)
|
const std::string &cookieName,
|
||||||
|
std::string &cookieValue)
|
||||||
{
|
{
|
||||||
// Maximum cookie length as per microsoft is 4096.
|
// Maximum cookie length as per microsoft is 4096.
|
||||||
// http://msdn.microsoft.com/en-us/library/ms178194.aspx
|
// http://msdn.microsoft.com/en-us/library/ms178194.aspx
|
||||||
char _cookieValue[4096];
|
char _cookieValue[4096];
|
||||||
const char *cookie = mg_get_header(conn, "Cookie");
|
const char *cookie = mg_get_header(conn, "Cookie");
|
||||||
int lRead = mg_get_cookie(
|
int lRead = mg_get_cookie(cookie,
|
||||||
cookie, cookieName.c_str(), _cookieValue, sizeof(_cookieValue));
|
cookieName.c_str(),
|
||||||
|
_cookieValue,
|
||||||
|
sizeof(_cookieValue));
|
||||||
cookieValue.clear();
|
cookieValue.clear();
|
||||||
cookieValue.append(_cookieValue);
|
cookieValue.append(_cookieValue);
|
||||||
return lRead;
|
return lRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CivetServer::getHeader(struct mg_connection *conn,
|
const char *
|
||||||
const std::string &headerName)
|
CivetServer::getHeader(struct mg_connection *conn,
|
||||||
|
const std::string &headerName)
|
||||||
{
|
{
|
||||||
return mg_get_header(conn, headerName.c_str());
|
return mg_get_header(conn, headerName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::urlDecode(const char *src,
|
void
|
||||||
std::string &dst,
|
CivetServer::urlDecode(const char *src,
|
||||||
bool is_form_url_encoded)
|
std::string &dst,
|
||||||
|
bool is_form_url_encoded)
|
||||||
{
|
{
|
||||||
urlDecode(src, strlen(src), dst, is_form_url_encoded);
|
urlDecode(src, strlen(src), dst, is_form_url_encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::urlDecode(const char *src,
|
void
|
||||||
size_t src_len,
|
CivetServer::urlDecode(const char *src,
|
||||||
std::string &dst,
|
size_t src_len,
|
||||||
bool is_form_url_encoded)
|
std::string &dst,
|
||||||
|
bool is_form_url_encoded)
|
||||||
{
|
{
|
||||||
int i, j, a, b;
|
int i, j, a, b;
|
||||||
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
|
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
|
||||||
|
|
||||||
dst.clear();
|
dst.clear();
|
||||||
for (i = j = 0; i < (int)src_len; i++, j++) {
|
for (i = j = 0; i < (int)src_len; i++, j++) {
|
||||||
if (i < (int)src_len - 2 && src[i] == '%' &&
|
if (i < (int)src_len - 2 && src[i] == '%'
|
||||||
isxdigit(*(const unsigned char *)(src + i + 1)) &&
|
&& isxdigit(*(const unsigned char *)(src + i + 1))
|
||||||
isxdigit(*(const unsigned char *)(src + i + 2))) {
|
&& isxdigit(*(const unsigned char *)(src + i + 2))) {
|
||||||
a = tolower(*(const unsigned char *)(src + i + 1));
|
a = tolower(*(const unsigned char *)(src + i + 1));
|
||||||
b = tolower(*(const unsigned char *)(src + i + 2));
|
b = tolower(*(const unsigned char *)(src + i + 2));
|
||||||
dst.push_back((char)((HEXTOI(a) << 4) | HEXTOI(b)));
|
dst.push_back((char)((HEXTOI(a) << 4) | HEXTOI(b)));
|
||||||
@ -199,10 +214,11 @@ void CivetServer::urlDecode(const char *src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetServer::getParam(struct mg_connection *conn,
|
bool
|
||||||
const char *name,
|
CivetServer::getParam(struct mg_connection *conn,
|
||||||
std::string &dst,
|
const char *name,
|
||||||
size_t occurrence)
|
std::string &dst,
|
||||||
|
size_t occurrence)
|
||||||
{
|
{
|
||||||
const char *formParams = NULL;
|
const char *formParams = NULL;
|
||||||
const struct mg_request_info *ri = mg_get_request_info(conn);
|
const struct mg_request_info *ri = mg_get_request_info(conn);
|
||||||
@ -250,11 +266,12 @@ bool CivetServer::getParam(struct mg_connection *conn,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetServer::getParam(const char *data,
|
bool
|
||||||
size_t data_len,
|
CivetServer::getParam(const char *data,
|
||||||
const char *name,
|
size_t data_len,
|
||||||
std::string &dst,
|
const char *name,
|
||||||
size_t occurrence)
|
std::string &dst,
|
||||||
|
size_t occurrence)
|
||||||
{
|
{
|
||||||
const char *p, *e, *s;
|
const char *p, *e, *s;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
@ -268,8 +285,8 @@ bool CivetServer::getParam(const char *data,
|
|||||||
|
|
||||||
// data is "var1=val1&var2=val2...". Find variable first
|
// data is "var1=val1&var2=val2...". Find variable first
|
||||||
for (p = data; p + name_len < e; p++) {
|
for (p = data; p + name_len < e; p++) {
|
||||||
if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
|
if ((p == data || p[-1] == '&') && p[name_len] == '='
|
||||||
!mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
|
&& !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
|
||||||
|
|
||||||
// Point p to variable value
|
// Point p to variable value
|
||||||
p += name_len + 1;
|
p += name_len + 1;
|
||||||
@ -289,15 +306,17 @@ bool CivetServer::getParam(const char *data,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::urlEncode(const char *src, std::string &dst, bool append)
|
void
|
||||||
|
CivetServer::urlEncode(const char *src, std::string &dst, bool append)
|
||||||
{
|
{
|
||||||
urlEncode(src, strlen(src), dst, append);
|
urlEncode(src, strlen(src), dst, append);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::urlEncode(const char *src,
|
void
|
||||||
size_t src_len,
|
CivetServer::urlEncode(const char *src,
|
||||||
std::string &dst,
|
size_t src_len,
|
||||||
bool append)
|
std::string &dst,
|
||||||
|
bool append)
|
||||||
{
|
{
|
||||||
static const char *dont_escape = "._-$,;~()";
|
static const char *dont_escape = "._-$,;~()";
|
||||||
static const char *hex = "0123456789abcdef";
|
static const char *hex = "0123456789abcdef";
|
||||||
@ -306,8 +325,8 @@ void CivetServer::urlEncode(const char *src,
|
|||||||
dst.clear();
|
dst.clear();
|
||||||
|
|
||||||
for (; src_len > 0; src++, src_len--) {
|
for (; src_len > 0; src++, src_len--) {
|
||||||
if (isalnum(*(const unsigned char *)src) ||
|
if (isalnum(*(const unsigned char *)src)
|
||||||
strchr(dont_escape, *(const unsigned char *)src) != NULL) {
|
|| strchr(dont_escape, *(const unsigned char *)src) != NULL) {
|
||||||
dst.push_back(*src);
|
dst.push_back(*src);
|
||||||
} else {
|
} else {
|
||||||
dst.push_back('%');
|
dst.push_back('%');
|
||||||
@ -317,7 +336,8 @@ void CivetServer::urlEncode(const char *src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> CivetServer::getListeningPorts()
|
std::vector<int>
|
||||||
|
CivetServer::getListeningPorts()
|
||||||
{
|
{
|
||||||
std::vector<int> ports(10);
|
std::vector<int> ports(10);
|
||||||
std::vector<int> ssl(10);
|
std::vector<int> ssl(10);
|
||||||
|
1924
src/civetweb.c
1924
src/civetweb.c
File diff suppressed because it is too large
Load Diff
300
src/main.c
300
src/main.c
@ -71,8 +71,8 @@
|
|||||||
#define printf \
|
#define printf \
|
||||||
DO_NOT_USE_THIS_FUNCTION__USE_fprintf /* Required for unit testing */
|
DO_NOT_USE_THIS_FUNCTION__USE_fprintf /* Required for unit testing */
|
||||||
|
|
||||||
#if defined(_WIN32) && \
|
#if defined(_WIN32) \
|
||||||
!defined(__SYMBIAN32__) /* WINDOWS / UNIX include block */
|
&& !defined(__SYMBIAN32__) /* WINDOWS / UNIX include block */
|
||||||
#ifndef _WIN32_WINNT
|
#ifndef _WIN32_WINNT
|
||||||
#define _WIN32_WINNT 0x0501 /* for tdm-gcc so we can use getconsolewindow */
|
#define _WIN32_WINNT 0x0501 /* for tdm-gcc so we can use getconsolewindow */
|
||||||
#endif
|
#endif
|
||||||
@ -157,12 +157,14 @@ static struct mg_option main_config_options[] = {
|
|||||||
{"icon", CONFIG_TYPE_STRING, NULL},
|
{"icon", CONFIG_TYPE_STRING, NULL},
|
||||||
{NULL, CONFIG_TYPE_UNKNOWN, NULL}};
|
{NULL, CONFIG_TYPE_UNKNOWN, NULL}};
|
||||||
|
|
||||||
static void WINCDECL signal_handler(int sig_num)
|
static void WINCDECL
|
||||||
|
signal_handler(int sig_num)
|
||||||
{
|
{
|
||||||
g_exit_flag = sig_num;
|
g_exit_flag = sig_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NO_RETURN void die(const char *fmt, ...)
|
static NO_RETURN void
|
||||||
|
die(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char msg[200] = "";
|
char msg[200] = "";
|
||||||
@ -185,7 +187,8 @@ static NO_RETURN void die(const char *fmt, ...)
|
|||||||
static int MakeConsole(void);
|
static int MakeConsole(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void show_server_name(void)
|
static void
|
||||||
|
show_server_name(void)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
(void)MakeConsole();
|
(void)MakeConsole();
|
||||||
@ -194,7 +197,8 @@ static void show_server_name(void)
|
|||||||
fprintf(stderr, "CivetWeb v%s, built on %s\n", mg_version(), __DATE__);
|
fprintf(stderr, "CivetWeb v%s, built on %s\n", mg_version(), __DATE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NO_RETURN void show_usage_and_exit(const char *exeName)
|
static NO_RETURN void
|
||||||
|
show_usage_and_exit(const char *exeName)
|
||||||
{
|
{
|
||||||
const struct mg_option *options;
|
const struct mg_option *options;
|
||||||
int i;
|
int i;
|
||||||
@ -212,8 +216,9 @@ static NO_RETURN void show_usage_and_exit(const char *exeName)
|
|||||||
fprintf(stderr, " Show system information:\n");
|
fprintf(stderr, " Show system information:\n");
|
||||||
fprintf(stderr, " %s -I\n", exeName);
|
fprintf(stderr, " %s -I\n", exeName);
|
||||||
fprintf(stderr, " Add user/change password:\n");
|
fprintf(stderr, " Add user/change password:\n");
|
||||||
fprintf(
|
fprintf(stderr,
|
||||||
stderr, " %s -A <htpasswd_file> <realm> <user> <passwd>\n", exeName);
|
" %s -A <htpasswd_file> <realm> <user> <passwd>\n",
|
||||||
|
exeName);
|
||||||
fprintf(stderr, " Remove user:\n");
|
fprintf(stderr, " Remove user:\n");
|
||||||
fprintf(stderr, " %s -R <htpasswd_file> <realm> <user>\n", exeName);
|
fprintf(stderr, " %s -R <htpasswd_file> <realm> <user>\n", exeName);
|
||||||
fprintf(stderr, "\nOPTIONS:\n");
|
fprintf(stderr, "\nOPTIONS:\n");
|
||||||
@ -250,14 +255,15 @@ static const char *config_file_top_comment =
|
|||||||
"# To make a change, remove leading '#', modify option's value,\n"
|
"# To make a change, remove leading '#', modify option's value,\n"
|
||||||
"# save this file and then restart Civetweb.\n\n";
|
"# save this file and then restart Civetweb.\n\n";
|
||||||
|
|
||||||
static const char *get_url_to_first_open_port(const struct mg_context *ctx)
|
static const char *
|
||||||
|
get_url_to_first_open_port(const struct mg_context *ctx)
|
||||||
{
|
{
|
||||||
static char url[100];
|
static char url[100];
|
||||||
const char *open_ports = mg_get_option(ctx, "listening_ports");
|
const char *open_ports = mg_get_option(ctx, "listening_ports");
|
||||||
int a, b, c, d, port, n;
|
int a, b, c, d, port, n;
|
||||||
|
|
||||||
if (sscanf(open_ports, "%d.%d.%d.%d:%d%n", &a, &b, &c, &d, &port, &n) ==
|
if (sscanf(open_ports, "%d.%d.%d.%d:%d%n", &a, &b, &c, &d, &port, &n)
|
||||||
5) {
|
== 5) {
|
||||||
snprintf(url,
|
snprintf(url,
|
||||||
sizeof(url),
|
sizeof(url),
|
||||||
"%s://%d.%d.%d.%d:%d",
|
"%s://%d.%d.%d.%d:%d",
|
||||||
@ -281,7 +287,8 @@ static const char *get_url_to_first_open_port(const struct mg_context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_CREATE_CONFIG_FILE
|
#ifdef ENABLE_CREATE_CONFIG_FILE
|
||||||
static void create_config_file(const struct mg_context *ctx, const char *path)
|
static void
|
||||||
|
create_config_file(const struct mg_context *ctx, const char *path)
|
||||||
{
|
{
|
||||||
const struct mg_option *options;
|
const struct mg_option *options;
|
||||||
const char *value;
|
const char *value;
|
||||||
@ -296,8 +303,10 @@ static void create_config_file(const struct mg_context *ctx, const char *path)
|
|||||||
options = mg_get_valid_options();
|
options = mg_get_valid_options();
|
||||||
for (i = 0; options[i].name != NULL; i++) {
|
for (i = 0; options[i].name != NULL; i++) {
|
||||||
value = mg_get_option(ctx, options[i].name);
|
value = mg_get_option(ctx, options[i].name);
|
||||||
fprintf(
|
fprintf(fp,
|
||||||
fp, "# %s %s\n", options[i].name, value ? value : "<value>");
|
"# %s %s\n",
|
||||||
|
options[i].name,
|
||||||
|
value ? value : "<value>");
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
@ -305,7 +314,8 @@ static void create_config_file(const struct mg_context *ctx, const char *path)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *sdup(const char *str)
|
static char *
|
||||||
|
sdup(const char *str)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char *p;
|
char *p;
|
||||||
@ -317,7 +327,8 @@ static char *sdup(const char *str)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *get_option(char **options, const char *option_name)
|
static const char *
|
||||||
|
get_option(char **options, const char *option_name)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
const char *opt_value = NULL;
|
const char *opt_value = NULL;
|
||||||
@ -339,7 +350,8 @@ static const char *get_option(char **options, const char *option_name)
|
|||||||
return opt_value;
|
return opt_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_option(char **options, const char *name, const char *value)
|
static int
|
||||||
|
set_option(char **options, const char *name, const char *value)
|
||||||
{
|
{
|
||||||
int i, type;
|
int i, type;
|
||||||
const struct mg_option *default_options = mg_get_valid_options();
|
const struct mg_option *default_options = mg_get_valid_options();
|
||||||
@ -416,7 +428,8 @@ static int set_option(char **options, const char *name, const char *value)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_config_file(const char *config_file, char **options)
|
static void
|
||||||
|
read_config_file(const char *config_file, char **options)
|
||||||
{
|
{
|
||||||
char line[MAX_CONF_FILE_LINE_SIZE], *p;
|
char line[MAX_CONF_FILE_LINE_SIZE], *p;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
@ -452,8 +465,9 @@ static void read_config_file(const char *config_file, char **options)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Skip spaces, \r and \n at the end of the line */
|
/* Skip spaces, \r and \n at the end of the line */
|
||||||
for (j = strlen(line) - 1; isspace(*(unsigned char *)&line[j]) ||
|
for (j = strlen(line) - 1;
|
||||||
iscntrl(*(unsigned char *)&line[j]);)
|
isspace(*(unsigned char *)&line[j])
|
||||||
|
|| iscntrl(*(unsigned char *)&line[j]);)
|
||||||
line[j--] = 0;
|
line[j--] = 0;
|
||||||
|
|
||||||
/* Find the space character between option name and value */
|
/* Find the space character between option name and value */
|
||||||
@ -484,7 +498,8 @@ static void read_config_file(const char *config_file, char **options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_command_line_arguments(char *argv[], char **options)
|
static void
|
||||||
|
process_command_line_arguments(char *argv[], char **options)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
size_t i, cmd_line_opts_start = 1;
|
size_t i, cmd_line_opts_start = 1;
|
||||||
@ -549,11 +564,12 @@ static void process_command_line_arguments(char *argv[], char **options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_server_name(int argc, const char *argv[])
|
static void
|
||||||
|
init_server_name(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
assert(sizeof(main_config_options) / sizeof(main_config_options[0]) ==
|
assert(sizeof(main_config_options) / sizeof(main_config_options[0])
|
||||||
NUM_MAIN_OPTIONS + 1);
|
== NUM_MAIN_OPTIONS + 1);
|
||||||
assert((strlen(mg_version()) + 12) < sizeof(g_server_base_name));
|
assert((strlen(mg_version()) + 12) < sizeof(g_server_base_name));
|
||||||
snprintf(g_server_base_name,
|
snprintf(g_server_base_name,
|
||||||
sizeof(g_server_base_name),
|
sizeof(g_server_base_name),
|
||||||
@ -562,22 +578,24 @@ static void init_server_name(int argc, const char *argv[])
|
|||||||
|
|
||||||
g_server_name = g_server_base_name;
|
g_server_name = g_server_base_name;
|
||||||
for (i = 0; i < argc - 1; i++) {
|
for (i = 0; i < argc - 1; i++) {
|
||||||
if ((argv[i][0] == '-') &&
|
if ((argv[i][0] == '-')
|
||||||
(0 ==
|
&& (0 == strcmp(argv[i] + 1,
|
||||||
strcmp(argv[i] + 1, main_config_options[OPTION_TITLE].name))) {
|
main_config_options[OPTION_TITLE].name))) {
|
||||||
g_server_name = (char *)(argv[i + 1]);
|
g_server_name = (char *)(argv[i + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_icon_name = NULL;
|
g_icon_name = NULL;
|
||||||
for (i = 0; i < argc - 1; i++) {
|
for (i = 0; i < argc - 1; i++) {
|
||||||
if ((argv[i][0] == '-') &&
|
if ((argv[i][0] == '-')
|
||||||
(0 == strcmp(argv[i] + 1, main_config_options[OPTION_ICON].name))) {
|
&& (0 == strcmp(argv[i] + 1,
|
||||||
|
main_config_options[OPTION_ICON].name))) {
|
||||||
g_icon_name = (char *)(argv[i + 1]);
|
g_icon_name = (char *)(argv[i + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int log_message(const struct mg_connection *conn, const char *message)
|
static int
|
||||||
|
log_message(const struct mg_connection *conn, const char *message)
|
||||||
{
|
{
|
||||||
const struct mg_context *ctx = mg_get_context(conn);
|
const struct mg_context *ctx = mg_get_context(conn);
|
||||||
struct tuser_data *ud = (struct tuser_data *)mg_get_user_data(ctx);
|
struct tuser_data *ud = (struct tuser_data *)mg_get_user_data(ctx);
|
||||||
@ -591,14 +609,15 @@ static int log_message(const struct mg_connection *conn, const char *message)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_path_absolute(const char *path)
|
static int
|
||||||
|
is_path_absolute(const char *path)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return path != NULL &&
|
return path != NULL
|
||||||
((path[0] == '\\' && path[1] == '\\') || /* UNC path, e.g.
|
&& ((path[0] == '\\' && path[1] == '\\') || /* UNC path, e.g.
|
||||||
\\server\dir */
|
\\server\dir */
|
||||||
(isalpha(path[0]) && path[1] == ':' &&
|
(isalpha(path[0]) && path[1] == ':'
|
||||||
path[2] == '\\')); /* E.g. X:\dir */
|
&& path[2] == '\\')); /* E.g. X:\dir */
|
||||||
#else
|
#else
|
||||||
return path != NULL && path[0] == '/';
|
return path != NULL && path[0] == '/';
|
||||||
#endif
|
#endif
|
||||||
@ -630,8 +649,8 @@ verify_existence(char **options, const char *option_name, int must_be_dir)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (path != NULL && (stat(path, &st) != 0 ||
|
if (path != NULL && (stat(path, &st) != 0
|
||||||
((S_ISDIR(st.st_mode) ? 1 : 0) != must_be_dir))) {
|
|| ((S_ISDIR(st.st_mode) ? 1 : 0) != must_be_dir))) {
|
||||||
die("Invalid path for %s: [%s]: (%s). Make sure that path is either "
|
die("Invalid path for %s: [%s]: (%s). Make sure that path is either "
|
||||||
"absolute, or it is relative to civetweb executable.",
|
"absolute, or it is relative to civetweb executable.",
|
||||||
option_name,
|
option_name,
|
||||||
@ -640,9 +659,10 @@ verify_existence(char **options, const char *option_name, int must_be_dir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_absolute_path(char *options[],
|
static void
|
||||||
const char *option_name,
|
set_absolute_path(char *options[],
|
||||||
const char *path_to_civetweb_exe)
|
const char *option_name,
|
||||||
|
const char *path_to_civetweb_exe)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX] = "", absolute[PATH_MAX] = "";
|
char path[PATH_MAX] = "", absolute[PATH_MAX] = "";
|
||||||
const char *option_value;
|
const char *option_value;
|
||||||
@ -682,7 +702,8 @@ static void set_absolute_path(char *options[],
|
|||||||
#include "civetweb_lua.h"
|
#include "civetweb_lua.h"
|
||||||
#include "civetweb_private_lua.h"
|
#include "civetweb_private_lua.h"
|
||||||
|
|
||||||
static int run_lua(const char *file_name)
|
static int
|
||||||
|
run_lua(const char *file_name)
|
||||||
{
|
{
|
||||||
struct lua_State *L;
|
struct lua_State *L;
|
||||||
int lua_ret;
|
int lua_ret;
|
||||||
@ -715,8 +736,10 @@ static int run_lua(const char *file_name)
|
|||||||
if (lua_ret != LUA_OK) {
|
if (lua_ret != LUA_OK) {
|
||||||
/* Error when executing the script */
|
/* Error when executing the script */
|
||||||
lua_err_txt = lua_tostring(L, -1);
|
lua_err_txt = lua_tostring(L, -1);
|
||||||
fprintf(
|
fprintf(stderr,
|
||||||
stderr, "Error running file %s: %s\n", file_name, lua_err_txt);
|
"Error running file %s: %s\n",
|
||||||
|
file_name,
|
||||||
|
lua_err_txt);
|
||||||
} else {
|
} else {
|
||||||
/* Script executed */
|
/* Script executed */
|
||||||
if (lua_type(L, -1) == LUA_TNUMBER) {
|
if (lua_type(L, -1) == LUA_TNUMBER) {
|
||||||
@ -732,12 +755,12 @@ static int run_lua(const char *file_name)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_DUKTAPE
|
#ifdef USE_DUKTAPE
|
||||||
|
|
||||||
#include "duktape.h"
|
#include "duktape.h"
|
||||||
|
|
||||||
static int run_duktape(const char *file_name)
|
static int
|
||||||
|
run_duktape(const char *file_name)
|
||||||
{
|
{
|
||||||
duk_context *ctx = NULL;
|
duk_context *ctx = NULL;
|
||||||
|
|
||||||
@ -764,14 +787,13 @@ finished:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
/* For __MINGW32/64_MAJOR/MINOR_VERSION define */
|
/* For __MINGW32/64_MAJOR/MINOR_VERSION define */
|
||||||
#include <_mingw.h>
|
#include <_mingw.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
static void start_civetweb(int argc, char *argv[])
|
start_civetweb(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct mg_callbacks callbacks;
|
struct mg_callbacks callbacks;
|
||||||
char *options[2 * MAX_OPTIONS + 1];
|
char *options[2 * MAX_OPTIONS + 1];
|
||||||
@ -966,8 +988,8 @@ static void start_civetweb(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Show usage if -h or --help options are specified */
|
/* Show usage if -h or --help options are specified */
|
||||||
if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-H") ||
|
if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-H")
|
||||||
!strcmp(argv[1], "--help"))) {
|
|| !strcmp(argv[1], "--help"))) {
|
||||||
show_usage_and_exit(argv[0]);
|
show_usage_and_exit(argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,7 +1041,8 @@ static void start_civetweb(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stop_civetweb(void)
|
static void
|
||||||
|
stop_civetweb(void)
|
||||||
{
|
{
|
||||||
mg_stop(g_ctx);
|
mg_stop(g_ctx);
|
||||||
free(g_user_data.first_message);
|
free(g_user_data.first_message);
|
||||||
@ -1049,12 +1072,12 @@ enum {
|
|||||||
ID_INPUT_LINE,
|
ID_INPUT_LINE,
|
||||||
|
|
||||||
/* All dynamically created text boxes for options have IDs starting from
|
/* All dynamically created text boxes for options have IDs starting from
|
||||||
ID_CONTROLS, incremented by one. */
|
ID_CONTROLS, incremented by one. */
|
||||||
ID_CONTROLS = 200,
|
ID_CONTROLS = 200,
|
||||||
|
|
||||||
/* Text boxes for files have "..." buttons to open file browser. These
|
/* Text boxes for files have "..." buttons to open file browser. These
|
||||||
buttons have IDs that are ID_FILE_BUTTONS_DELTA higher than associated
|
buttons have IDs that are ID_FILE_BUTTONS_DELTA higher than associated
|
||||||
text box ID. */
|
text box ID. */
|
||||||
ID_FILE_BUTTONS_DELTA = 1000
|
ID_FILE_BUTTONS_DELTA = 1000
|
||||||
};
|
};
|
||||||
static HICON hIcon;
|
static HICON hIcon;
|
||||||
@ -1063,7 +1086,8 @@ static SERVICE_STATUS_HANDLE hStatus;
|
|||||||
static const char *service_magic_argument = "--";
|
static const char *service_magic_argument = "--";
|
||||||
static NOTIFYICONDATA TrayIcon;
|
static NOTIFYICONDATA TrayIcon;
|
||||||
|
|
||||||
static void WINAPI ControlHandler(DWORD code)
|
static void WINAPI
|
||||||
|
ControlHandler(DWORD code)
|
||||||
{
|
{
|
||||||
if (code == SERVICE_CONTROL_STOP || code == SERVICE_CONTROL_SHUTDOWN) {
|
if (code == SERVICE_CONTROL_STOP || code == SERVICE_CONTROL_SHUTDOWN) {
|
||||||
ss.dwWin32ExitCode = 0;
|
ss.dwWin32ExitCode = 0;
|
||||||
@ -1072,7 +1096,8 @@ static void WINAPI ControlHandler(DWORD code)
|
|||||||
SetServiceStatus(hStatus, &ss);
|
SetServiceStatus(hStatus, &ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WINAPI ServiceMain(void)
|
static void WINAPI
|
||||||
|
ServiceMain(void)
|
||||||
{
|
{
|
||||||
ss.dwServiceType = SERVICE_WIN32;
|
ss.dwServiceType = SERVICE_WIN32;
|
||||||
ss.dwCurrentState = SERVICE_RUNNING;
|
ss.dwCurrentState = SERVICE_RUNNING;
|
||||||
@ -1091,7 +1116,8 @@ static void WINAPI ServiceMain(void)
|
|||||||
SetServiceStatus(hStatus, &ss);
|
SetServiceStatus(hStatus, &ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_error(void)
|
static void
|
||||||
|
show_error(void)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
@ -1104,7 +1130,8 @@ static void show_error(void)
|
|||||||
MessageBox(NULL, buf, "Error", MB_OK);
|
MessageBox(NULL, buf, "Error", MB_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *align(void *ptr, DWORD alig)
|
static void *
|
||||||
|
align(void *ptr, DWORD alig)
|
||||||
{
|
{
|
||||||
uintptr_t ul = (uintptr_t)ptr;
|
uintptr_t ul = (uintptr_t)ptr;
|
||||||
ul += alig;
|
ul += alig;
|
||||||
@ -1112,7 +1139,8 @@ static void *align(void *ptr, DWORD alig)
|
|||||||
return ((void *)ul);
|
return ((void *)ul);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_config(HWND hDlg, FILE *fp)
|
static void
|
||||||
|
save_config(HWND hDlg, FILE *fp)
|
||||||
{
|
{
|
||||||
char value[2000] = "";
|
char value[2000] = "";
|
||||||
const char *default_value;
|
const char *default_value;
|
||||||
@ -1226,8 +1254,9 @@ SettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
!strcmp(value, "yes") ? BST_CHECKED
|
!strcmp(value, "yes") ? BST_CHECKED
|
||||||
: BST_UNCHECKED);
|
: BST_UNCHECKED);
|
||||||
} else {
|
} else {
|
||||||
SetDlgItemText(
|
SetDlgItemText(hDlg,
|
||||||
hDlg, ID_CONTROLS + i, value == NULL ? "" : value);
|
ID_CONTROLS + i,
|
||||||
|
value == NULL ? "" : value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1235,9 +1264,9 @@ SettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
|
|
||||||
for (i = 0; default_options[i].name != NULL; i++) {
|
for (i = 0; default_options[i].name != NULL; i++) {
|
||||||
name = default_options[i].name;
|
name = default_options[i].name;
|
||||||
if (((default_options[i].type == CONFIG_TYPE_FILE) ||
|
if (((default_options[i].type == CONFIG_TYPE_FILE)
|
||||||
(default_options[i].type == CONFIG_TYPE_DIRECTORY)) &&
|
|| (default_options[i].type == CONFIG_TYPE_DIRECTORY))
|
||||||
LOWORD(wParam) == ID_CONTROLS + i + ID_FILE_BUTTONS_DELTA) {
|
&& LOWORD(wParam) == ID_CONTROLS + i + ID_FILE_BUTTONS_DELTA) {
|
||||||
OPENFILENAME of;
|
OPENFILENAME of;
|
||||||
BROWSEINFO bi;
|
BROWSEINFO bi;
|
||||||
char path[PATH_MAX] = "";
|
char path[PATH_MAX] = "";
|
||||||
@ -1346,7 +1375,8 @@ InputDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void suggest_passwd(char *passwd)
|
static void
|
||||||
|
suggest_passwd(char *passwd)
|
||||||
{
|
{
|
||||||
unsigned u;
|
unsigned u;
|
||||||
char *p;
|
char *p;
|
||||||
@ -1379,10 +1409,11 @@ static void add_control(unsigned char **mem,
|
|||||||
short cy,
|
short cy,
|
||||||
const char *caption);
|
const char *caption);
|
||||||
|
|
||||||
static int get_password(const char *user,
|
static int
|
||||||
const char *realm,
|
get_password(const char *user,
|
||||||
char *passwd,
|
const char *realm,
|
||||||
unsigned passwd_len)
|
char *passwd,
|
||||||
|
unsigned passwd_len)
|
||||||
{
|
{
|
||||||
#define HEIGHT (15)
|
#define HEIGHT (15)
|
||||||
#define WIDTH (280)
|
#define WIDTH (280)
|
||||||
@ -1400,8 +1431,8 @@ static int get_password(const char *user,
|
|||||||
wchar_t caption[1];
|
wchar_t caption[1];
|
||||||
WORD fontsiz;
|
WORD fontsiz;
|
||||||
wchar_t fontface[7];
|
wchar_t fontface[7];
|
||||||
} dialog_header = {{WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE |
|
} dialog_header = {{WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE
|
||||||
DS_SETFONT | WS_DLGFRAME,
|
| DS_SETFONT | WS_DLGFRAME,
|
||||||
WS_EX_TOOLWINDOW,
|
WS_EX_TOOLWINDOW,
|
||||||
0,
|
0,
|
||||||
200,
|
200,
|
||||||
@ -1449,8 +1480,8 @@ static int get_password(const char *user,
|
|||||||
dia,
|
dia,
|
||||||
0x81,
|
0x81,
|
||||||
ID_CONTROLS + 1,
|
ID_CONTROLS + 1,
|
||||||
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL |
|
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
|
||||||
WS_DISABLED,
|
| WS_DISABLED,
|
||||||
15 + LABEL_WIDTH,
|
15 + LABEL_WIDTH,
|
||||||
y,
|
y,
|
||||||
WIDTH - LABEL_WIDTH - 25,
|
WIDTH - LABEL_WIDTH - 25,
|
||||||
@ -1472,8 +1503,8 @@ static int get_password(const char *user,
|
|||||||
dia,
|
dia,
|
||||||
0x81,
|
0x81,
|
||||||
ID_CONTROLS + 2,
|
ID_CONTROLS + 2,
|
||||||
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL |
|
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
|
||||||
WS_DISABLED,
|
| WS_DISABLED,
|
||||||
15 + LABEL_WIDTH,
|
15 + LABEL_WIDTH,
|
||||||
y,
|
y,
|
||||||
WIDTH - LABEL_WIDTH - 25,
|
WIDTH - LABEL_WIDTH - 25,
|
||||||
@ -1557,16 +1588,18 @@ PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|||||||
ctrlId = LOWORD(wParam);
|
ctrlId = LOWORD(wParam);
|
||||||
if (ctrlId == ID_ADD_USER) {
|
if (ctrlId == ID_ADD_USER) {
|
||||||
/* Add user */
|
/* Add user */
|
||||||
GetWindowText(
|
GetWindowText(GetDlgItem(hDlg, ID_ADD_USER_NAME),
|
||||||
GetDlgItem(hDlg, ID_ADD_USER_NAME), user, sizeof(user));
|
user,
|
||||||
GetWindowText(
|
sizeof(user));
|
||||||
GetDlgItem(hDlg, ID_ADD_USER_REALM), domain, sizeof(domain));
|
GetWindowText(GetDlgItem(hDlg, ID_ADD_USER_REALM),
|
||||||
|
domain,
|
||||||
|
sizeof(domain));
|
||||||
if (get_password(user, domain, password, sizeof(password))) {
|
if (get_password(user, domain, password, sizeof(password))) {
|
||||||
mg_modify_passwords_file(passfile, domain, user, password);
|
mg_modify_passwords_file(passfile, domain, user, password);
|
||||||
EndDialog(hDlg, IDOK);
|
EndDialog(hDlg, IDOK);
|
||||||
}
|
}
|
||||||
} else if ((ctrlId >= (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 3)) &&
|
} else if ((ctrlId >= (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 3))
|
||||||
(ctrlId < (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 4))) {
|
&& (ctrlId < (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 4))) {
|
||||||
/* Modify password */
|
/* Modify password */
|
||||||
GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 3),
|
GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 3),
|
||||||
user,
|
user,
|
||||||
@ -1578,8 +1611,8 @@ PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|||||||
mg_modify_passwords_file(passfile, domain, user, password);
|
mg_modify_passwords_file(passfile, domain, user, password);
|
||||||
EndDialog(hDlg, IDOK);
|
EndDialog(hDlg, IDOK);
|
||||||
}
|
}
|
||||||
} else if ((ctrlId >= (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 2)) &&
|
} else if ((ctrlId >= (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 2))
|
||||||
(ctrlId < (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 3))) {
|
&& (ctrlId < (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 3))) {
|
||||||
/* Remove user */
|
/* Remove user */
|
||||||
GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 2),
|
GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 2),
|
||||||
user,
|
user,
|
||||||
@ -1607,16 +1640,17 @@ PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_control(unsigned char **mem,
|
static void
|
||||||
DLGTEMPLATE *dia,
|
add_control(unsigned char **mem,
|
||||||
WORD type,
|
DLGTEMPLATE *dia,
|
||||||
WORD id,
|
WORD type,
|
||||||
DWORD style,
|
WORD id,
|
||||||
short x,
|
DWORD style,
|
||||||
short y,
|
short x,
|
||||||
short cx,
|
short y,
|
||||||
short cy,
|
short cx,
|
||||||
const char *caption)
|
short cy,
|
||||||
|
const char *caption)
|
||||||
{
|
{
|
||||||
DLGITEMTEMPLATE *tp;
|
DLGITEMTEMPLATE *tp;
|
||||||
LPWORD p;
|
LPWORD p;
|
||||||
@ -1648,7 +1682,8 @@ static void add_control(unsigned char **mem,
|
|||||||
*mem = (unsigned char *)p;
|
*mem = (unsigned char *)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_settings_dialog()
|
static void
|
||||||
|
show_settings_dialog()
|
||||||
{
|
{
|
||||||
#define HEIGHT (15)
|
#define HEIGHT (15)
|
||||||
#define WIDTH (460)
|
#define WIDTH (460)
|
||||||
@ -1667,8 +1702,8 @@ static void show_settings_dialog()
|
|||||||
wchar_t caption[1];
|
wchar_t caption[1];
|
||||||
WORD fontsiz;
|
WORD fontsiz;
|
||||||
wchar_t fontface[7];
|
wchar_t fontface[7];
|
||||||
} dialog_header = {{WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE |
|
} dialog_header = {{WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE
|
||||||
DS_SETFONT | WS_DLGFRAME,
|
| DS_SETFONT | WS_DLGFRAME,
|
||||||
WS_EX_TOOLWINDOW,
|
WS_EX_TOOLWINDOW,
|
||||||
0,
|
0,
|
||||||
200,
|
200,
|
||||||
@ -1704,8 +1739,8 @@ static void show_settings_dialog()
|
|||||||
} else if (options[i].type == CONFIG_TYPE_BOOLEAN) {
|
} else if (options[i].type == CONFIG_TYPE_BOOLEAN) {
|
||||||
cl = 0x80;
|
cl = 0x80;
|
||||||
style |= BS_AUTOCHECKBOX;
|
style |= BS_AUTOCHECKBOX;
|
||||||
} else if ((options[i].type == CONFIG_TYPE_FILE) ||
|
} else if ((options[i].type == CONFIG_TYPE_FILE)
|
||||||
(options[i].type == CONFIG_TYPE_DIRECTORY)) {
|
|| (options[i].type == CONFIG_TYPE_DIRECTORY)) {
|
||||||
style |= WS_BORDER | ES_AUTOHSCROLL;
|
style |= WS_BORDER | ES_AUTOHSCROLL;
|
||||||
width -= 20;
|
width -= 20;
|
||||||
cl = 0x81;
|
cl = 0x81;
|
||||||
@ -1822,7 +1857,8 @@ static void show_settings_dialog()
|
|||||||
#undef LABEL_WIDTH
|
#undef LABEL_WIDTH
|
||||||
}
|
}
|
||||||
|
|
||||||
static void change_password_file()
|
static void
|
||||||
|
change_password_file()
|
||||||
{
|
{
|
||||||
#define HEIGHT (15)
|
#define HEIGHT (15)
|
||||||
#define WIDTH (320)
|
#define WIDTH (320)
|
||||||
@ -1844,8 +1880,8 @@ static void change_password_file()
|
|||||||
wchar_t caption[1];
|
wchar_t caption[1];
|
||||||
WORD fontsiz;
|
WORD fontsiz;
|
||||||
wchar_t fontface[7];
|
wchar_t fontface[7];
|
||||||
} dialog_header = {{WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE |
|
} dialog_header = {{WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE
|
||||||
DS_SETFONT | WS_DLGFRAME,
|
| DS_SETFONT | WS_DLGFRAME,
|
||||||
WS_EX_TOOLWINDOW,
|
WS_EX_TOOLWINDOW,
|
||||||
0,
|
0,
|
||||||
200,
|
200,
|
||||||
@ -1930,8 +1966,8 @@ static void change_password_file()
|
|||||||
dia,
|
dia,
|
||||||
0x81,
|
0x81,
|
||||||
ID_CONTROLS + nelems + ID_FILE_BUTTONS_DELTA,
|
ID_CONTROLS + nelems + ID_FILE_BUTTONS_DELTA,
|
||||||
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL |
|
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
|
||||||
WS_DISABLED,
|
| WS_DISABLED,
|
||||||
245,
|
245,
|
||||||
y,
|
y,
|
||||||
60,
|
60,
|
||||||
@ -1941,8 +1977,8 @@ static void change_password_file()
|
|||||||
dia,
|
dia,
|
||||||
0x81,
|
0x81,
|
||||||
ID_CONTROLS + nelems,
|
ID_CONTROLS + nelems,
|
||||||
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL |
|
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
|
||||||
WS_DISABLED,
|
| WS_DISABLED,
|
||||||
140,
|
140,
|
||||||
y,
|
y,
|
||||||
100,
|
100,
|
||||||
@ -1969,8 +2005,8 @@ static void change_password_file()
|
|||||||
dia,
|
dia,
|
||||||
0x81,
|
0x81,
|
||||||
ID_ADD_USER_NAME,
|
ID_ADD_USER_NAME,
|
||||||
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL |
|
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
|
||||||
WS_TABSTOP,
|
| WS_TABSTOP,
|
||||||
140,
|
140,
|
||||||
y,
|
y,
|
||||||
100,
|
100,
|
||||||
@ -1980,8 +2016,8 @@ static void change_password_file()
|
|||||||
dia,
|
dia,
|
||||||
0x81,
|
0x81,
|
||||||
ID_ADD_USER_REALM,
|
ID_ADD_USER_REALM,
|
||||||
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL |
|
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
|
||||||
WS_TABSTOP,
|
| WS_TABSTOP,
|
||||||
245,
|
245,
|
||||||
y,
|
y,
|
||||||
60,
|
60,
|
||||||
@ -2016,8 +2052,8 @@ static void change_password_file()
|
|||||||
|
|
||||||
dia->cy = y + 20;
|
dia->cy = y + 20;
|
||||||
} while ((IDOK == DialogBoxIndirectParam(
|
} while ((IDOK == DialogBoxIndirectParam(
|
||||||
NULL, dia, NULL, PasswordDlgProc, (LPARAM)path)) &&
|
NULL, dia, NULL, PasswordDlgProc, (LPARAM)path))
|
||||||
(!g_exit_flag));
|
&& (!g_exit_flag));
|
||||||
|
|
||||||
guard--;
|
guard--;
|
||||||
|
|
||||||
@ -2026,7 +2062,8 @@ static void change_password_file()
|
|||||||
#undef LABEL_WIDTH
|
#undef LABEL_WIDTH
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manage_service(int action)
|
static int
|
||||||
|
manage_service(int action)
|
||||||
{
|
{
|
||||||
static const char *service_name =
|
static const char *service_name =
|
||||||
"Civetweb"; /* TODO (mid): check using server_name instead of
|
"Civetweb"; /* TODO (mid): check using server_name instead of
|
||||||
@ -2041,8 +2078,8 @@ static int manage_service(int action)
|
|||||||
if ((hSCM = OpenSCManager(NULL,
|
if ((hSCM = OpenSCManager(NULL,
|
||||||
NULL,
|
NULL,
|
||||||
action == ID_INSTALL_SERVICE ? GENERIC_WRITE
|
action == ID_INSTALL_SERVICE ? GENERIC_WRITE
|
||||||
: GENERIC_READ)) ==
|
: GENERIC_READ))
|
||||||
NULL) {
|
== NULL) {
|
||||||
success = 0;
|
success = 0;
|
||||||
show_error();
|
show_error();
|
||||||
} else if (action == ID_INSTALL_SERVICE) {
|
} else if (action == ID_INSTALL_SERVICE) {
|
||||||
@ -2069,12 +2106,13 @@ static int manage_service(int action)
|
|||||||
show_error();
|
show_error();
|
||||||
}
|
}
|
||||||
} else if (action == ID_REMOVE_SERVICE) {
|
} else if (action == ID_REMOVE_SERVICE) {
|
||||||
if ((hService = OpenService(hSCM, service_name, DELETE)) == NULL ||
|
if ((hService = OpenService(hSCM, service_name, DELETE)) == NULL
|
||||||
!DeleteService(hService)) {
|
|| !DeleteService(hService)) {
|
||||||
show_error();
|
show_error();
|
||||||
}
|
}
|
||||||
} else if ((hService = OpenService(
|
} else if ((hService =
|
||||||
hSCM, service_name, SERVICE_QUERY_STATUS)) == NULL) {
|
OpenService(hSCM, service_name, SERVICE_QUERY_STATUS))
|
||||||
|
== NULL) {
|
||||||
success = 0;
|
success = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2149,8 +2187,10 @@ WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
case WM_LBUTTONDBLCLK:
|
case WM_LBUTTONDBLCLK:
|
||||||
hMenu = CreatePopupMenu();
|
hMenu = CreatePopupMenu();
|
||||||
AppendMenu(
|
AppendMenu(hMenu,
|
||||||
hMenu, MF_STRING | MF_GRAYED, ID_SEPARATOR, g_server_name);
|
MF_STRING | MF_GRAYED,
|
||||||
|
ID_SEPARATOR,
|
||||||
|
g_server_name);
|
||||||
AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
|
AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
|
||||||
service_installed = manage_service(0);
|
service_installed = manage_service(0);
|
||||||
snprintf(buf,
|
snprintf(buf,
|
||||||
@ -2195,7 +2235,8 @@ WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MakeConsole(void)
|
static int
|
||||||
|
MakeConsole(void)
|
||||||
{
|
{
|
||||||
DWORD err;
|
DWORD err;
|
||||||
int ok = (GetConsoleWindow() != NULL);
|
int ok = (GetConsoleWindow() != NULL);
|
||||||
@ -2229,7 +2270,8 @@ static int MakeConsole(void)
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show)
|
int WINAPI
|
||||||
|
WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show)
|
||||||
{
|
{
|
||||||
WNDCLASS cls;
|
WNDCLASS cls;
|
||||||
HWND hWnd;
|
HWND hWnd;
|
||||||
@ -2290,8 +2332,8 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show)
|
|||||||
return (int)msg.wParam;
|
return (int)msg.wParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
int main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
@ -2299,7 +2341,6 @@ int main(int argc, char *argv[])
|
|||||||
return WinMain(0, 0, 0, 0);
|
return WinMain(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#elif defined(USE_COCOA)
|
#elif defined(USE_COCOA)
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
@ -2329,8 +2370,8 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
int
|
||||||
int main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
init_server_name(argc, (const char **)argv);
|
init_server_name(argc, (const char **)argv);
|
||||||
start_civetweb(argc, argv);
|
start_civetweb(argc, argv);
|
||||||
@ -2396,7 +2437,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
init_server_name(argc, (const char **)argv);
|
init_server_name(argc, (const char **)argv);
|
||||||
start_civetweb(argc, argv);
|
start_civetweb(argc, argv);
|
||||||
|
23
src/md5.inl
23
src/md5.inl
@ -207,7 +207,8 @@ MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
|||||||
#define T63 (0x2ad7d2bb)
|
#define T63 (0x2ad7d2bb)
|
||||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||||
|
|
||||||
static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
static void
|
||||||
|
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
||||||
{
|
{
|
||||||
md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2],
|
md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2],
|
||||||
d = pms->abcd[3];
|
d = pms->abcd[3];
|
||||||
@ -270,8 +271,9 @@ static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
|||||||
#define xbuf X /* (static only) */
|
#define xbuf X /* (static only) */
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < 16; ++i, xp += 4)
|
for (i = 0; i < 16; ++i, xp += 4)
|
||||||
xbuf[i] = (md5_word_t)(xp[0]) + (md5_word_t)(xp[1] << 8) +
|
xbuf[i] = (md5_word_t)(xp[0]) + (md5_word_t)(xp[1] << 8)
|
||||||
(md5_word_t)(xp[2] << 16) + (md5_word_t)(xp[3] << 24);
|
+ (md5_word_t)(xp[2] << 16)
|
||||||
|
+ (md5_word_t)(xp[3] << 24);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -395,7 +397,8 @@ static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
|||||||
pms->abcd[3] += d;
|
pms->abcd[3] += d;
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5_STATIC void md5_init(md5_state_t *pms)
|
MD5_STATIC void
|
||||||
|
md5_init(md5_state_t *pms)
|
||||||
{
|
{
|
||||||
pms->count[0] = pms->count[1] = 0;
|
pms->count[0] = pms->count[1] = 0;
|
||||||
pms->abcd[0] = 0x67452301;
|
pms->abcd[0] = 0x67452301;
|
||||||
@ -442,12 +445,14 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes)
|
|||||||
memcpy(pms->buf, p, left);
|
memcpy(pms->buf, p, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16])
|
MD5_STATIC void
|
||||||
|
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
|
||||||
{
|
{
|
||||||
static const md5_byte_t pad[64] = {
|
static const md5_byte_t pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
md5_byte_t data[8];
|
md5_byte_t data[8];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -13,29 +13,27 @@
|
|||||||
|
|
||||||
/* Note: This is only experimental support, so any API may still change. */
|
/* Note: This is only experimental support, so any API may still change. */
|
||||||
|
|
||||||
|
|
||||||
static const char *civetweb_conn_id = "\xFF"
|
static const char *civetweb_conn_id = "\xFF"
|
||||||
"civetweb_conn";
|
"civetweb_conn";
|
||||||
|
|
||||||
|
static void *
|
||||||
static void *mg_duk_mem_alloc(void *udata, duk_size_t size)
|
mg_duk_mem_alloc(void *udata, duk_size_t size)
|
||||||
{
|
{
|
||||||
return mg_malloc(size);
|
return mg_malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
static void *mg_duk_mem_realloc(void *udata, void *ptr, duk_size_t newsize)
|
mg_duk_mem_realloc(void *udata, void *ptr, duk_size_t newsize)
|
||||||
{
|
{
|
||||||
return mg_realloc(ptr, newsize);
|
return mg_realloc(ptr, newsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
static void mg_duk_mem_free(void *udata, void *ptr)
|
mg_duk_mem_free(void *udata, void *ptr)
|
||||||
{
|
{
|
||||||
mg_free(ptr);
|
mg_free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mg_duk_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg)
|
mg_duk_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg)
|
||||||
{
|
{
|
||||||
@ -51,22 +49,22 @@ mg_duk_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg)
|
|||||||
mg_cry(conn, "%s", msg);
|
mg_cry(conn, "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static duk_ret_t
|
||||||
static duk_ret_t duk_itf_write(duk_context *ctx)
|
duk_itf_write(duk_context *ctx)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn;
|
struct mg_connection *conn;
|
||||||
duk_double_t ret;
|
duk_double_t ret;
|
||||||
duk_size_t len = 0;
|
duk_size_t len = 0;
|
||||||
const char *val = duk_require_lstring(ctx, -1, &len);
|
const char *val = duk_require_lstring(ctx, -1, &len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
duk_push_global_stash(ctx);
|
duk_push_global_stash(ctx);
|
||||||
|
duk_get_prop_string(ctx, -1, civetweb_conn_id);
|
||||||
|
conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
|
||||||
|
*/
|
||||||
|
duk_push_current_function(ctx);
|
||||||
duk_get_prop_string(ctx, -1, civetweb_conn_id);
|
duk_get_prop_string(ctx, -1, civetweb_conn_id);
|
||||||
conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
|
conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
|
||||||
*/
|
|
||||||
duk_push_current_function(ctx);
|
|
||||||
duk_get_prop_string(ctx, -1, civetweb_conn_id);
|
|
||||||
conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
|
|
||||||
|
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
duk_error(ctx,
|
duk_error(ctx,
|
||||||
@ -82,8 +80,8 @@ static duk_ret_t duk_itf_write(duk_context *ctx)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static duk_ret_t
|
||||||
static duk_ret_t duk_itf_read(duk_context *ctx)
|
duk_itf_read(duk_context *ctx)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn;
|
struct mg_connection *conn;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@ -107,8 +105,8 @@ static duk_ret_t duk_itf_read(duk_context *ctx)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
static void mg_exec_duktape_script(struct mg_connection *conn, const char *path)
|
mg_exec_duktape_script(struct mg_connection *conn, const char *path)
|
||||||
{
|
{
|
||||||
duk_context *ctx = NULL;
|
duk_context *ctx = NULL;
|
||||||
|
|
||||||
@ -131,12 +129,12 @@ static void mg_exec_duktape_script(struct mg_connection *conn, const char *path)
|
|||||||
|
|
||||||
duk_push_c_function(ctx, duk_itf_write, 1 /* 1 = nargs */);
|
duk_push_c_function(ctx, duk_itf_write, 1 /* 1 = nargs */);
|
||||||
duk_put_prop_string(ctx, -2, "write"); /* add function conn.write */
|
duk_put_prop_string(ctx, -2, "write"); /* add function conn.write */
|
||||||
duk_push_pointer(ctx, (void *)conn);
|
duk_push_pointer(ctx, (void *)conn);
|
||||||
duk_put_prop_string(ctx, -2, civetweb_conn_id);
|
duk_put_prop_string(ctx, -2, civetweb_conn_id);
|
||||||
|
|
||||||
duk_push_c_function(ctx, duk_itf_read, 0 /* 0 = nargs */);
|
duk_push_c_function(ctx, duk_itf_read, 0 /* 0 = nargs */);
|
||||||
duk_put_prop_string(ctx, -2, "read"); /* add function conn.read */
|
duk_put_prop_string(ctx, -2, "read"); /* add function conn.read */
|
||||||
duk_push_pointer(ctx, (void *)conn);
|
duk_push_pointer(ctx, (void *)conn);
|
||||||
duk_put_prop_string(ctx, -2, civetweb_conn_id);
|
duk_put_prop_string(ctx, -2, civetweb_conn_id);
|
||||||
|
|
||||||
duk_put_prop_string(ctx, -2, "conn"); /* call the table "conn" */
|
duk_put_prop_string(ctx, -2, "conn"); /* call the table "conn" */
|
||||||
|
256
src/mod_lua.inl
256
src/mod_lua.inl
@ -25,7 +25,8 @@ mmap(void *addr, int64_t len, int prot, int flags, int fd, int offset)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void munmap(void *addr, int64_t length)
|
static void
|
||||||
|
munmap(void *addr, int64_t length)
|
||||||
{
|
{
|
||||||
/* unused parameters */
|
/* unused parameters */
|
||||||
(void)length;
|
(void)length;
|
||||||
@ -51,7 +52,8 @@ static int handle_lsp_request(struct mg_connection *,
|
|||||||
struct file *,
|
struct file *,
|
||||||
struct lua_State *);
|
struct lua_State *);
|
||||||
|
|
||||||
static void reg_string(struct lua_State *L, const char *name, const char *val)
|
static void
|
||||||
|
reg_string(struct lua_State *L, const char *name, const char *val)
|
||||||
{
|
{
|
||||||
if (name != NULL && val != NULL) {
|
if (name != NULL && val != NULL) {
|
||||||
lua_pushstring(L, name);
|
lua_pushstring(L, name);
|
||||||
@ -60,7 +62,8 @@ static void reg_string(struct lua_State *L, const char *name, const char *val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reg_int(struct lua_State *L, const char *name, int val)
|
static void
|
||||||
|
reg_int(struct lua_State *L, const char *name, int val)
|
||||||
{
|
{
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
lua_pushstring(L, name);
|
lua_pushstring(L, name);
|
||||||
@ -69,7 +72,8 @@ static void reg_int(struct lua_State *L, const char *name, int val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reg_boolean(struct lua_State *L, const char *name, int val)
|
static void
|
||||||
|
reg_boolean(struct lua_State *L, const char *name, int val)
|
||||||
{
|
{
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
lua_pushstring(L, name);
|
lua_pushstring(L, name);
|
||||||
@ -78,10 +82,11 @@ static void reg_boolean(struct lua_State *L, const char *name, int val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reg_conn_function(struct lua_State *L,
|
static void
|
||||||
const char *name,
|
reg_conn_function(struct lua_State *L,
|
||||||
lua_CFunction func,
|
const char *name,
|
||||||
struct mg_connection *conn)
|
lua_CFunction func,
|
||||||
|
struct mg_connection *conn)
|
||||||
{
|
{
|
||||||
if (name != NULL && func != NULL && conn != NULL) {
|
if (name != NULL && func != NULL && conn != NULL) {
|
||||||
lua_pushstring(L, name);
|
lua_pushstring(L, name);
|
||||||
@ -101,11 +106,12 @@ reg_function(struct lua_State *L, const char *name, lua_CFunction func)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lua_cry(struct mg_connection *conn,
|
static void
|
||||||
int err,
|
lua_cry(struct mg_connection *conn,
|
||||||
lua_State *L,
|
int err,
|
||||||
const char *lua_title,
|
lua_State *L,
|
||||||
const char *lua_operation)
|
const char *lua_title,
|
||||||
|
const char *lua_operation)
|
||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case LUA_OK:
|
case LUA_OK:
|
||||||
@ -147,7 +153,8 @@ static void lua_cry(struct mg_connection *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lsp_sock_close(lua_State *L)
|
static int
|
||||||
|
lsp_sock_close(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
if ((num_args == 1) && lua_istable(L, -1)) {
|
if ((num_args == 1) && lua_istable(L, -1)) {
|
||||||
@ -159,7 +166,8 @@ static int lsp_sock_close(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lsp_sock_recv(lua_State *L)
|
static int
|
||||||
|
lsp_sock_recv(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
char buf[2000];
|
char buf[2000];
|
||||||
@ -179,7 +187,8 @@ static int lsp_sock_recv(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lsp_sock_send(lua_State *L)
|
static int
|
||||||
|
lsp_sock_send(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
const char *buf;
|
const char *buf;
|
||||||
@ -208,7 +217,8 @@ static const struct luaL_Reg luasocket_methods[] = {{"close", lsp_sock_close},
|
|||||||
{"recv", lsp_sock_recv},
|
{"recv", lsp_sock_recv},
|
||||||
{NULL, NULL}};
|
{NULL, NULL}};
|
||||||
|
|
||||||
static int lsp_connect(lua_State *L)
|
static int
|
||||||
|
lsp_connect(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
char ebuf[100];
|
char ebuf[100];
|
||||||
@ -216,8 +226,8 @@ static int lsp_connect(lua_State *L)
|
|||||||
union usa sa;
|
union usa sa;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
if ((num_args == 3) && lua_isstring(L, -3) && lua_isnumber(L, -2) &&
|
if ((num_args == 3) && lua_isstring(L, -3) && lua_isnumber(L, -2)
|
||||||
lua_isnumber(L, -1)) {
|
&& lua_isnumber(L, -1)) {
|
||||||
ok = connect_socket(NULL,
|
ok = connect_socket(NULL,
|
||||||
lua_tostring(L, -3),
|
lua_tostring(L, -3),
|
||||||
(int)lua_tonumber(L, -2),
|
(int)lua_tonumber(L, -2),
|
||||||
@ -244,7 +254,8 @@ static int lsp_connect(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lsp_error(lua_State *L)
|
static int
|
||||||
|
lsp_error(lua_State *L)
|
||||||
{
|
{
|
||||||
lua_getglobal(L, "mg");
|
lua_getglobal(L, "mg");
|
||||||
lua_getfield(L, -1, "onerror");
|
lua_getfield(L, -1, "onerror");
|
||||||
@ -254,7 +265,8 @@ static int lsp_error(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Silently stop processing chunks. */
|
/* Silently stop processing chunks. */
|
||||||
static void lsp_abort(lua_State *L)
|
static void
|
||||||
|
lsp_abort(lua_State *L)
|
||||||
{
|
{
|
||||||
int top = lua_gettop(L);
|
int top = lua_gettop(L);
|
||||||
lua_getglobal(L, "mg");
|
lua_getglobal(L, "mg");
|
||||||
@ -271,7 +283,8 @@ struct lsp_var_reader_data {
|
|||||||
unsigned state;
|
unsigned state;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *lsp_var_reader(lua_State *L, void *ud, size_t *sz)
|
static const char *
|
||||||
|
lsp_var_reader(lua_State *L, void *ud, size_t *sz)
|
||||||
{
|
{
|
||||||
struct lsp_var_reader_data *reader = (struct lsp_var_reader_data *)ud;
|
struct lsp_var_reader_data *reader = (struct lsp_var_reader_data *)ud;
|
||||||
const char *ret;
|
const char *ret;
|
||||||
@ -299,11 +312,12 @@ static const char *lsp_var_reader(lua_State *L, void *ud, size_t *sz)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lsp(struct mg_connection *conn,
|
static int
|
||||||
const char *path,
|
lsp(struct mg_connection *conn,
|
||||||
const char *p,
|
const char *path,
|
||||||
int64_t len,
|
const char *p,
|
||||||
lua_State *L)
|
int64_t len,
|
||||||
|
lua_State *L)
|
||||||
{
|
{
|
||||||
int i, j, pos = 0, lines = 1, lualines = 0, is_var, lua_ok;
|
int i, j, pos = 0, lines = 1, lualines = 0, is_var, lua_ok;
|
||||||
char chunkname[MG_BUF_LEN];
|
char chunkname[MG_BUF_LEN];
|
||||||
@ -346,8 +360,10 @@ static int lsp(struct mg_connection *conn,
|
|||||||
lua_ok = mg_lua_load(
|
lua_ok = mg_lua_load(
|
||||||
L, lsp_var_reader, &data, chunkname, NULL);
|
L, lsp_var_reader, &data, chunkname, NULL);
|
||||||
} else {
|
} else {
|
||||||
lua_ok = luaL_loadbuffer(
|
lua_ok = luaL_loadbuffer(L,
|
||||||
L, p + (i + 2), j - (i + 2), chunkname);
|
p + (i + 2),
|
||||||
|
j - (i + 2),
|
||||||
|
chunkname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lua_ok) {
|
if (lua_ok) {
|
||||||
@ -381,7 +397,8 @@ static int lsp(struct mg_connection *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.write: Send data to the client */
|
/* mg.write: Send data to the client */
|
||||||
static int lsp_write(lua_State *L)
|
static int
|
||||||
|
lsp_write(lua_State *L)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn =
|
struct mg_connection *conn =
|
||||||
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
||||||
@ -401,7 +418,8 @@ static int lsp_write(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.read: Read data from the client (e.g., from a POST request) */
|
/* mg.read: Read data from the client (e.g., from a POST request) */
|
||||||
static int lsp_read(lua_State *L)
|
static int
|
||||||
|
lsp_read(lua_State *L)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn =
|
struct mg_connection *conn =
|
||||||
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
||||||
@ -416,7 +434,8 @@ static int lsp_read(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.keep_alive: Allow Lua pages to use the http keep-alive mechanism */
|
/* mg.keep_alive: Allow Lua pages to use the http keep-alive mechanism */
|
||||||
static int lsp_keep_alive(lua_State *L)
|
static int
|
||||||
|
lsp_keep_alive(lua_State *L)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn =
|
struct mg_connection *conn =
|
||||||
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
||||||
@ -439,7 +458,8 @@ static int lsp_keep_alive(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.include: Include another .lp file */
|
/* mg.include: Include another .lp file */
|
||||||
static int lsp_include(lua_State *L)
|
static int
|
||||||
|
lsp_include(lua_State *L)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn =
|
struct mg_connection *conn =
|
||||||
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
||||||
@ -463,7 +483,8 @@ static int lsp_include(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.cry: Log an error. Default value for mg.onerror. */
|
/* mg.cry: Log an error. Default value for mg.onerror. */
|
||||||
static int lsp_cry(lua_State *L)
|
static int
|
||||||
|
lsp_cry(lua_State *L)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn =
|
struct mg_connection *conn =
|
||||||
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
||||||
@ -480,7 +501,8 @@ static int lsp_cry(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.redirect: Redirect the request (internally). */
|
/* mg.redirect: Redirect the request (internally). */
|
||||||
static int lsp_redirect(lua_State *L)
|
static int
|
||||||
|
lsp_redirect(lua_State *L)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn =
|
struct mg_connection *conn =
|
||||||
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
||||||
@ -499,7 +521,8 @@ static int lsp_redirect(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.send_file */
|
/* mg.send_file */
|
||||||
static int lsp_send_file(lua_State *L)
|
static int
|
||||||
|
lsp_send_file(lua_State *L)
|
||||||
{
|
{
|
||||||
struct mg_connection *conn =
|
struct mg_connection *conn =
|
||||||
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
(struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
|
||||||
@ -516,7 +539,8 @@ static int lsp_send_file(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.get_time */
|
/* mg.get_time */
|
||||||
static int lsp_get_time(lua_State *L)
|
static int
|
||||||
|
lsp_get_time(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
int monotonic = (num_args > 0) ? lua_toboolean(L, 1) : 0;
|
int monotonic = (num_args > 0) ? lua_toboolean(L, 1) : 0;
|
||||||
@ -530,7 +554,8 @@ static int lsp_get_time(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.get_var */
|
/* mg.get_var */
|
||||||
static int lsp_get_var(lua_State *L)
|
static int
|
||||||
|
lsp_get_var(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
const char *data, *var_name;
|
const char *data, *var_name;
|
||||||
@ -560,7 +585,8 @@ static int lsp_get_var(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.get_mime_type */
|
/* mg.get_mime_type */
|
||||||
static int lsp_get_mime_type(lua_State *L)
|
static int
|
||||||
|
lsp_get_mime_type(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
struct vec mime_type = {0, 0};
|
struct vec mime_type = {0, 0};
|
||||||
@ -593,7 +619,8 @@ static int lsp_get_mime_type(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.get_cookie */
|
/* mg.get_cookie */
|
||||||
static int lsp_get_cookie(lua_State *L)
|
static int
|
||||||
|
lsp_get_cookie(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
const char *cookie;
|
const char *cookie;
|
||||||
@ -623,7 +650,8 @@ static int lsp_get_cookie(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.md5 */
|
/* mg.md5 */
|
||||||
static int lsp_md5(lua_State *L)
|
static int
|
||||||
|
lsp_md5(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
const char *text;
|
const char *text;
|
||||||
@ -651,7 +679,8 @@ static int lsp_md5(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.url_encode */
|
/* mg.url_encode */
|
||||||
static int lsp_url_encode(lua_State *L)
|
static int
|
||||||
|
lsp_url_encode(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
const char *text;
|
const char *text;
|
||||||
@ -674,7 +703,8 @@ static int lsp_url_encode(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.url_decode */
|
/* mg.url_decode */
|
||||||
static int lsp_url_decode(lua_State *L)
|
static int
|
||||||
|
lsp_url_decode(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
const char *text;
|
const char *text;
|
||||||
@ -699,7 +729,8 @@ static int lsp_url_decode(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.base64_encode */
|
/* mg.base64_encode */
|
||||||
static int lsp_base64_encode(lua_State *L)
|
static int
|
||||||
|
lsp_base64_encode(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
const char *text;
|
const char *text;
|
||||||
@ -728,7 +759,8 @@ static int lsp_base64_encode(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.base64_encode */
|
/* mg.base64_encode */
|
||||||
static int lsp_base64_decode(lua_State *L)
|
static int
|
||||||
|
lsp_base64_decode(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
const char *text;
|
const char *text;
|
||||||
@ -741,8 +773,10 @@ static int lsp_base64_decode(lua_State *L)
|
|||||||
if (text) {
|
if (text) {
|
||||||
dst = (char *)mg_malloc(text_len);
|
dst = (char *)mg_malloc(text_len);
|
||||||
if (dst) {
|
if (dst) {
|
||||||
ret = base64_decode(
|
ret = base64_decode((const unsigned char *)text,
|
||||||
(const unsigned char *)text, text_len, dst, &dst_len);
|
text_len,
|
||||||
|
dst,
|
||||||
|
&dst_len);
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
mg_free(dst);
|
mg_free(dst);
|
||||||
return luaL_error(
|
return luaL_error(
|
||||||
@ -766,7 +800,8 @@ static int lsp_base64_decode(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.get_response_code_text */
|
/* mg.get_response_code_text */
|
||||||
static int lsp_get_response_code_text(lua_State *L)
|
static int
|
||||||
|
lsp_get_response_code_text(lua_State *L)
|
||||||
{
|
{
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
int type1;
|
int type1;
|
||||||
@ -801,7 +836,8 @@ struct lua_websock_data {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* mg.write for websockets */
|
/* mg.write for websockets */
|
||||||
static int lwebsock_write(lua_State *L)
|
static int
|
||||||
|
lwebsock_write(lua_State *L)
|
||||||
{
|
{
|
||||||
#ifdef USE_WEBSOCKET
|
#ifdef USE_WEBSOCKET
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
@ -905,7 +941,8 @@ struct laction_arg {
|
|||||||
char txt[1];
|
char txt[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
static int lua_action(struct laction_arg *arg)
|
static int
|
||||||
|
lua_action(struct laction_arg *arg)
|
||||||
{
|
{
|
||||||
int err, ok;
|
int err, ok;
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
@ -947,7 +984,8 @@ static int lua_action(struct laction_arg *arg)
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lua_action_free(struct laction_arg *arg)
|
static int
|
||||||
|
lua_action_free(struct laction_arg *arg)
|
||||||
{
|
{
|
||||||
if (lua_action(arg)) {
|
if (lua_action(arg)) {
|
||||||
mg_free(arg);
|
mg_free(arg);
|
||||||
@ -955,7 +993,8 @@ static int lua_action_free(struct laction_arg *arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lwebsocket_set_timer(lua_State *L, int is_periodic)
|
static int
|
||||||
|
lwebsocket_set_timer(lua_State *L, int is_periodic)
|
||||||
{
|
{
|
||||||
#if defined(USE_TIMERS) && defined(USE_WEBSOCKET)
|
#if defined(USE_TIMERS) && defined(USE_WEBSOCKET)
|
||||||
int num_args = lua_gettop(L);
|
int num_args = lua_gettop(L);
|
||||||
@ -987,8 +1026,8 @@ static int lwebsocket_set_timer(lua_State *L, int is_periodic)
|
|||||||
timediff = (double)lua_tonumber(L, 2);
|
timediff = (double)lua_tonumber(L, 2);
|
||||||
txt = lua_tostring(L, 1);
|
txt = lua_tostring(L, 1);
|
||||||
txt_len = strlen(txt);
|
txt_len = strlen(txt);
|
||||||
arg = (struct laction_arg *)mg_malloc(sizeof(struct laction_arg) +
|
arg = (struct laction_arg *)mg_malloc(sizeof(struct laction_arg)
|
||||||
txt_len + 10);
|
+ txt_len + 10);
|
||||||
arg->state = L;
|
arg->state = L;
|
||||||
arg->script = ws->script;
|
arg->script = ws->script;
|
||||||
arg->pmutex = &(ws->ws_mutex);
|
arg->pmutex = &(ws->ws_mutex);
|
||||||
@ -996,13 +1035,14 @@ static int lwebsocket_set_timer(lua_State *L, int is_periodic)
|
|||||||
memcpy(arg->txt + 7, txt, txt_len);
|
memcpy(arg->txt + 7, txt, txt_len);
|
||||||
arg->txt[txt_len + 7] = ')';
|
arg->txt[txt_len + 7] = ')';
|
||||||
arg->txt[txt_len + 8] = 0;
|
arg->txt[txt_len + 8] = 0;
|
||||||
ok = (0 ==
|
ok =
|
||||||
timer_add(ctx,
|
(0
|
||||||
timediff,
|
== timer_add(ctx,
|
||||||
is_periodic,
|
timediff,
|
||||||
1,
|
is_periodic,
|
||||||
(taction)(is_periodic ? lua_action : lua_action_free),
|
1,
|
||||||
(void *)arg));
|
(taction)(is_periodic ? lua_action : lua_action_free),
|
||||||
|
(void *)arg));
|
||||||
} else if (type1 == LUA_TFUNCTION && type2 == LUA_TNUMBER) {
|
} else if (type1 == LUA_TFUNCTION && type2 == LUA_TNUMBER) {
|
||||||
/* TODO (mid): not implemented yet */
|
/* TODO (mid): not implemented yet */
|
||||||
return luaL_error(L, "invalid arguments for set_timer/interval() call");
|
return luaL_error(L, "invalid arguments for set_timer/interval() call");
|
||||||
@ -1021,13 +1061,15 @@ static int lwebsocket_set_timer(lua_State *L, int is_periodic)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mg.set_timeout for websockets */
|
/* mg.set_timeout for websockets */
|
||||||
static int lwebsocket_set_timeout(lua_State *L)
|
static int
|
||||||
|
lwebsocket_set_timeout(lua_State *L)
|
||||||
{
|
{
|
||||||
return lwebsocket_set_timer(L, 0);
|
return lwebsocket_set_timer(L, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mg.set_interval for websockets */
|
/* mg.set_interval for websockets */
|
||||||
static int lwebsocket_set_interval(lua_State *L)
|
static int
|
||||||
|
lwebsocket_set_interval(lua_State *L)
|
||||||
{
|
{
|
||||||
return lwebsocket_set_timer(L, 1);
|
return lwebsocket_set_timer(L, 1);
|
||||||
}
|
}
|
||||||
@ -1038,7 +1080,8 @@ enum {
|
|||||||
LUA_ENV_TYPE_LUA_WEBSOCKET = 2,
|
LUA_ENV_TYPE_LUA_WEBSOCKET = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void prepare_lua_request_info(struct mg_connection *conn, lua_State *L)
|
static void
|
||||||
|
prepare_lua_request_info(struct mg_connection *conn, lua_State *L)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
int i;
|
int i;
|
||||||
@ -1100,7 +1143,8 @@ static void prepare_lua_request_info(struct mg_connection *conn, lua_State *L)
|
|||||||
lua_rawset(L, -3);
|
lua_rawset(L, -3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void civetweb_open_lua_libs(lua_State *L)
|
void
|
||||||
|
civetweb_open_lua_libs(lua_State *L)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
extern void luaL_openlibs(lua_State *);
|
extern void luaL_openlibs(lua_State *);
|
||||||
@ -1137,12 +1181,13 @@ void civetweb_open_lua_libs(lua_State *L)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_lua_environment(struct mg_context *ctx,
|
static void
|
||||||
struct mg_connection *conn,
|
prepare_lua_environment(struct mg_context *ctx,
|
||||||
struct lua_websock_data *ws_conn_list,
|
struct mg_connection *conn,
|
||||||
lua_State *L,
|
struct lua_websock_data *ws_conn_list,
|
||||||
const char *script_name,
|
lua_State *L,
|
||||||
int lua_env_type)
|
const char *script_name,
|
||||||
|
int lua_env_type)
|
||||||
{
|
{
|
||||||
civetweb_open_lua_libs(L);
|
civetweb_open_lua_libs(L);
|
||||||
|
|
||||||
@ -1186,8 +1231,8 @@ static void prepare_lua_environment(struct mg_context *ctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE ||
|
if (lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE
|
||||||
lua_env_type == LUA_ENV_TYPE_PLAIN_LUA_PAGE) {
|
|| lua_env_type == LUA_ENV_TYPE_PLAIN_LUA_PAGE) {
|
||||||
reg_conn_function(L, "cry", lsp_cry, conn);
|
reg_conn_function(L, "cry", lsp_cry, conn);
|
||||||
reg_conn_function(L, "read", lsp_read, conn);
|
reg_conn_function(L, "read", lsp_read, conn);
|
||||||
reg_conn_function(L, "write", lsp_write, conn);
|
reg_conn_function(L, "write", lsp_write, conn);
|
||||||
@ -1231,7 +1276,6 @@ static void prepare_lua_environment(struct mg_context *ctx,
|
|||||||
reg_string(L, "websocket_root", ctx->config[WEBSOCKET_ROOT]);
|
reg_string(L, "websocket_root", ctx->config[WEBSOCKET_ROOT]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (ctx->systemName != NULL) {
|
if (ctx->systemName != NULL) {
|
||||||
reg_string(L, "system", ctx->systemName);
|
reg_string(L, "system", ctx->systemName);
|
||||||
}
|
}
|
||||||
@ -1262,7 +1306,8 @@ static void prepare_lua_environment(struct mg_context *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lua_error_handler(lua_State *L)
|
static int
|
||||||
|
lua_error_handler(lua_State *L)
|
||||||
{
|
{
|
||||||
const char *error_msg = lua_isstring(L, -1) ? lua_tostring(L, -1) : "?\n";
|
const char *error_msg = lua_isstring(L, -1) ? lua_tostring(L, -1) : "?\n";
|
||||||
|
|
||||||
@ -1284,7 +1329,8 @@ static int lua_error_handler(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
|
static void *
|
||||||
|
lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
|
||||||
{
|
{
|
||||||
|
|
||||||
(void)ud;
|
(void)ud;
|
||||||
@ -1297,9 +1343,10 @@ static void *lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
|
|||||||
return mg_realloc(ptr, nsize);
|
return mg_realloc(ptr, nsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mg_exec_lua_script(struct mg_connection *conn,
|
static void
|
||||||
const char *path,
|
mg_exec_lua_script(struct mg_connection *conn,
|
||||||
const void **exports)
|
const char *path,
|
||||||
|
const void **exports)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
@ -1342,10 +1389,11 @@ static void mg_exec_lua_script(struct mg_connection *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_lsp_request(struct mg_connection *conn,
|
static int
|
||||||
const char *path,
|
handle_lsp_request(struct mg_connection *conn,
|
||||||
struct file *filep,
|
const char *path,
|
||||||
struct lua_State *ls)
|
struct file *filep,
|
||||||
|
struct lua_State *ls)
|
||||||
{
|
{
|
||||||
void *p = NULL;
|
void *p = NULL;
|
||||||
lua_State *L = NULL;
|
lua_State *L = NULL;
|
||||||
@ -1367,13 +1415,13 @@ static int handle_lsp_request(struct mg_connection *conn,
|
|||||||
} else {
|
} else {
|
||||||
luaL_error(ls, "File [%s] not found", path);
|
luaL_error(ls, "File [%s] not found", path);
|
||||||
}
|
}
|
||||||
} else if (filep->membuf == NULL &&
|
} else if (filep->membuf == NULL
|
||||||
(p = mmap(NULL,
|
&& (p = mmap(NULL,
|
||||||
(size_t)filep->size,
|
(size_t)filep->size,
|
||||||
PROT_READ,
|
PROT_READ,
|
||||||
MAP_PRIVATE,
|
MAP_PRIVATE,
|
||||||
fileno(filep->fp),
|
fileno(filep->fp),
|
||||||
0)) == MAP_FAILED) {
|
0)) == MAP_FAILED) {
|
||||||
/* mmap failed */
|
/* mmap failed */
|
||||||
if (ls == NULL) {
|
if (ls == NULL) {
|
||||||
send_http_error(
|
send_http_error(
|
||||||
@ -1389,8 +1437,8 @@ static int handle_lsp_request(struct mg_connection *conn,
|
|||||||
fileno(filep->fp),
|
fileno(filep->fp),
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
} else if ((L = (ls != NULL ? ls : lua_newstate(lua_allocator, NULL))) ==
|
} else if ((L = (ls != NULL ? ls : lua_newstate(lua_allocator, NULL)))
|
||||||
NULL) {
|
== NULL) {
|
||||||
send_http_error(conn,
|
send_http_error(conn,
|
||||||
500,
|
500,
|
||||||
"%s",
|
"%s",
|
||||||
@ -1423,7 +1471,8 @@ struct mg_shared_lua_websocket_list {
|
|||||||
struct mg_shared_lua_websocket_list *next;
|
struct mg_shared_lua_websocket_list *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *lua_websocket_new(const char *script, struct mg_connection *conn)
|
static void *
|
||||||
|
lua_websocket_new(const char *script, struct mg_connection *conn)
|
||||||
{
|
{
|
||||||
struct mg_shared_lua_websocket_list **shared_websock_list =
|
struct mg_shared_lua_websocket_list **shared_websock_list =
|
||||||
&(conn->ctx->shared_lua_websockets);
|
&(conn->ctx->shared_lua_websockets);
|
||||||
@ -1443,8 +1492,8 @@ static void *lua_websocket_new(const char *script, struct mg_connection *conn)
|
|||||||
}
|
}
|
||||||
if (*shared_websock_list == NULL) {
|
if (*shared_websock_list == NULL) {
|
||||||
/* add ws to list */
|
/* add ws to list */
|
||||||
*shared_websock_list = (struct mg_shared_lua_websocket_list *)mg_calloc(
|
*shared_websock_list = (struct mg_shared_lua_websocket_list *)
|
||||||
sizeof(struct mg_shared_lua_websocket_list), 1);
|
mg_calloc(sizeof(struct mg_shared_lua_websocket_list), 1);
|
||||||
if (*shared_websock_list == NULL) {
|
if (*shared_websock_list == NULL) {
|
||||||
mg_unlock_context(conn->ctx);
|
mg_unlock_context(conn->ctx);
|
||||||
mg_cry(conn, "Cannot create shared websocket struct, OOM");
|
mg_cry(conn, "Cannot create shared websocket struct, OOM");
|
||||||
@ -1505,11 +1554,12 @@ static void *lua_websocket_new(const char *script, struct mg_connection *conn)
|
|||||||
return ok ? (void *)ws : NULL;
|
return ok ? (void *)ws : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lua_websocket_data(struct mg_connection *conn,
|
static int
|
||||||
int bits,
|
lua_websocket_data(struct mg_connection *conn,
|
||||||
char *data,
|
int bits,
|
||||||
size_t data_len,
|
char *data,
|
||||||
void *ws_arg)
|
size_t data_len,
|
||||||
|
void *ws_arg)
|
||||||
{
|
{
|
||||||
struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
|
struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
|
||||||
int err, ok = 0;
|
int err, ok = 0;
|
||||||
@ -1548,7 +1598,8 @@ static int lua_websocket_data(struct mg_connection *conn,
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lua_websocket_ready(struct mg_connection *conn, void *ws_arg)
|
static int
|
||||||
|
lua_websocket_ready(struct mg_connection *conn, void *ws_arg)
|
||||||
{
|
{
|
||||||
struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
|
struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
|
||||||
int err, ok = 0;
|
int err, ok = 0;
|
||||||
@ -1579,7 +1630,8 @@ static int lua_websocket_ready(struct mg_connection *conn, void *ws_arg)
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lua_websocket_close(struct mg_connection *conn, void *ws_arg)
|
static void
|
||||||
|
lua_websocket_close(struct mg_connection *conn, void *ws_arg)
|
||||||
{
|
{
|
||||||
struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
|
struct lua_websock_data *ws = (struct lua_websock_data *)(ws_arg);
|
||||||
struct mg_shared_lua_websocket_list **shared_websock_list =
|
struct mg_shared_lua_websocket_list **shared_websock_list =
|
||||||
|
@ -19,12 +19,13 @@ struct ttimers {
|
|||||||
unsigned timer_count; /* Current size of timer list */
|
unsigned timer_count; /* Current size of timer list */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int timer_add(struct mg_context *ctx,
|
static int
|
||||||
double next_time,
|
timer_add(struct mg_context *ctx,
|
||||||
double period,
|
double next_time,
|
||||||
int is_relative,
|
double period,
|
||||||
taction action,
|
int is_relative,
|
||||||
void *arg)
|
taction action,
|
||||||
|
void *arg)
|
||||||
{
|
{
|
||||||
unsigned u, v;
|
unsigned u, v;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
@ -62,7 +63,8 @@ static int timer_add(struct mg_context *ctx,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timer_thread_run(void *thread_func_param)
|
static void
|
||||||
|
timer_thread_run(void *thread_func_param)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = (struct mg_context *)thread_func_param;
|
struct mg_context *ctx = (struct mg_context *)thread_func_param;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
@ -73,9 +75,8 @@ static void timer_thread_run(void *thread_func_param)
|
|||||||
|
|
||||||
#if defined(HAVE_CLOCK_NANOSLEEP) /* Linux with librt */
|
#if defined(HAVE_CLOCK_NANOSLEEP) /* Linux with librt */
|
||||||
/* TODO */
|
/* TODO */
|
||||||
while (
|
while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &request, &request)
|
||||||
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &request, &request) ==
|
== EINTR) { /*nop*/
|
||||||
EINTR) { /*nop*/
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -112,14 +113,16 @@ static unsigned __stdcall timer_thread(void *thread_func_param)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void *timer_thread(void *thread_func_param)
|
static void *
|
||||||
|
timer_thread(void *thread_func_param)
|
||||||
{
|
{
|
||||||
timer_thread_run(thread_func_param);
|
timer_thread_run(thread_func_param);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
static int timers_init(struct mg_context *ctx)
|
static int
|
||||||
|
timers_init(struct mg_context *ctx)
|
||||||
{
|
{
|
||||||
ctx->timers = (struct ttimers *)mg_calloc(sizeof(struct ttimers), 1);
|
ctx->timers = (struct ttimers *)mg_calloc(sizeof(struct ttimers), 1);
|
||||||
(void)pthread_mutex_init(&ctx->timers->mutex, NULL);
|
(void)pthread_mutex_init(&ctx->timers->mutex, NULL);
|
||||||
@ -130,7 +133,8 @@ static int timers_init(struct mg_context *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timers_exit(struct mg_context *ctx)
|
static void
|
||||||
|
timers_exit(struct mg_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->timers) {
|
if (ctx->timers) {
|
||||||
(void)pthread_mutex_destroy(&ctx->timers->mutex);
|
(void)pthread_mutex_destroy(&ctx->timers->mutex);
|
||||||
|
16
test/main.c
16
test/main.c
@ -30,13 +30,13 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
/* This unit test file uses the excellent Check unit testing library.
|
/* This unit test file uses the excellent Check unit testing library.
|
||||||
* The API documentation is available here:
|
* The API documentation is available here:
|
||||||
* http://check.sourceforge.net/doc/check_html/index.html
|
* http://check.sourceforge.net/doc/check_html/index.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int main(const int argc, char *argv[])
|
int
|
||||||
|
main(const int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// Determine what tests to run
|
// Determine what tests to run
|
||||||
const char *suite = NULL;
|
const char *suite = NULL;
|
||||||
@ -48,14 +48,14 @@ int main(const int argc, char *argv[])
|
|||||||
const char *const test_dir_arg = "--test-dir=";
|
const char *const test_dir_arg = "--test-dir=";
|
||||||
const size_t test_dir_arg_size = strlen(test_dir_arg);
|
const size_t test_dir_arg_size = strlen(test_dir_arg);
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
if (0 == strncmp(suite_arg, argv[i], suite_arg_size) &&
|
if (0 == strncmp(suite_arg, argv[i], suite_arg_size)
|
||||||
(strlen(argv[i]) > suite_arg_size)) {
|
&& (strlen(argv[i]) > suite_arg_size)) {
|
||||||
suite = &argv[i][suite_arg_size];
|
suite = &argv[i][suite_arg_size];
|
||||||
} else if (0 == strncmp(test_case_arg, argv[i], test_case_arg_size) &&
|
} else if (0 == strncmp(test_case_arg, argv[i], test_case_arg_size)
|
||||||
(strlen(argv[i]) > test_case_arg_size)) {
|
&& (strlen(argv[i]) > test_case_arg_size)) {
|
||||||
test_case = &argv[i][test_case_arg_size];
|
test_case = &argv[i][test_case_arg_size];
|
||||||
} else if (0 == strncmp(test_dir_arg, argv[i], test_dir_arg_size) &&
|
} else if (0 == strncmp(test_dir_arg, argv[i], test_dir_arg_size)
|
||||||
(strlen(argv[i]) > test_dir_arg_size)) {
|
&& (strlen(argv[i]) > test_dir_arg_size)) {
|
||||||
set_test_directory(&argv[i][test_dir_arg_size]);
|
set_test_directory(&argv[i][test_dir_arg_size]);
|
||||||
} else if (0 == strcmp("--help", argv[i])) {
|
} else if (0 == strcmp("--help", argv[i])) {
|
||||||
printf(
|
printf(
|
||||||
|
@ -91,7 +91,6 @@ START_TEST(test_parse_http_message)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_should_keep_alive)
|
START_TEST(test_should_keep_alive)
|
||||||
{
|
{
|
||||||
/* Adapted from unit_test.c */
|
/* Adapted from unit_test.c */
|
||||||
@ -139,7 +138,6 @@ START_TEST(test_should_keep_alive)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_match_prefix)
|
START_TEST(test_match_prefix)
|
||||||
{
|
{
|
||||||
/* Adapted from unit_test.c */
|
/* Adapted from unit_test.c */
|
||||||
@ -176,7 +174,6 @@ START_TEST(test_match_prefix)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_remove_double_dots_and_double_slashes)
|
START_TEST(test_remove_double_dots_and_double_slashes)
|
||||||
{
|
{
|
||||||
/* Adapted from unit_test.c */
|
/* Adapted from unit_test.c */
|
||||||
@ -205,7 +202,6 @@ START_TEST(test_remove_double_dots_and_double_slashes)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_is_valid_uri)
|
START_TEST(test_is_valid_uri)
|
||||||
{
|
{
|
||||||
/* is_valid_uri is superseeded by get_uri_type */
|
/* is_valid_uri is superseeded by get_uri_type */
|
||||||
@ -223,7 +219,6 @@ START_TEST(test_is_valid_uri)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_next_option)
|
START_TEST(test_next_option)
|
||||||
{
|
{
|
||||||
/* Adapted from unit_test.c */
|
/* Adapted from unit_test.c */
|
||||||
@ -236,14 +231,14 @@ START_TEST(test_next_option)
|
|||||||
ck_assert(next_option(NULL, &a, &b) == NULL);
|
ck_assert(next_option(NULL, &a, &b) == NULL);
|
||||||
for (i = 0, p = list; (p = next_option(p, &a, &b)) != NULL; i++) {
|
for (i = 0, p = list; (p = next_option(p, &a, &b)) != NULL; i++) {
|
||||||
ck_assert(i != 0 || (a.ptr == list && a.len == 3 && b.len == 0));
|
ck_assert(i != 0 || (a.ptr == list && a.len == 3 && b.len == 0));
|
||||||
ck_assert(i != 1 || (a.ptr == list + 4 && a.len == 4 &&
|
ck_assert(i != 1
|
||||||
b.ptr == list + 9 && b.len == 4));
|
|| (a.ptr == list + 4 && a.len == 4 && b.ptr == list + 9
|
||||||
|
&& b.len == 4));
|
||||||
ck_assert(i != 2 || (a.ptr == list + 14 && a.len == 1 && b.len == 0));
|
ck_assert(i != 2 || (a.ptr == list + 14 && a.len == 1 && b.len == 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_skip_quoted)
|
START_TEST(test_skip_quoted)
|
||||||
{
|
{
|
||||||
/* Adapted from unit_test.c */
|
/* Adapted from unit_test.c */
|
||||||
@ -266,8 +261,8 @@ START_TEST(test_skip_quoted)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
static int
|
||||||
static int alloc_printf(char **buf, size_t size, const char *fmt, ...)
|
alloc_printf(char **buf, size_t size, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
/* Test helper function - adapted from unit_test.c */
|
/* Test helper function - adapted from unit_test.c */
|
||||||
/* Copyright (c) 2013-2015 the Civetweb developers */
|
/* Copyright (c) 2013-2015 the Civetweb developers */
|
||||||
@ -280,7 +275,6 @@ static int alloc_printf(char **buf, size_t size, const char *fmt, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_alloc_vprintf)
|
START_TEST(test_alloc_vprintf)
|
||||||
{
|
{
|
||||||
/* Adapted from unit_test.c */
|
/* Adapted from unit_test.c */
|
||||||
@ -300,7 +294,6 @@ START_TEST(test_alloc_vprintf)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_strcasestr)
|
START_TEST(test_mg_strcasestr)
|
||||||
{
|
{
|
||||||
/* Adapted from unit_test.c */
|
/* Adapted from unit_test.c */
|
||||||
@ -315,27 +308,25 @@ START_TEST(test_mg_strcasestr)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_parse_port_string)
|
START_TEST(test_parse_port_string)
|
||||||
{
|
{
|
||||||
/* Adapted from unit_test.c */
|
/* Adapted from unit_test.c */
|
||||||
/* Copyright (c) 2013-2015 the Civetweb developers */
|
/* Copyright (c) 2013-2015 the Civetweb developers */
|
||||||
/* Copyright (c) 2004-2013 Sergey Lyubka */
|
/* Copyright (c) 2004-2013 Sergey Lyubka */
|
||||||
static const char *valid[] = {
|
static const char *valid[] =
|
||||||
"0",
|
{ "0",
|
||||||
"1",
|
"1",
|
||||||
"1s",
|
"1s",
|
||||||
"1r",
|
"1r",
|
||||||
"1.2.3.4:1",
|
"1.2.3.4:1",
|
||||||
"1.2.3.4:1s",
|
"1.2.3.4:1s",
|
||||||
"1.2.3.4:1r",
|
"1.2.3.4:1r",
|
||||||
#if defined(USE_IPV6)
|
#if defined(USE_IPV6)
|
||||||
"[::1]:123",
|
"[::1]:123",
|
||||||
"[::]:80",
|
"[::]:80",
|
||||||
"[3ffe:2a00:100:7031::1]:900",
|
"[3ffe:2a00:100:7031::1]:900",
|
||||||
#endif
|
#endif
|
||||||
NULL
|
NULL };
|
||||||
};
|
|
||||||
static const char *invalid[] = {
|
static const char *invalid[] = {
|
||||||
"99999", "1k", "1.2.3", "1.2.3.4:", "1.2.3.4:2p", NULL};
|
"99999", "1k", "1.2.3", "1.2.3.4:", "1.2.3.4:2p", NULL};
|
||||||
struct socket so;
|
struct socket so;
|
||||||
@ -356,7 +347,6 @@ START_TEST(test_parse_port_string)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_encode_decode)
|
START_TEST(test_encode_decode)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -414,8 +404,10 @@ START_TEST(test_encode_decode)
|
|||||||
#if defined(USE_LUA)
|
#if defined(USE_LUA)
|
||||||
memset(buf, 77, sizeof(buf));
|
memset(buf, 77, sizeof(buf));
|
||||||
len = 9999;
|
len = 9999;
|
||||||
ret = base64_decode(
|
ret = base64_decode((unsigned char *)alpha_b64_enc,
|
||||||
(unsigned char *)alpha_b64_enc, (int)strlen(alpha_b64_enc), buf, &len);
|
(int)strlen(alpha_b64_enc),
|
||||||
|
buf,
|
||||||
|
&len);
|
||||||
ck_assert_int_eq(ret, -1);
|
ck_assert_int_eq(ret, -1);
|
||||||
ck_assert_uint_eq((unsigned int)len, (unsigned int)strlen(alpha));
|
ck_assert_uint_eq((unsigned int)len, (unsigned int)strlen(alpha));
|
||||||
ck_assert_str_eq(buf, alpha);
|
ck_assert_str_eq(buf, alpha);
|
||||||
@ -464,8 +456,8 @@ START_TEST(test_encode_decode)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
Suite *
|
||||||
Suite *make_private_suite(void)
|
make_private_suite(void)
|
||||||
{
|
{
|
||||||
Suite *const suite = suite_create("Private");
|
Suite *const suite = suite_create("Private");
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ START_TEST(test_helper_funcs)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
Suite *
|
||||||
Suite *make_private_exe_suite(void)
|
make_private_exe_suite(void)
|
||||||
{
|
{
|
||||||
Suite *const suite = suite_create("EXE");
|
Suite *const suite = suite_create("EXE");
|
||||||
|
|
||||||
|
@ -28,5 +28,4 @@ Suite *make_private_exe_suite(void);
|
|||||||
/* This is a redefine for "main" in main.c */
|
/* This is a redefine for "main" in main.c */
|
||||||
int exe_main(int argc, char *argv[]);
|
int exe_main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
|
||||||
#endif /* TEST_PRIVATE_H_ */
|
#endif /* TEST_PRIVATE_H_ */
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
* http://check.sourceforge.net/doc/check_html/index.html
|
* http://check.sourceforge.net/doc/check_html/index.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_version)
|
START_TEST(test_mg_version)
|
||||||
{
|
{
|
||||||
const char *ver = mg_version();
|
const char *ver = mg_version();
|
||||||
@ -89,7 +88,6 @@ START_TEST(test_mg_version)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_get_valid_options)
|
START_TEST(test_mg_get_valid_options)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -107,7 +105,6 @@ START_TEST(test_mg_get_valid_options)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_get_builtin_mime_type)
|
START_TEST(test_mg_get_builtin_mime_type)
|
||||||
{
|
{
|
||||||
ck_assert_str_eq(mg_get_builtin_mime_type("x.txt"), "text/plain");
|
ck_assert_str_eq(mg_get_builtin_mime_type("x.txt"), "text/plain");
|
||||||
@ -120,7 +117,6 @@ START_TEST(test_mg_get_builtin_mime_type)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_strncasecmp)
|
START_TEST(test_mg_strncasecmp)
|
||||||
{
|
{
|
||||||
ck_assert(mg_strncasecmp("abc", "abc", 3) == 0);
|
ck_assert(mg_strncasecmp("abc", "abc", 3) == 0);
|
||||||
@ -148,7 +144,6 @@ START_TEST(test_mg_strncasecmp)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_get_cookie)
|
START_TEST(test_mg_get_cookie)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
@ -215,7 +210,6 @@ START_TEST(test_mg_get_cookie)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_get_var)
|
START_TEST(test_mg_get_var)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
@ -318,7 +312,6 @@ START_TEST(test_mg_get_var)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_md5)
|
START_TEST(test_mg_md5)
|
||||||
{
|
{
|
||||||
char buf[33];
|
char buf[33];
|
||||||
@ -373,7 +366,6 @@ START_TEST(test_mg_md5)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_url_encode)
|
START_TEST(test_mg_url_encode)
|
||||||
{
|
{
|
||||||
char buf[20];
|
char buf[20];
|
||||||
@ -396,7 +388,6 @@ START_TEST(test_mg_url_encode)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_url_decode)
|
START_TEST(test_mg_url_decode)
|
||||||
{
|
{
|
||||||
char buf[20];
|
char buf[20];
|
||||||
@ -424,8 +415,8 @@ START_TEST(test_mg_url_decode)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
Suite *
|
||||||
Suite *make_public_func_suite(void)
|
make_public_func_suite(void)
|
||||||
{
|
{
|
||||||
Suite *const suite = suite_create("PublicFunc");
|
Suite *const suite = suite_create("PublicFunc");
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@
|
|||||||
* http://check.sourceforge.net/doc/check_html/index.html
|
* http://check.sourceforge.net/doc/check_html/index.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static const char *
|
||||||
static const char *locate_ssl_cert(void)
|
locate_ssl_cert(void)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -70,8 +70,8 @@ static const char *locate_ssl_cert(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
static int wait_not_null(void *volatile *data)
|
wait_not_null(void *volatile *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++) {
|
||||||
@ -83,7 +83,6 @@ static int wait_not_null(void *volatile *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_the_test_environment)
|
START_TEST(test_the_test_environment)
|
||||||
{
|
{
|
||||||
char wd[300];
|
char wd[300];
|
||||||
@ -96,7 +95,6 @@ START_TEST(test_the_test_environment)
|
|||||||
memset(wd, 0, sizeof(wd));
|
memset(wd, 0, sizeof(wd));
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
|
||||||
/* Get the current working directory */
|
/* Get the current working directory */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
(void)GetCurrentDirectoryA(sizeof(wd), wd);
|
(void)GetCurrentDirectoryA(sizeof(wd), wd);
|
||||||
@ -143,10 +141,10 @@ START_TEST(test_the_test_environment)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
static void *threading_data;
|
static void *threading_data;
|
||||||
|
|
||||||
static void *test_thread_func_t(void *param)
|
static void *
|
||||||
|
test_thread_func_t(void *param)
|
||||||
{
|
{
|
||||||
ck_assert_ptr_eq(param, &threading_data);
|
ck_assert_ptr_eq(param, &threading_data);
|
||||||
ck_assert_ptr_eq(threading_data, NULL);
|
ck_assert_ptr_eq(threading_data, NULL);
|
||||||
@ -154,7 +152,6 @@ static void *test_thread_func_t(void *param)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_threading)
|
START_TEST(test_threading)
|
||||||
{
|
{
|
||||||
int ok;
|
int ok;
|
||||||
@ -169,8 +166,8 @@ START_TEST(test_threading)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
static int
|
||||||
static int log_msg_func(const struct mg_connection *conn, const char *message)
|
log_msg_func(const struct mg_connection *conn, const char *message)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
char *ud;
|
char *ud;
|
||||||
@ -185,7 +182,6 @@ static int log_msg_func(const struct mg_connection *conn, const char *message)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_start_stop_http_server)
|
START_TEST(test_mg_start_stop_http_server)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
@ -228,7 +224,6 @@ START_TEST(test_mg_start_stop_http_server)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_mg_start_stop_https_server)
|
START_TEST(test_mg_start_stop_https_server)
|
||||||
{
|
{
|
||||||
#ifndef NO_SSL
|
#ifndef NO_SSL
|
||||||
@ -260,7 +255,6 @@ START_TEST(test_mg_start_stop_https_server)
|
|||||||
ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL);
|
ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL);
|
||||||
ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL);
|
ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL);
|
||||||
|
|
||||||
|
|
||||||
memset(ports, 0, sizeof(ports));
|
memset(ports, 0, sizeof(ports));
|
||||||
memset(ssl, 0, sizeof(ssl));
|
memset(ssl, 0, sizeof(ssl));
|
||||||
memset(&callbacks, 0, sizeof(callbacks));
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
@ -288,10 +282,10 @@ START_TEST(test_mg_start_stop_https_server)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
static struct mg_context *g_ctx;
|
static struct mg_context *g_ctx;
|
||||||
|
|
||||||
static int request_test_handler(struct mg_connection *conn, void *cbdata)
|
static int
|
||||||
|
request_test_handler(struct mg_connection *conn, void *cbdata)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char chunk_data[32];
|
char chunk_data[32];
|
||||||
@ -330,7 +324,6 @@ static int request_test_handler(struct mg_connection *conn, void *cbdata)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_WEBSOCKET
|
#ifdef USE_WEBSOCKET
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* WEBSOCKET SERVER */
|
/* WEBSOCKET SERVER */
|
||||||
@ -345,8 +338,8 @@ static const char *websocket_goodbye_msg = "websocket bye\n";
|
|||||||
static const size_t websocket_goodbye_msg_len =
|
static const size_t websocket_goodbye_msg_len =
|
||||||
14 /* strlen(websocket_goodbye_msg) */;
|
14 /* strlen(websocket_goodbye_msg) */;
|
||||||
|
|
||||||
|
static int
|
||||||
static int websock_server_connect(const struct mg_connection *conn, void *udata)
|
websock_server_connect(const struct mg_connection *conn, void *udata)
|
||||||
{
|
{
|
||||||
(void)conn;
|
(void)conn;
|
||||||
|
|
||||||
@ -356,8 +349,8 @@ static int websock_server_connect(const struct mg_connection *conn, void *udata)
|
|||||||
return 0; /* return 0 to accept every connection */
|
return 0; /* return 0 to accept every connection */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
static void websock_server_ready(struct mg_connection *conn, void *udata)
|
websock_server_ready(struct mg_connection *conn, void *udata)
|
||||||
{
|
{
|
||||||
ck_assert_ptr_eq((void *)udata, (void *)7531);
|
ck_assert_ptr_eq((void *)udata, (void *)7531);
|
||||||
printf("Server: Websocket ready\n");
|
printf("Server: Websocket ready\n");
|
||||||
@ -373,11 +366,12 @@ static void websock_server_ready(struct mg_connection *conn, void *udata)
|
|||||||
printf("Server: Websocket ready X\n");
|
printf("Server: Websocket ready X\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int websock_server_data(struct mg_connection *conn,
|
static int
|
||||||
int bits,
|
websock_server_data(struct mg_connection *conn,
|
||||||
char *data,
|
int bits,
|
||||||
size_t data_len,
|
char *data,
|
||||||
void *udata)
|
size_t data_len,
|
||||||
|
void *udata)
|
||||||
{
|
{
|
||||||
(void)bits;
|
(void)bits;
|
||||||
|
|
||||||
@ -405,7 +399,8 @@ static int websock_server_data(struct mg_connection *conn,
|
|||||||
return 1; /* return 1 to keep the connetion open */
|
return 1; /* return 1 to keep the connetion open */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void websock_server_close(const struct mg_connection *conn, void *udata)
|
static void
|
||||||
|
websock_server_close(const struct mg_connection *conn, void *udata)
|
||||||
{
|
{
|
||||||
(void)conn;
|
(void)conn;
|
||||||
|
|
||||||
@ -416,7 +411,6 @@ static void websock_server_close(const struct mg_connection *conn, void *udata)
|
|||||||
* closed */
|
* closed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* WEBSOCKET CLIENT */
|
/* WEBSOCKET CLIENT */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@ -426,12 +420,12 @@ struct tclient_data {
|
|||||||
int closed;
|
int closed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
static int websocket_client_data_handler(struct mg_connection *conn,
|
websocket_client_data_handler(struct mg_connection *conn,
|
||||||
int flags,
|
int flags,
|
||||||
char *data,
|
char *data,
|
||||||
size_t data_len,
|
size_t data_len,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
struct tclient_data *pclient_data =
|
struct tclient_data *pclient_data =
|
||||||
@ -454,9 +448,9 @@ static int websocket_client_data_handler(struct mg_connection *conn,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
static void websocket_client_close_handler(const struct mg_connection *conn,
|
websocket_client_close_handler(const struct mg_connection *conn,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct mg_context *ctx = mg_get_context(conn);
|
struct mg_context *ctx = mg_get_context(conn);
|
||||||
struct tclient_data *pclient_data =
|
struct tclient_data *pclient_data =
|
||||||
@ -471,7 +465,6 @@ static void websocket_client_close_handler(const struct mg_connection *conn,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
START_TEST(test_request_handlers)
|
START_TEST(test_request_handlers)
|
||||||
{
|
{
|
||||||
char ebuf[100];
|
char ebuf[100];
|
||||||
@ -526,7 +519,6 @@ START_TEST(test_request_handlers)
|
|||||||
struct mg_connection *ws_client3_conn = NULL;
|
struct mg_connection *ws_client3_conn = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
memset((void *)OPTIONS, 0, sizeof(OPTIONS));
|
memset((void *)OPTIONS, 0, sizeof(OPTIONS));
|
||||||
OPTIONS[opt_idx++] = "listening_ports";
|
OPTIONS[opt_idx++] = "listening_ports";
|
||||||
OPTIONS[opt_idx++] = HTTP_PORT;
|
OPTIONS[opt_idx++] = HTTP_PORT;
|
||||||
@ -572,11 +564,12 @@ START_TEST(test_request_handlers)
|
|||||||
}
|
}
|
||||||
for (i = 5; i < 9; i++) {
|
for (i = 5; i < 9; i++) {
|
||||||
sprintf(uri, "/U%u", i);
|
sprintf(uri, "/U%u", i);
|
||||||
mg_set_request_handler(
|
mg_set_request_handler(ctx,
|
||||||
ctx, uri, request_test_handler, (void *)(ptrdiff_t)i);
|
uri,
|
||||||
|
request_test_handler,
|
||||||
|
(void *)(ptrdiff_t)i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_WEBSOCKET
|
#ifdef USE_WEBSOCKET
|
||||||
mg_set_websocket_handler(ctx,
|
mg_set_websocket_handler(ctx,
|
||||||
"/websocket",
|
"/websocket",
|
||||||
@ -587,7 +580,6 @@ START_TEST(test_request_handlers)
|
|||||||
(void *)7531);
|
(void *)7531);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Try to load non existing file */
|
/* Try to load non existing file */
|
||||||
client_conn = mg_download("localhost",
|
client_conn = mg_download("localhost",
|
||||||
ipv4_port,
|
ipv4_port,
|
||||||
@ -603,7 +595,6 @@ START_TEST(test_request_handlers)
|
|||||||
ck_assert_str_eq(ri->uri, "404");
|
ck_assert_str_eq(ri->uri, "404");
|
||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
|
|
||||||
|
|
||||||
/* Get data from callback */
|
/* Get data from callback */
|
||||||
client_conn = mg_download(
|
client_conn = mg_download(
|
||||||
"localhost", ipv4_port, 0, ebuf, sizeof(ebuf), "%s", request);
|
"localhost", ipv4_port, 0, ebuf, sizeof(ebuf), "%s", request);
|
||||||
@ -618,7 +609,6 @@ START_TEST(test_request_handlers)
|
|||||||
ck_assert_str_eq(buf, expected);
|
ck_assert_str_eq(buf, expected);
|
||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
|
|
||||||
|
|
||||||
/* Get data from callback using http://127.0.0.1 */
|
/* Get data from callback using http://127.0.0.1 */
|
||||||
client_conn = mg_download(
|
client_conn = mg_download(
|
||||||
"127.0.0.1", ipv4_port, 0, ebuf, sizeof(ebuf), "%s", request);
|
"127.0.0.1", ipv4_port, 0, ebuf, sizeof(ebuf), "%s", request);
|
||||||
@ -633,7 +623,6 @@ START_TEST(test_request_handlers)
|
|||||||
ck_assert_str_eq(buf, expected);
|
ck_assert_str_eq(buf, expected);
|
||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
|
|
||||||
|
|
||||||
#if defined(USE_IPV6)
|
#if defined(USE_IPV6)
|
||||||
/* Get data from callback using http://[::1] */
|
/* Get data from callback using http://[::1] */
|
||||||
client_conn =
|
client_conn =
|
||||||
@ -650,7 +639,6 @@ START_TEST(test_request_handlers)
|
|||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if !defined(NO_SSL)
|
#if !defined(NO_SSL)
|
||||||
/* Get data from callback using https://127.0.0.1 */
|
/* Get data from callback using https://127.0.0.1 */
|
||||||
client_conn = mg_download(
|
client_conn = mg_download(
|
||||||
@ -679,7 +667,6 @@ START_TEST(test_request_handlers)
|
|||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(USE_IPV6) && !defined(NO_SSL)
|
#if defined(USE_IPV6) && !defined(NO_SSL)
|
||||||
/* Get data from callback using https://[::1] */
|
/* Get data from callback using https://[::1] */
|
||||||
client_conn =
|
client_conn =
|
||||||
@ -734,7 +721,6 @@ START_TEST(test_request_handlers)
|
|||||||
fwrite(encoded_file_content, 1, 52, f);
|
fwrite(encoded_file_content, 1, 52, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
|
||||||
/* Get static data */
|
/* Get static data */
|
||||||
client_conn = mg_download("localhost",
|
client_conn = mg_download("localhost",
|
||||||
ipv4_port,
|
ipv4_port,
|
||||||
@ -761,7 +747,6 @@ START_TEST(test_request_handlers)
|
|||||||
#endif
|
#endif
|
||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
|
|
||||||
|
|
||||||
/* Get zipped static data - will not work if Accept-Encoding is not set */
|
/* Get zipped static data - will not work if Accept-Encoding is not set */
|
||||||
client_conn = mg_download("localhost",
|
client_conn = mg_download("localhost",
|
||||||
ipv4_port,
|
ipv4_port,
|
||||||
@ -806,7 +791,6 @@ START_TEST(test_request_handlers)
|
|||||||
#endif
|
#endif
|
||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
|
|
||||||
|
|
||||||
/* Get directory listing */
|
/* Get directory listing */
|
||||||
client_conn = mg_download("localhost",
|
client_conn = mg_download("localhost",
|
||||||
ipv4_port,
|
ipv4_port,
|
||||||
@ -830,7 +814,6 @@ START_TEST(test_request_handlers)
|
|||||||
#endif
|
#endif
|
||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
|
|
||||||
|
|
||||||
/* POST to static file (will not work) */
|
/* POST to static file (will not work) */
|
||||||
client_conn = mg_download("localhost",
|
client_conn = mg_download("localhost",
|
||||||
ipv4_port,
|
ipv4_port,
|
||||||
@ -854,7 +837,6 @@ START_TEST(test_request_handlers)
|
|||||||
#endif
|
#endif
|
||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
|
|
||||||
|
|
||||||
/* PUT to static file (will not work) */
|
/* PUT to static file (will not work) */
|
||||||
client_conn = mg_download("localhost",
|
client_conn = mg_download("localhost",
|
||||||
ipv4_port,
|
ipv4_port,
|
||||||
@ -874,7 +856,6 @@ START_TEST(test_request_handlers)
|
|||||||
#endif
|
#endif
|
||||||
mg_close_connection(client_conn);
|
mg_close_connection(client_conn);
|
||||||
|
|
||||||
|
|
||||||
/* Websocket test */
|
/* Websocket test */
|
||||||
#ifdef USE_WEBSOCKET
|
#ifdef USE_WEBSOCKET
|
||||||
/* Then connect a first client */
|
/* Then connect a first client */
|
||||||
@ -1097,8 +1078,8 @@ START_TEST(test_request_handlers)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
Suite *
|
||||||
Suite *make_public_server_suite(void)
|
make_public_server_suite(void)
|
||||||
{
|
{
|
||||||
Suite *const suite = suite_create("PublicServer");
|
Suite *const suite = suite_create("PublicServer");
|
||||||
|
|
||||||
@ -1108,7 +1089,6 @@ Suite *make_public_server_suite(void)
|
|||||||
TCase *const startstophttps = tcase_create("Start Stop HTTPS Server");
|
TCase *const startstophttps = tcase_create("Start Stop HTTPS Server");
|
||||||
TCase *const serverrequests = tcase_create("Server Requests");
|
TCase *const serverrequests = tcase_create("Server Requests");
|
||||||
|
|
||||||
|
|
||||||
tcase_add_test(checktestenv, test_the_test_environment);
|
tcase_add_test(checktestenv, test_the_test_environment);
|
||||||
tcase_set_timeout(checktestenv, civetweb_min_test_timeout);
|
tcase_set_timeout(checktestenv, civetweb_min_test_timeout);
|
||||||
suite_add_tcase(suite, checktestenv);
|
suite_add_tcase(suite, checktestenv);
|
||||||
@ -1132,14 +1112,14 @@ Suite *make_public_server_suite(void)
|
|||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef REPLACE_CHECK_FOR_LOCAL_DEBUGGING
|
#ifdef REPLACE_CHECK_FOR_LOCAL_DEBUGGING
|
||||||
/* Used to debug test cases without using the check framework */
|
/* Used to debug test cases without using the check framework */
|
||||||
|
|
||||||
static int chk_ok = 0;
|
static int chk_ok = 0;
|
||||||
static int chk_failed = 0;
|
static int chk_failed = 0;
|
||||||
|
|
||||||
void main(void)
|
void
|
||||||
|
main(void)
|
||||||
{
|
{
|
||||||
test_the_test_environment(0);
|
test_the_test_environment(0);
|
||||||
test_threading(0);
|
test_threading(0);
|
||||||
@ -1150,7 +1130,8 @@ void main(void)
|
|||||||
printf("\nok: %i\nfailed: %i\n\n", chk_ok, chk_failed);
|
printf("\nok: %i\nfailed: %i\n\n", chk_ok, chk_failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ck_assert_failed(const char *file, int line, const char *expr, ...)
|
void
|
||||||
|
_ck_assert_failed(const char *file, int line, const char *expr, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, expr);
|
va_start(va, expr);
|
||||||
@ -1161,7 +1142,8 @@ void _ck_assert_failed(const char *file, int line, const char *expr, ...)
|
|||||||
chk_failed++;
|
chk_failed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ck_assert_msg(int cond, const char *file, int line, const char *expr, ...)
|
void
|
||||||
|
_ck_assert_msg(int cond, const char *file, int line, const char *expr, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
|
|
||||||
@ -1178,12 +1160,14 @@ void _ck_assert_msg(int cond, const char *file, int line, const char *expr, ...)
|
|||||||
chk_failed++;
|
chk_failed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _mark_point(const char *file, int line)
|
void
|
||||||
|
_mark_point(const char *file, int line)
|
||||||
{
|
{
|
||||||
chk_ok++;
|
chk_ok++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcase_fn_start(const char *fname, const char *file, int line)
|
void
|
||||||
|
tcase_fn_start(const char *fname, const char *file, int line)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void suite_add_tcase(Suite *s, TCase *tc){};
|
void suite_add_tcase(Suite *s, TCase *tc){};
|
||||||
@ -1194,11 +1178,13 @@ void _tcase_add_test(TCase *tc,
|
|||||||
int allowed_exit_value,
|
int allowed_exit_value,
|
||||||
int start,
|
int start,
|
||||||
int end){};
|
int end){};
|
||||||
TCase *tcase_create(const char *name)
|
TCase *
|
||||||
|
tcase_create(const char *name)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
Suite *suite_create(const char *name)
|
Suite *
|
||||||
|
suite_create(const char *name)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if !defined(_CRT_SECURE_NO_WARNINGS)
|
#if !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
@ -27,18 +26,19 @@
|
|||||||
#define _CRT_SECURE_NO_DEPRECATE
|
#define _CRT_SECURE_NO_DEPRECATE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "shared.h"
|
#include "shared.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static char s_test_directory[1024] = {'\0'};
|
static char s_test_directory[1024] = {'\0'};
|
||||||
|
|
||||||
const char *get_test_directory(void)
|
const char *
|
||||||
|
get_test_directory(void)
|
||||||
{
|
{
|
||||||
return s_test_directory;
|
return s_test_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_test_directory(const char *const path)
|
void
|
||||||
|
set_test_directory(const char *const path)
|
||||||
{
|
{
|
||||||
strncpy(s_test_directory,
|
strncpy(s_test_directory,
|
||||||
path,
|
path,
|
||||||
|
@ -21,9 +21,7 @@
|
|||||||
#ifndef TEST_SHARED_H_
|
#ifndef TEST_SHARED_H_
|
||||||
#define TEST_SHARED_H_
|
#define TEST_SHARED_H_
|
||||||
|
|
||||||
|
|
||||||
const char *get_test_directory(void);
|
const char *get_test_directory(void);
|
||||||
void set_test_directory(const char *const path);
|
void set_test_directory(const char *const path);
|
||||||
|
|
||||||
|
|
||||||
#endif /* TEST_SHARED_H_ */
|
#endif /* TEST_SHARED_H_ */
|
||||||
|
Reference in New Issue
Block a user