1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00

CivetWeb as a potential library.

This commit is contained in:
Sandu Liviu Catalin 2021-09-04 22:44:47 +03:00
parent d879999aeb
commit bc2260a0f0
21 changed files with 30501 additions and 1 deletions

View File

@ -89,6 +89,7 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
Library/Utils/Announce.cpp Library/Utils/Announce.hpp
Library/Utils/String.cpp Library/Utils/String.hpp
Library/Utils/Vector.cpp Library/Utils/Vector.hpp
Library/Web.cpp Library/Web.hpp
Library/XML.cpp Library/XML.hpp
Library/ZMQ.cpp Library/ZMQ.hpp
# Misc
@ -133,7 +134,7 @@ if(WIN32 OR MINGW)
target_link_libraries(SqModule wsock32 ws2_32 shlwapi)
endif()
# Link to base libraries
target_link_libraries(SqModule Squirrel fmt::fmt SimpleINI TinyDir xxHash ConcurrentQueue SAJSON CPR PUGIXML maxminddb libzmq-static)
target_link_libraries(SqModule Squirrel fmt::fmt SimpleINI TinyDir xxHash ConcurrentQueue SAJSON CPR PUGIXML CivetWeb maxminddb libzmq-static)
# Link to POCO libraries
target_link_libraries(SqModule Poco::Foundation Poco::Crypto Poco::Data Poco::Net Poco::JSON Poco::XML)
# Does POCO have SQLite support?

15
module/Library/Web.cpp Normal file
View File

@ -0,0 +1,15 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Web.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
// ================================================================================================
void Register_Web(HSQUIRRELVM vm)
{
}
} // Namespace:: SqMod

14
module/Library/Web.hpp Normal file
View File

@ -0,0 +1,14 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Core/Common.hpp"
// ------------------------------------------------------------------------------------------------
#include <civetweb.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
} // Namespace:: SqMod

View File

@ -41,6 +41,7 @@ extern void Register_Numeric(HSQUIRRELVM vm);
extern void Register_String(HSQUIRRELVM vm);
extern void Register_System(HSQUIRRELVM vm);
extern void Register_Utils(HSQUIRRELVM vm);
extern void Register_Web(HSQUIRRELVM vm);
extern void Register_XML(HSQUIRRELVM vm);
extern void Register_ZMQ(HSQUIRRELVM vm);
#ifdef SQMOD_POCO_HAS_SQLITE
@ -106,6 +107,7 @@ bool RegisterAPI(HSQUIRRELVM vm)
Register_String(vm);
Register_System(vm);
Register_Utils(vm);
Register_Web(vm);
Register_XML(vm);
Register_ZMQ(vm);
#ifdef SQMOD_POCO_HAS_SQLITE

View File

@ -7,6 +7,7 @@ add_subdirectory(TinyDir)
add_subdirectory(SAJSON)
add_subdirectory(CPR)
add_subdirectory(PUGIXML)
add_subdirectory(CivetWeb)
set(BUILD_TESTING OFF CACHE INTERNAL "" FORCE)
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE)
add_subdirectory(MaxmindDB)

48
vendor/CivetWeb/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,48 @@
# Create the CivetWeb library
add_library(CivetWeb STATIC
include/civetweb.h civetweb.c
include/CivetServer.h CivetServer.cpp
mod_mbedtls.inl
mod_zlib.inl
openssl_dl.inl
response.inl
sha1.inl
timer.inl
wolfssl_extras.inl
handle_form.inl
md5.inl
mod_http2.inl
)
# Configure include folders
target_include_directories(CivetWeb PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_include_directories(CivetWeb PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
# Configure macro options
if(WIN32 OR MINGW)
target_compile_definitions(CivetWeb PRIVATE _WIN32_WINNT=0x0601)
endif()
# Generic macro options
target_compile_definitions(CivetWeb PRIVATE USE_TIMERS=1 USE_WEBSOCKET=1 USE_IPV6=1)
# Look for SSL
find_package(OpenSSL)
# Check SSL status
if (OPENSSL_FOUND)
message(STATUS "CivetWeb: OpenSSL was found")
target_link_libraries(CivetWeb PUBLIC OpenSSL::Crypto OpenSSL::SSL)
string(REPLACE "." ";" OPENSSL_VERSION_LIST ${OPENSSL_VERSION})
list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_PATCH)
# Tell the library what SSL version to expect
target_compile_definitions(CivetWeb PRIVATE "OPENSSL_API_${OPENSSL_VERSION_MAJOR}_${OPENSSL_VERSION_MINOR}")
message(STATUS "CivetWeb: OPENSSL_API_${OPENSSL_VERSION_MAJOR}_${OPENSSL_VERSION_MINOR}")
else()
target_compile_definitions(CivetWeb PRIVATE NO_SSL=1)
endif()
# Look for ZLib
find_package(ZLIB)
# Check ZLib status
if (ZLIB_FOUND)
message(STATUS "CivetWeb: ZLib was found")
target_link_libraries(CivetWeb PUBLIC ZLIB::ZLIB)
target_compile_definitions(CivetWeb PRIVATE USE_ZLIB=1)
endif()

757
vendor/CivetWeb/CivetServer.cpp vendored Normal file
View File

@ -0,0 +1,757 @@
/* Copyright (c) 2013-2020 the Civetweb developers
* Copyright (c) 2013 No Face Press, LLC
*
* License http://opensource.org/licenses/mit-license.php MIT License
*/
#include "CivetServer.h"
#include <assert.h>
#include <stdexcept>
#include <string.h>
#ifndef UNUSED_PARAMETER
#define UNUSED_PARAMETER(x) (void)(x)
#endif
#ifndef MAX_PARAM_BODY_LENGTH
// Set a default limit for parameters in a form body: 2 MB
#define MAX_PARAM_BODY_LENGTH (1024 * 1024 * 2)
#endif
bool
CivetHandler::handleGet(CivetServer *server, struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return false;
}
bool
CivetHandler::handleGet(CivetServer *server,
struct mg_connection *conn,
int *status_code)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
if (status_code) {
*status_code = -1;
}
return false;
}
bool
CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return false;
}
bool
CivetHandler::handlePost(CivetServer *server,
struct mg_connection *conn,
int *status_code)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
if (status_code) {
*status_code = -1;
}
return false;
}
bool
CivetHandler::handleHead(CivetServer *server, struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return false;
}
bool
CivetHandler::handleHead(CivetServer *server,
struct mg_connection *conn,
int *status_code)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
if (status_code) {
*status_code = -1;
}
return false;
}
bool
CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return false;
}
bool
CivetHandler::handlePut(CivetServer *server,
struct mg_connection *conn,
int *status_code)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
if (status_code) {
*status_code = -1;
}
return false;
}
bool
CivetHandler::handlePatch(CivetServer *server, struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return false;
}
bool
CivetHandler::handlePatch(CivetServer *server,
struct mg_connection *conn,
int *status_code)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
if (status_code) {
*status_code = -1;
}
return false;
}
bool
CivetHandler::handleDelete(CivetServer *server, struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return false;
}
bool
CivetHandler::handleDelete(CivetServer *server,
struct mg_connection *conn,
int *status_code)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
if (status_code) {
*status_code = -1;
}
return false;
}
bool
CivetHandler::handleOptions(CivetServer *server, struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return false;
}
bool
CivetHandler::handleOptions(CivetServer *server,
struct mg_connection *conn,
int *status_code)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
if (status_code) {
*status_code = -1;
}
return false;
}
bool
CivetWebSocketHandler::handleConnection(CivetServer *server,
const struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return true;
}
void
CivetWebSocketHandler::handleReadyState(CivetServer *server,
struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return;
}
bool
CivetWebSocketHandler::handleData(CivetServer *server,
struct mg_connection *conn,
int bits,
char *data,
size_t data_len)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
UNUSED_PARAMETER(bits);
UNUSED_PARAMETER(data);
UNUSED_PARAMETER(data_len);
return true;
}
void
CivetWebSocketHandler::handleClose(CivetServer *server,
const struct mg_connection *conn)
{
UNUSED_PARAMETER(server);
UNUSED_PARAMETER(conn);
return;
}
int
CivetServer::requestHandler(struct mg_connection *conn, void *cbdata)
{
const struct mg_request_info *request_info = mg_get_request_info(conn);
assert(request_info != NULL);
CivetServer *me = (CivetServer *)(request_info->user_data);
assert(me != NULL);
int http_status_code = -1;
bool status_ok = false;
// Happens when a request hits the server before the context is saved
if (me->context == NULL)
return 0;
mg_lock_context(me->context);
me->connections[conn] = CivetConnection();
mg_unlock_context(me->context);
CivetHandler *handler = (CivetHandler *)cbdata;
if (handler) {
if (strcmp(request_info->request_method, "GET") == 0) {
status_ok = handler->handleGet(me, conn, &http_status_code);
if (http_status_code < 0) {
status_ok = handler->handleGet(me, conn);
}
} else if (strcmp(request_info->request_method, "POST") == 0) {
status_ok = handler->handlePost(me, conn, &http_status_code);
if (http_status_code < 0) {
status_ok = handler->handlePost(me, conn);
}
} else if (strcmp(request_info->request_method, "HEAD") == 0) {
status_ok = handler->handleHead(me, conn, &http_status_code);
if (http_status_code < 0) {
status_ok = handler->handleHead(me, conn);
}
} else if (strcmp(request_info->request_method, "PUT") == 0) {
status_ok = handler->handlePut(me, conn, &http_status_code);
if (http_status_code < 0) {
status_ok = handler->handlePut(me, conn);
}
} else if (strcmp(request_info->request_method, "DELETE") == 0) {
status_ok = handler->handleDelete(me, conn, &http_status_code);
if (http_status_code < 0) {
status_ok = handler->handleDelete(me, conn);
}
} else if (strcmp(request_info->request_method, "OPTIONS") == 0) {
status_ok = handler->handleOptions(me, conn, &http_status_code);
if (http_status_code < 0) {
status_ok = handler->handleOptions(me, conn);
}
} else if (strcmp(request_info->request_method, "PATCH") == 0) {
status_ok = handler->handlePatch(me, conn, &http_status_code);
if (http_status_code < 0) {
status_ok = handler->handlePatch(me, conn);
}
}
}
if (http_status_code < 0) {
http_status_code = status_ok ? 1 : 0;
}
return http_status_code;
}
int
CivetServer::authHandler(struct mg_connection *conn, void *cbdata)
{
const struct mg_request_info *request_info = mg_get_request_info(conn);
assert(request_info != NULL);
CivetServer *me = (CivetServer *)(request_info->user_data);
assert(me != NULL);
// Happens when a request hits the server before the context is saved
if (me->context == NULL)
return 0;
mg_lock_context(me->context);
me->connections[conn] = CivetConnection();
mg_unlock_context(me->context);
CivetAuthHandler *handler = (CivetAuthHandler *)cbdata;
if (handler) {
return handler->authorize(me, conn) ? 1 : 0;
}
return 0; // No handler found
}
int
CivetServer::webSocketConnectionHandler(const struct mg_connection *conn,
void *cbdata)
{
const struct mg_request_info *request_info = mg_get_request_info(conn);
assert(request_info != NULL);
CivetServer *me = (CivetServer *)(request_info->user_data);
assert(me != NULL);
// Happens when a request hits the server before the context is saved
if (me->context == NULL)
return 0;
CivetWebSocketHandler *handler = (CivetWebSocketHandler *)cbdata;
if (handler) {
return handler->handleConnection(me, conn) ? 0 : 1;
}
return 1; // No handler found, close connection
}
void
CivetServer::webSocketReadyHandler(struct mg_connection *conn, void *cbdata)
{
const struct mg_request_info *request_info = mg_get_request_info(conn);
assert(request_info != NULL);
CivetServer *me = (CivetServer *)(request_info->user_data);
assert(me != NULL);
// Happens when a request hits the server before the context is saved
if (me->context == NULL)
return;
CivetWebSocketHandler *handler = (CivetWebSocketHandler *)cbdata;
if (handler) {
handler->handleReadyState(me, conn);
}
}
int
CivetServer::webSocketDataHandler(struct mg_connection *conn,
int bits,
char *data,
size_t data_len,
void *cbdata)
{
const struct mg_request_info *request_info = mg_get_request_info(conn);
assert(request_info != NULL);
CivetServer *me = (CivetServer *)(request_info->user_data);
assert(me != NULL);
// Happens when a request hits the server before the context is saved
if (me->context == NULL)
return 0;
CivetWebSocketHandler *handler = (CivetWebSocketHandler *)cbdata;
if (handler) {
return handler->handleData(me, conn, bits, data, data_len) ? 1 : 0;
}
return 1; // No handler found
}
void
CivetServer::webSocketCloseHandler(const struct mg_connection *conn,
void *cbdata)
{
const struct mg_request_info *request_info = mg_get_request_info(conn);
assert(request_info != NULL);
CivetServer *me = (CivetServer *)(request_info->user_data);
assert(me != NULL);
// Happens when a request hits the server before the context is saved
if (me->context == NULL)
return;
CivetWebSocketHandler *handler = (CivetWebSocketHandler *)cbdata;
if (handler) {
handler->handleClose(me, conn);
}
}
CivetCallbacks::CivetCallbacks()
{
memset(this, 0, sizeof(*this));
}
CivetServer::CivetServer(const char **options,
const struct CivetCallbacks *_callbacks,
const void *UserContextIn)
: context(0)
{
struct CivetCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
UserContext = UserContextIn;
if (_callbacks) {
callbacks = *_callbacks;
userCloseHandler = _callbacks->connection_close;
} else {
userCloseHandler = NULL;
}
callbacks.connection_close = closeHandler;
context = mg_start(&callbacks, this, options);
if (context == NULL) {
throw CivetException("null context when constructing CivetServer. "
"Possible problem binding to port.");
}
}
CivetServer::CivetServer(const std::vector<std::string> &options,
const struct CivetCallbacks *_callbacks,
const void *UserContextIn)
: context(0)
{
struct CivetCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
UserContext = UserContextIn;
if (_callbacks) {
callbacks = *_callbacks;
userCloseHandler = _callbacks->connection_close;
} else {
userCloseHandler = NULL;
}
callbacks.connection_close = closeHandler;
std::vector<const char *> pointers(options.size() + 1);
for (size_t i = 0; i < options.size(); i++) {
pointers[i] = (options[i].c_str());
}
pointers.back() = NULL;
context = mg_start(&callbacks, this, &pointers[0]);
if (context == NULL)
throw CivetException("null context when constructing CivetServer. "
"Possible problem binding to port.");
}
CivetServer::~CivetServer()
{
close();
}
void
CivetServer::closeHandler(const struct mg_connection *conn)
{
CivetServer *me = (CivetServer *)mg_get_user_data(mg_get_context(conn));
assert(me != NULL);
// Happens when a request hits the server before the context is saved
if (me->context == NULL)
return;
if (me->userCloseHandler) {
me->userCloseHandler(conn);
}
mg_lock_context(me->context);
me->connections.erase(conn);
mg_unlock_context(me->context);
}
void
CivetServer::addHandler(const std::string &uri, CivetHandler *handler)
{
mg_set_request_handler(context, uri.c_str(), requestHandler, handler);
}
void
CivetServer::addWebSocketHandler(const std::string &uri,
CivetWebSocketHandler *handler)
{
mg_set_websocket_handler(context,
uri.c_str(),
webSocketConnectionHandler,
webSocketReadyHandler,
webSocketDataHandler,
webSocketCloseHandler,
handler);
}
void
CivetServer::addAuthHandler(const std::string &uri, CivetAuthHandler *handler)
{
mg_set_auth_handler(context, uri.c_str(), authHandler, handler);
}
void
CivetServer::removeHandler(const std::string &uri)
{
mg_set_request_handler(context, uri.c_str(), NULL, NULL);
}
void
CivetServer::removeWebSocketHandler(const std::string &uri)
{
mg_set_websocket_handler(
context, uri.c_str(), NULL, NULL, NULL, NULL, NULL);
}
void
CivetServer::removeAuthHandler(const std::string &uri)
{
mg_set_auth_handler(context, uri.c_str(), NULL, NULL);
}
void
CivetServer::close()
{
if (context) {
mg_stop(context);
context = 0;
}
}
int
CivetServer::getCookie(struct mg_connection *conn,
const std::string &cookieName,
std::string &cookieValue)
{
// Maximum cookie length as per microsoft is 4096.
// http://msdn.microsoft.com/en-us/library/ms178194.aspx
char _cookieValue[4096];
const char *cookie = mg_get_header(conn, "Cookie");
int lRead = mg_get_cookie(cookie,
cookieName.c_str(),
_cookieValue,
sizeof(_cookieValue));
cookieValue.clear();
cookieValue.append(_cookieValue);
return lRead;
}
const char *
CivetServer::getHeader(struct mg_connection *conn,
const std::string &headerName)
{
return mg_get_header(conn, headerName.c_str());
}
const char *
CivetServer::getMethod(struct mg_connection *conn)
{
const struct mg_request_info *request_info = mg_get_request_info(conn);
assert(request_info != NULL);
return request_info->request_method;
}
void
CivetServer::urlDecode(const char *src,
std::string &dst,
bool is_form_url_encoded)
{
urlDecode(src, strlen(src), dst, is_form_url_encoded);
}
void
CivetServer::urlDecode(const char *src,
size_t src_len,
std::string &dst,
bool is_form_url_encoded)
{
// assign enough buffer
std::vector<char> buf(src_len + 1);
int r = mg_url_decode(src,
static_cast<int>(src_len),
&buf[0],
static_cast<int>(buf.size()),
is_form_url_encoded);
if (r < 0) {
// never reach here
throw std::out_of_range("");
}
// dst can contain NUL characters
dst.assign(buf.begin(), buf.begin() + r);
}
bool
CivetServer::getParam(struct mg_connection *conn,
const char *name,
std::string &dst,
size_t occurrence)
{
const char *formParams = NULL;
const char *queryString = NULL;
const struct mg_request_info *ri = mg_get_request_info(conn);
assert(ri != NULL);
CivetServer *me = (CivetServer *)(ri->user_data);
assert(me != NULL);
mg_lock_context(me->context);
CivetConnection &conobj = me->connections[conn];
mg_unlock_context(me->context);
mg_lock_connection(conn);
if (conobj.postData.empty()) {
// check if there is a request body
for (;;) {
char buf[2048];
int r = mg_read(conn, buf, sizeof(buf));
try {
if (r == 0) {
conobj.postData.push_back('\0');
break;
} else if ((r < 0)
|| ((conobj.postData.size() + r)
> MAX_PARAM_BODY_LENGTH)) {
conobj.postData.assign(1, '\0');
break;
}
conobj.postData.insert(conobj.postData.end(), buf, buf + r);
} catch (...) {
conobj.postData.clear();
break;
}
}
}
if (!conobj.postData.empty()) {
// check if form parameter are already stored
formParams = &conobj.postData[0];
}
if (ri->query_string != NULL) {
// get requests do store html <form> field values in the http
// query_string
queryString = ri->query_string;
}
mg_unlock_connection(conn);
bool get_param_success = false;
if (formParams != NULL) {
get_param_success =
getParam(formParams, strlen(formParams), name, dst, occurrence);
}
if (!get_param_success && queryString != NULL) {
get_param_success =
getParam(queryString, strlen(queryString), name, dst, occurrence);
}
return get_param_success;
}
bool
CivetServer::getParam(const char *data,
size_t data_len,
const char *name,
std::string &dst,
size_t occurrence)
{
char buf[256];
int r = mg_get_var2(data, data_len, name, buf, sizeof(buf), occurrence);
if (r >= 0) {
// dst can contain NUL characters
dst.assign(buf, r);
return true;
} else if (r == -2) {
// more buffer
std::vector<char> vbuf(sizeof(buf) * 2);
for (;;) {
r = mg_get_var2(
data, data_len, name, &vbuf[0], vbuf.size(), occurrence);
if (r >= 0) {
dst.assign(vbuf.begin(), vbuf.begin() + r);
return true;
} else if (r != -2) {
break;
}
// more buffer
vbuf.resize(vbuf.size() * 2);
}
}
dst.clear();
return false;
}
std::string
CivetServer::getPostData(struct mg_connection *conn)
{
mg_lock_connection(conn);
std::string postdata;
char buf[2048];
int r = mg_read(conn, buf, sizeof(buf));
while (r > 0) {
postdata.append(buf, r);
r = mg_read(conn, buf, sizeof(buf));
}
mg_unlock_connection(conn);
return postdata;
}
void
CivetServer::urlEncode(const char *src, std::string &dst, bool append)
{
urlEncode(src, strlen(src), dst, append);
}
void
CivetServer::urlEncode(const char *src,
size_t src_len,
std::string &dst,
bool append)
{
if (!append)
dst.clear();
for (; src_len > 0; src++, src_len--) {
if (*src == '\0') {
// src and dst can contain NUL characters without encoding
dst.push_back(*src);
} else {
char buf[2] = {*src, '\0'};
char dst_buf[4];
if (mg_url_encode(buf, dst_buf, sizeof(dst_buf)) < 0) {
// never reach here
throw std::out_of_range("");
}
dst.append(dst_buf);
}
}
}
std::vector<int>
CivetServer::getListeningPorts()
{
std::vector<struct mg_server_port> server_ports = getListeningPortsFull();
std::vector<int> ports(server_ports.size());
for (size_t i = 0; i < server_ports.size(); i++) {
ports[i] = server_ports[i].port;
}
return ports;
}
std::vector<struct mg_server_port>
CivetServer::getListeningPortsFull()
{
std::vector<struct mg_server_port> server_ports(8);
for (;;) {
int size = mg_get_server_ports(context,
static_cast<int>(server_ports.size()),
&server_ports[0]);
if (size < static_cast<int>(server_ports.size())) {
server_ports.resize(size < 0 ? 0 : size);
break;
}
server_ports.resize(server_ports.size() * 2);
}
return server_ports;
}

