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:
parent
d879999aeb
commit
bc2260a0f0
@ -89,6 +89,7 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
|
|||||||
Library/Utils/Announce.cpp Library/Utils/Announce.hpp
|
Library/Utils/Announce.cpp Library/Utils/Announce.hpp
|
||||||
Library/Utils/String.cpp Library/Utils/String.hpp
|
Library/Utils/String.cpp Library/Utils/String.hpp
|
||||||
Library/Utils/Vector.cpp Library/Utils/Vector.hpp
|
Library/Utils/Vector.cpp Library/Utils/Vector.hpp
|
||||||
|
Library/Web.cpp Library/Web.hpp
|
||||||
Library/XML.cpp Library/XML.hpp
|
Library/XML.cpp Library/XML.hpp
|
||||||
Library/ZMQ.cpp Library/ZMQ.hpp
|
Library/ZMQ.cpp Library/ZMQ.hpp
|
||||||
# Misc
|
# Misc
|
||||||
@ -133,7 +134,7 @@ if(WIN32 OR MINGW)
|
|||||||
target_link_libraries(SqModule wsock32 ws2_32 shlwapi)
|
target_link_libraries(SqModule wsock32 ws2_32 shlwapi)
|
||||||
endif()
|
endif()
|
||||||
# Link to base libraries
|
# 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
|
# Link to POCO libraries
|
||||||
target_link_libraries(SqModule Poco::Foundation Poco::Crypto Poco::Data Poco::Net Poco::JSON Poco::XML)
|
target_link_libraries(SqModule Poco::Foundation Poco::Crypto Poco::Data Poco::Net Poco::JSON Poco::XML)
|
||||||
# Does POCO have SQLite support?
|
# Does POCO have SQLite support?
|
||||||
|
15
module/Library/Web.cpp
Normal file
15
module/Library/Web.cpp
Normal 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
14
module/Library/Web.hpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "Core/Common.hpp"
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <civetweb.h>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
namespace SqMod {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // Namespace:: SqMod
|
@ -41,6 +41,7 @@ extern void Register_Numeric(HSQUIRRELVM vm);
|
|||||||
extern void Register_String(HSQUIRRELVM vm);
|
extern void Register_String(HSQUIRRELVM vm);
|
||||||
extern void Register_System(HSQUIRRELVM vm);
|
extern void Register_System(HSQUIRRELVM vm);
|
||||||
extern void Register_Utils(HSQUIRRELVM vm);
|
extern void Register_Utils(HSQUIRRELVM vm);
|
||||||
|
extern void Register_Web(HSQUIRRELVM vm);
|
||||||
extern void Register_XML(HSQUIRRELVM vm);
|
extern void Register_XML(HSQUIRRELVM vm);
|
||||||
extern void Register_ZMQ(HSQUIRRELVM vm);
|
extern void Register_ZMQ(HSQUIRRELVM vm);
|
||||||
#ifdef SQMOD_POCO_HAS_SQLITE
|
#ifdef SQMOD_POCO_HAS_SQLITE
|
||||||
@ -106,6 +107,7 @@ bool RegisterAPI(HSQUIRRELVM vm)
|
|||||||
Register_String(vm);
|
Register_String(vm);
|
||||||
Register_System(vm);
|
Register_System(vm);
|
||||||
Register_Utils(vm);
|
Register_Utils(vm);
|
||||||
|
Register_Web(vm);
|
||||||
Register_XML(vm);
|
Register_XML(vm);
|
||||||
Register_ZMQ(vm);
|
Register_ZMQ(vm);
|
||||||
#ifdef SQMOD_POCO_HAS_SQLITE
|
#ifdef SQMOD_POCO_HAS_SQLITE
|
||||||
|
1
vendor/CMakeLists.txt
vendored
1
vendor/CMakeLists.txt
vendored
@ -7,6 +7,7 @@ add_subdirectory(TinyDir)
|
|||||||
add_subdirectory(SAJSON)
|
add_subdirectory(SAJSON)
|
||||||
add_subdirectory(CPR)
|
add_subdirectory(CPR)
|
||||||
add_subdirectory(PUGIXML)
|
add_subdirectory(PUGIXML)
|
||||||
|
add_subdirectory(CivetWeb)
|
||||||
set(BUILD_TESTING OFF CACHE INTERNAL "" FORCE)
|
set(BUILD_TESTING OFF CACHE INTERNAL "" FORCE)
|
||||||
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE)
|
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE)
|
||||||
add_subdirectory(MaxmindDB)
|
add_subdirectory(MaxmindDB)
|
||||||
|
48
vendor/CivetWeb/CMakeLists.txt
vendored
Normal file
48
vendor/CivetWeb/CMakeLists.txt
vendored
Normal 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
757
vendor/CivetWeb/CivetServer.cpp
vendored
Normal 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
248
vendor/CivetWeb/LICENSE.md
vendored
Normal 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
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
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
736
vendor/CivetWeb/include/CivetServer.h
vendored
Normal 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
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
471
vendor/CivetWeb/md5.inl
vendored
Normal 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
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
239
vendor/CivetWeb/mod_mbedtls.inl
vendored
Normal 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
281
vendor/CivetWeb/mod_zlib.inl
vendored
Normal 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
545
vendor/CivetWeb/openssl_dl.inl
vendored
Normal 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
326
vendor/CivetWeb/response.inl
vendored
Normal 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
323
vendor/CivetWeb/sha1.inl
vendored
Normal 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
294
vendor/CivetWeb/timer.inl
vendored
Normal 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
77
vendor/CivetWeb/wolfssl_extras.inl
vendored
Normal 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)
|
Loading…
Reference in New Issue
Block a user