http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/upload/upload.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/upload/upload.c b/thirdparty/civetweb-1.9.1/examples/_obsolete/upload/upload.c new file mode 100644 index 0000000..56c4be4 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/upload/upload.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2014 the Civetweb developers + * Copyright (c) 2004-2012 Sergey Lyubka + * This file is a part of civetweb project, http://github.com/bel2125/civetweb + */ + +/* This example is deprecated and no longer maintained. + * All relevant parts have been merged into the embedded_c example. */ + + +#ifdef _WIN32 +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif +#include <windows.h> +#include <io.h> +#define strtoll strtol +typedef __int64 int64_t; +#else +#include <inttypes.h> +#include <unistd.h> +#endif /* !_WIN32 */ + +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <stdlib.h> + +#include "civetweb.h" + + +/* callback: used to generate all content */ +static int begin_request_handler(struct mg_connection *conn) +{ + const char * tempPath = "."; +#ifdef _WIN32 + const char * env = getenv("TEMP"); + if (!env) env = getenv("TMP"); + if (env) tempPath = env; +#else + tempPath = "/tmp"; +#endif + + if (!strcmp(mg_get_request_info(conn)->uri, "/handle_post_request")) { + + mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n\r\n"); + mg_upload(conn, tempPath); + } else { + /* Show HTML form. */ + /* See http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 */ + static const char *html_form = + "<html><body>Upload example." + "" + /* enctype="multipart/form-data" */ + "<form method=\"POST\" action=\"/handle_post_request\" " + " enctype=\"multipart/form-data\">" + "<input type=\"file\" name=\"file\" /> <br/>" + "<input type=\"file\" name=\"file2\" /> <br/>" + "<input type=\"submit\" value=\"Upload\" />" + "</form>" + "" + "</body></html>"; + + mg_printf(conn, "HTTP/1.0 200 OK\r\n" + "Content-Length: %d\r\n" + "Content-Type: text/html\r\n\r\n%s", + (int) strlen(html_form), html_form); + } + + /* Mark request as processed */ + return 1; +} + + +/* callback: called after uploading a file is completed */ +static void upload_handler(struct mg_connection *conn, const char *path) +{ + mg_printf(conn, "Saved [%s]", path); +} + + +/* Main program: Set callbacks and start the server. */ +int main(void) +{ + /* Test server will use this port */ + const char * PORT = "8080"; + + /* Startup options for the server */ + struct mg_context *ctx; + const char *options[] = { + "listening_ports", PORT, + NULL}; + struct mg_callbacks callbacks; + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.begin_request = begin_request_handler; + callbacks.upload = upload_handler; + + /* Display a welcome message */ + printf("File upload demo.\n"); + printf("Open http://localhost:%s/ in your browser.\n\n", PORT); + + /* Start the server */ + ctx = mg_start(&callbacks, NULL, options); + + /* Wait until thr user hits "enter", then stop the server */ + getchar(); + mg_stop(ctx); + + return 0; +}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/WebSockCallbacks.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/WebSockCallbacks.c b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/WebSockCallbacks.c new file mode 100644 index 0000000..bb81fb0 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/WebSockCallbacks.c @@ -0,0 +1,225 @@ +/* This example uses deprecated interfaces: global websocket callbacks. + They have been superseeded by URI specific callbacks. + See examples/embedded_c for an up to date example. + */ + +#include <assert.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include "WebSockCallbacks.h" + +#ifdef _WIN32 +#include <windows.h> +#define mg_sleep(x) Sleep(x) +#else +#include <unistd.h> +#include <pthread.h> +#define mg_sleep(x) usleep((x)*1000) +#endif + + +static void +send_to_all_websockets(struct mg_context *ctx, const char *data, int data_len) +{ + + int i; + tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx); + + mg_lock_context(ctx); + for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) { + if (ws_ctx->socketList[i] + && (ws_ctx->socketList[i]->webSockState == 2)) { + mg_websocket_write(ws_ctx->socketList[i]->conn, + WEBSOCKET_OPCODE_TEXT, + data, + data_len); + } + } + mg_unlock_context(ctx); +} + + +void +websocket_ready_handler(struct mg_connection *conn, void *_ignored) +{ + + int i; + const struct mg_request_info *rq = mg_get_request_info(conn); + struct mg_context *ctx = mg_get_context(conn); + tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx); + tWebSockInfo *wsock = malloc(sizeof(tWebSockInfo)); + assert(wsock); + wsock->webSockState = 0; + mg_set_user_connection_data(conn, wsock); + + mg_lock_context(ctx); + for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) { + if (0 == ws_ctx->socketList[i]) { + ws_ctx->socketList[i] = wsock; + wsock->conn = conn; + wsock->webSockState = 1; + break; + } + } + printf("\nNew websocket attached: %s:%u\n", + rq->remote_addr, + rq->remote_port); + mg_unlock_context(ctx); +} + + +static void +websocket_done(tWebSockContext *ws_ctx, tWebSockInfo *wsock) +{ + + int i; + + if (wsock) { + wsock->webSockState = 99; + for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) { + if (wsock == ws_ctx->socketList[i]) { + ws_ctx->socketList[i] = 0; + break; + } + } + printf("\nClose websocket attached: %s:%u\n", + 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) +{ + + const struct mg_request_info *rq = mg_get_request_info(conn); + tWebSockInfo *wsock = (tWebSockInfo *)rq->conn_data; + struct mg_context *ctx = mg_get_context(conn); + tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx); + char msg[128]; + + mg_lock_context(ctx); + if (flags == 136) { + // close websock + websocket_done(ws_ctx, wsock); + mg_set_user_connection_data(conn, NULL); + mg_unlock_context(ctx); + return 1; + } + if (((data_len >= 5) && (data_len < 100) && (flags == 129)) + || (flags == 130)) { + + // init command + if ((wsock->webSockState == 1) && (!memcmp(data, "init ", 5))) { + char *chk; + unsigned long gid; + memcpy(msg, data + 5, data_len - 5); + msg[data_len - 5] = 0; + gid = strtoul(msg, &chk, 10); + wsock->initId = gid; + if (gid > 0 && chk != NULL && *chk == 0) { + wsock->webSockState = 2; + } + mg_unlock_context(ctx); + return 1; + } + + // chat message + if ((wsock->webSockState == 2) && (!memcmp(data, "msg ", 4))) { + send_to_all_websockets(ctx, data, data_len); + mg_unlock_context(ctx); + return 1; + } + } + + // keep alive + if ((data_len == 4) && !memcmp(data, "ping", 4)) { + mg_unlock_context(ctx); + return 1; + } + + mg_unlock_context(ctx); + return 0; +} + + +void +connection_close_handler(const struct mg_connection *conn, void *_ignored) +{ + + const struct mg_request_info *rq = mg_get_request_info(conn); + tWebSockInfo *wsock = (tWebSockInfo *)rq->conn_data; + struct mg_context *ctx = mg_get_context(conn); + tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx); + + mg_lock_context(ctx); + websocket_done(ws_ctx, wsock); + mg_set_user_connection_data(conn, NULL); + mg_unlock_context(ctx); +} + + +static void * +eventMain(void *arg) +{ + + char msg[256]; + struct mg_context *ctx = (struct mg_context *)arg; + tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx); + + ws_ctx->runLoop = 1; + while (ws_ctx->runLoop) { + time_t t = time(0); + struct tm *timestr = localtime(&t); + strftime(msg, sizeof(msg), "title %c", timestr); + send_to_all_websockets(ctx, msg, strlen(msg)); + + mg_sleep(1000); + } + + return NULL; +} + + +void +websock_send_broadcast(struct mg_context *ctx, const char *data, int data_len) +{ + + char buffer[260]; + + if (data_len <= 256) { + strcpy(buffer, "msg "); + memcpy(buffer + 4, data, data_len); + + send_to_all_websockets(ctx, buffer, data_len + 4); + } +} + + +void +websock_init_lib(const struct mg_context *ctx) +{ + + tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx); + memset(ws_ctx, 0, sizeof(*ws_ctx)); + /* todo: use mg_start_thread_id instead of mg_start_thread */ + mg_start_thread(eventMain, (void *)ctx); +} + + +void +websock_exit_lib(const struct mg_context *ctx) +{ + + tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx); + ws_ctx->runLoop = 0; + /* todo: wait for the thread instead of a timeout */ + mg_sleep(2000); +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/WebSockCallbacks.h ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/WebSockCallbacks.h b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/WebSockCallbacks.h new file mode 100644 index 0000000..f44821d --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/WebSockCallbacks.h @@ -0,0 +1,44 @@ + +#ifndef WEBSOCKCALLBACKS_H_INCLUDED +#define WEBSOCKCALLBACKS_H_INCLUDED + +#include "civetweb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct tWebSockInfo { + int webSockState; + unsigned long initId; + struct mg_connection *conn; +} tWebSockInfo; + +#define MAX_NUM_OF_WEBSOCKS (256) +typedef struct tWebSockContext { + int runLoop; + void *thread_id; + tWebSockInfo *socketList[MAX_NUM_OF_WEBSOCKS]; +} tWebSockContext; + + +void websock_init_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 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); +void connection_close_handler(const struct mg_connection *conn, void *_ignored); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/websock.htm ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/websock.htm b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/websock.htm new file mode 100644 index 0000000..4ff3a5f --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/websock.htm @@ -0,0 +1,55 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> + <title>Test</title> + <script type='text/javascript' language="javascript"> + <!-- + var connection; + var keepAlive = false; + + function webSockKeepAlive() { + if (keepAlive) { + connection.send('ping'); // Send the message 'ping' to the server + setTimeout("webSockKeepAlive()", 10000); + } + } + + function load() { + connection = new WebSocket("ws://127.0.0.1/MyWebSock"); + + connection.onopen = function () { + var send = "init " + Math.round(Math.random()*4294967294+1); + console.log('Client: ' + send); + connection.send(send); + keepAlive = true; + webSockKeepAlive(); + }; + + connection.onerror = function (error) { + keepAlive = false; + connection.close(); + console.log('WebSocket error: ' + error); + alert("WebSocket error"); + }; + + connection.onmessage = function (e) { + console.log('Server: ' + e.data); + if (e.data.substring(0,5) == "title") {window.document.title = e.data.substring(6);} + else if (e.data.substring(0,3) == "msg") { + var msgStr = document.getElementById('msg'); + msgStr.innerHTML = msgStr.innerHTML + e.data.substring(4); + } + }; + } + //--> + </script> + +</head> +<body onload="load()"> + <input type="button" onclick="connection.send('msg A');" value="A"></button> + <input type="button" onclick="connection.send('msg B');" value="B"></button> + <input type="button" onclick="connection.send('msg C');" value="C"></button> + <input type="button" onclick="connection.send('msg D');" value="D"></button> + <b id="msg"></b> +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/websocket.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/websocket.c b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/websocket.c new file mode 100644 index 0000000..3aadf98 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket/websocket.c @@ -0,0 +1,65 @@ +/* This example uses deprecated interfaces: global websocket callbacks. + They have been superseeded by URI specific callbacks. + See examples/embedded_c for an up to date example. + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#include "civetweb.h" +#include "WebSockCallbacks.h" + +int +main(void) +{ + struct mg_context *ctx = 0; + struct mg_callbacks callback_funcs = {0}; + tWebSockContext ws_ctx; + char inbuf[4]; + + const char *server_options[] = { + /* document_root: The path to the test function websock.htm */ + "document_root", + "../../examples/websocket", + + /* port: use http standard to match websocket url in websock.htm: + ws://127.0.0.1/MyWebSock */ + /* if the port is changed here, it needs to be changed in + websock.htm as well */ + "listening_ports", + "80", + + NULL}; + + callback_funcs.init_context = websock_init_lib; + callback_funcs.exit_context = websock_exit_lib; + + ctx = mg_start(&callback_funcs, &ws_ctx, server_options); + + mg_set_websocket_handler(ctx, + "/MyWebSock", + NULL, + websocket_ready_handler, + websocket_data_handler, + connection_close_handler, + NULL); + + printf("Connect to localhost:%s/websock.htm\n", + mg_get_option(ctx, "listening_ports")); + + puts("Enter an (ASCII) character or * to exit:"); + for (;;) { + fgets(inbuf, sizeof(inbuf), stdin); + + if (inbuf[0] == '*') { + break; + } + inbuf[0] = toupper(inbuf[0]); + websock_send_broadcast(ctx, inbuf, 1); + } + + mg_stop(ctx); + + return 0; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.crt ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.crt b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.crt new file mode 100644 index 0000000..a26359a --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQC2BCIqIvgSUTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE0MDgyMTEyMzAwMVoXDTI0MDgxODEyMzAwMVowRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA9k9s +gH22BCo9neTeB/YnilK7n0sMe0+pjS9KSWhU59Q4w8hqPrW0tuYikIDd0wVggkJF +BZNg4WPoulTdwXsgNBeG88q2wnNtUosXTS+KQTQBSiQof9Ay9GHQtgxnogI1zIXb +HOppyyG5zre8a/X6fzDOnFc4iJMBwxTAnjCqObkCAwEAATANBgkqhkiG9w0BAQUF +AAOBgQBX9V46VUVsB9P9fb8sFuMx2ezFE42ynEeJPrKRrof+dFYbjvR1OUZFSLCy +aZKwVH7iCnVBJiU12JxO7PR3L6ob3FYPyNHQWYq1/IFUvqBRagehldj5H8iFeEDz +Wtz2+p1rUyVxcSUqTjobaji0aC8lzPZio0nd1KKM6A92/adHyQ== +-----END CERTIFICATE----- http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.csr ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.csr b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.csr new file mode 100644 index 0000000..4d4723b --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.csr @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBhDCB7gIBADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEh +MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQD2T2yAfbYEKj2d5N4H9ieKUrufSwx7T6mNL0pJaFTn1DjD +yGo+tbS25iKQgN3TBWCCQkUFk2DhY+i6VN3BeyA0F4bzyrbCc21SixdNL4pBNAFK +JCh/0DL0YdC2DGeiAjXMhdsc6mnLIbnOt7xr9fp/MM6cVziIkwHDFMCeMKo5uQID +AQABoAAwDQYJKoZIhvcNAQEFBQADgYEA1EOFwyFJ2NAnRNktZCy5yVcLx9C78HoC +oHPPCOElu0VDIqe6ZecYdaqWbYlhGE0+isbOQn2CwHOeBGN8mIDsNUYzVEpsEfgg +9OK873LpE5pf4mdjSiRBXkk/h8BxuqkcKi+Qx+qEE7+dH2nK5aKeIHVvbLyfGOch +9I85q+msBNE= +-----END CERTIFICATE REQUEST----- http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.key ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.key b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.key new file mode 100644 index 0000000..f09cc38 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQD2T2yAfbYEKj2d5N4H9ieKUrufSwx7T6mNL0pJaFTn1DjDyGo+ +tbS25iKQgN3TBWCCQkUFk2DhY+i6VN3BeyA0F4bzyrbCc21SixdNL4pBNAFKJCh/ +0DL0YdC2DGeiAjXMhdsc6mnLIbnOt7xr9fp/MM6cVziIkwHDFMCeMKo5uQIDAQAB +AoGAYwospr3lomcZv5N3c9wWqhf6OWMD8dFma87IIBxDh7Rd3tuHXQ/TSnffDhvD +FkbjN31OI5/PJNH3knTtdg78MywPloE4jYsbt4+fEaW7Fzww2nU61N1p+mYk5d/b +SCTAHhGzF9g9ZMw25CCUFGjDU2z+Ty6my22Euxhk2Qq8tMECQQD9ZYIxWkPhywDW +pX3v70dqIv7411hEYpuL/ZJl26UCmQsj4HPtXQCraQksVPs74WY5aTtd6MAV9V3M +UnErHO5/AkEA+NdG2MmfBOBPusDB/WwQaUPiCWGITS9llGTR2JXbvDqmKgL1+UTG +o27sLNIFCrF1wejpyRGqwjcObFYR0yKrxwJBAOB2uPuK4DL1psp9Uq/mIDbOxVod +OF1rlCpP9w0vol5Iv+uJ+mc7SUqOAsg4h0yl/+2/YA1yDiXlcq96IDF2sXUCQGAv +Nh9Nr72+xpK1N0axopZNuu1NWdYb3/PAFKzXIBxdvyS2CEXVo8JAeeHJPFGpzo6p +bNRfk9WGWnjdu/4UhLkCQQCekR9zpIpzdJiPYCd6XMya+TPCDYlOQL1jlnJIRa2V +BEOz0rSpzXAGh0PyCB/kMneyVk87LWn8joE6179RoUfv +-----END RSA PRIVATE KEY----- http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.pem ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.pem b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.pem new file mode 100644 index 0000000..300834e --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/ssl/server.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIICATCCAWoCCQC2BCIqIvgSUTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE0MDgyMTEyMzAwMVoXDTI0MDgxODEyMzAwMVowRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA9k9s +gH22BCo9neTeB/YnilK7n0sMe0+pjS9KSWhU59Q4w8hqPrW0tuYikIDd0wVggkJF +BZNg4WPoulTdwXsgNBeG88q2wnNtUosXTS+KQTQBSiQof9Ay9GHQtgxnogI1zIXb +HOppyyG5zre8a/X6fzDOnFc4iJMBwxTAnjCqObkCAwEAATANBgkqhkiG9w0BAQUF +AAOBgQBX9V46VUVsB9P9fb8sFuMx2ezFE42ynEeJPrKRrof+dFYbjvR1OUZFSLCy +aZKwVH7iCnVBJiU12JxO7PR3L6ob3FYPyNHQWYq1/IFUvqBRagehldj5H8iFeEDz +Wtz2+p1rUyVxcSUqTjobaji0aC8lzPZio0nd1KKM6A92/adHyQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQD2T2yAfbYEKj2d5N4H9ieKUrufSwx7T6mNL0pJaFTn1DjDyGo+ +tbS25iKQgN3TBWCCQkUFk2DhY+i6VN3BeyA0F4bzyrbCc21SixdNL4pBNAFKJCh/ +0DL0YdC2DGeiAjXMhdsc6mnLIbnOt7xr9fp/MM6cVziIkwHDFMCeMKo5uQIDAQAB +AoGAYwospr3lomcZv5N3c9wWqhf6OWMD8dFma87IIBxDh7Rd3tuHXQ/TSnffDhvD +FkbjN31OI5/PJNH3knTtdg78MywPloE4jYsbt4+fEaW7Fzww2nU61N1p+mYk5d/b +SCTAHhGzF9g9ZMw25CCUFGjDU2z+Ty6my22Euxhk2Qq8tMECQQD9ZYIxWkPhywDW +pX3v70dqIv7411hEYpuL/ZJl26UCmQsj4HPtXQCraQksVPs74WY5aTtd6MAV9V3M +UnErHO5/AkEA+NdG2MmfBOBPusDB/WwQaUPiCWGITS9llGTR2JXbvDqmKgL1+UTG +o27sLNIFCrF1wejpyRGqwjcObFYR0yKrxwJBAOB2uPuK4DL1psp9Uq/mIDbOxVod +OF1rlCpP9w0vol5Iv+uJ+mc7SUqOAsg4h0yl/+2/YA1yDiXlcq96IDF2sXUCQGAv +Nh9Nr72+xpK1N0axopZNuu1NWdYb3/PAFKzXIBxdvyS2CEXVo8JAeeHJPFGpzo6p +bNRfk9WGWnjdu/4UhLkCQQCekR9zpIpzdJiPYCd6XMya+TPCDYlOQL1jlnJIRa2V +BEOz0rSpzXAGh0PyCB/kMneyVk87LWn8joE6179RoUfv +-----END RSA PRIVATE KEY----- http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/websocket_client.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/websocket_client.c b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/websocket_client.c new file mode 100644 index 0000000..158ad7d --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/websocket_client/websocket_client.c @@ -0,0 +1,421 @@ +/* +* Copyright (c) 2014-2016 the Civetweb developers +* Copyright (c) 2014 Jordan Shelley +* https://github.com/jshelley +* License http://opensource.org/licenses/mit-license.php MIT License +*/ + +/* This example is superseeded by other examples, and no longer + * actively maintained. + * See examples/embedded_c for an up to date example. + */ + +// Simple example program on how to use websocket client embedded C interface. +#ifdef _WIN32 +#include <windows.h> +#define sleep(x) Sleep(1000 * (x)) +#else +#include <unistd.h> +#endif + +#include <assert.h> +#include <string.h> +#include "civetweb.h" + +#define DOCUMENT_ROOT "." +#define PORT "8888" +#define SSL_CERT "./ssl/server.pem" + +const char *websocket_welcome_msg = "websocket welcome\n"; +const size_t websocket_welcome_msg_len = 18 /* strlen(websocket_welcome_msg) */; +const char *websocket_acknowledge_msg = "websocket msg ok\n"; +const size_t websocket_acknowledge_msg_len = + 17 /* strlen(websocket_acknowledge_msg) */; +const char *websocket_goodbye_msg = "websocket bye\n"; +const size_t websocket_goodbye_msg_len = 14 /* strlen(websocket_goodbye_msg) */; + + +/*************************************************************************************/ +/* WEBSOCKET SERVER */ +/*************************************************************************************/ +#if defined(MG_LEGACY_INTERFACE) +int +websock_server_connect(const struct mg_connection *conn) +#else +int +websocket_server_connect(const struct mg_connection *conn, void *_ignored) +#endif +{ + printf("Server: Websocket connected\n"); + return 0; /* return 0 to accept every connection */ +} + + +#if defined(MG_LEGACY_INTERFACE) +void +websocket_server_ready(struct mg_connection *conn) +#else +void +websocket_server_ready(struct mg_connection *conn, void *_ignored) +#endif +{ + printf("Server: Websocket ready\n"); + + /* Send websocket welcome message */ + mg_lock_connection(conn); + mg_websocket_write(conn, + WEBSOCKET_OPCODE_TEXT, + websocket_welcome_msg, + websocket_welcome_msg_len); + mg_unlock_connection(conn); +} + + +#if defined(MG_LEGACY_INTERFACE) +int +websocket_server_data(struct mg_connection *conn, + int bits, + char *data, + size_t data_len) +#else +int +websocket_server_data(struct mg_connection *conn, + int bits, + char *data, + size_t data_len, + void *_ignored) +#endif +{ + printf("Server: Got %lu bytes from the client\n", (unsigned long)data_len); + printf("Server received data from client: "); + fwrite(data, 1, data_len, stdout); + printf("\n"); + + if (data_len < 3 || 0 != memcmp(data, "bye", 3)) { + /* Send websocket acknowledge message */ + mg_lock_connection(conn); + mg_websocket_write(conn, + WEBSOCKET_OPCODE_TEXT, + websocket_acknowledge_msg, + websocket_acknowledge_msg_len); + mg_unlock_connection(conn); + } else { + /* 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 */ +} + + +#if defined(MG_LEGACY_INTERFACE) +void +websocket_server_connection_close(const struct mg_connection *conn) +#else +void +websocket_server_connection_close(const struct mg_connection *conn, + void *_ignored) +#endif +{ + printf("Server: Close connection\n"); + + /* Can not send a websocket goodbye message here - the connection is already + * closed */ +} + + +struct mg_context * +start_websocket_server() +{ + const char *options[] = {"document_root", + DOCUMENT_ROOT, + "ssl_certificate", + SSL_CERT, + "listening_ports", + PORT, + "request_timeout_ms", + "5000", + 0}; + struct mg_callbacks callbacks; + struct mg_context *ctx; + + memset(&callbacks, 0, sizeof(callbacks)); + +#if defined(MG_LEGACY_INTERFACE) + /* Obsolete: */ + callbacks.websocket_connect = websock_server_connect; + callbacks.websocket_ready = websocket_server_ready; + callbacks.websocket_data = websocket_server_data; + callbacks.connection_close = websocket_server_connection_close; + + ctx = mg_start(&callbacks, 0, options); +#else + /* New interface: */ + ctx = mg_start(&callbacks, 0, options); + + mg_set_websocket_handler(ctx, + "/websocket", + websocket_server_connect, + websocket_server_ready, + websocket_server_data, + websocket_server_connection_close, + NULL); +#endif + + return ctx; +} + + +/*************************************************************************************/ +/* WEBSOCKET CLIENT */ +/*************************************************************************************/ +struct tclient_data { + void *data; + size_t len; + int closed; +}; + +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 tclient_data *pclient_data = + (struct tclient_data *)mg_get_user_data(ctx); + + printf("Client received data from server: "); + fwrite(data, 1, data_len, stdout); + printf("\n"); + + pclient_data->data = malloc(data_len); + assert(pclient_data->data != NULL); + memcpy(pclient_data->data, data, data_len); + pclient_data->len = data_len; + + return 1; +} + +static void +websocket_client_close_handler(const struct mg_connection *conn, + void *user_data) +{ + struct mg_context *ctx = mg_get_context(conn); + struct tclient_data *pclient_data = + (struct tclient_data *)mg_get_user_data(ctx); + + printf("Client: Close handler\n"); + pclient_data->closed++; +} + + +int +main(int argc, char *argv[]) +{ + struct mg_context *ctx = NULL; + struct tclient_data client1_data = {NULL, 0, 0}; + struct tclient_data client2_data = {NULL, 0, 0}; + struct tclient_data client3_data = {NULL, 0, 0}; + struct mg_connection *newconn1 = NULL; + struct mg_connection *newconn2 = NULL; + struct mg_connection *newconn3 = NULL; + char ebuf[100] = {0}; + + assert(websocket_welcome_msg_len == strlen(websocket_welcome_msg)); + + /* First set up a websocket server */ + ctx = start_websocket_server(); + assert(ctx != NULL); + printf("Server init\n\n"); + + /* Then connect a first client */ + newconn1 = mg_connect_websocket_client("localhost", + atoi(PORT), + 0, + ebuf, + sizeof(ebuf), + "/websocket", + NULL, + websocket_client_data_handler, + websocket_client_close_handler, + &client1_data); + + if (newconn1 == NULL) { + printf("Error: %s", ebuf); + return 1; + } + + sleep(1); /* Should get the websocket welcome message */ + assert(client1_data.closed == 0); + assert(client2_data.closed == 0); + assert(client2_data.data == NULL); + assert(client2_data.len == 0); + assert(client1_data.data != NULL); + assert(client1_data.len == websocket_welcome_msg_len); + assert(!memcmp(client1_data.data, + websocket_welcome_msg, + websocket_welcome_msg_len)); + free(client1_data.data); + client1_data.data = NULL; + client1_data.len = 0; + + mg_websocket_client_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data1", 5); + + sleep(1); /* Should get the acknowledge message */ + assert(client1_data.closed == 0); + assert(client2_data.closed == 0); + assert(client2_data.data == NULL); + assert(client2_data.len == 0); + assert(client1_data.data != NULL); + assert(client1_data.len == websocket_acknowledge_msg_len); + assert(!memcmp(client1_data.data, + websocket_acknowledge_msg, + websocket_acknowledge_msg_len)); + free(client1_data.data); + client1_data.data = NULL; + client1_data.len = 0; + + /* Now connect a second client */ + newconn2 = mg_connect_websocket_client("localhost", + atoi(PORT), + 0, + ebuf, + sizeof(ebuf), + "/websocket", + NULL, + websocket_client_data_handler, + websocket_client_close_handler, + &client2_data); + + if (newconn2 == NULL) { + printf("Error: %s", ebuf); + return 1; + } + + sleep(1); /* Client 2 should get the websocket welcome message */ + assert(client1_data.closed == 0); + assert(client2_data.closed == 0); + assert(client1_data.data == NULL); + assert(client1_data.len == 0); + assert(client2_data.data != NULL); + assert(client2_data.len == websocket_welcome_msg_len); + assert(!memcmp(client2_data.data, + websocket_welcome_msg, + websocket_welcome_msg_len)); + free(client2_data.data); + client2_data.data = NULL; + client2_data.len = 0; + + mg_websocket_client_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data2", 5); + + sleep(1); /* Should get the acknowledge message */ + assert(client1_data.closed == 0); + assert(client2_data.closed == 0); + assert(client2_data.data == NULL); + assert(client2_data.len == 0); + assert(client1_data.data != NULL); + assert(client1_data.len == websocket_acknowledge_msg_len); + assert(!memcmp(client1_data.data, + websocket_acknowledge_msg, + websocket_acknowledge_msg_len)); + free(client1_data.data); + client1_data.data = NULL; + client1_data.len = 0; + + mg_websocket_client_write(newconn1, WEBSOCKET_OPCODE_TEXT, "bye", 3); + + sleep(1); /* Should get the goodbye message */ + assert(client1_data.closed == 0); + assert(client2_data.closed == 0); + assert(client2_data.data == NULL); + assert(client2_data.len == 0); + assert(client1_data.data != NULL); + assert(client1_data.len == websocket_goodbye_msg_len); + assert(!memcmp(client1_data.data, + websocket_goodbye_msg, + websocket_goodbye_msg_len)); + free(client1_data.data); + client1_data.data = NULL; + client1_data.len = 0; + + mg_close_connection(newconn1); + + sleep(1); /* Won't get any message */ + assert(client1_data.closed == 1); + assert(client2_data.closed == 0); + assert(client1_data.data == NULL); + assert(client1_data.len == 0); + assert(client2_data.data == NULL); + assert(client2_data.len == 0); + + mg_websocket_client_write(newconn2, WEBSOCKET_OPCODE_TEXT, "bye", 3); + + sleep(1); /* Should get the goodbye message */ + assert(client1_data.closed == 1); + assert(client2_data.closed == 0); + assert(client1_data.data == NULL); + assert(client1_data.len == 0); + assert(client2_data.data != NULL); + assert(client2_data.len == websocket_goodbye_msg_len); + assert(!memcmp(client2_data.data, + websocket_goodbye_msg, + websocket_goodbye_msg_len)); + free(client2_data.data); + client2_data.data = NULL; + client2_data.len = 0; + + mg_close_connection(newconn2); + + sleep(1); /* Won't get any message */ + assert(client1_data.closed == 1); + assert(client2_data.closed == 1); + assert(client1_data.data == NULL); + assert(client1_data.len == 0); + assert(client2_data.data == NULL); + assert(client2_data.len == 0); + + /* Connect client 3 */ + newconn3 = mg_connect_websocket_client("localhost", + atoi(PORT), + 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 */ + assert(client1_data.closed == 1); + assert(client2_data.closed == 1); + assert(client3_data.closed == 0); + assert(client1_data.data == NULL); + assert(client1_data.len == 0); + assert(client2_data.data == NULL); + assert(client2_data.len == 0); + assert(client3_data.data != NULL); + assert(client3_data.len == websocket_welcome_msg_len); + assert(!memcmp(client3_data.data, + websocket_welcome_msg, + websocket_welcome_msg_len)); + free(client3_data.data); + client3_data.data = NULL; + client3_data.len = 0; + + mg_stop(ctx); + printf("Server shutdown\n"); + + sleep(10); + + assert(client3_data.closed == 1); + + return 0; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/ws_server/docroot/index.html ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/ws_server/docroot/index.html b/thirdparty/civetweb-1.9.1/examples/_obsolete/ws_server/docroot/index.html new file mode 100644 index 0000000..f1d1af3 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/ws_server/docroot/index.html @@ -0,0 +1,316 @@ +<!DOCTYPE html> +<html> + +<head> + <meta charset='UTF-8'> + + <title>Websocket Meters</title> + <!-- + Version 0.1 Contributed by William Greathouse 9-Sep-2013 + Simple demo of WebSocket connection use. Not a great example of web coding, + but it is functional. + + The meter displays are adapted from CSS-TRICKS Progress Bars by Chris Coyier + at http://css-tricks.com/css3-progress-bars/ + --> + <style> + body { + background: #222; + } + h1 { + color: white; + text-align: center; + } + button { + width: 225px; + height: 30px; + margin: auto 10px; + background-color: #ccc; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius:6px; + color: blue; + font-size: 20px; + } + button:hover { + background-color: #888; + } + button:hover:disabled { + background-color: #ccc; + } + button:disabled { + color: lightgray; + } + + .button_container { + width:550px; + display:block; + margin-left:auto; + margin-right:auto; + } + + .meter { + height: 20px; /* Can be anything */ + position: relative; + background: #555; + -moz-border-radius: 25px; + -webkit-border-radius: 25px; + border-radius: 25px; + padding: 10px; + -webkit-box-shadow: inset 0 -1px 1px rgba(255,255,255,0.3); + -moz-box-shadow : inset 0 -1px 1px rgba(255,255,255,0.3); + box-shadow : inset 0 -1px 1px rgba(255,255,255,0.3); + } + .meter > span { + display: block; + height: 100%; + -webkit-border-top-right-radius: 20px; + -webkit-border-bottom-right-radius: 20px; + -moz-border-radius-topright: 20px; + -moz-border-radius-bottomright: 20px; + border-top-right-radius: 20px; + border-bottom-right-radius: 20px; + -webkit-border-top-left-radius: 20px; + -webkit-border-bottom-left-radius: 20px; + -moz-border-radius-topleft: 20px; + -moz-border-radius-bottomleft: 20px; + border-top-left-radius: 20px; + border-bottom-left-radius: 20px; + background-color: rgb(43,194,83); + background-image: -webkit-gradient( + linear, + left bottom, + left top, + color-stop(0, rgb(43,194,83)), + color-stop(1, rgb(84,240,84)) + ); + background-image: -moz-linear-gradient( + center bottom, + rgb(43,194,83) 37%, + rgb(84,240,84) 69% + ); + -webkit-box-shadow: + inset 0 2px 9px rgba(255,255,255,0.3), + inset 0 -2px 6px rgba(0,0,0,0.4); + -moz-box-shadow: + inset 0 2px 9px rgba(255,255,255,0.3), + inset 0 -2px 6px rgba(0,0,0,0.4); + box-shadow: + inset 0 2px 9px rgba(255,255,255,0.3), + inset 0 -2px 6px rgba(0,0,0,0.4); + position: relative; + overflow: hidden; + } + .meter > span:after, .animate > span > span { + content: ""; + position: absolute; + top: 0; left: 0; bottom: 0; right: 0; + background-image: + -webkit-gradient(linear, 0 0, 100% 100%, + color-stop(.25, rgba(255, 255, 255, .2)), + color-stop(.25, transparent), color-stop(.5, transparent), + color-stop(.5, rgba(255, 255, 255, .2)), + color-stop(.75, rgba(255, 255, 255, .2)), + color-stop(.75, transparent), to(transparent) + ); + background-image: + -moz-linear-gradient( + -45deg, + rgba(255, 255, 255, .2) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, .2) 50%, + rgba(255, 255, 255, .2) 75%, + transparent 75%, + transparent + ); + z-index: 1; + -webkit-background-size: 50px 50px; + -moz-background-size: 50px 50px; + -webkit-animation: move 2s linear infinite; + -webkit-border-top-right-radius: 20px; + -webkit-border-bottom-right-radius: 20px; + -moz-border-radius-topright: 20px; + -moz-border-radius-bottomright: 20px; + border-top-right-radius: 20px; + border-bottom-right-radius: 20px; + -webkit-border-top-left-radius: 20px; + -webkit-border-bottom-left-radius: 20px; + -moz-border-radius-topleft: 20px; + -moz-border-radius-bottomleft: 20px; + border-top-left-radius: 20px; + border-bottom-left-radius: 20px; + overflow: hidden; + } + + .animate > span:after { + display: none; + } + + @-webkit-keyframes move { + 0% { + background-position: 0 0; + } + 100% { + background-position: 50px 50px; + } + } + + .orange > span { + background-color: #f1a165; + background-image: -moz-linear-gradient(top, #f1a165, #f36d0a); + background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #f1a165),color-stop(1, #f36d0a)); + background-image: -webkit-linear-gradient(#f1a165, #f36d0a); + } + + .red > span { + background-color: #f0a3a3; + background-image: -moz-linear-gradient(top, #f0a3a3, #f42323); + background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #f0a3a3),color-stop(1, #f42323)); + background-image: -webkit-linear-gradient(#f0a3a3, #f42323); + } + + .nostripes > span > span, .nostripes > span:after { + -webkit-animation: none; + background-image: none; + } + + #output { + background-color: #ccc; + height: 240px; + overflow-y: auto; + } + + </style> +</head> + +<body> + <div id="page_wrap"> + + <h1>Meter Updates via WebSocket</h1> + + <p/> + + <div class="meter"> + <span id="meter1" style="width: 25%"></span> + </div> + + <p/> + + <div class="meter orange nostripes"> + <span id="meter2" style="width: 33.3%"></span> + </div> + + <p/> + + <div class="meter red"> + <span id="meter3" style="width: 80%"></span> + </div> + + <p/> + + </div> + <div class="button_container"> + <div> + <button id="connection" onclick="toggleConnection(this)">WebSocket Connect</button> + <button id="update" disabled onclick="toggleUpdate(this)">Disable Update</button> + </div> + </div> + <p/> + <div id="output"></div> + +</body> + +<script language="javascript" type="text/javascript"> + var connection; // websocket connection + + function writeToScreen (message) { + var div = document.createElement('div'); + var output = document.getElementById('output'); + div.innerHTML = message; + output.appendChild(div); + output.scrollTop = output.scrollHeight; + } + + function ws_connect() { + // check for websocket support + // for Internet Explorer < 10 there are options for websocket support that + // could be integrated into production code, but for now, we are expecting + // browser support to be present for this demo + if ('WebSocket' in window) { + + writeToScreen('Connecting'); + connection = new WebSocket('ws://' + window.location.host + '/meters'); + connection.onopen = function(ev) { + document.getElementById("connection").innerHTML = "WebSocket Disconnect"; + document.getElementById("update").disabled=false; + document.getElementById("update").innerHTML = "Disable Update"; + writeToScreen('CONNECTED'); + var message = 'update on'; + writeToScreen('SENT: ' + message); + connection.send(message); + }; + + connection.onclose = function(ev) { + document.getElementById("update").disabled=true; + document.getElementById("update").innerHTML = "Enable Update"; + document.getElementById("connection").innerHTML = "WebSocket Connect"; + writeToScreen('DISCONNECTED'); + }; + + connection.onmessage = function(ev) { + if (ev.data.substr(0,5) == "meter") + { + var target = ev.data.split(":")[0]; + var meter = document.getElementById(target); + var data = ev.data.split(":")[1].split(","); + var percent = (data[0]*100)/data[1]; + meter.style.width = percent+"%"; + } + else + writeToScreen('RECEIVED: ' + ev.data); + }; + + connection.onerror = function(ev) { + alert("WebSocket error"); + }; + + } else { + alert("WebSocket is not available!!!\n" + + "Demo will not function."); + } + } + + // user connect/disconnect + function toggleConnection(el) { + var tag=el.innerHTML; + if (tag == "WebSocket Connect") + { + ws_connect(); + } + else + { + connection.close(); + } + } + + // user turn updates on/off + function toggleUpdate(el) { + var tag=el.innerHTML; + var message; + if (tag == "Enable Update") + { + message = 'update on'; + el.innerHTML = "Disable Update"; + } + else + { + message = 'update off'; + el.innerHTML = "Enable Update"; + } + writeToScreen('SENT: ' + message); + connection.send(message); + } +</script> + +</html> http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/_obsolete/ws_server/ws_server.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/_obsolete/ws_server/ws_server.c b/thirdparty/civetweb-1.9.1/examples/_obsolete/ws_server/ws_server.c new file mode 100644 index 0000000..575a26a --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/_obsolete/ws_server/ws_server.c @@ -0,0 +1,271 @@ +// Copyright (c) 2004-2012 Sergey Lyubka +// This file is a part of civetweb project, http://github.com/bel2125/civetweb +// +// v 0.1 Contributed by William Greathouse 9-Sep-2013 + +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "civetweb.h" + +// simple structure for keeping track of websocket connection +struct ws_connection { + struct mg_connection *conn; + int update; + int closing; +}; + +// time base and structure periodic updates to client for demo +#define BASETIME 100000 /* 0.1 seconds */ +struct progress { + int limit; + int increment; + int period; + int value; +}; + +// up to 16 independent client connections +#define CONNECTIONS 16 +static struct ws_connection ws_conn[CONNECTIONS]; + + +// ws_server_thread() +// Simple demo server thread. Sends periodic updates to connected clients +static void *ws_server_thread(void *parm) +{ + int wsd = (long)parm; + struct mg_connection *conn = ws_conn[wsd].conn; + int timer = 0; + char tstr[32]; + int i; + struct progress meter[] = { + /* first meter 0 to 1000, by 5 every 0.1 second */ + { 1000, 5, 1, 0 }, + /* second meter 0 to 500, by 10 every 0.5 second */ + { 500, 10, 5, 0 }, + /* third meter 0 to 100, by 10 every 1.0 second */ + { 100, 10, 10, 0}, + /* end of list */ + { 0, 0, 0, 0} + }; + + fprintf(stderr, "ws_server_thread %d\n", wsd); + + /* Send initial meter updates */ + for (i=0; meter[i].period != 0; i++) { + if (meter[i].value >= meter[i].limit) + meter[i].value = 0; + if (meter[i].value >= meter[i].limit) + meter[i].value = meter[i].limit; + sprintf(tstr, "meter%d:%d,%d", i+1, + meter[i].value, meter[i].limit); + mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, tstr, strlen(tstr)); + } + + /* While the connection is open, send periodic updates */ + while(!ws_conn[wsd].closing) { + usleep(100000); /* 0.1 second */ + timer++; + + /* Send meter updates */ + if (ws_conn[wsd].update) { + for (i=0; meter[i].period != 0; i++) { + if (timer%meter[i].period == 0) { + if (meter[i].value >= meter[i].limit) + meter[i].value = 0; + else + meter[i].value += meter[i].increment; + if (meter[i].value >= meter[i].limit) + meter[i].value = meter[i].limit; + // if we are closing, server should not send new data + if (!ws_conn[wsd].closing) { + sprintf(tstr, "meter%d:%d,%d", i+1, + meter[i].value, meter[i].limit); + mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, tstr, strlen(tstr)); + } + } + } + } + + /* Send periodic PING to assure websocket remains connected, except if we are closing */ + if (timer%100 == 0 && !ws_conn[wsd].closing) + mg_websocket_write(conn, WEBSOCKET_OPCODE_PING, NULL, 0); + } + + fprintf(stderr, "ws_server_thread %d exiting\n", wsd); + + // reset connection information to allow reuse by new client + ws_conn[wsd].conn = NULL; + ws_conn[wsd].update = 0; + ws_conn[wsd].closing = 2; + + return NULL; +} + +// websocket_connect_handler() +// On new client connection, find next available server connection and store +// new connection information. If no more server connections are available +// tell civetweb to not accept the client request. +static int websocket_connect_handler(const struct mg_connection *conn) +{ + int i; + + fprintf(stderr, "connect handler\n"); + + for(i=0; i < CONNECTIONS; ++i) { + if (ws_conn[i].conn == NULL) { + fprintf(stderr, "...prep for server %d\n", i); + ws_conn[i].conn = (struct mg_connection *)conn; + ws_conn[i].closing = 0; + ws_conn[i].update = 0; + break; + } + } + if (i >= CONNECTIONS) { + fprintf(stderr, "Refused connection: Max connections exceeded\n"); + return 1; + } + + return 0; +} + +// websocket_ready_handler() +// Once websocket negotiation is complete, start a server for the connection +static void websocket_ready_handler(struct mg_connection *conn) +{ + int i; + + fprintf(stderr, "ready handler\n"); + + for(i=0; i < CONNECTIONS; ++i) { + if (ws_conn[i].conn == conn) { + fprintf(stderr, "...start server %d\n", i); + mg_start_thread(ws_server_thread, (void *)(long)i); + break; + } + } +} + +// websocket_close_handler() +// When websocket is closed, tell the associated server to shut down +static void websocket_close_handler(struct mg_connection *conn) +{ + int i; + + //fprintf(stderr, "close handler\n"); /* called for every close, not just websockets */ + + for(i=0; i < CONNECTIONS; ++i) { + if (ws_conn[i].conn == conn) { + fprintf(stderr, "...close server %d\n", i); + ws_conn[i].closing = 1; + } + } +} + +// Arguments: +// flags: first byte of websocket frame, see websocket RFC, +// http://tools.ietf.org/html/rfc6455, section 5.2 +// data, data_len: payload data. Mask, if any, is already applied. +static int websocket_data_handler(struct mg_connection *conn, int flags, + char *data, size_t data_len) +{ + int i; + int wsd; + + for(i=0; i < CONNECTIONS; ++i) { + if (ws_conn[i].conn == conn) { + wsd = i; + break; + } + } + if (i >= CONNECTIONS) { + fprintf(stderr, "Received websocket data from unknown connection\n"); + return 1; + } + + if (flags & 0x80) { + flags &= 0x7f; + switch (flags) { + case WEBSOCKET_OPCODE_CONTINUATION: + fprintf(stderr, "CONTINUATION...\n"); + break; + case WEBSOCKET_OPCODE_TEXT: + fprintf(stderr, "TEXT: %-.*s\n", (int)data_len, data); + /*** interpret data as commands here ***/ + if (strncmp("update on", data, data_len)== 0) { + /* turn on updates */ + ws_conn[wsd].update = 1; + /* echo back */ + mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, data, data_len); + } else if (strncmp("update off", data, data_len)== 0) { + /* turn off updates */ + ws_conn[wsd].update = 0; + /* echo back */ + mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, data, data_len); + } + break; + case WEBSOCKET_OPCODE_BINARY: + fprintf(stderr, "BINARY...\n"); + break; + case WEBSOCKET_OPCODE_CONNECTION_CLOSE: + fprintf(stderr, "CLOSE...\n"); + /* If client initiated close, respond with close message in acknowlegement */ + if (!ws_conn[wsd].closing) { + mg_websocket_write(conn, WEBSOCKET_OPCODE_CONNECTION_CLOSE, data, data_len); + ws_conn[wsd].closing = 1; /* we should not send addional messages when close requested/acknowledged */ + } + return 0; /* time to close the connection */ + break; + case WEBSOCKET_OPCODE_PING: + /* client sent PING, respond with PONG */ + mg_websocket_write(conn, WEBSOCKET_OPCODE_PONG, data, data_len); + break; + case WEBSOCKET_OPCODE_PONG: + /* received PONG to our PING, no action */ + break; + default: + fprintf(stderr, "Unknown flags: %02x\n", flags); + break; + } + } + + return 1; /* keep connection open */ +} + + +int main(void) +{ + char server_name[40]; + struct mg_context *ctx; + struct mg_callbacks callbacks; + const char *options[] = { + "listening_ports", "8080", + "document_root", "docroot", + NULL + }; + + /* get simple greeting for the web server */ + snprintf(server_name, sizeof(server_name), + "Civetweb websocket server v. %s", + mg_version()); + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.websocket_connect = websocket_connect_handler; + callbacks.websocket_ready = websocket_ready_handler; + callbacks.websocket_data = websocket_data_handler; + callbacks.connection_close = websocket_close_handler; + + ctx = mg_start(&callbacks, NULL, options); + + /* show the greeting and some basic information */ + printf("%s started on port(s) %s with web root [%s]\n", + server_name, mg_get_option(ctx, "listening_ports"), + mg_get_option(ctx, "document_root")); + + getchar(); // Wait until user hits "enter" + mg_stop(ctx); + + return 0; +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/a9485aeb/thirdparty/civetweb-1.9.1/examples/embedded_c/embedded_c.c ---------------------------------------------------------------------- diff --git a/thirdparty/civetweb-1.9.1/examples/embedded_c/embedded_c.c b/thirdparty/civetweb-1.9.1/examples/embedded_c/embedded_c.c new file mode 100644 index 0000000..5dc91f0 --- /dev/null +++ b/thirdparty/civetweb-1.9.1/examples/embedded_c/embedded_c.c @@ -0,0 +1,922 @@ +/* +* Copyright (c) 2013-2017 the CivetWeb developers +* Copyright (c) 2013 No Face Press, LLC +* License http://opensource.org/licenses/mit-license.php MIT License +*/ + +/* Simple example program on how to use CivetWeb embedded into a C program. */ +#ifdef _WIN32 +#include <windows.h> +#else +#include <unistd.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "civetweb.h" + + +#define DOCUMENT_ROOT "." +#ifdef NO_SSL +#ifdef USE_IPV6 +#define PORT "[::]:8888" +#else +#define PORT "8888" +#endif +#else +#ifdef USE_IPV6 +#define PORT "[::]:8888r,[::]:8843s,8884" +#else +#define PORT "8888r,8843s" +#endif +#endif +#define EXAMPLE_URI "/example" +#define EXIT_URI "/exit" +int exitNow = 0; + + +int +ExampleHandler(struct mg_connection *conn, void *cbdata) +{ + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2>This is an example text from a C handler</h2>"); + mg_printf( + conn, + "<p>To see a page from the A handler <a href=\"A\">click A</a></p>"); + mg_printf(conn, + "<p>To see a page from the A handler <a href=\"A/A\">click " + "A/A</a></p>"); + mg_printf(conn, + "<p>To see a page from the A/B handler <a " + "href=\"A/B\">click A/B</a></p>"); + mg_printf(conn, + "<p>To see a page from the B handler (0) <a " + "href=\"B\">click B</a></p>"); + mg_printf(conn, + "<p>To see a page from the B handler (1) <a " + "href=\"B/A\">click B/A</a></p>"); + mg_printf(conn, + "<p>To see a page from the B handler (2) <a " + "href=\"B/B\">click B/B</a></p>"); + mg_printf(conn, + "<p>To see a page from the *.foo handler <a " + "href=\"xy.foo\">click xy.foo</a></p>"); + mg_printf(conn, + "<p>To see a page from the close handler <a " + "href=\"close\">click close</a></p>"); + mg_printf(conn, + "<p>To see a page from the FileHandler handler <a " + "href=\"form\">click form</a> (the starting point of the " + "<b>form</b> test)</p>"); + mg_printf(conn, + "<p>To see a page from the CookieHandler handler <a " + "href=\"cookie\">click cookie</a></p>"); + mg_printf(conn, + "<p>To see an example for parsing files on the fly <a " + "href=\"on_the_fly_form\">click form</a> (form for " + "uploading files)</p>"); + +#ifdef USE_WEBSOCKET + mg_printf(conn, + "<p>To test websocket handler <a href=\"/websocket\">click " + "websocket</a></p>"); +#endif + mg_printf(conn, "<p>To exit <a href=\"%s\">click exit</a></p>", EXIT_URI); + mg_printf(conn, "</body></html>\n"); + return 1; +} + + +int +ExitHandler(struct mg_connection *conn, void *cbdata) +{ + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); + mg_printf(conn, "Server will shut down.\n"); + mg_printf(conn, "Bye!\n"); + exitNow = 1; + return 1; +} + + +int +AHandler(struct mg_connection *conn, void *cbdata) +{ + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2>This is the A handler!!!</h2>"); + mg_printf(conn, "</body></html>\n"); + return 1; +} + + +int +ABHandler(struct mg_connection *conn, void *cbdata) +{ + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2>This is the AB handler!!!</h2>"); + mg_printf(conn, "</body></html>\n"); + return 1; +} + + +int +BXHandler(struct mg_connection *conn, void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2>This is the BX handler %p!!!</h2>", cbdata); + mg_printf(conn, "<p>The actual uri is %s</p>", req_info->uri); + mg_printf(conn, "</body></html>\n"); + return 1; +} + + +int +FooHandler(struct mg_connection *conn, void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + 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>", + req_info->request_method, + req_info->uri, + req_info->http_version); + mg_printf(conn, "</body></html>\n"); + return 1; +} + + +int +CloseHandler(struct mg_connection *conn, void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, + "<h2>This handler will close the connection in a second</h2>"); +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + mg_printf(conn, "bye"); + printf("CloseHandler: close connection\n"); + mg_close_connection(conn); + printf("CloseHandler: wait 10 sec\n"); +#ifdef _WIN32 + Sleep(10000); +#else + sleep(10); +#endif + printf("CloseHandler: return from function\n"); + return 1; +} + + +int +FileHandler(struct mg_connection *conn, void *cbdata) +{ + /* In this handler, we ignore the req_info and send the file "fileName". */ + const char *fileName = (const char *)cbdata; + + mg_send_file(conn, fileName); + return 1; +} + + +int +field_found(const char *key, + const char *filename, + char *path, + size_t pathlen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + mg_printf(conn, "\r\n\r\n%s:\r\n", key); + + if (filename && *filename) { +#ifdef _WIN32 + _snprintf(path, pathlen, "D:\\tmp\\%s", filename); +#else + snprintf(path, pathlen, "/tmp/%s", filename); +#endif + return FORM_FIELD_STORAGE_STORE; + } + return FORM_FIELD_STORAGE_GET; +} + + +int +field_get(const char *key, const char *value, size_t valuelen, void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + if (key[0]) { + mg_printf(conn, "%s = ", key); + } + mg_write(conn, value, valuelen); + + return 0; +} + + +int +field_stored(const char *path, long long file_size, void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + mg_printf(conn, + "stored as %s (%lu bytes)\r\n\r\n", + path, + (unsigned long)file_size); + + return 0; +} + + +int +FormHandler(struct mg_connection *conn, void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + int ret; + struct mg_form_data_handler fdh = {field_found, field_get, field_stored, 0}; + + /* It would be possible to check the request info here before calling + * mg_handle_form_request. */ + (void)req_info; + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); + fdh.user_data = (void *)conn; + + /* Call the form handler */ + mg_printf(conn, "Form data:"); + ret = mg_handle_form_request(conn, &fdh); + mg_printf(conn, "\r\n%i fields found", ret); + + return 1; +} + + +int +FileUploadForm(struct mg_connection *conn, void *cbdata) +{ + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + + mg_printf(conn, "<!DOCTYPE html>\n"); + mg_printf(conn, "<html>\n<head>\n"); + mg_printf(conn, "<meta charset=\"UTF-8\">\n"); + mg_printf(conn, "<title>File upload</title>\n"); + mg_printf(conn, "</head>\n<body>\n"); + mg_printf(conn, + "<form action=\"%s\" method=\"POST\" " + "enctype=\"multipart/form-data\">\n", + (const char *)cbdata); + mg_printf(conn, "<input type=\"file\" name=\"filesin\" multiple>\n"); + mg_printf(conn, "<input type=\"submit\" value=\"Submit\">\n"); + mg_printf(conn, "</form>\n</body>\n</html>\n"); + return 1; +} + +#define MD5_STATIC static +#include "../src/md5.inl" + +struct tfile_checksum { + char name[128]; + unsigned long long length; + md5_state_t chksum; +}; + +#define MAX_FILES (10) + +struct tfiles_checksums { + int index; + struct tfile_checksum file[MAX_FILES]; +}; + + +int +field_disp_read_on_the_fly(const char *key, + const char *filename, + char *path, + size_t pathlen, + void *user_data) +{ + struct tfiles_checksums *context = (struct tfiles_checksums *)user_data; + + (void)key; + (void)path; + (void)pathlen; + + if (context->index < MAX_FILES) { + context->index++; + strncpy(context->file[context->index - 1].name, filename, 128); + context->file[context->index - 1].name[127] = 0; + context->file[context->index - 1].length = 0; + md5_init(&(context->file[context->index - 1].chksum)); + return FORM_FIELD_STORAGE_GET; + } + return FORM_FIELD_STORAGE_ABORT; +} + + +int +field_get_checksum(const char *key, + const char *value, + size_t valuelen, + void *user_data) +{ + struct tfiles_checksums *context = (struct tfiles_checksums *)user_data; + (void)key; + + context->file[context->index - 1].length += valuelen; + md5_append(&(context->file[context->index - 1].chksum), + (const md5_byte_t *)value, + valuelen); + + return 0; +} + + +int +CheckSumHandler(struct mg_connection *conn, void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + int i, j, ret; + struct tfiles_checksums chksums; + md5_byte_t digest[16]; + struct mg_form_data_handler fdh = {field_disp_read_on_the_fly, + field_get_checksum, + 0, + (void *)&chksums}; + + /* It would be possible to check the request info here before calling + * mg_handle_form_request. */ + (void)req_info; + + memset(&chksums, 0, sizeof(chksums)); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n"); + + /* Call the form handler */ + mg_printf(conn, "File checksums:"); + ret = mg_handle_form_request(conn, &fdh); + for (i = 0; i < chksums.index; i++) { + md5_finish(&(chksums.file[i].chksum), digest); + /* Visual Studio 2010+ support llu */ + mg_printf(conn, + "\r\n%s %llu ", + chksums.file[i].name, + chksums.file[i].length); + for (j = 0; j < 16; j++) { + mg_printf(conn, "%02x", (unsigned int)digest[j]); + } + } + mg_printf(conn, "\r\n%i files\r\n", ret); + + return 1; +} + + +int +CookieHandler(struct mg_connection *conn, void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + const char *cookie = mg_get_header(conn, "Cookie"); + char first_str[64], count_str[64]; + int count; + + (void)mg_get_cookie(cookie, "first", first_str, sizeof(first_str)); + (void)mg_get_cookie(cookie, "count", count_str, sizeof(count_str)); + + mg_printf(conn, "HTTP/1.1 200 OK\r\nConnection: close\r\n"); + if (first_str[0] == 0) { + time_t t = time(0); + struct tm *ptm = localtime(&t); + mg_printf(conn, + "Set-Cookie: first=%04i-%02i-%02iT%02i:%02i:%02i\r\n", + ptm->tm_year + 1900, + ptm->tm_mon + 1, + ptm->tm_mday, + ptm->tm_hour, + ptm->tm_min, + ptm->tm_sec); + } + count = (count_str[0] == 0) ? 0 : atoi(count_str); + mg_printf(conn, "Set-Cookie: count=%i\r\n", count + 1); + mg_printf(conn, "Content-Type: text/html\r\n\r\n"); + + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2>This is the CookieHandler.</h2>"); + mg_printf(conn, "<p>The actual uri is %s</p>", req_info->uri); + + if (first_str[0] == 0) { + mg_printf(conn, "<p>This is the first time, you opened this page</p>"); + } else { + mg_printf(conn, "<p>You opened this page %i times before.</p>", count); + mg_printf(conn, "<p>You first opened this page on %s.</p>", first_str); + } + + mg_printf(conn, "</body></html>\n"); + return 1; +} + + +int +WebSocketStartHandler(struct mg_connection *conn, void *cbdata) +{ + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + + mg_printf(conn, "<!DOCTYPE html>\n"); + mg_printf(conn, "<html>\n<head>\n"); + mg_printf(conn, "<meta charset=\"UTF-8\">\n"); + mg_printf(conn, "<title>Embedded websocket example</title>\n"); + +#ifdef USE_WEBSOCKET + /* mg_printf(conn, "<script type=\"text/javascript\"><![CDATA[\n"); ... + * xhtml style */ + mg_printf(conn, "<script>\n"); + mg_printf( + conn, + "function load() {\n" + " var wsproto = (location.protocol === 'https:') ? 'wss:' : 'ws:';\n" + " connection = new WebSocket(wsproto + '//' + window.location.host + " + "'/websocket');\n" + " websock_text_field = " + "document.getElementById('websock_text_field');\n" + " connection.onmessage = function (e) {\n" + " websock_text_field.innerHTML=e.data;\n" + " }\n" + " connection.onerror = function (error) {\n" + " alert('WebSocket error');\n" + " connection.close();\n" + " }\n" + "}\n"); + /* mg_printf(conn, "]]></script>\n"); ... xhtml style */ + mg_printf(conn, "</script>\n"); + mg_printf(conn, "</head>\n<body onload=\"load()\">\n"); + mg_printf( + conn, + "<div id='websock_text_field'>No websocket connection yet</div>\n"); +#else + mg_printf(conn, "</head>\n<body>\n"); + mg_printf(conn, "Example not compiled with USE_WEBSOCKET\n"); +#endif + mg_printf(conn, "</body>\n</html>\n"); + + return 1; +} + + +#ifdef USE_WEBSOCKET + +/* MAX_WS_CLIENTS defines how many clients can connect to a websocket at the + * same time. The value 5 is very small and used here only for demonstration; + * it can be easily tested to connect more than MAX_WS_CLIENTS clients. + * A real server should use a much higher number, or better use a dynamic list + * of currently connected websocket clients. */ +#define MAX_WS_CLIENTS (5) + +struct t_ws_client { + struct mg_connection *conn; + int state; +} static ws_clients[MAX_WS_CLIENTS]; + + +#define ASSERT(x) \ + { \ + if (!(x)) { \ + fprintf(stderr, \ + "Assertion failed in line %u\n", \ + (unsigned)__LINE__); \ + } \ + } + + +int +WebSocketConnectHandler(const struct mg_connection *conn, void *cbdata) +{ + struct mg_context *ctx = mg_get_context(conn); + int reject = 1; + int i; + + mg_lock_context(ctx); + for (i = 0; i < MAX_WS_CLIENTS; i++) { + if (ws_clients[i].conn == NULL) { + ws_clients[i].conn = (struct mg_connection *)conn; + ws_clients[i].state = 1; + mg_set_user_connection_data(ws_clients[i].conn, + (void *)(ws_clients + i)); + reject = 0; + break; + } + } + mg_unlock_context(ctx); + + fprintf(stdout, + "Websocket client %s\r\n\r\n", + (reject ? "rejected" : "accepted")); + return reject; +} + + +void +WebSocketReadyHandler(struct mg_connection *conn, void *cbdata) +{ + const char *text = "Hello from the websocket ready handler"; + struct t_ws_client *client = mg_get_user_connection_data(conn); + + mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text)); + fprintf(stdout, "Greeting message sent to websocket client\r\n\r\n"); + ASSERT(client->conn == conn); + ASSERT(client->state == 1); + + client->state = 2; +} + + +int +WebsocketDataHandler(struct mg_connection *conn, + int bits, + char *data, + size_t len, + void *cbdata) +{ + struct t_ws_client *client = mg_get_user_connection_data(conn); + ASSERT(client->conn == conn); + ASSERT(client->state >= 1); + + fprintf(stdout, "Websocket got data:\r\n"); + fwrite(data, len, 1, stdout); + fprintf(stdout, "\r\n\r\n"); + + return 1; +} + + +void +WebSocketCloseHandler(const struct mg_connection *conn, void *cbdata) +{ + struct mg_context *ctx = mg_get_context(conn); + struct t_ws_client *client = mg_get_user_connection_data(conn); + ASSERT(client->conn == conn); + ASSERT(client->state >= 1); + + mg_lock_context(ctx); + client->state = 0; + client->conn = NULL; + mg_unlock_context(ctx); + + fprintf(stdout, + "Client droped from the set of webserver connections\r\n\r\n"); +} + + +void +InformWebsockets(struct mg_context *ctx) +{ + static unsigned long cnt = 0; + char text[32]; + int i; + + sprintf(text, "%lu", ++cnt); + + mg_lock_context(ctx); + for (i = 0; i < MAX_WS_CLIENTS; i++) { + if (ws_clients[i].state == 2) { + mg_websocket_write(ws_clients[i].conn, + WEBSOCKET_OPCODE_TEXT, + text, + strlen(text)); + } + } + mg_unlock_context(ctx); +} +#endif + + +#ifdef USE_SSL_DH +#include "openssl/ssl.h" +#include "openssl/dh.h" +#include "openssl/ec.h" +#include "openssl/evp.h" +#include "openssl/ecdsa.h" + +DH * +get_dh2236() +{ + static unsigned char dh2236_p[] = { + 0x0E, 0x97, 0x6E, 0x6A, 0x88, 0x84, 0xD2, 0xD7, 0x55, 0x6A, 0x17, 0xB7, + 0x81, 0x9A, 0x98, 0xBC, 0x7E, 0xD1, 0x6A, 0x44, 0xB1, 0x18, 0xE6, 0x25, + 0x3A, 0x62, 0x35, 0xF0, 0x41, 0x91, 0xE2, 0x16, 0x43, 0x9D, 0x8F, 0x7D, + 0x5D, 0xDA, 0x85, 0x47, 0x25, 0xC4, 0xBA, 0x68, 0x0A, 0x87, 0xDC, 0x2C, + 0x33, 0xF9, 0x75, 0x65, 0x17, 0xCB, 0x8B, 0x80, 0xFE, 0xE0, 0xA8, 0xAF, + 0xC7, 0x9E, 0x82, 0xBE, 0x6F, 0x1F, 0x00, 0x04, 0xBD, 0x69, 0x50, 0x8D, + 0x9C, 0x3C, 0x41, 0x69, 0x21, 0x4E, 0x86, 0xC8, 0x2B, 0xCC, 0x07, 0x4D, + 0xCF, 0xE4, 0xA2, 0x90, 0x8F, 0x66, 0xA9, 0xEF, 0xF7, 0xFC, 0x6F, 0x5F, + 0x06, 0x22, 0x00, 0xCB, 0xCB, 0xC3, 0x98, 0x3F, 0x06, 0xB9, 0xEC, 0x48, + 0x3B, 0x70, 0x6E, 0x94, 0xE9, 0x16, 0xE1, 0xB7, 0x63, 0x2E, 0xAB, 0xB2, + 0xF3, 0x84, 0xB5, 0x3D, 0xD7, 0x74, 0xF1, 0x6A, 0xD1, 0xEF, 0xE8, 0x04, + 0x18, 0x76, 0xD2, 0xD6, 0xB0, 0xB7, 0x71, 0xB6, 0x12, 0x8F, 0xD1, 0x33, + 0xAB, 0x49, 0xAB, 0x09, 0x97, 0x35, 0x9D, 0x4B, 0xBB, 0x54, 0x22, 0x6E, + 0x1A, 0x33, 0x18, 0x02, 0x8A, 0xF4, 0x7C, 0x0A, 0xCE, 0x89, 0x75, 0x2D, + 0x10, 0x68, 0x25, 0xA9, 0x6E, 0xCD, 0x97, 0x49, 0xED, 0xAE, 0xE6, 0xA7, + 0xB0, 0x07, 0x26, 0x25, 0x60, 0x15, 0x2B, 0x65, 0x88, 0x17, 0xF2, 0x5D, + 0x2C, 0xF6, 0x2A, 0x7A, 0x8C, 0xAD, 0xB6, 0x0A, 0xA2, 0x57, 0xB0, 0xC1, + 0x0E, 0x5C, 0xA8, 0xA1, 0x96, 0x58, 0x9A, 0x2B, 0xD4, 0xC0, 0x8A, 0xCF, + 0x91, 0x25, 0x94, 0xB4, 0x14, 0xA7, 0xE4, 0xE2, 0x1B, 0x64, 0x5F, 0xD2, + 0xCA, 0x70, 0x46, 0xD0, 0x2C, 0x95, 0x6B, 0x9A, 0xFB, 0x83, 0xF9, 0x76, + 0xE6, 0xD4, 0xA4, 0xA1, 0x2B, 0x2F, 0xF5, 0x1D, 0xE4, 0x06, 0xAF, 0x7D, + 0x22, 0xF3, 0x04, 0x30, 0x2E, 0x4C, 0x64, 0x12, 0x5B, 0xB0, 0x55, 0x3E, + 0xC0, 0x5E, 0x56, 0xCB, 0x99, 0xBC, 0xA8, 0xD9, 0x23, 0xF5, 0x57, 0x40, + 0xF0, 0x52, 0x85, 0x9B, + }; + static unsigned char dh2236_g[] = { + 0x02, + }; + DH *dh; + + if ((dh = DH_new()) == NULL) + return (NULL); + dh->p = BN_bin2bn(dh2236_p, sizeof(dh2236_p), NULL); + dh->g = BN_bin2bn(dh2236_g, sizeof(dh2236_g), NULL); + if ((dh->p == NULL) || (dh->g == NULL)) { + DH_free(dh); + return (NULL); + } + return (dh); +} +#endif + + +#ifndef NO_SSL +int +init_ssl(void *ssl_context, void *user_data) +{ + /* Add application specific SSL initialization */ + struct ssl_ctx_st *ctx = (struct ssl_ctx_st *)ssl_context; + +#ifdef USE_SSL_DH + /* example from https://github.com/civetweb/civetweb/issues/347 */ + DH *dh = get_dh2236(); + if (!dh) + return -1; + if (1 != SSL_CTX_set_tmp_dh(ctx, dh)) + return -1; + DH_free(dh); + + EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (!ecdh) + return -1; + if (1 != SSL_CTX_set_tmp_ecdh(ctx, ecdh)) + return -1; + EC_KEY_free(ecdh); + + printf("ECDH ciphers initialized\n"); +#endif + return 0; +} +#endif + + +int +log_message(const struct mg_connection *conn, const char *message) +{ + puts(message); + return 1; +} + + +int +main(int argc, char *argv[]) +{ + const char *options[] = { + "document_root", + DOCUMENT_ROOT, + "listening_ports", + PORT, + "request_timeout_ms", + "10000", + "error_log_file", + "error.log", +#ifdef USE_WEBSOCKET + "websocket_timeout_ms", + "3600000", +#endif +#ifndef NO_SSL + "ssl_certificate", + "../../resources/cert/server.pem", + "ssl_protocol_version", + "3", + "ssl_cipher_list", +#ifdef USE_SSL_DH + "ECDHE-RSA-AES256-GCM-SHA384:DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256", +#else + "DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256", +#endif +#endif + 0}; + struct mg_callbacks callbacks; + struct mg_context *ctx; + struct mg_server_ports ports[32]; + int port_cnt, n; + int err = 0; + +/* Check if libcivetweb has been built with all required features. */ +#ifdef USE_IPV6 + if (!mg_check_feature(8)) { + fprintf(stderr, + "Error: Embedded example built with IPv6 support, " + "but civetweb library build without.\n"); + err = 1; + } +#endif +#ifdef USE_WEBSOCKET + if (!mg_check_feature(16)) { + fprintf(stderr, + "Error: Embedded example built with websocket support, " + "but civetweb library build without.\n"); + err = 1; + } +#endif +#ifndef NO_SSL + if (!mg_check_feature(2)) { + fprintf(stderr, + "Error: Embedded example built with SSL support, " + "but civetweb library build without.\n"); + err = 1; + } +#endif + if (err) { + fprintf(stderr, "Cannot start CivetWeb - inconsistent build.\n"); + return EXIT_FAILURE; + } + + /* Start CivetWeb web server */ + memset(&callbacks, 0, sizeof(callbacks)); +#ifndef NO_SSL + callbacks.init_ssl = init_ssl; +#endif + callbacks.log_message = log_message; + ctx = mg_start(&callbacks, 0, options); + + /* Check return value: */ + if (ctx == NULL) { + fprintf(stderr, "Cannot start CivetWeb - mg_start failed.\n"); + return EXIT_FAILURE; + } + + /* Add handler EXAMPLE_URI, to explain the example */ + mg_set_request_handler(ctx, EXAMPLE_URI, ExampleHandler, 0); + mg_set_request_handler(ctx, EXIT_URI, ExitHandler, 0); + + /* Add handler for /A* and special handler for /A/B */ + mg_set_request_handler(ctx, "/A", AHandler, 0); + mg_set_request_handler(ctx, "/A/B", ABHandler, 0); + + /* Add handler for /B, /B/A, /B/B but not for /B* */ + mg_set_request_handler(ctx, "/B$", BXHandler, (void *)0); + mg_set_request_handler(ctx, "/B/A$", BXHandler, (void *)1); + mg_set_request_handler(ctx, "/B/B$", BXHandler, (void *)2); + + /* Add handler for all files with .foo extention */ + mg_set_request_handler(ctx, "**.foo$", FooHandler, 0); + + /* Add handler for /close extention */ + mg_set_request_handler(ctx, "/close", CloseHandler, 0); + + /* Add handler for /form (serve a file outside the document root) */ + mg_set_request_handler(ctx, + "/form", + FileHandler, + (void *)"../../test/form.html"); + + /* Add handler for form data */ + mg_set_request_handler(ctx, + "/handle_form.embedded_c.example.callback", + FormHandler, + (void *)0); + + /* Add a file upload handler for parsing files on the fly */ + mg_set_request_handler(ctx, + "/on_the_fly_form", + FileUploadForm, + (void *)"/on_the_fly_form.md5.callback"); + mg_set_request_handler(ctx, + "/on_the_fly_form.md5.callback", + CheckSumHandler, + (void *)0); + + /* Add handler for /cookie example */ + mg_set_request_handler(ctx, "/cookie", CookieHandler, 0); + + /* Add HTTP site to open a websocket connection */ + mg_set_request_handler(ctx, "/websocket", WebSocketStartHandler, 0); + +#ifdef USE_WEBSOCKET + /* WS site for the websocket connection */ + mg_set_websocket_handler(ctx, + "/websocket", + WebSocketConnectHandler, + WebSocketReadyHandler, + WebsocketDataHandler, + WebSocketCloseHandler, + 0); +#endif + + /* List all listening ports */ + memset(ports, 0, sizeof(ports)); + port_cnt = mg_get_server_ports(ctx, 32, ports); + printf("\n%i listening ports:\n\n", port_cnt); + + for (n = 0; n < port_cnt && n < 32; n++) { + const char *proto = ports[n].is_ssl ? "https" : "http"; + const char *host; + + if ((ports[n].protocol & 1) == 1) { + /* IPv4 */ + host = "127.0.0.1"; + printf("Browse files at %s://%s:%i/\n", proto, host, ports[n].port); + printf("Run example at %s://%s:%i%s\n", + proto, + host, + ports[n].port, + EXAMPLE_URI); + printf( + "Exit at %s://%s:%i%s\n", proto, host, ports[n].port, EXIT_URI); + printf("\n"); + } + + if ((ports[n].protocol & 2) == 2) { + /* IPv6 */ + host = "[::1]"; + printf("Browse files at %s://%s:%i/\n", proto, host, ports[n].port); + printf("Run example at %s://%s:%i%s\n", + proto, + host, + ports[n].port, + EXAMPLE_URI); + printf( + "Exit at %s://%s:%i%s\n", proto, host, ports[n].port, EXIT_URI); + printf("\n"); + } + } + + /* Wait until the server should be closed */ + while (!exitNow) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif +#ifdef USE_WEBSOCKET + InformWebsockets(ctx); +#endif + } + + /* Stop the server */ + mg_stop(ctx); + printf("Server stopped.\n"); + printf("Bye!\n"); + + return EXIT_SUCCESS; +}