248
vendor/CivetWeb/LICENSE.md vendored Normal file
View File

@ -0,0 +1,248 @@
ALL LICENSES
=====
This document includes several copyright licenses for different
aspects of the software. Not all licenses may apply depending
on the features chosen.
Civetweb License
-----
### Included with all features.
> Copyright (c) 2013-2021 The CivetWeb developers ([CREDITS.md](https://github.com/civetweb/civetweb/blob/master/CREDITS.md))
>
> Copyright (c) 2004-2013 Sergey Lyubka
>
> Copyright (c) 2013 No Face Press, LLC (Thomas Davis)
>
> Copyright (c) 2013 F-Secure Corporation
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
Lua License
------
### Included only if built with Lua support.
http://www.lua.org/license.html
> Copyright (C) 1994-2020 Lua.org, PUC-Rio.
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
SQLite3 License
------
### Included only if built with Lua and SQLite support.
http://www.sqlite.org/copyright.html
> 2001-09-15
>
> The author disclaims copyright to this source code. In place of
> a legal notice, here is a blessing:
>
> May you do good and not evil.
> May you find forgiveness for yourself and forgive others.
> May you share freely, never taking more than you give.
lsqlite3 License
------
### Included only if built with Lua and SQLite support.
> Copyright (C) 2002-2016 Tiago Dionizio, Doug Currie
> All rights reserved.
> Author : Tiago Dionizio <tiago.dionizio@ist.utl.pt>
> Author : Doug Currie <doug.currie@alum.mit.edu>
> Library : lsqlite3 - an SQLite 3 database binding for Lua 5
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
Lua File System License
------
### Included only if built with Lua support.
https://github.com/keplerproject/luafilesystem/blob/master/LICENSE
> Copyright © 2003-2020 Kepler Project.
>
> Permission is hereby granted, free of charge, to any person
> obtaining a copy of this software and associated documentation
> files (the "Software"), to deal in the Software without
> restriction, including without limitation the rights to use, copy,
> modify, merge, publish, distribute, sublicense, and/or sell copies
> of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
LuaXML License
------
### Included only if built with Lua and LuaXML support.
Version 1.8.0 (Lua 5.2), 2013-06-10 by Gerald Franz, eludi.net
Modified and extended 2015 by Bernhard Nortmann, https://github.com/n1tehawk/LuaXML version 2.0.x, compatible with Lua 5.1 to 5.3 and LuaJIT.
> LuaXML License
>
> LuaXml is licensed under the terms of the MIT license reproduced below,
> the same as Lua itself. This means that LuaXml is free software and can be
> used for both academic and commercial purposes at absolutely no cost.
>
> Copyright (C) 2007-2013 Gerald Franz, eludi.net
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
Duktape License
------
### Included only if built with Duktape support.
https://github.com/svaarala/duktape/blob/master/LICENSE.txt
> ===============
> Duktape license
> ===============
>
> (http://opensource.org/licenses/MIT)
>
> Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst)
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
zlib License
------
### Included only if built with zlib support.
https://www.zlib.net/zlib_license.html
> zlib.h -- interface of the 'zlib' general purpose compression library
> version 1.2.11, January 15th, 2017
>
> Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
>
> This software is provided 'as-is', without any express or implied
> warranty. In no event will the authors be held liable for any damages
> arising from the use of this software.
>
> Permission is granted to anyone to use this software for any purpose,
> including commercial applications, and to alter it and redistribute it
> freely, subject to the following restrictions:
>
> 1. The origin of this software must not be misrepresented; you must not
> claim that you wrote the original software. If you use this software
> in a product, an acknowledgment in the product documentation would be
> appreciated but is not required.
> 2. Altered source versions must be plainly marked as such, and must not be
> misrepresented as being the original software.
> 3. This notice may not be removed or altered from any source distribution.
>
> Jean-loup Gailly Mark Adler
> jloup@gzip.org madler@alumni.caltech.edu

21475
vendor/CivetWeb/civetweb.c vendored Normal file

File diff suppressed because it is too large Load Diff

1082
vendor/CivetWeb/handle_form.inl vendored Normal file

File diff suppressed because it is too large Load Diff

736
vendor/CivetWeb/include/CivetServer.h vendored Normal file
View File

@ -0,0 +1,736 @@
/* Copyright (c) 2013-2017 the Civetweb developers
* Copyright (c) 2013 No Face Press, LLC
*
* License http://opensource.org/licenses/mit-license.php MIT License
*/
#ifndef CIVETSERVER_HEADER_INCLUDED
#define CIVETSERVER_HEADER_INCLUDED
#ifdef __cplusplus
#include "civetweb.h"
#include <map>
#include <stdexcept>
#include <string>
#include <vector>
#ifndef CIVETWEB_CXX_API
#if defined(_WIN32)
#if defined(CIVETWEB_CXX_DLL_EXPORTS)
#define CIVETWEB_CXX_API __declspec(dllexport)
#elif defined(CIVETWEB_CXX_DLL_IMPORTS)
#define CIVETWEB_CXX_API __declspec(dllimport)
#else
#define CIVETWEB_CXX_API
#endif
#elif __GNUC__ >= 4
#define CIVETWEB_CXX_API __attribute__((visibility("default")))
#else
#define CIVETWEB_CXX_API
#endif
#endif
// forward declaration
class CivetServer;
/**
* Exception class for thrown exceptions within the CivetHandler object.
*/
class CIVETWEB_CXX_API CivetException : public std::runtime_error
{
public:
CivetException(const std::string &msg) : std::runtime_error(msg)
{
}
};
/**
* Basic interface for a URI request handler. Handlers implementations
* must be reentrant.
*/
class CIVETWEB_CXX_API CivetHandler
{
public:
/**
* Destructor
*/
virtual ~CivetHandler()
{
}
/**
* Callback method for GET request.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true if implemented, false otherwise
*/
virtual bool handleGet(CivetServer *server, struct mg_connection *conn);
/**
* Callback method for GET request.
*
* @param server - the calling server
* @param conn - the connection information
* @param http - pointer to return status code
* @returns true if implemented, false otherwise
*/
virtual bool handleGet(CivetServer *server,
struct mg_connection *conn,
int *status_code);
/**
* Callback method for POST request.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true if implemented, false otherwise
*/
virtual bool handlePost(CivetServer *server, struct mg_connection *conn);
/**
* Callback method for POST request.
*
* @param server - the calling server
* @param conn - the connection information
* @param http - pointer to return status code
* @returns true if implemented, false otherwise
*/
virtual bool handlePost(CivetServer *server,
struct mg_connection *conn,
int *status_code);
/**
* Callback method for HEAD request.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true if implemented, false otherwise
*/
virtual bool handleHead(CivetServer *server, struct mg_connection *conn);
/**
* Callback method for HEAD request.
*
* @param server - the calling server
* @param conn - the connection information
* @param http - pointer to return status code
* @returns true if implemented, false otherwise
*/
virtual bool handleHead(CivetServer *server,
struct mg_connection *conn,
int *status_code);
/**
* Callback method for PUT request.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true if implemented, false otherwise
*/
virtual bool handlePut(CivetServer *server, struct mg_connection *conn);
/**
* Callback method for PUT request.
*
* @param server - the calling server
* @param conn - the connection information
* @param http - pointer to return status code
* @returns true if implemented, false otherwise
*/
virtual bool handlePut(CivetServer *server,
struct mg_connection *conn,
int *status_code);
/**
* Callback method for DELETE request.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true if implemented, false otherwise
*/
virtual bool handleDelete(CivetServer *server, struct mg_connection *conn);
/**
* Callback method for DELETE request.
*
* @param server - the calling server
* @param conn - the connection information
* @param http - pointer to return status code
* @returns true if implemented, false otherwise
*/
virtual bool handleDelete(CivetServer *server,
struct mg_connection *conn,
int *status_code);
/**
* Callback method for OPTIONS request.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true if implemented, false otherwise
*/
virtual bool handleOptions(CivetServer *server, struct mg_connection *conn);
/**
* Callback method for OPTIONS request.
*
* @param server - the calling server
* @param conn - the connection information
* @param http - pointer to return status code
* @returns true if implemented, false otherwise
*/
virtual bool handleOptions(CivetServer *server,
struct mg_connection *conn,
int *status_code);
/**
* Callback method for PATCH request.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true if implemented, false otherwise
*/
virtual bool handlePatch(CivetServer *server, struct mg_connection *conn);
/**
* Callback method for PATCH request.
*
* @param server - the calling server
* @param conn - the connection information
* @param http - pointer to return status code
* @returns true if implemented, false otherwise
*/
virtual bool handlePatch(CivetServer *server,
struct mg_connection *conn,
int *status_code);
};
/**
* Basic interface for a URI authorization handler. Handler implementations
* must be reentrant.
*/
class CIVETWEB_CXX_API CivetAuthHandler
{
public:
/**
* Destructor
*/
virtual ~CivetAuthHandler()
{
}
/**
* Callback method for authorization requests. It is up the this handler
* to generate 401 responses if authorization fails.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true if authorization succeeded, false otherwise
*/
virtual bool authorize(CivetServer *server, struct mg_connection *conn) = 0;
};
/**
* Basic interface for a websocket handler. Handlers implementations
* must be reentrant.
*/
class CIVETWEB_CXX_API CivetWebSocketHandler
{
public:
/**
* Destructor
*/
virtual ~CivetWebSocketHandler()
{
}
/**
* Callback method for when the client intends to establish a websocket
*connection, before websocket handshake.
*
* @param server - the calling server
* @param conn - the connection information
* @returns true to keep socket open, false to close it
*/
virtual bool handleConnection(CivetServer *server,
const struct mg_connection *conn);
/**
* Callback method for when websocket handshake is successfully completed,
*and connection is ready for data exchange.
*
* @param server - the calling server
* @param conn - the connection information
*/
virtual void handleReadyState(CivetServer *server,
struct mg_connection *conn);
/**
* Callback method for when a data frame has been received from the client.
*
* @param server - the calling server
* @param conn - the connection information
* @bits: first byte of the websocket frame, see websocket RFC at
*http://tools.ietf.org/html/rfc6455, section 5.2
* @data, data_len: payload, with mask (if any) already applied.
* @returns true to keep socket open, false to close it
*/
virtual bool handleData(CivetServer *server,
struct mg_connection *conn,
int bits,
char *data,
size_t data_len);
/**
* Callback method for when the connection is closed.
*
* @param server - the calling server
* @param conn - the connection information
*/
virtual void handleClose(CivetServer *server,
const struct mg_connection *conn);
};
/**
* CivetCallbacks
*
* wrapper for mg_callbacks
*/
struct CIVETWEB_CXX_API CivetCallbacks : public mg_callbacks {
CivetCallbacks();
};
/**
* CivetServer
*
* Basic class for embedded web server. This has an URL mapping built-in.
*/
class CIVETWEB_CXX_API CivetServer
{
public:
/**
* Constructor
*
* This automatically starts the sever.
* It is good practice to call getContext() after this in case there
* were errors starting the server.
*
* Note: CivetServer should not be used as a static instance in a Windows
* DLL, since the constructor creates threads and the destructor joins
* them again (creating/joining threads should not be done in static
* constructors).
*
* @param options - the web server options.
* @param callbacks - optional web server callback methods.
*
* @throws CivetException
*/
CivetServer(const char **options,
const struct CivetCallbacks *callbacks = 0,
const void *UserContext = 0);
CivetServer(const std::vector<std::string> &options,
const struct CivetCallbacks *callbacks = 0,
const void *UserContext = 0);
/**
* Destructor
*/
virtual ~CivetServer();
/**
* close()
*
* Stops server and frees resources.
*/
void close();
/**
* getContext()
*
* @return the context or 0 if not running.
*/
const struct mg_context *
getContext() const
{
return context;
}
/**
* addHandler(const std::string &, CivetHandler *)
*
* Adds a URI handler. If there is existing URI handler, it will
* be replaced with this one.
*
* URI's are ordered and prefix (REST) URI's are supported.
*
* @param uri - URI to match.
* @param handler - handler instance to use.
*/
void addHandler(const std::string &uri, CivetHandler *handler);
void
addHandler(const std::string &uri, CivetHandler &handler)
{
addHandler(uri, &handler);
}
/**
* addWebSocketHandler
*
* Adds a WebSocket handler for a specific URI. If there is existing URI
*handler, it will
* be replaced with this one.
*
* URI's are ordered and prefix (REST) URI's are supported.
*
* @param uri - URI to match.
* @param handler - handler instance to use.
*/
void addWebSocketHandler(const std::string &uri,
CivetWebSocketHandler *handler);
void
addWebSocketHandler(const std::string &uri, CivetWebSocketHandler &handler)
{
addWebSocketHandler(uri, &handler);
}
/**
* removeHandler(const std::string &)
*
* Removes a handler.
*
* @param uri - the exact URL used in addHandler().
*/
void removeHandler(const std::string &uri);
/**
* removeWebSocketHandler(const std::string &)
*
* Removes a web socket handler.
*
* @param uri - the exact URL used in addWebSocketHandler().
*/
void removeWebSocketHandler(const std::string &uri);
/**
* addAuthHandler(const std::string &, CivetAuthHandler *)
*
* Adds a URI authorization handler. If there is existing URI authorization
* handler, it will be replaced with this one.
*
* URI's are ordered and prefix (REST) URI's are supported.
*
* @param uri - URI to match.
* @param handler - authorization handler instance to use.
*/
void addAuthHandler(const std::string &uri, CivetAuthHandler *handler);
void
addAuthHandler(const std::string &uri, CivetAuthHandler &handler)
{
addAuthHandler(uri, &handler);
}
/**
* removeAuthHandler(const std::string &)
*
* Removes an authorization handler.
*
* @param uri - the exact URL used in addAuthHandler().
*/
void removeAuthHandler(const std::string &uri);
/**
* getListeningPorts()
*
* Returns a list of ports that are listening
*
* @return A vector of ports
*/
std::vector<int> getListeningPorts();
/**
* getListeningPorts()
*
* Variant of getListeningPorts() returning the full port information
* (protocol, SSL, ...)
*
* @return A vector of ports
*/
std::vector<struct mg_server_port> getListeningPortsFull();
/**
* getCookie(struct mg_connection *conn, const std::string &cookieName,
* std::string &cookieValue)
*
* Puts the cookie value string that matches the cookie name in the
* cookieValue destination string.
*
* @param conn - the connection information
* @param cookieName - cookie name to get the value from
* @param cookieValue - cookie value is returned using this reference
* @returns the size of the cookie value string read.
*/
static int getCookie(struct mg_connection *conn,
const std::string &cookieName,
std::string &cookieValue);
/**
* getHeader(struct mg_connection *conn, const std::string &headerName)
* @param conn - the connection information
* @param headerName - header name to get the value from
* @returns a char array which contains the header value as string
*/
static const char *getHeader(struct mg_connection *conn,
const std::string &headerName);
/**
* getMethod(struct mg_connection *conn)
* @param conn - the connection information
* @returns method of HTTP request
*/
static const char *getMethod(struct mg_connection *conn);
/**
* getParam(struct mg_connection *conn, const char *, std::string &, size_t)
*
* Returns a query which contained in the supplied buffer. The
* occurrence value is a zero-based index of a particular key name. This
* should not be confused with the index over all of the keys. Note that
*this
* function assumes that parameters are sent as text in http query string
* format, which is the default for web forms. This function will work for
* html forms with method="GET" and method="POST" attributes. In other
*cases,
* you may use a getParam version that directly takes the data instead of
*the
* connection as a first argument.
*
* @param conn - parameters are read from the data sent through this
*connection
* @param name - the key to search for
* @param dst - the destination string
* @param occurrence - the occurrence of the selected name in the query (0
*based).
* @return true if key was found
*/
static bool getParam(struct mg_connection *conn,
const char *name,
std::string &dst,
size_t occurrence = 0);
/**
* getParam(const std::string &, const char *, std::string &, size_t)
*
* Returns a query parameter contained in the supplied buffer. The
* occurrence value is a zero-based index of a particular key name. This
* should not be confused with the index over all of the keys.
*
* @param data - the query string (text)
* @param name - the key to search for
* @param dst - the destination string
* @param occurrence - the occurrence of the selected name in the query (0
*based).
* @return true if key was found
*/
static bool
getParam(const std::string &data,
const char *name,
std::string &dst,
size_t occurrence = 0)
{
return getParam(data.c_str(), data.length(), name, dst, occurrence);
}
/**
* getParam(const char *, size_t, const char *, std::string &, size_t)
*
* Returns a query parameter contained in the supplied buffer. The
* occurrence value is a zero-based index of a particular key name. This
* should not be confused with the index over all of the keys.
*
* @param data the - query string (text)
* @param data_len - length of the query string
* @param name - the key to search for
* @param dst - the destination string
* @param occurrence - the occurrence of the selected name in the query (0
*based).
* @return true if key was found
*/
static bool getParam(const char *data,
size_t data_len,
const char *name,
std::string &dst,
size_t occurrence = 0);
/**
* getPostData(struct mg_connection *)
*
* Returns response body from a request made as POST. Since the
* connections map is protected, it can't be directly accessed.
* This uses string to store post data to handle big posts.
*
* @param conn - connection from which post data will be read
* @return Post data (empty if not available).
*/
static std::string getPostData(struct mg_connection *conn);
/**
* urlDecode(const std::string &, std::string &, bool)
*
* @param src - string to be decoded
* @param dst - destination string
* @param is_form_url_encoded - true if form url encoded
* form-url-encoded data differs from URI encoding in a way that it
* uses '+' as character for space, see RFC 1866 section 8.2.1
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
*/
static void
urlDecode(const std::string &src,
std::string &dst,
bool is_form_url_encoded = true)
{
urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
}
/**
* urlDecode(const char *, size_t, std::string &, bool)
*
* @param src - buffer to be decoded
* @param src_len - length of buffer to be decoded
* @param dst - destination string
* @param is_form_url_encoded - true if form url encoded
* form-url-encoded data differs from URI encoding in a way that it
* uses '+' as character for space, see RFC 1866 section 8.2.1
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
*/
static void urlDecode(const char *src,
size_t src_len,
std::string &dst,
bool is_form_url_encoded = true);
/**
* urlDecode(const char *, std::string &, bool)
*
* @param src - buffer to be decoded (0 terminated)
* @param dst - destination string
* @param is_form_url_encoded true - if form url encoded
* form-url-encoded data differs from URI encoding in a way that it
* uses '+' as character for space, see RFC 1866 section 8.2.1
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
*/
static void urlDecode(const char *src,
std::string &dst,
bool is_form_url_encoded = true);
/**
* urlEncode(const std::string &, std::string &, bool)
*
* @param src - buffer to be encoded
* @param dst - destination string
* @param append - true if string should not be cleared before encoding.
*/
static void
urlEncode(const std::string &src, std::string &dst, bool append = false)
{
urlEncode(src.c_str(), src.length(), dst, append);
}
/**
* urlEncode(const char *, size_t, std::string &, bool)
*
* @param src - buffer to be encoded (0 terminated)
* @param dst - destination string
* @param append - true if string should not be cleared before encoding.
*/
static void
urlEncode(const char *src, std::string &dst, bool append = false);
/**
* urlEncode(const char *, size_t, std::string &, bool)
*
* @param src - buffer to be encoded
* @param src_len - length of buffer to be decoded
* @param dst - destination string
* @param append - true if string should not be cleared before encoding.
*/
static void urlEncode(const char *src,
size_t src_len,
std::string &dst,
bool append = false);
// generic user context which can be set/read,
// the server does nothing with this apart from keep it.
const void *
getUserContext() const
{
return UserContext;
}
protected:
class CivetConnection
{
public:
std::vector<char> postData;
};
struct mg_context *context;
std::map<const struct mg_connection *, CivetConnection> connections;
// generic user context which can be set/read,
// the server does nothing with this apart from keep it.
const void *UserContext;
private:
/**
* requestHandler(struct mg_connection *, void *cbdata)
*
* Handles the incoming request.
*
* @param conn - the connection information
* @param cbdata - pointer to the CivetHandler instance.
* @returns 0 if implemented, false otherwise
*/
static int requestHandler(struct mg_connection *conn, void *cbdata);
static int webSocketConnectionHandler(const struct mg_connection *conn,
void *cbdata);
static void webSocketReadyHandler(struct mg_connection *conn, void *cbdata);
static int webSocketDataHandler(struct mg_connection *conn,
int bits,
char *data,
size_t data_len,
void *cbdata);
static void webSocketCloseHandler(const struct mg_connection *conn,
void *cbdata);
/**
* authHandler(struct mg_connection *, void *cbdata)
*
* Handles the authorization requests.
*
* @param conn - the connection information
* @param cbdata - pointer to the CivetAuthHandler instance.
* @returns 1 if authorized, 0 otherwise
*/
static int authHandler(struct mg_connection *conn, void *cbdata);
/**
* closeHandler(struct mg_connection *)
*
* Handles closing a request (internal handler)
*
* @param conn - the connection information
*/
static void closeHandler(const struct mg_connection *conn);
/**
* Stores the user provided close handler
*/
void (*userCloseHandler)(const struct mg_connection *conn);
};
#endif /* __cplusplus */
#endif /* CIVETSERVER_HEADER_INCLUDED */

1712
vendor/CivetWeb/include/civetweb.h vendored Normal file

File diff suppressed because it is too large Load Diff

471
vendor/CivetWeb/md5.inl vendored Normal file
View File

@ -0,0 +1,471 @@
/*
* This an amalgamation of md5.c and md5.h into a single file
* with all static declaration to reduce linker conflicts
* in Civetweb.
*
* The MD5_STATIC declaration was added to facilitate static
* inclusion.
* No Face Press, LLC
*/
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.h is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
#if !defined(md5_INCLUDED)
#define md5_INCLUDED
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#if defined(__cplusplus)
extern "C" {
#endif
/* Initialize the algorithm. */
MD5_STATIC void md5_init(md5_state_t *pms);
/* Append a string to the message. */
MD5_STATIC void
md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes);
/* Finish the message and return the digest. */
MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#if defined(__cplusplus)
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */
/*
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.c is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
either statically or dynamically; added missing #include <string.h>
in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
unsigned in ANSI C, signed in traditional"; made test program
self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
*/
#if !defined(MD5_STATIC)
#include <string.h>
#endif
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#if defined(ARCH_IS_BIG_ENDIAN)
#define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
#define BYTE_ORDER (0)
#endif
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 (0x242070db)
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 (0x4787c62a)
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 (0x698098d8)
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 (0x6b901122)
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 (0x49b40821)
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 (0x265e5a51)
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 (0x02441453)
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 (0x21e1cde6)
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 (0x455a14ed)
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 (0x676f02d9)
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 (0x6d9d6122)
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 (0x4bdecfa9)
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 (0x289b7ec6)
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 (0x04881d05)
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 (0x1fa27cf8)
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 (0x432aff97)
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 (0x655b59c3)
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 (0x6fa87e4f)
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 (0x4e0811a1)
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 (0x2ad7d2bb)
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
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],
d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
md5_word_t X[16];
#else
/* Define storage for little-endian or both types of CPUs. */
md5_word_t xbuf[16];
const md5_word_t *X;
#endif
{
#if BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static const int w = 1;
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
#if BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (const md5_byte_t *)0) & 3)) {
/* data are properly aligned, a direct assignment is possible */
/* cast through a (void *) should avoid a compiler warning,
see
https://github.com/bel2125/civetweb/issues/94#issuecomment-98112861
*/
X = (const md5_word_t *)(const void *)data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if BYTE_ORDER == 0
else /* dynamic big-endian */
#endif
#if BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
#if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
#else
#define xbuf X /* (static only) */
#endif
for (i = 0; i < 16; ++i, xp += 4)
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);
}
#endif
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti) \
t = (a) + F(b, c, d) + X[k] + (Ti); \
(a) = ROTATE_LEFT(t, s) + (b)
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti) \
t = (a) + G(b, c, d) + X[k] + (Ti); \
(a) = ROTATE_LEFT(t, s) + (b)
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti) \
t = (a) + H(b, c, d) + X[k] + (Ti); \
(a) = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti) \
t = (a) + I(b, c, d) + X[k] + (Ti); \
(a) = ROTATE_LEFT(t, s) + (b)
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
MD5_STATIC void
md5_init(md5_state_t *pms)
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
MD5_STATIC void
md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes)
{
const md5_byte_t *p = data;
size_t left = nbytes;
size_t offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
/* Update the message length. */
pms->count[1] += (md5_word_t)(nbytes >> 29);
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
}
MD5_STATIC void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {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};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}
/* End of md5.inl */

1853
vendor/CivetWeb/mod_http2.inl vendored Normal file

File diff suppressed because it is too large Load Diff

239
vendor/CivetWeb/mod_mbedtls.inl vendored Normal file
View File

@ -0,0 +1,239 @@
#if defined(USE_MBEDTLS) // USE_MBEDTLS used with NO_SSL
#include "mbedtls/certs.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"
#include "mbedtls/entropy.h"
#include "mbedtls/error.h"
#include "mbedtls/net.h"
#include "mbedtls/pk.h"
#include "mbedtls/platform.h"
#include "mbedtls/ssl.h"
#include "mbedtls/x509.h"
#include "mbedtls/x509_crt.h"
#include <string.h>
typedef mbedtls_ssl_context SSL;
typedef struct {
mbedtls_ssl_config conf; /* SSL configuration */
mbedtls_x509_crt cert; /* Certificate */
mbedtls_ctr_drbg_context ctr; /* Counter random generator state */
mbedtls_entropy_context entropy; /* Entropy context */
mbedtls_pk_context pkey; /* Private key */
} SSL_CTX;
/* public api */
int mbed_sslctx_init(SSL_CTX *ctx, const char *crt);
void mbed_sslctx_uninit(SSL_CTX *ctx);
void mbed_ssl_close(mbedtls_ssl_context *ssl);
int mbed_ssl_accept(mbedtls_ssl_context **ssl,
SSL_CTX *ssl_ctx,
int *sock,
struct mg_context *phys_ctx);
int mbed_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, int len);
int mbed_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, int len);
static void mbed_debug(void *context,
int level,
const char *file,
int line,
const char *str);
static int mbed_ssl_handshake(mbedtls_ssl_context *ssl);
int
mbed_sslctx_init(SSL_CTX *ctx, const char *crt)
{
mbedtls_ssl_config *conf;
int rc;
if (ctx == NULL || crt == NULL) {
return -1;
}
DEBUG_TRACE("%s", "Initializing MbedTLS SSL");
mbedtls_entropy_init(&ctx->entropy);
conf = &ctx->conf;
mbedtls_ssl_config_init(conf);
/* Set mbedTLS debug level by defining MG_CONFIG_MBEDTLS_DEBUG:
* 0 No debug = mbedTLS DEFAULT
* 1 Error (default if "DEBUG" is set for CivetWeb)
* 2 State change
* 3 Informational
* 4 Verbose
*/
#if defined(DEBUG) || defined(MG_CONFIG_MBEDTLS_DEBUG)
#if defined(MG_CONFIG_MBEDTLS_DEBUG)
mbedtls_debug_set_threshold(MG_CONFIG_MBEDTLS_DEBUG);
#else
mbedtls_debug_set_threshold(1);
#endif
mbedtls_ssl_conf_dbg(conf, mbed_debug, (void *)ctx);
#endif
/* Initialize TLS key and cert */
mbedtls_pk_init(&ctx->pkey);
mbedtls_ctr_drbg_init(&ctx->ctr);
mbedtls_x509_crt_init(&ctx->cert);
rc = mbedtls_ctr_drbg_seed(&ctx->ctr,
mbedtls_entropy_func,
&ctx->entropy,
(unsigned char *)"CivetWeb",
strlen("CivetWeb"));
if (rc != 0) {
DEBUG_TRACE("TLS random seed failed (%i)", rc);
return -1;
}
rc = mbedtls_pk_parse_keyfile(&ctx->pkey, crt, NULL);
if (rc != 0) {
DEBUG_TRACE("TLS parse key file failed (%i)", rc);
return -1;
}
rc = mbedtls_x509_crt_parse_file(&ctx->cert, crt);
if (rc != 0) {
DEBUG_TRACE("TLS parse crt file failed (%i)", rc);
return -1;
}
rc = mbedtls_ssl_config_defaults(conf,
MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (rc != 0) {
DEBUG_TRACE("TLS set defaults failed (%i)", rc);
return -1;
}
mbedtls_ssl_conf_rng(conf, mbedtls_ctr_drbg_random, &ctx->ctr);
/* Set auth mode if peer cert should be verified */
mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_ca_chain(conf, NULL, NULL);
/* Configure server cert and key */
rc = mbedtls_ssl_conf_own_cert(conf, &ctx->cert, &ctx->pkey);
if (rc != 0) {
DEBUG_TRACE("TLS cannot set certificate and private key (%i)", rc);
return -1;
}
return 0;
}
void
mbed_sslctx_uninit(SSL_CTX *ctx)
{
mbedtls_ctr_drbg_free(&ctx->ctr);
mbedtls_pk_free(&ctx->pkey);
mbedtls_x509_crt_free(&ctx->cert);
mbedtls_entropy_free(&ctx->entropy);
mbedtls_ssl_config_free(&ctx->conf);
}
int
mbed_ssl_accept(mbedtls_ssl_context **ssl,
SSL_CTX *ssl_ctx,
int *sock,
struct mg_context *phys_ctx)
{
int rc;
(void)phys_ctx; /* unused, if server statistics is not turned on */
DEBUG_TRACE("TLS accept processing %p", ssl);
*ssl = (mbedtls_ssl_context *)mg_calloc_ctx(1,
sizeof(mbedtls_ssl_context),
phys_ctx);
if (*ssl == NULL) {
DEBUG_TRACE("TLS accept: malloc ssl failed (%i)",
(int)sizeof(mbedtls_ssl_context));
return -1;
}
mbedtls_ssl_init(*ssl);
mbedtls_ssl_setup(*ssl, &ssl_ctx->conf);
mbedtls_ssl_set_bio(*ssl, sock, mbedtls_net_send, mbedtls_net_recv, NULL);
rc = mbed_ssl_handshake(*ssl);
if (rc != 0) {
DEBUG_TRACE("TLS handshake failed (%i)", rc);
mbedtls_ssl_free(*ssl);
mg_free(*ssl);
*ssl = NULL;
return -1;
}
DEBUG_TRACE("TLS connection %p accepted, state: %d", ssl, (*ssl)->state);
return 0;
}
void
mbed_ssl_close(mbedtls_ssl_context *ssl)
{
DEBUG_TRACE("TLS connection %p closed", ssl);
mbedtls_ssl_close_notify(ssl);
mbedtls_ssl_free(ssl);
mg_free(ssl); /* mg_free for mg_calloc in mbed_ssl_accept */
}
static int
mbed_ssl_handshake(mbedtls_ssl_context *ssl)
{
int rc;
while ((rc = mbedtls_ssl_handshake(ssl)) != 0) {
if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE
&& rc != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
break;
}
}
DEBUG_TRACE("TLS handshake rc: %d, state: %d", rc, ssl->state);
return rc;
}
int
mbed_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, int len)
{
int rc = mbedtls_ssl_read(ssl, buf, len);
/* DEBUG_TRACE("mbedtls_ssl_read: %d", rc); */
return rc;
}
int
mbed_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, int len)
{
int rc = mbedtls_ssl_write(ssl, buf, len);
/* DEBUG_TRACE("mbedtls_ssl_write: %d", rc); */
return rc;
}
static void
mbed_debug(void *user_param,
int level,
const char *file,
int line,
const char *str)
{
(void)level; /* Ignored. Limit is set using mbedtls_debug_set_threshold */
(void)user_param; /* Ignored. User parameter (context) is set using
mbedtls_ssl_conf_dbg */
DEBUG_TRACE("mbedTLS DEBUG: file: [%s] line: [%d] str: [%s]",
file,
line,
str);
}
#endif /* USE_MBEDTLS */

281
vendor/CivetWeb/mod_zlib.inl vendored Normal file
View File

@ -0,0 +1,281 @@
/* Experimental implementation for on-the-fly compression */
#if !defined(USE_ZLIB)
#error "This file must only be included, if USE_ZLIB is set"
#endif
#if !defined(MEM_LEVEL)
#define MEM_LEVEL (8)
#endif
static void *
zalloc(void *opaque, uInt items, uInt size)
{
struct mg_connection *conn = (struct mg_connection *)opaque;
void *ret = mg_calloc_ctx(items, size, conn->phys_ctx);
(void)conn; /* mg_calloc_ctx makro might not need it */
return ret;
}
static void
zfree(void *opaque, void *address)
{
struct mg_connection *conn = (struct mg_connection *)opaque;
(void)conn; /* not required */
mg_free(address);
}
static void
send_compressed_data(struct mg_connection *conn, struct mg_file *filep)
{
int zret;
z_stream zstream;
int do_flush;
unsigned bytes_avail;
unsigned char in_buf[MG_BUF_LEN];
unsigned char out_buf[MG_BUF_LEN];
FILE *in_file = filep->access.fp;
/* Prepare state buffer. User server context memory allocation. */
memset(&zstream, 0, sizeof(zstream));
zstream.zalloc = zalloc;
zstream.zfree = zfree;
zstream.opaque = (void *)conn;
/* Initialize for GZIP compression (MAX_WBITS | 16) */
zret = deflateInit2(&zstream,
Z_BEST_COMPRESSION,
Z_DEFLATED,
MAX_WBITS | 16,
MEM_LEVEL,
Z_DEFAULT_STRATEGY);
if (zret != Z_OK) {
mg_cry_internal(conn,
"GZIP init failed (%i): %s",
zret,
(zstream.msg ? zstream.msg : "<no error message>"));
deflateEnd(&zstream);
return;
}
/* Read until end of file */
do {
zstream.avail_in = fread(in_buf, 1, MG_BUF_LEN, in_file);
if (ferror(in_file)) {
mg_cry_internal(conn, "fread failed: %s", strerror(ERRNO));
(void)deflateEnd(&zstream);
return;
}
do_flush = (feof(in_file) ? Z_FINISH : Z_NO_FLUSH);
zstream.next_in = in_buf;
/* run deflate() on input until output buffer not full, finish
* compression if all of source has been read in */
do {
zstream.avail_out = MG_BUF_LEN;
zstream.next_out = out_buf;
zret = deflate(&zstream, do_flush);
if (zret == Z_STREAM_ERROR) {
/* deflate error */
zret = -97;
break;
}
bytes_avail = MG_BUF_LEN - zstream.avail_out;
if (bytes_avail) {
if (mg_send_chunk(conn, (char *)out_buf, bytes_avail) < 0) {
zret = -98;
break;
}
}
} while (zstream.avail_out == 0);
if (zret < -90) {
/* Forward write error */
break;
}
if (zstream.avail_in != 0) {
/* all input will be used, otherwise GZIP is incomplete */
zret = -99;
break;
}
/* done when last data in file processed */
} while (do_flush != Z_FINISH);
if (zret != Z_STREAM_END) {
/* Error: We did not compress everything. */
mg_cry_internal(conn,
"GZIP incomplete (%i): %s",
zret,
(zstream.msg ? zstream.msg : "<no error message>"));
}
deflateEnd(&zstream);
/* Send "end of chunked data" marker */
mg_write(conn, "0\r\n\r\n", 5);
}
#if defined(USE_WEBSOCKET) && defined(MG_EXPERIMENTAL_INTERFACES)
static int
websocket_deflate_initialize(struct mg_connection *conn, int server)
{
int zret =
deflateInit2(&conn->websocket_deflate_state,
Z_BEST_COMPRESSION,
Z_DEFLATED,
server
? -1 * conn->websocket_deflate_server_max_windows_bits
: -1 * conn->websocket_deflate_client_max_windows_bits,
MEM_LEVEL,
Z_DEFAULT_STRATEGY);
if (zret != Z_OK) {
mg_cry_internal(conn,
"Websocket deflate init failed (%i): %s",
zret,
(conn->websocket_deflate_state.msg
? conn->websocket_deflate_state.msg
: "<no error message>"));
deflateEnd(&conn->websocket_deflate_state);
return zret;
}
zret = inflateInit2(
&conn->websocket_inflate_state,
server ? -1 * conn->websocket_deflate_client_max_windows_bits
: -1 * conn->websocket_deflate_server_max_windows_bits);
if (zret != Z_OK) {
mg_cry_internal(conn,
"Websocket inflate init failed (%i): %s",
zret,
(conn->websocket_inflate_state.msg
? conn->websocket_inflate_state.msg
: "<no error message>"));
inflateEnd(&conn->websocket_inflate_state);
return zret;
}
if ((conn->websocket_deflate_server_no_context_takeover && server)
|| (conn->websocket_deflate_client_no_context_takeover && !server))
conn->websocket_deflate_flush = Z_FULL_FLUSH;
else
conn->websocket_deflate_flush = Z_SYNC_FLUSH;
conn->websocket_deflate_initialized = 1;
return Z_OK;
}
static void
websocket_deflate_negotiate(struct mg_connection *conn)
{
const char *extensions = mg_get_header(conn, "Sec-WebSocket-Extensions");
int val;
if (extensions && !strncmp(extensions, "permessage-deflate", 18)) {
conn->accept_gzip = 1;
conn->websocket_deflate_client_max_windows_bits = 15;
conn->websocket_deflate_server_max_windows_bits = 15;
conn->websocket_deflate_server_no_context_takeover = 0;
conn->websocket_deflate_client_no_context_takeover = 0;
extensions += 18;
while (*extensions != '\0') {
if (*extensions == ';' || *extensions == ' ')
++extensions;
else if (!strncmp(extensions, "server_no_context_takeover", 26)) {
extensions += 26;
conn->websocket_deflate_server_no_context_takeover = 1;
} else if (!strncmp(extensions, "client_no_context_takeover", 26)) {
extensions += 26;
conn->websocket_deflate_client_no_context_takeover = 1;
} else if (!strncmp(extensions, "server_max_window_bits", 22)) {
extensions += 22;
if (*extensions == '=') {
++extensions;
if (*extensions == '"')
++extensions;
val = 0;
while (*extensions >= '0' && *extensions <= '9') {
val = val * 10 + (*extensions - '0');
++extensions;
}
if (val < 9 || val > 15) {
// The permessage-deflate spec specifies that a
// value of 8 is also allowed, but zlib doesn't accept
// that.
mg_cry_internal(conn,
"server-max-window-bits must be "
"between 9 and 15. Got %i",
val);
} else
conn->websocket_deflate_server_max_windows_bits = val;
if (*extensions == '"')
++extensions;
}
} else if (!strncmp(extensions, "client_max_window_bits", 22)) {
extensions += 22;
if (*extensions == '=') {
++extensions;
if (*extensions == '"')
++extensions;
val = 0;
while (*extensions >= '0' && *extensions <= '9') {
val = val * 10 + (*extensions - '0');
++extensions;
}
if (val < 9 || val > 15)
// The permessage-deflate spec specifies that a
// value of 8 is also allowed, but zlib doesn't
// accept that.
mg_cry_internal(conn,
"client-max-window-bits must be "
"between 9 and 15. Got %i",
val);
else
conn->websocket_deflate_client_max_windows_bits = val;
if (*extensions == '"')
++extensions;
}
} else {
mg_cry_internal(conn,
"Unknown parameter %s for permessage-deflate",
extensions);
break;
}
}
} else {
conn->accept_gzip = 0;
}
conn->websocket_deflate_initialized = 0;
}
static void
websocket_deflate_response(struct mg_connection *conn)
{
if (conn->accept_gzip) {
mg_printf(conn,
"Sec-WebSocket-Extensions: permessage-deflate; "
"server_max_window_bits=%i; "
"client_max_window_bits=%i"
"%s%s\r\n",
conn->websocket_deflate_server_max_windows_bits,
conn->websocket_deflate_client_max_windows_bits,
conn->websocket_deflate_client_no_context_takeover
? "; client_no_context_takeover"
: "",
conn->websocket_deflate_server_no_context_takeover
? "; server_no_context_takeover"
: "");
};
}
#endif

545
vendor/CivetWeb/openssl_dl.inl vendored Normal file
View File

@ -0,0 +1,545 @@
/* Copyright (c) 2013-2021 the Civetweb developers
* Copyright (c) 2004-2013 Sergey Lyubka
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
typedef struct ssl_st SSL;
typedef struct ssl_method_st SSL_METHOD;
typedef struct ssl_ctx_st SSL_CTX;
typedef struct x509_store_ctx_st X509_STORE_CTX;
typedef struct x509_name X509_NAME;
typedef struct asn1_integer ASN1_INTEGER;
typedef struct bignum BIGNUM;
typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
typedef struct evp_md EVP_MD;
typedef struct x509 X509;
#define SSL_CTRL_OPTIONS (32)
#define SSL_CTRL_CLEAR_OPTIONS (77)
#define SSL_CTRL_SET_ECDH_AUTO (94)
#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L
#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
#define SSL_VERIFY_NONE (0)
#define SSL_VERIFY_PEER (1)
#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
#define SSL_VERIFY_CLIENT_ONCE (4)
#define SSL_OP_ALL (0x80000BFFul)
#define SSL_OP_NO_SSLv2 (0x01000000ul)
#define SSL_OP_NO_SSLv3 (0x02000000ul)
#define SSL_OP_NO_TLSv1 (0x04000000ul)
#define SSL_OP_NO_TLSv1_2 (0x08000000ul)
#define SSL_OP_NO_TLSv1_1 (0x10000000ul)
#define SSL_OP_NO_TLSv1_3 (0x20000000ul)
#define SSL_OP_SINGLE_DH_USE (0x00100000ul)
#define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000ul)
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000ul)
#define SSL_OP_NO_COMPRESSION (0x00020000ul)
#define SSL_OP_NO_RENEGOTIATION (0x40000000ul)
#define SSL_CB_HANDSHAKE_START (0x10)
#define SSL_CB_HANDSHAKE_DONE (0x20)
#define SSL_ERROR_NONE (0)
#define SSL_ERROR_SSL (1)
#define SSL_ERROR_WANT_READ (2)
#define SSL_ERROR_WANT_WRITE (3)
#define SSL_ERROR_WANT_X509_LOOKUP (4)
#define SSL_ERROR_SYSCALL (5) /* see errno */
#define SSL_ERROR_ZERO_RETURN (6)
#define SSL_ERROR_WANT_CONNECT (7)
#define SSL_ERROR_WANT_ACCEPT (8)
#define TLSEXT_TYPE_server_name (0)
#define TLSEXT_NAMETYPE_host_name (0)
#define SSL_TLSEXT_ERR_OK (0)
#define SSL_TLSEXT_ERR_ALERT_WARNING (1)
#define SSL_TLSEXT_ERR_ALERT_FATAL (2)
#define SSL_TLSEXT_ERR_NOACK (3)
#define SSL_SESS_CACHE_BOTH (3)
enum ssl_func_category {
TLS_Mandatory, /* required for HTTPS */
TLS_ALPN, /* required for Application Layer Protocol Negotiation */
TLS_END_OF_LIST
};
/* Check if all TLS functions/features are available */
static int tls_feature_missing[TLS_END_OF_LIST] = {0};
struct ssl_func {
const char *name; /* SSL function name */
enum ssl_func_category required; /* Mandatory or optional */
void (*ptr)(void); /* Function pointer */
};
#if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \
&& !defined(NO_SSL_DL)
#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
#define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
#define TLS_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
#define OPENSSL_init_ssl \
(*(int (*)(uint64_t opts, \
const OPENSSL_INIT_SETTINGS *settings))ssl_sw[10] \
.ptr)
#define SSL_CTX_use_PrivateKey_file \
(*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
#define SSL_CTX_use_certificate_file \
(*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
#define SSL_CTX_set_default_passwd_cb \
(*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
#define SSL_CTX_use_certificate_chain_file \
(*(int (*)(SSL_CTX *, const char *))ssl_sw[15].ptr)
#define TLS_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[16].ptr)
#define SSL_pending (*(int (*)(SSL *))ssl_sw[17].ptr)
#define SSL_CTX_set_verify \
(*(void (*)(SSL_CTX *, \
int, \
int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[18] \
.ptr)
#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[19].ptr)
#define SSL_CTX_load_verify_locations \
(*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[20].ptr)
#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[21].ptr)
#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[22].ptr)
#define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[23].ptr)
#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[24].ptr)
#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[25].ptr)
#define SSL_CIPHER_get_name \
(*(const char *(*)(const SSL_CIPHER *))ssl_sw[26].ptr)
#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[27].ptr)
#define SSL_CTX_set_session_id_context \
(*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[28].ptr)
#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[29].ptr)
#define SSL_CTX_set_cipher_list \
(*(int (*)(SSL_CTX *, const char *))ssl_sw[30].ptr)
#define SSL_CTX_set_options \
(*(unsigned long (*)(SSL_CTX *, unsigned long))ssl_sw[31].ptr)
#define SSL_CTX_set_info_callback \
(*(void (*)(SSL_CTX * ctx, void (*callback)(const SSL *, int, int))) \
ssl_sw[32] \
.ptr)
#define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr)
#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr)
#define SSL_CTX_callback_ctrl \
(*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr)
#define SSL_get_servername \
(*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr)
#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr)
#define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr)
#define SSL_CTX_set_alpn_protos \
(*(int (*)(SSL_CTX *, const unsigned char *, unsigned))ssl_sw[39].ptr)
typedef int (*tSSL_alpn_select_cb)(SSL *ssl,
const unsigned char **out,
unsigned char *outlen,
const unsigned char *in,
unsigned int inlen,
void *arg);
#define SSL_CTX_set_alpn_select_cb \
(*(void (*)(SSL_CTX *, tSSL_alpn_select_cb, void *))ssl_sw[40].ptr)
typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl,
const unsigned char **out,
unsigned int *outlen,
void *arg);
#define SSL_CTX_set_next_protos_advertised_cb \
(*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \
.ptr)
#define SSL_CTX_set_timeout (*(long (*)(SSL_CTX *, long))ssl_sw[42].ptr)
#define SSL_CTX_clear_options(ctx, op) \
SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
#define SSL_CTX_set_ecdh_auto(ctx, onoff) \
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
SSL_CTX_callback_ctrl(ctx, \
SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \
(void (*)(void))cb)
#define SSL_set_tlsext_host_name(ctx, arg) \
SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg)
#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
#define SSL_CTX_sess_set_cache_size(ctx, size) SSL_CTX_ctrl(ctx, 42, size, NULL)
#define SSL_CTX_set_session_cache_mode(ctx, mode) \
SSL_CTX_ctrl(ctx, 44, mode, NULL)
#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[0].ptr)
#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[1].ptr)
#define CONF_modules_unload (*(void (*)(int))crypto_sw[2].ptr)
#define X509_free (*(void (*)(X509 *))crypto_sw[3].ptr)
#define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[4].ptr)
#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[5].ptr)
#define X509_NAME_oneline \
(*(char *(*)(X509_NAME *, char *, int))crypto_sw[6].ptr)
#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[7].ptr)
#define EVP_get_digestbyname \
(*(const EVP_MD *(*)(const char *))crypto_sw[8].ptr)
#define EVP_Digest \
(*(int (*)( \
const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \
crypto_sw[9] \
.ptr)
#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[10].ptr)
#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[11].ptr)
#define ASN1_INTEGER_to_BN \
(*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[12].ptr)
#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[13].ptr)
#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[14].ptr)
#define ERR_clear_error (*(void (*)(void))crypto_sw[15].ptr)
#define OPENSSL_free(a) CRYPTO_free(a)
#define OPENSSL_REMOVE_THREAD_STATE()
/* init_ssl_ctx() function updates this array.
* It loads SSL library dynamically and changes NULLs to the actual addresses
* of respective functions. The macros above (like SSL_connect()) are really
* just calling these functions indirectly via the pointer. */
static struct ssl_func ssl_sw[] = {
{"SSL_free", TLS_Mandatory, NULL},
{"SSL_accept", TLS_Mandatory, NULL},
{"SSL_connect", TLS_Mandatory, NULL},
{"SSL_read", TLS_Mandatory, NULL},
{"SSL_write", TLS_Mandatory, NULL},
{"SSL_get_error", TLS_Mandatory, NULL},
{"SSL_set_fd", TLS_Mandatory, NULL},
{"SSL_new", TLS_Mandatory, NULL},
{"SSL_CTX_new", TLS_Mandatory, NULL},
{"TLS_server_method", TLS_Mandatory, NULL},
{"OPENSSL_init_ssl", TLS_Mandatory, NULL},
{"SSL_CTX_use_PrivateKey_file", TLS_Mandatory, NULL},
{"SSL_CTX_use_certificate_file", TLS_Mandatory, NULL},
{"SSL_CTX_set_default_passwd_cb", TLS_Mandatory, NULL},
{"SSL_CTX_free", TLS_Mandatory, NULL},
{"SSL_CTX_use_certificate_chain_file", TLS_Mandatory, NULL},
{"TLS_client_method", TLS_Mandatory, NULL},
{"SSL_pending", TLS_Mandatory, NULL},
{"SSL_CTX_set_verify", TLS_Mandatory, NULL},
{"SSL_shutdown", TLS_Mandatory, NULL},
{"SSL_CTX_load_verify_locations", TLS_Mandatory, NULL},
{"SSL_CTX_set_default_verify_paths", TLS_Mandatory, NULL},
{"SSL_CTX_set_verify_depth", TLS_Mandatory, NULL},
#if defined(OPENSSL_API_3_0)
{"SSL_get1_peer_certificate", TLS_Mandatory, NULL},
#else
{"SSL_get_peer_certificate", TLS_Mandatory, NULL},
#endif
{"SSL_get_version", TLS_Mandatory, NULL},
{"SSL_get_current_cipher", TLS_Mandatory, NULL},
{"SSL_CIPHER_get_name", TLS_Mandatory, NULL},
{"SSL_CTX_check_private_key", TLS_Mandatory, NULL},
{"SSL_CTX_set_session_id_context", TLS_Mandatory, NULL},
{"SSL_CTX_ctrl", TLS_Mandatory, NULL},
{"SSL_CTX_set_cipher_list", TLS_Mandatory, NULL},
{"SSL_CTX_set_options", TLS_Mandatory, NULL},
{"SSL_CTX_set_info_callback", TLS_Mandatory, NULL},
{"SSL_get_ex_data", TLS_Mandatory, NULL},
{"SSL_set_ex_data", TLS_Mandatory, NULL},
{"SSL_CTX_callback_ctrl", TLS_Mandatory, NULL},
{"SSL_get_servername", TLS_Mandatory, NULL},
{"SSL_set_SSL_CTX", TLS_Mandatory, NULL},
{"SSL_ctrl", TLS_Mandatory, NULL},
{"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL},
{"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL},
{"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL},
{"SSL_CTX_set_timeout", TLS_Mandatory, NULL},
{NULL, TLS_END_OF_LIST, NULL}};
/* Similar array as ssl_sw. These functions could be located in different
* lib. */
static struct ssl_func crypto_sw[] = {
{"ERR_get_error", TLS_Mandatory, NULL},
{"ERR_error_string", TLS_Mandatory, NULL},
{"CONF_modules_unload", TLS_Mandatory, NULL},
{"X509_free", TLS_Mandatory, NULL},
{"X509_get_subject_name", TLS_Mandatory, NULL},
{"X509_get_issuer_name", TLS_Mandatory, NULL},
{"X509_NAME_oneline", TLS_Mandatory, NULL},
{"X509_get_serialNumber", TLS_Mandatory, NULL},
{"EVP_get_digestbyname", TLS_Mandatory, NULL},
{"EVP_Digest", TLS_Mandatory, NULL},
{"i2d_X509", TLS_Mandatory, NULL},
{"BN_bn2hex", TLS_Mandatory, NULL},
{"ASN1_INTEGER_to_BN", TLS_Mandatory, NULL},
{"BN_free", TLS_Mandatory, NULL},
{"CRYPTO_free", TLS_Mandatory, NULL},
{"ERR_clear_error", TLS_Mandatory, NULL},
{NULL, TLS_END_OF_LIST, NULL}};
#endif
#if defined(OPENSSL_API_1_0)
#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
#define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
#define SSLv23_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
#define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr)
#define SSL_CTX_use_PrivateKey_file \
(*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
#define SSL_CTX_use_certificate_file \
(*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
#define SSL_CTX_set_default_passwd_cb \
(*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
#define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr)
#define SSL_CTX_use_certificate_chain_file \
(*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr)
#define SSLv23_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[17].ptr)
#define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr)
#define SSL_CTX_set_verify \
(*(void (*)(SSL_CTX *, \
int, \
int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19] \
.ptr)
#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr)
#define SSL_CTX_load_verify_locations \
(*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr)
#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr)
#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr)
#define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[24].ptr)
#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr)
#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[26].ptr)
#define SSL_CIPHER_get_name \
(*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr)
#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
#define SSL_CTX_set_session_id_context \
(*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr)
#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr)
#define SSL_CTX_set_cipher_list \
(*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr)
#define SSL_CTX_set_info_callback \
(*(void (*)(SSL_CTX *, void (*callback)(const SSL *, int, int)))ssl_sw[32] \
.ptr)
#define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr)
#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr)
#define SSL_CTX_callback_ctrl \
(*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr)
#define SSL_get_servername \
(*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr)
#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr)
#define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr)
#define SSL_CTX_set_alpn_protos \
(*(int (*)(SSL_CTX *, const unsigned char *, unsigned))ssl_sw[39].ptr)
typedef int (*tSSL_alpn_select_cb)(SSL *ssl,
const unsigned char **out,
unsigned char *outlen,
const unsigned char *in,
unsigned int inlen,
void *arg);
#define SSL_CTX_set_alpn_select_cb \
(*(void (*)(SSL_CTX *, tSSL_alpn_select_cb, void *))ssl_sw[40].ptr)
typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl,
const unsigned char **out,
unsigned int *outlen,
void *arg);
#define SSL_CTX_set_next_protos_advertised_cb \
(*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \
.ptr)
#define SSL_CTX_set_timeout (*(long (*)(SSL_CTX *, long))ssl_sw[42].ptr)
#define SSL_CTX_set_options(ctx, op) \
SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
#define SSL_CTX_clear_options(ctx, op) \
SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
#define SSL_CTX_set_ecdh_auto(ctx, onoff) \
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
SSL_CTX_callback_ctrl(ctx, \
SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \
(void (*)(void))cb)
#define SSL_set_tlsext_host_name(ctx, arg) \
SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg)
#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
#define SSL_CTX_sess_set_cache_size(ctx, size) SSL_CTX_ctrl(ctx, 42, size, NULL)
#define SSL_CTX_set_session_cache_mode(ctx, mode) \
SSL_CTX_ctrl(ctx, 44, mode, NULL)
#define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
#define CRYPTO_set_locking_callback \
(*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr)
#define CRYPTO_set_id_callback \
(*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr)
#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr)
#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr)
#define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr)
#define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr)
#define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr)
#define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr)
#define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr)
#define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr)
#define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr)
#define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[12].ptr)
#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[13].ptr)
#define X509_NAME_oneline \
(*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr)
#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[15].ptr)
#define i2c_ASN1_INTEGER \
(*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr)
#define EVP_get_digestbyname \
(*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr)
#define EVP_Digest \
(*(int (*)( \
const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \
crypto_sw[18] \
.ptr)
#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr)
#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[20].ptr)
#define ASN1_INTEGER_to_BN \
(*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[21].ptr)
#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[22].ptr)
#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[23].ptr)
#define ERR_clear_error (*(void (*)(void))crypto_sw[24].ptr)
#define OPENSSL_free(a) CRYPTO_free(a)
/* use here ERR_remove_state,
* while on some platforms function is not included into library due to
* deprication */
#define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_state(0)
/* init_ssl_ctx() function updates this array.
* It loads SSL library dynamically and changes NULLs to the actual addresses
* of respective functions. The macros above (like SSL_connect()) are really
* just calling these functions indirectly via the pointer. */
static struct ssl_func ssl_sw[] = {
{"SSL_free", TLS_Mandatory, NULL},
{"SSL_accept", TLS_Mandatory, NULL},
{"SSL_connect", TLS_Mandatory, NULL},
{"SSL_read", TLS_Mandatory, NULL},
{"SSL_write", TLS_Mandatory, NULL},
{"SSL_get_error", TLS_Mandatory, NULL},
{"SSL_set_fd", TLS_Mandatory, NULL},
{"SSL_new", TLS_Mandatory, NULL},
{"SSL_CTX_new", TLS_Mandatory, NULL},
{"SSLv23_server_method", TLS_Mandatory, NULL},
{"SSL_library_init", TLS_Mandatory, NULL},
{"SSL_CTX_use_PrivateKey_file", TLS_Mandatory, NULL},
{"SSL_CTX_use_certificate_file", TLS_Mandatory, NULL},
{"SSL_CTX_set_default_passwd_cb", TLS_Mandatory, NULL},
{"SSL_CTX_free", TLS_Mandatory, NULL},
{"SSL_load_error_strings", TLS_Mandatory, NULL},
{"SSL_CTX_use_certificate_chain_file", TLS_Mandatory, NULL},
{"SSLv23_client_method", TLS_Mandatory, NULL},
{"SSL_pending", TLS_Mandatory, NULL},
{"SSL_CTX_set_verify", TLS_Mandatory, NULL},
{"SSL_shutdown", TLS_Mandatory, NULL},
{"SSL_CTX_load_verify_locations", TLS_Mandatory, NULL},
{"SSL_CTX_set_default_verify_paths", TLS_Mandatory, NULL},
{"SSL_CTX_set_verify_depth", TLS_Mandatory, NULL},
{"SSL_get_peer_certificate", TLS_Mandatory, NULL},
{"SSL_get_version", TLS_Mandatory, NULL},
{"SSL_get_current_cipher", TLS_Mandatory, NULL},
{"SSL_CIPHER_get_name", TLS_Mandatory, NULL},
{"SSL_CTX_check_private_key", TLS_Mandatory, NULL},
{"SSL_CTX_set_session_id_context", TLS_Mandatory, NULL},
{"SSL_CTX_ctrl", TLS_Mandatory, NULL},
{"SSL_CTX_set_cipher_list", TLS_Mandatory, NULL},
{"SSL_CTX_set_info_callback", TLS_Mandatory, NULL},
{"SSL_get_ex_data", TLS_Mandatory, NULL},
{"SSL_set_ex_data", TLS_Mandatory, NULL},
{"SSL_CTX_callback_ctrl", TLS_Mandatory, NULL},
{"SSL_get_servername", TLS_Mandatory, NULL},
{"SSL_set_SSL_CTX", TLS_Mandatory, NULL},
{"SSL_ctrl", TLS_Mandatory, NULL},
{"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL},
{"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL},
{"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL},
{"SSL_CTX_set_timeout", TLS_Mandatory, NULL},
{NULL, TLS_END_OF_LIST, NULL}};
/* Similar array as ssl_sw. These functions could be located in different
* lib. */
static struct ssl_func crypto_sw[] = {
{"CRYPTO_num_locks", TLS_Mandatory, NULL},
{"CRYPTO_set_locking_callback", TLS_Mandatory, NULL},
{"CRYPTO_set_id_callback", TLS_Mandatory, NULL},
{"ERR_get_error", TLS_Mandatory, NULL},
{"ERR_error_string", TLS_Mandatory, NULL},
{"ERR_remove_state", TLS_Mandatory, NULL},
{"ERR_free_strings", TLS_Mandatory, NULL},
{"ENGINE_cleanup", TLS_Mandatory, NULL},
{"CONF_modules_unload", TLS_Mandatory, NULL},
{"CRYPTO_cleanup_all_ex_data", TLS_Mandatory, NULL},
{"EVP_cleanup", TLS_Mandatory, NULL},
{"X509_free", TLS_Mandatory, NULL},
{"X509_get_subject_name", TLS_Mandatory, NULL},
{"X509_get_issuer_name", TLS_Mandatory, NULL},
{"X509_NAME_oneline", TLS_Mandatory, NULL},
{"X509_get_serialNumber", TLS_Mandatory, NULL},
{"i2c_ASN1_INTEGER", TLS_Mandatory, NULL},
{"EVP_get_digestbyname", TLS_Mandatory, NULL},
{"EVP_Digest", TLS_Mandatory, NULL},
{"i2d_X509", TLS_Mandatory, NULL},
{"BN_bn2hex", TLS_Mandatory, NULL},
{"ASN1_INTEGER_to_BN", TLS_Mandatory, NULL},
{"BN_free", TLS_Mandatory, NULL},
{"CRYPTO_free", TLS_Mandatory, NULL},
{"ERR_clear_error", TLS_Mandatory, NULL},
{NULL, TLS_END_OF_LIST, NULL}};
#endif /* OPENSSL_API_1_0 */

326
vendor/CivetWeb/response.inl vendored Normal file
View File

@ -0,0 +1,326 @@
/* response.inl
*
* Bufferring for HTTP headers for HTTP response.
* This function are only intended to be used at the server side.
* Optional for HTTP/1.0 and HTTP/1.1, mandatory for HTTP/2.
*
* This file is part of the CivetWeb project.
*/
#if defined(NO_RESPONSE_BUFFERING) && defined(USE_HTTP2)
#error "HTTP2 works only if NO_RESPONSE_BUFFERING is not set"
#endif
/* Internal function to free header list */
static void
free_buffered_response_header_list(struct mg_connection *conn)
{
#if !defined(NO_RESPONSE_BUFFERING)
while (conn->response_info.num_headers > 0) {
conn->response_info.num_headers--;
mg_free((void *)conn->response_info
.http_headers[conn->response_info.num_headers]
.name);
conn->response_info.http_headers[conn->response_info.num_headers].name =
0;
mg_free((void *)conn->response_info
.http_headers[conn->response_info.num_headers]
.value);
conn->response_info.http_headers[conn->response_info.num_headers]
.value = 0;
}
#else
(void)conn; /* Nothing to do */
#endif
}
/* Send first line of HTTP/1.x response */
static void
send_http1_response_status_line(struct mg_connection *conn)
{
const char *status_txt;
const char *http_version = conn->request_info.http_version;
int status_code = conn->status_code;
if ((status_code < 100) || (status_code > 999)) {
/* Set invalid status code to "500 Internal Server Error" */
status_code = 500;
}
if (!http_version) {
http_version = "1.0";
}
/* mg_get_response_code_text will never return NULL */
status_txt = mg_get_response_code_text(conn, conn->status_code);
mg_printf(conn, "HTTP/%s %i %s\r\n", http_version, status_code, status_txt);
}
/* Initialize a new HTTP response
* Parameters:
* conn: Current connection handle.
* status: HTTP status code (e.g., 200 for "OK").
* Return:
* 0: ok
* -1: parameter error
* -2: invalid connection type
* -3: invalid connection status
*/
int
mg_response_header_start(struct mg_connection *conn, int status)
{
if ((conn == NULL) || (status < 100) || (status > 999)) {
/* Parameter error */
return -1;
}
if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
|| (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
/* Only allowed in server context */
return -2;
}
if (conn->request_state != 0) {
/* only allowed if nothing was sent up to now */
return -3;
}
conn->status_code = status;
conn->request_state = 1;
/* Buffered response is stored, unbuffered response will be sent directly,
* but we can only send HTTP/1.x response here */
#if !defined(NO_RESPONSE_BUFFERING)
free_buffered_response_header_list(conn);
#else
send_http1_response_status_line(conn);
conn->request_state = 1; /* Reset from 10 to 1 */
#endif
return 0;
}
/* Add a new HTTP response header line
* Parameters:
* conn: Current connection handle.
* header: Header name.
* value: Header value.
* value_len: Length of header value, excluding the terminating zero.
* Use -1 for "strlen(value)".
* Return:
* 0: ok
* -1: parameter error
* -2: invalid connection type
* -3: invalid connection status
* -4: too many headers
* -5: out of memory
*/
int
mg_response_header_add(struct mg_connection *conn,
const char *header,
const char *value,
int value_len)
{
#if !defined(NO_RESPONSE_BUFFERING)
int hidx;
#endif
if ((conn == NULL) || (header == NULL) || (value == NULL)) {
/* Parameter error */
return -1;
}
if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
|| (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
/* Only allowed in server context */
return -2;
}
if (conn->request_state != 1) {
/* only allowed if mg_response_header_start has been called before */
return -3;
}
#if !defined(NO_RESPONSE_BUFFERING)
hidx = conn->response_info.num_headers;
if (hidx >= MG_MAX_HEADERS) {
/* Too many headers */
return -4;
}
/* Alloc new element */
conn->response_info.http_headers[hidx].name =
mg_strdup_ctx(header, conn->phys_ctx);
if (value_len >= 0) {
char *hbuf =
(char *)mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx);
if (hbuf) {
memcpy(hbuf, value, (unsigned)value_len);
hbuf[value_len] = 0;
}
conn->response_info.http_headers[hidx].value = hbuf;
} else {
conn->response_info.http_headers[hidx].value =
mg_strdup_ctx(value, conn->phys_ctx);
}
if ((conn->response_info.http_headers[hidx].name == 0)
|| (conn->response_info.http_headers[hidx].value == 0)) {
/* Out of memory */
mg_free((void *)conn->response_info.http_headers[hidx].name);
conn->response_info.http_headers[hidx].name = 0;
mg_free((void *)conn->response_info.http_headers[hidx].value);
conn->response_info.http_headers[hidx].value = 0;
return -5;
}
/* OK, header stored */
conn->response_info.num_headers++;
#else
if (value_len >= 0) {
mg_printf(conn, "%s: %.*s\r\n", header, (int)value_len, value);
} else {
mg_printf(conn, "%s: %s\r\n", header, value);
}
conn->request_state = 1; /* Reset from 10 to 1 */
#endif
return 0;
}
/* forward */
static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS]);
/* Add a complete header string (key + value).
* Parameters:
* conn: Current connection handle.
* http1_headers: Header line(s) in the form "name: value".
* Return:
* >=0: no error, number of header lines added
* -1: parameter error
* -2: invalid connection type
* -3: invalid connection status
* -4: too many headers
* -5: out of memory
*/
int
mg_response_header_add_lines(struct mg_connection *conn,
const char *http1_headers)
{
struct mg_header add_hdr[MG_MAX_HEADERS];
int num_hdr, i, ret;
char *workbuffer, *parse;
/* We need to work on a copy of the work buffer, sice parse_http_headers
* will modify */
workbuffer = mg_strdup_ctx(http1_headers, conn->phys_ctx);
if (!workbuffer) {
/* Out of memory */
return -5;
}
/* Call existing method to split header buffer */
parse = workbuffer;
num_hdr = parse_http_headers(&parse, add_hdr);
ret = num_hdr;
for (i = 0; i < num_hdr; i++) {
int lret =
mg_response_header_add(conn, add_hdr[i].name, add_hdr[i].value, -1);
if ((ret > 0) && (lret < 0)) {
/* Store error return value */
ret = lret;
}
}
/* mg_response_header_add created a copy, so we can free the original */
mg_free(workbuffer);
return ret;
}
#if defined(USE_HTTP2)
static int http2_send_response_headers(struct mg_connection *conn);
#endif
/* Send http response
* Parameters:
* conn: Current connection handle.
* Return:
* 0: ok
* -1: parameter error
* -2: invalid connection type
* -3: invalid connection status
*/
int
mg_response_header_send(struct mg_connection *conn)
{
#if !defined(NO_RESPONSE_BUFFERING)
int i;
int has_date = 0;
int has_connection = 0;
#endif
if (conn == NULL) {
/* Parameter error */
return -1;
}
if ((conn->connection_type != CONNECTION_TYPE_REQUEST)
|| (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) {
/* Only allowed in server context */
return -2;
}
if (conn->request_state != 1) {
/* only allowed if mg_response_header_start has been called before */
return -3;
}
/* State: 2 */
conn->request_state = 2;
#if !defined(NO_RESPONSE_BUFFERING)
#if defined(USE_HTTP2)
if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) {
int ret = http2_send_response_headers(conn);
return ret ? 0 : 0; /* todo */
}
#endif
/* Send */
send_http1_response_status_line(conn);
for (i = 0; i < conn->response_info.num_headers; i++) {
mg_printf(conn,
"%s: %s\r\n",
conn->response_info.http_headers[i].name,
conn->response_info.http_headers[i].value);
/* Check for some special headers */
if (!mg_strcasecmp("Date", conn->response_info.http_headers[i].name)) {
has_date = 1;
}
if (!mg_strcasecmp("Connection",
conn->response_info.http_headers[i].name)) {
has_connection = 1;
}
}
if (!has_date) {
time_t curtime = time(NULL);
char date[64];
gmt_time_string(date, sizeof(date), &curtime);
mg_printf(conn, "Date: %s\r\n", date);
}
if (!has_connection) {
mg_printf(conn, "Connection: %s\r\n", suggest_connection_header(conn));
}
#endif
mg_write(conn, "\r\n", 2);
conn->request_state = 3;
/* ok */
return 0;
}

323
vendor/CivetWeb/sha1.inl vendored Normal file
View File

@ -0,0 +1,323 @@
/*
SHA-1 in C
By Steve Reid <sreid@sea-to-sky.net>
100% Public Domain
-----------------
Modified 7/98
By James H. Brown <jbrown@burgoyne.com>
Still 100% Public Domain
Corrected a problem which generated improper hash values on 16 bit machines
Routine SHA1Update changed from
void SHA1Update(SHA_CTX* context, unsigned char* data, unsigned int
len)
to
void SHA1Update(SHA_CTX* context, unsigned char* data, unsigned
long len)
The 'len' parameter was declared an int which works fine on 32 bit machines.
However, on 16 bit machines an int is too small for the shifts being done
against
it. This caused the hash function to generate incorrect values if len was
greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
Since the file IO in main() reads 16K at a time, any file 8K or larger would
be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
"a"s).
I also changed the declaration of variables i & j in SHA1Update to
unsigned long from unsigned int for the same reason.
These changes should make no difference to any 32 bit implementations since
an
int and a long are the same size in those environments.
--
I also corrected a few compiler warnings generated by Borland C.
1. Added #include <process.h> for exit() prototype
2. Removed unused variable 'j' in SHA1Final
3. Changed exit(0) to return(0) at end of main.
ALL changes I made can be located by searching for comments containing 'JHB'
-----------------
Modified 8/98
By Steve Reid <sreid@sea-to-sky.net>
Still 100% public domain
1- Removed #include <process.h> and used return() instead of exit()
2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
-----------------
Modified 4/01
By Saul Kravitz <Saul.Kravitz@celera.com>
Still 100% PD
Modified to run on Compaq Alpha hardware.
-----------------
Modified 07/2002
By Ralph Giles <giles@ghostscript.com>
Still 100% public domain
modified for use with stdint types, autoconf
code cleanup, removed attribution comments
switched SHA1Final() argument order for consistency
use SHA1_ prefix for public api
move public api to sha1.h
*/
/*
11/2016 adapted for CivetWeb:
include sha1.h in sha1.c,
rename to sha1.inl
remove unused #ifdef sections
make endian independent
align buffer to 4 bytes
remove unused variable assignments
*/
/*
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#include <stdint.h>
#include <string.h>
typedef struct {
uint32_t state[5];
uint32_t count[2];
uint8_t buffer[64];
} SHA_CTX;
#define SHA1_DIGEST_SIZE 20
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
typedef union {
uint8_t c[64];
uint32_t l[16];
} CHAR64LONG16;
static uint32_t
blk0(CHAR64LONG16 *block, int i)
{
static const uint32_t n = 1u;
if ((*((uint8_t *)(&n))) == 1) {
/* little endian / intel byte order */
block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00)
| (rol(block->l[i], 8) & 0x00FF00FF);
}
return block->l[i];
}
#define blk(block, i) \
((block)->l[(i)&15] = \
rol((block)->l[((i) + 13) & 15] ^ (block)->l[((i) + 8) & 15] \
^ (block)->l[((i) + 2) & 15] ^ (block)->l[(i)&15], \
1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R1(v, w, x, y, z, i) \
z += ((w & (x ^ y)) ^ y) + blk(block, i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R2(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(block, i) + 0x6ED9EBA1 + rol(v, 5); \
w = rol(w, 30);
#define R3(v, w, x, y, z, i) \
z += (((w | x) & y) | (w & x)) + blk(block, i) + 0x8F1BBCDC + rol(v, 5); \
w = rol(w, 30);
#define R4(v, w, x, y, z, i) \
z += (w ^ x ^ y) + blk(block, i) + 0xCA62C1D6 + rol(v, 5); \
w = rol(w, 30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
static void
SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
{
uint32_t a, b, c, d, e;
/* Must use an aligned, read/write buffer */
CHAR64LONG16 block[1];
memcpy(block, buffer, sizeof(block));
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a, b, c, d, e, 0);
R0(e, a, b, c, d, 1);
R0(d, e, a, b, c, 2);
R0(c, d, e, a, b, 3);
R0(b, c, d, e, a, 4);
R0(a, b, c, d, e, 5);
R0(e, a, b, c, d, 6);
R0(d, e, a, b, c, 7);
R0(c, d, e, a, b, 8);
R0(b, c, d, e, a, 9);
R0(a, b, c, d, e, 10);
R0(e, a, b, c, d, 11);
R0(d, e, a, b, c, 12);
R0(c, d, e, a, b, 13);
R0(b, c, d, e, a, 14);
R0(a, b, c, d, e, 15);
R1(e, a, b, c, d, 16);
R1(d, e, a, b, c, 17);
R1(c, d, e, a, b, 18);
R1(b, c, d, e, a, 19);
R2(a, b, c, d, e, 20);
R2(e, a, b, c, d, 21);
R2(d, e, a, b, c, 22);
R2(c, d, e, a, b, 23);
R2(b, c, d, e, a, 24);
R2(a, b, c, d, e, 25);
R2(e, a, b, c, d, 26);
R2(d, e, a, b, c, 27);
R2(c, d, e, a, b, 28);
R2(b, c, d, e, a, 29);
R2(a, b, c, d, e, 30);
R2(e, a, b, c, d, 31);
R2(d, e, a, b, c, 32);
R2(c, d, e, a, b, 33);
R2(b, c, d, e, a, 34);
R2(a, b, c, d, e, 35);
R2(e, a, b, c, d, 36);
R2(d, e, a, b, c, 37);
R2(c, d, e, a, b, 38);
R2(b, c, d, e, a, 39);
R3(a, b, c, d, e, 40);
R3(e, a, b, c, d, 41);
R3(d, e, a, b, c, 42);
R3(c, d, e, a, b, 43);
R3(b, c, d, e, a, 44);
R3(a, b, c, d, e, 45);
R3(e, a, b, c, d, 46);
R3(d, e, a, b, c, 47);
R3(c, d, e, a, b, 48);
R3(b, c, d, e, a, 49);
R3(a, b, c, d, e, 50);
R3(e, a, b, c, d, 51);
R3(d, e, a, b, c, 52);
R3(c, d, e, a, b, 53);
R3(b, c, d, e, a, 54);
R3(a, b, c, d, e, 55);
R3(e, a, b, c, d, 56);
R3(d, e, a, b, c, 57);
R3(c, d, e, a, b, 58);
R3(b, c, d, e, a, 59);
R4(a, b, c, d, e, 60);
R4(e, a, b, c, d, 61);
R4(d, e, a, b, c, 62);
R4(c, d, e, a, b, 63);
R4(b, c, d, e, a, 64);
R4(a, b, c, d, e, 65);
R4(e, a, b, c, d, 66);
R4(d, e, a, b, c, 67);
R4(c, d, e, a, b, 68);
R4(b, c, d, e, a, 69);
R4(a, b, c, d, e, 70);
R4(e, a, b, c, d, 71);
R4(d, e, a, b, c, 72);
R4(c, d, e, a, b, 73);
R4(b, c, d, e, a, 74);
R4(a, b, c, d, e, 75);
R4(e, a, b, c, d, 76);
R4(d, e, a, b, c, 77);
R4(c, d, e, a, b, 78);
R4(b, c, d, e, a, 79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
}
/* SHA1Init - Initialize new context */
SHA_API void
SHA1_Init(SHA_CTX *context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
SHA_API void
SHA1_Update(SHA_CTX *context, const uint8_t *data, const uint32_t len)
{
uint32_t i, j;
j = context->count[0];
if ((context->count[0] += (len << 3)) < j) {
context->count[1]++;
}
context->count[1] += (len >> 29);
j = (j >> 3) & 63;
if ((j + len) > 63) {
i = 64 - j;
memcpy(&context->buffer[j], data, i);
SHA1_Transform(context->state, context->buffer);
for (; i + 63 < len; i += 64) {
SHA1_Transform(context->state, &data[i]);
}
j = 0;
} else {
i = 0;
}
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
SHA_API void
SHA1_Final(unsigned char *digest, SHA_CTX *context)
{
uint32_t i;
uint8_t finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] =
(uint8_t)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8))
& 255); /* Endian independent */
}
SHA1_Update(context, (uint8_t *)"\x80", 1);
while ((context->count[0] & 504) != 448) {
SHA1_Update(context, (uint8_t *)"\x00", 1);
}
SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
digest[i] =
(uint8_t)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
}
/* Wipe variables */
memset(context, '\0', sizeof(*context));
}
/* End of sha1.inl */

294
vendor/CivetWeb/timer.inl vendored Normal file
View File

@ -0,0 +1,294 @@
/* This file is part of the CivetWeb web server.
* See https://github.com/civetweb/civetweb/
* (C) 2014-2021 by the CivetWeb authors, MIT license.
*/
#if !defined(MAX_TIMERS)
#define MAX_TIMERS MAX_WORKER_THREADS
#endif
#if !defined(TIMER_RESOLUTION)
/* Timer resolution in ms */
#define TIMER_RESOLUTION (10)
#endif
typedef int (*taction)(void *arg);
typedef void (*tcancelaction)(void *arg);
struct ttimer {
double time;
double period;
taction action;
void *arg;
tcancelaction cancel;
};
struct ttimers {
pthread_t threadid; /* Timer thread ID */
pthread_mutex_t mutex; /* Protects timer lists */
struct ttimer *timers; /* List of timers */
unsigned timer_count; /* Current size of timer list */
unsigned timer_capacity; /* Capacity of timer list */
#if defined(_WIN32)
DWORD last_tick;
uint64_t now_tick64;
#endif
};
TIMER_API double
timer_getcurrenttime(struct mg_context *ctx)
{
#if defined(_WIN32)
/* GetTickCount returns milliseconds since system start as
* unsigned 32 bit value. It will wrap around every 49.7 days.
* We need to use a 64 bit counter (will wrap in 500 mio. years),
* by adding the 32 bit difference since the last call to a
* 64 bit counter. This algorithm will only work, if this
* function is called at least once every 7 weeks. */
uint64_t now_tick64 = 0;
DWORD now_tick = GetTickCount();
if (ctx->timers) {
pthread_mutex_lock(&ctx->timers->mutex);
ctx->timers->now_tick64 += now_tick - ctx->timers->last_tick;
now_tick64 = ctx->timers->now_tick64;
ctx->timers->last_tick = now_tick;
pthread_mutex_unlock(&ctx->timers->mutex);
}
return (double)now_tick64 * 1.0E-3;
#else
struct timespec now_ts;
(void)ctx;
clock_gettime(CLOCK_MONOTONIC, &now_ts);
return (double)now_ts.tv_sec + (double)now_ts.tv_nsec * 1.0E-9;
#endif
}
TIMER_API int
timer_add(struct mg_context *ctx,
double next_time,
double period,
int is_relative,
taction action,
void *arg,
tcancelaction cancel)
{
int error = 0;
double now;
if (!ctx->timers) {
return 1;
}
now = timer_getcurrenttime(ctx);
/* HCP24: if is_relative = 0 and next_time < now
* action will be called so fast as possible
* if additional period > 0
* action will be called so fast as possible
* n times until (next_time + (n * period)) > now
* then the period is working
* Solution:
* if next_time < now then we set next_time = now.
* The first callback will be so fast as possible (now)
* but the next callback on period
*/
if (is_relative) {
next_time += now;
}
/* You can not set timers into the past */
if (next_time < now) {
next_time = now;
}
pthread_mutex_lock(&ctx->timers->mutex);
if (ctx->timers->timer_count == MAX_TIMERS) {
error = 1;
} else if (ctx->timers->timer_count == ctx->timers->timer_capacity) {
unsigned capacity = (ctx->timers->timer_capacity * 2) + 1;
struct ttimer *timers =
(struct ttimer *)mg_realloc_ctx(ctx->timers->timers,
capacity * sizeof(struct ttimer),
ctx);
if (timers) {
ctx->timers->timers = timers;
ctx->timers->timer_capacity = capacity;
} else {
error = 1;
}
}
if (!error) {
/* Insert new timer into a sorted list. */
/* The linear list is still most efficient for short lists (small
* number of timers) - if there are many timers, different
* algorithms will work better. */
unsigned u = ctx->timers->timer_count;
for (; (u > 0) && (ctx->timers->timers[u - 1].time > next_time); u--) {
ctx->timers->timers[u] = ctx->timers->timers[u - 1];
}
ctx->timers->timers[u].time = next_time;
ctx->timers->timers[u].period = period;
ctx->timers->timers[u].action = action;
ctx->timers->timers[u].arg = arg;
ctx->timers->timers[u].cancel = cancel;
ctx->timers->timer_count++;
}
pthread_mutex_unlock(&ctx->timers->mutex);
return error;
}
static void
timer_thread_run(void *thread_func_param)
{
struct mg_context *ctx = (struct mg_context *)thread_func_param;
double d;
unsigned u;
int action_res;
struct ttimer t;
mg_set_thread_name("timer");
if (ctx->callbacks.init_thread) {
/* Timer thread */
ctx->callbacks.init_thread(ctx, 2);
}
/* Timer main loop */
d = timer_getcurrenttime(ctx);
while (STOP_FLAG_IS_ZERO(&ctx->stop_flag)) {
pthread_mutex_lock(&ctx->timers->mutex);
if ((ctx->timers->timer_count > 0)
&& (d >= ctx->timers->timers[0].time)) {
/* Timer list is sorted. First action should run now. */
/* Store active timer in "t" */
t = ctx->timers->timers[0];
/* Shift all other timers */
for (u = 1; u < ctx->timers->timer_count; u++) {
ctx->timers->timers[u - 1] = ctx->timers->timers[u];
}
ctx->timers->timer_count--;
pthread_mutex_unlock(&ctx->timers->mutex);
/* Call timer action */
action_res = t.action(t.arg);
/* action_res == 1: reschedule */
/* action_res == 0: do not reschedule, free(arg) */
if ((action_res > 0) && (t.period > 0)) {
/* Should schedule timer again */
timer_add(ctx,
t.time + t.period,
t.period,
0,
t.action,
t.arg,
t.cancel);
} else {
/* Allow user to free timer argument */
if (t.cancel != NULL) {
t.cancel(t.arg);
}
}
continue;
} else {
pthread_mutex_unlock(&ctx->timers->mutex);
}
/* TIMER_RESOLUTION = 10 ms seems reasonable.
* A faster loop (smaller sleep value) increases CPU load,
* a slower loop (higher sleep value) decreases timer accuracy.
*/
mg_sleep(TIMER_RESOLUTION);
d = timer_getcurrenttime(ctx);
}
/* Remove remaining timers */
for (u = 0; u < ctx->timers->timer_count; u++) {
t = ctx->timers->timers[u];
if (t.cancel != NULL) {
t.cancel(t.arg);
}
}
}
#if defined(_WIN32)
static unsigned __stdcall timer_thread(void *thread_func_param)
{
timer_thread_run(thread_func_param);
return 0;
}
#else
static void *
timer_thread(void *thread_func_param)
{
struct sigaction sa;
/* Ignore SIGPIPE */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
timer_thread_run(thread_func_param);
return NULL;
}
#endif /* _WIN32 */
TIMER_API int
timers_init(struct mg_context *ctx)
{
/* Initialize timers data structure */
ctx->timers =
(struct ttimers *)mg_calloc_ctx(sizeof(struct ttimers), 1, ctx);
if (!ctx->timers) {
return -1;
}
ctx->timers->timers = NULL;
/* Initialize mutex */
if (0 != pthread_mutex_init(&ctx->timers->mutex, NULL)) {
mg_free(ctx->timers);
ctx->timers = NULL;
return -1;
}
/* For some systems timer_getcurrenttime does some initialization
* during the first call. Call it once now, ignore the result. */
(void)timer_getcurrenttime(ctx);
/* Start timer thread */
if (mg_start_thread_with_id(timer_thread, ctx, &ctx->timers->threadid)
!= 0) {
(void)pthread_mutex_destroy(&ctx->timers->mutex);
mg_free(ctx->timers);
ctx->timers = NULL;
return -1;
}
return 0;
}
TIMER_API void
timers_exit(struct mg_context *ctx)
{
if (ctx->timers) {
mg_join_thread(ctx->timers->threadid);
(void)pthread_mutex_destroy(&ctx->timers->mutex);
mg_free(ctx->timers->timers);
mg_free(ctx->timers);
ctx->timers = NULL;
}
}
/* End of timer.inl */

77
vendor/CivetWeb/wolfssl_extras.inl vendored Normal file
View File

@ -0,0 +1,77 @@
/* Additional defines for WolfSSL, see
* https://github.com/civetweb/civetweb/issues/583 */
/* Required for WOLFSSL_X509 */
#include <openssl/../internal.h>
#define i2d_X509 cw_i2d_X509
#define EVP_Digest cw_EVP_Digest
/* i2d_X509 has no valid implementation in wolfssl
*
* The letters i and d in for example i2d_X509 stand for "internal" (that is an
*internal C structure)
* and " DER ". So that i2d_X509 converts from internal to DER.
*
* For OpenSSL 0.9.7 and later if *out is NULL memory will be allocated for a
*buffer and the encoded
* data written to it. In this case *out is not incremented and it points to the
*start of the data
* just written.
*/
int
cw_i2d_X509(struct WOLFSSL_X509 *x, unsigned char **out)
{
if (!x || !x->derCert) {
return -1;
}
const int ret = (int)x->derCert->length;
if (out && (ret > 0)) {
if (*out == NULL) {
*out = mg_malloc(ret);
}
if (*out != NULL) {
memcpy(*out, x->derCert->buffer, ret);
}
}
return ret;
}
/* EVP_Digest not in wolfssl */
int
cw_EVP_Digest(const void *data,
size_t count,
unsigned char *md,
unsigned int *size,
const EVP_MD *type,
ENGINE *impl)
{
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
int ret;
if (ctx == NULL)
return 0;
/* EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT); */
ret = EVP_DigestInit_ex(ctx, type, impl)
&& EVP_DigestUpdate(ctx, data, count)
&& EVP_DigestFinal_ex(ctx, md, size);
EVP_MD_CTX_free(ctx);
return ret;
}
/*
* the variable SSL_OP_NO_TLSv1_1 is not defined within the context of
* wolfssl but since the methods using the value are all stubs, we can
* define it arbitrarily and it will not have any consequences
*/
#define SSL_OP_NO_TLSv1_1 (0x10000000L)