mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +01:00
Compare commits
4 Commits
d947bf75f5
...
5dcc57a130
Author | SHA1 | Date | |
---|---|---|---|
|
5dcc57a130 | ||
|
1bd1b5545b | ||
|
8288c32d41 | ||
|
e577a96f7e |
@ -76,6 +76,7 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
|
|||||||
Library/IO/Stream.cpp Library/IO/Stream.hpp
|
Library/IO/Stream.cpp Library/IO/Stream.hpp
|
||||||
Library/JSON.cpp Library/JSON.hpp
|
Library/JSON.cpp Library/JSON.hpp
|
||||||
Library/MMDB.cpp Library/MMDB.hpp
|
Library/MMDB.cpp Library/MMDB.hpp
|
||||||
|
Library/Net.cpp Library/Net.hpp
|
||||||
Library/Numeric.cpp Library/Numeric.hpp
|
Library/Numeric.cpp Library/Numeric.hpp
|
||||||
Library/Numeric/Long.cpp Library/Numeric/Long.hpp
|
Library/Numeric/Long.cpp Library/Numeric/Long.hpp
|
||||||
Library/Numeric/Math.cpp Library/Numeric/Math.hpp
|
Library/Numeric/Math.cpp Library/Numeric/Math.hpp
|
||||||
@ -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?
|
||||||
|
@ -48,6 +48,7 @@ extern void TerminatePrivileges();
|
|||||||
extern void TerminateRoutines();
|
extern void TerminateRoutines();
|
||||||
extern void TerminateCommands();
|
extern void TerminateCommands();
|
||||||
extern void TerminateSignals();
|
extern void TerminateSignals();
|
||||||
|
extern void TerminateNet();
|
||||||
extern void TerminatePocoNet();
|
extern void TerminatePocoNet();
|
||||||
extern void TerminatePocoData();
|
extern void TerminatePocoData();
|
||||||
|
|
||||||
@ -548,6 +549,9 @@ void Core::Terminate(bool shutdown)
|
|||||||
// Release announcers
|
// Release announcers
|
||||||
AnnounceTerminate();
|
AnnounceTerminate();
|
||||||
cLogDbg(m_Verbosity >= 1, "Announcer terminated");
|
cLogDbg(m_Verbosity >= 1, "Announcer terminated");
|
||||||
|
// Release network
|
||||||
|
TerminateNet();
|
||||||
|
cLogDbg(m_Verbosity >= 1, "Network terminated");
|
||||||
// Release Poco statement results
|
// Release Poco statement results
|
||||||
TerminatePocoNet();
|
TerminatePocoNet();
|
||||||
TerminatePocoData();
|
TerminatePocoData();
|
||||||
|
203
module/Library/Net.cpp
Normal file
203
module/Library/Net.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "Library/Net.hpp"
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <sqratConst.h>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
namespace SqMod {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
SQMOD_DECL_TYPENAME(SqWebSocketClient, _SC("SqWebSocketClient"))
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static std::thread::id sMainThreadID{}; // Main thread ID
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void InitializeNet()
|
||||||
|
{
|
||||||
|
int f = MG_FEATURES_DEFAULT;
|
||||||
|
#ifndef NO_FILES
|
||||||
|
f |= MG_FEATURES_FILES;
|
||||||
|
#endif
|
||||||
|
#ifndef NO_SSL
|
||||||
|
f |= MG_FEATURES_SSL;
|
||||||
|
#endif
|
||||||
|
#ifndef NO_CGI
|
||||||
|
f |= MG_FEATURES_CGI;
|
||||||
|
#endif
|
||||||
|
#ifndef NO_CACHING
|
||||||
|
f |= MG_FEATURES_CACHE;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
f |= MG_FEATURES_CGI;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_WEBSOCKET
|
||||||
|
f |= MG_FEATURES_WEBSOCKET;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SERVER_STATS
|
||||||
|
f |= MG_FEATURES_STATS;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
f |= MG_FEATURES_COMPRESSION;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_HTTP2
|
||||||
|
f |= MG_FEATURES_HTTP2;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_X_DOM_SOCKET
|
||||||
|
f |= MG_FEATURES_X_DOMAIN_SOCKET;
|
||||||
|
#endif
|
||||||
|
mg_init_library(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void TerminateNet()
|
||||||
|
{
|
||||||
|
// Go over all connections and try to terminate them
|
||||||
|
for (WebSocketClient * inst = WebSocketClient::sHead; inst && inst->mNext != WebSocketClient::sHead; inst = inst->mNext)
|
||||||
|
{
|
||||||
|
inst->Terminate(); // Terminate() the connection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void ProcessNet()
|
||||||
|
{
|
||||||
|
// Go over all connections and allow them to process data
|
||||||
|
for (WebSocketClient * inst = WebSocketClient::sHead; inst && inst->mNext != WebSocketClient::sHead; inst = inst->mNext)
|
||||||
|
{
|
||||||
|
inst->Process();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
WebSocketClient & WebSocketClient::Connect()
|
||||||
|
{
|
||||||
|
// Make sure another connection does not exist
|
||||||
|
Invalid();
|
||||||
|
// Error buffer
|
||||||
|
char err_buf[128] = {0};
|
||||||
|
// Connect to the given WS or WSS (WS secure) server
|
||||||
|
mHandle = mg_connect_websocket_client(mHost.c_str(), mPort, mSecure?1:0,
|
||||||
|
err_buf, sizeof(err_buf), mPath.c_str(),
|
||||||
|
mOrigin.empty() ? nullptr : mOrigin.c_str(),
|
||||||
|
&WebSocketClient::DataHandler_,
|
||||||
|
&WebSocketClient::CloseHandler_,
|
||||||
|
this);
|
||||||
|
// Check if connection was possible
|
||||||
|
if (!mHandle)
|
||||||
|
{
|
||||||
|
STHROWF("Connection failed: {}", err_buf);
|
||||||
|
}
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
WebSocketClient & WebSocketClient::ConnectExt()
|
||||||
|
{
|
||||||
|
// Make sure another connection does not exist
|
||||||
|
Invalid();
|
||||||
|
// Error buffer
|
||||||
|
char err_buf[128] = {0};
|
||||||
|
// Connect to the given WS or WSS (WS secure) server
|
||||||
|
mHandle = mg_connect_websocket_client_extensions(mHost.c_str(), mPort, mSecure?1:0,
|
||||||
|
err_buf, sizeof(err_buf), mPath.c_str(),
|
||||||
|
mOrigin.empty() ? nullptr : mOrigin.c_str(),
|
||||||
|
mExtensions.empty() ? nullptr : mExtensions.c_str(),
|
||||||
|
&WebSocketClient::DataHandler_,
|
||||||
|
&WebSocketClient::CloseHandler_,
|
||||||
|
this);
|
||||||
|
// Check if connection was possible
|
||||||
|
if (!mHandle)
|
||||||
|
{
|
||||||
|
STHROWF("Connection failed: {}", err_buf);
|
||||||
|
}
|
||||||
|
// Allow chaining
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
int WebSocketClient::DataHandler(int flags, char * data, size_t data_len) noexcept
|
||||||
|
{
|
||||||
|
// Create a frame instance to store information and queue it
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mQueue.enqueue(std::make_unique< Frame >(data, data_len, flags));
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
LogFtl("Failed to queue web-socket data");
|
||||||
|
}
|
||||||
|
// Return 1 to keep the connection open
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void WebSocketClient::CloseHandler() noexcept
|
||||||
|
{
|
||||||
|
mClosing.store(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
void Register_Net(HSQUIRRELVM vm)
|
||||||
|
{
|
||||||
|
Table ns(vm);
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
ns.Bind(_SC("WebSocketClient"),
|
||||||
|
Class< WebSocketClient, NoCopy< WebSocketClient > >(ns.GetVM(), SqWebSocketClient::Str)
|
||||||
|
// Constructors
|
||||||
|
.Ctor()
|
||||||
|
.Ctor< StackStrF &, uint16_t, StackStrF & >()
|
||||||
|
.Ctor< StackStrF &, uint16_t, StackStrF &, bool >()
|
||||||
|
.Ctor< StackStrF &, uint16_t, StackStrF &, bool, StackStrF & >()
|
||||||
|
.Ctor< StackStrF &, uint16_t, StackStrF &, bool, StackStrF &, StackStrF & >()
|
||||||
|
// Meta-methods
|
||||||
|
.SquirrelFunc(_SC("_typename"), &SqWebSocketClient::Fn)
|
||||||
|
// Properties
|
||||||
|
.Prop(_SC("Tag"), &WebSocketClient::GetTag, &WebSocketClient::SetTag)
|
||||||
|
.Prop(_SC("Data"), &WebSocketClient::GetData, &WebSocketClient::SetData)
|
||||||
|
.Prop(_SC("Host"), &WebSocketClient::GetHost, &WebSocketClient::SetHost)
|
||||||
|
.Prop(_SC("Port"), &WebSocketClient::GetPort, &WebSocketClient::SetPort)
|
||||||
|
.Prop(_SC("Path"), &WebSocketClient::GetPath, &WebSocketClient::SetPath)
|
||||||
|
.Prop(_SC("Secure"), &WebSocketClient::GetSecure, &WebSocketClient::SetSecure)
|
||||||
|
.Prop(_SC("Origin"), &WebSocketClient::GetOrigin, &WebSocketClient::SetOrigin)
|
||||||
|
.Prop(_SC("Extensions"), &WebSocketClient::GetExtensions, &WebSocketClient::SetExtensions)
|
||||||
|
.Prop(_SC("OnData"), &WebSocketClient::GetOnData, &WebSocketClient::SetOnData)
|
||||||
|
.Prop(_SC("OnClose"), &WebSocketClient::GetOnClose, &WebSocketClient::SetOnClose)
|
||||||
|
.Prop(_SC("Valid"), &WebSocketClient::IsValid)
|
||||||
|
.Prop(_SC("Closing"), &WebSocketClient::IsClosing)
|
||||||
|
// Member Methods
|
||||||
|
.FmtFunc(_SC("SetTag"), &WebSocketClient::ApplyTag)
|
||||||
|
.FmtFunc(_SC("SetData"), &WebSocketClient::ApplyData)
|
||||||
|
.FmtFunc(_SC("SetHost"), &WebSocketClient::ApplyHost)
|
||||||
|
.Func(_SC("SetPort"), &WebSocketClient::ApplyPort)
|
||||||
|
.FmtFunc(_SC("SetPath"), &WebSocketClient::ApplyPath)
|
||||||
|
.Func(_SC("SetSecure"), &WebSocketClient::ApplySecure)
|
||||||
|
.FmtFunc(_SC("SetOrigin"), &WebSocketClient::ApplyOrigin)
|
||||||
|
.FmtFunc(_SC("SetExtensions"), &WebSocketClient::ApplyExtensions)
|
||||||
|
.CbFunc(_SC("BindOnData"), &WebSocketClient::BindOnData)
|
||||||
|
.CbFunc(_SC("BindOnClose"), &WebSocketClient::BindOnClose)
|
||||||
|
.Func(_SC("Connect"), &WebSocketClient::Connect)
|
||||||
|
.Func(_SC("ConnectExt"), &WebSocketClient::ConnectExt)
|
||||||
|
.Func(_SC("SendOpCode"), &WebSocketClient::SendOpCode)
|
||||||
|
.Func(_SC("SendBuffer"), &WebSocketClient::SendBuffer)
|
||||||
|
.FmtFunc(_SC("SendString"), &WebSocketClient::SendString)
|
||||||
|
.Func(_SC("Close"), &WebSocketClient::Close)
|
||||||
|
);
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
RootTable(vm).Bind(_SC("SqNet"), ns);
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
ConstTable(vm).Enum(_SC("SqWsOpCode"), Enumeration(vm)
|
||||||
|
.Const(_SC("Continuation"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_CONTINUATION))
|
||||||
|
.Const(_SC("Text"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_TEXT))
|
||||||
|
.Const(_SC("Binary"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_BINARY))
|
||||||
|
.Const(_SC("ConnectionClose"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE))
|
||||||
|
.Const(_SC("Ping"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_PING))
|
||||||
|
.Const(_SC("Pong"), static_cast< SQInteger >(MG_WEBSOCKET_OPCODE_PONG))
|
||||||
|
);
|
||||||
|
// Main thread ID
|
||||||
|
sMainThreadID = std::this_thread::get_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Namespace:: SqMod
|
760
module/Library/Net.hpp
Normal file
760
module/Library/Net.hpp
Normal file
@ -0,0 +1,760 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "Library/IO/Buffer.hpp"
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <sqratFunction.h>
|
||||||
|
#include <concurrentqueue.h>
|
||||||
|
#include <civetweb.h>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
namespace SqMod {
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* WebSocket client implementation.
|
||||||
|
*/
|
||||||
|
struct WebSocketClient : public SqChainedInstances< WebSocketClient >
|
||||||
|
{
|
||||||
|
using Base = SqChainedInstances< WebSocketClient >;
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* WebSocket frame.
|
||||||
|
*/
|
||||||
|
struct Frame
|
||||||
|
{
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Frame data.
|
||||||
|
*/
|
||||||
|
char * mData{nullptr};
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Frame data capacity.
|
||||||
|
*/
|
||||||
|
uint32_t mSize{0};
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Frame flags.
|
||||||
|
*/
|
||||||
|
int mFlags{0};
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
Frame() = default;
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Explicit constructor.
|
||||||
|
*/
|
||||||
|
Frame(char * data, size_t size, int flags)
|
||||||
|
: mData(nullptr), mSize(static_cast< uint32_t >(size)), mFlags(flags)
|
||||||
|
{
|
||||||
|
// Do we need to allocate a buffer?
|
||||||
|
if (mSize != 0)
|
||||||
|
{
|
||||||
|
// Allocate the memory buffer.
|
||||||
|
mData = new char[mSize];
|
||||||
|
// Copy the data into the buffer we own
|
||||||
|
std::memcpy(mData, data, mSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Copy constructor (disabled).
|
||||||
|
*/
|
||||||
|
Frame(const Frame & o) = delete;
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Move constructor (disabled).
|
||||||
|
*/
|
||||||
|
Frame(Frame && o) noexcept = delete;
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
~Frame()
|
||||||
|
{
|
||||||
|
delete[] mData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Copy assignment operator (disabled).
|
||||||
|
*/
|
||||||
|
Frame & operator = (const Frame & o) = delete;
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Move assignment operator (disabled).
|
||||||
|
*/
|
||||||
|
Frame & operator = (Frame && o) noexcept = delete;
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Forget about the associated memory buffer.
|
||||||
|
*/
|
||||||
|
void ForgetBuffer() noexcept
|
||||||
|
{
|
||||||
|
mData = nullptr;
|
||||||
|
mSize = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Smart frame pointer.
|
||||||
|
*/
|
||||||
|
using FramePtr = std::unique_ptr< Frame >;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Queue of frames written from other threads.
|
||||||
|
*/
|
||||||
|
using FrameQueue = moodycamel::ConcurrentQueue< FramePtr >;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Connection handle.
|
||||||
|
*/
|
||||||
|
struct mg_connection * mHandle{nullptr};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Queue of frames that must be processed.
|
||||||
|
*/
|
||||||
|
FrameQueue mQueue{1024};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Callback to invoke when receiving data.
|
||||||
|
*/
|
||||||
|
Function mOnData{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Callback to invoke when the socket is shutting down.
|
||||||
|
*/
|
||||||
|
Function mOnClose{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* User tag associated with this instance.
|
||||||
|
*/
|
||||||
|
String mTag{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* User data associated with this instance.
|
||||||
|
*/
|
||||||
|
LightObj mData{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Server port.
|
||||||
|
*/
|
||||||
|
int mPort{0};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Make a secure connection to server.
|
||||||
|
*/
|
||||||
|
bool mSecure{false};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Whether the connection is currently closing.
|
||||||
|
*/
|
||||||
|
std::atomic< bool > mClosing{false};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Server host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or "localhost".
|
||||||
|
*/
|
||||||
|
String mHost{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Server path you are trying to connect to, i.e. if connection to localhost/app, path should be "/app".
|
||||||
|
*/
|
||||||
|
String mPath{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Value of the Origin HTTP header.
|
||||||
|
*/
|
||||||
|
String mOrigin{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Extensions to include in the connection.
|
||||||
|
*/
|
||||||
|
String mExtensions{};
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
WebSocketClient()
|
||||||
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
|
, mPort(0), mSecure(false), mClosing(false), mHost(), mPath(), mOrigin(), mExtensions()
|
||||||
|
{
|
||||||
|
ChainInstance(); // Remember this instance
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Explicit constructor.
|
||||||
|
*/
|
||||||
|
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path)
|
||||||
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
|
, mPort(port), mSecure(false), mClosing(false)
|
||||||
|
, mHost(host.mPtr, host.GetSize())
|
||||||
|
, mPath(path.mPtr, path.GetSize())
|
||||||
|
, mOrigin(), mExtensions()
|
||||||
|
{
|
||||||
|
ChainInstance(); // Remember this instance
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Explicit constructor.
|
||||||
|
*/
|
||||||
|
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure)
|
||||||
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
|
, mPort(port), mSecure(secure), mClosing(false)
|
||||||
|
, mHost(host.mPtr, host.GetSize())
|
||||||
|
, mPath(path.mPtr, path.GetSize())
|
||||||
|
, mOrigin(), mExtensions()
|
||||||
|
{
|
||||||
|
ChainInstance(); // Remember this instance
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Explicit constructor.
|
||||||
|
*/
|
||||||
|
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure, StackStrF & origin)
|
||||||
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
|
, mPort(port), mSecure(secure), mClosing(false)
|
||||||
|
, mHost(host.mPtr, host.GetSize())
|
||||||
|
, mPath(path.mPtr, path.GetSize())
|
||||||
|
, mOrigin(origin.mPtr, origin.GetSize())
|
||||||
|
, mExtensions()
|
||||||
|
{
|
||||||
|
ChainInstance(); // Remember this instance
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Explicit constructor.
|
||||||
|
*/
|
||||||
|
WebSocketClient(StackStrF & host, uint16_t port, StackStrF & path, bool secure, StackStrF & origin, StackStrF & ext)
|
||||||
|
: Base(), mHandle(nullptr), mQueue(1024), mOnData(), mOnClose(), mTag(), mData()
|
||||||
|
, mPort(port), mSecure(secure), mClosing(false)
|
||||||
|
, mHost(host.mPtr, host.GetSize())
|
||||||
|
, mPath(path.mPtr, path.GetSize())
|
||||||
|
, mOrigin(origin.mPtr, origin.GetSize())
|
||||||
|
, mExtensions(ext.mPtr, ext.GetSize())
|
||||||
|
{
|
||||||
|
ChainInstance(); // Remember this instance
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Copy constructor.
|
||||||
|
*/
|
||||||
|
WebSocketClient(const WebSocketClient &) = delete;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Move constructor.
|
||||||
|
*/
|
||||||
|
WebSocketClient(WebSocketClient &&) = delete;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Destructor. Closes the connection.
|
||||||
|
*/
|
||||||
|
~WebSocketClient()
|
||||||
|
{
|
||||||
|
// Is there a connection left to close?
|
||||||
|
if (mHandle != nullptr)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
// Forget about this instance
|
||||||
|
UnchainInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Copy assignment operator.
|
||||||
|
*/
|
||||||
|
WebSocketClient & operator = (const WebSocketClient &) = delete;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Move assignment operator.
|
||||||
|
*/
|
||||||
|
WebSocketClient & operator = (WebSocketClient &&) = delete;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated user tag.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD const String & GetTag() const
|
||||||
|
{
|
||||||
|
return mTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Return whether the associated connection handle is valid.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD bool IsValid() const
|
||||||
|
{
|
||||||
|
return mHandle != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Return whether the associated connection is closing.
|
||||||
|
* This is only valid inside the OnClose callback.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD bool IsClosing() const
|
||||||
|
{
|
||||||
|
return mClosing.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated user tag.
|
||||||
|
*/
|
||||||
|
void SetTag(StackStrF & tag)
|
||||||
|
{
|
||||||
|
if (tag.mLen > 0)
|
||||||
|
{
|
||||||
|
mTag.assign(tag.mPtr, static_cast< size_t >(tag.mLen));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTag.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated user tag.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ApplyTag(StackStrF & tag)
|
||||||
|
{
|
||||||
|
SetTag(tag);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated user data.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD LightObj & GetData()
|
||||||
|
{
|
||||||
|
return mData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated user data.
|
||||||
|
*/
|
||||||
|
void SetData(LightObj & data)
|
||||||
|
{
|
||||||
|
mData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated user data.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ApplyData(LightObj & data)
|
||||||
|
{
|
||||||
|
mData = data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Make sure a connection exists.
|
||||||
|
*/
|
||||||
|
void Validate() const
|
||||||
|
{
|
||||||
|
if (mHandle == nullptr)
|
||||||
|
{
|
||||||
|
STHROWF("No connection was made to server ({}:{}{})", mHost, mPort, mPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Return a valid connection.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD struct mg_connection * Valid() const
|
||||||
|
{
|
||||||
|
Validate();
|
||||||
|
return mHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Make sure a connection does not exist.
|
||||||
|
*/
|
||||||
|
void Invalid() const
|
||||||
|
{
|
||||||
|
if (mHandle != nullptr)
|
||||||
|
{
|
||||||
|
STHROWF("Connection already made to server ({}:{}{})", mHost, mPort, mPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated server host.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD const String & GetHost() const
|
||||||
|
{
|
||||||
|
return mHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated server host.
|
||||||
|
*/
|
||||||
|
void SetHost(StackStrF & host)
|
||||||
|
{
|
||||||
|
Invalid();
|
||||||
|
// Is there a valid host?
|
||||||
|
if (host.mLen > 0)
|
||||||
|
{
|
||||||
|
mHost.assign(host.mPtr, static_cast< size_t >(host.mLen));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mHost.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated server host.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ApplyHost(StackStrF & host)
|
||||||
|
{
|
||||||
|
SetHost(host);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated server path.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD const String & GetPath() const
|
||||||
|
{
|
||||||
|
return mPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated server path.
|
||||||
|
*/
|
||||||
|
void SetPath(StackStrF & path)
|
||||||
|
{
|
||||||
|
Invalid();
|
||||||
|
// Is there a valid path?
|
||||||
|
if (path.mLen > 0)
|
||||||
|
{
|
||||||
|
mPath.assign(path.mPtr, static_cast< size_t >(path.mLen));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mPath.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated server path.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ApplyPath(StackStrF & path)
|
||||||
|
{
|
||||||
|
SetPath(path);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated origin value.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD const String & GetOrigin() const
|
||||||
|
{
|
||||||
|
return mOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated origin value.
|
||||||
|
*/
|
||||||
|
void SetOrigin(StackStrF & origin)
|
||||||
|
{
|
||||||
|
Invalid();
|
||||||
|
// Is there a valid origin?
|
||||||
|
if (origin.mLen > 0)
|
||||||
|
{
|
||||||
|
mOrigin.assign(origin.mPtr, static_cast< size_t >(origin.mLen));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOrigin.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated origin value.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ApplyOrigin(StackStrF & origin)
|
||||||
|
{
|
||||||
|
SetOrigin(origin);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated connection extensions.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD const String & GetExtensions() const
|
||||||
|
{
|
||||||
|
return mExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated connection extensions.
|
||||||
|
*/
|
||||||
|
void SetExtensions(StackStrF & ext)
|
||||||
|
{
|
||||||
|
Invalid();
|
||||||
|
// Is there a valid extension?
|
||||||
|
if (ext.mLen > 0)
|
||||||
|
{
|
||||||
|
mExtensions.assign(ext.mPtr, static_cast< size_t >(ext.mLen));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mExtensions.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated connection extensions.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ApplyExtensions(StackStrF & ext)
|
||||||
|
{
|
||||||
|
SetExtensions(ext);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated server port number.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD int GetPort() const
|
||||||
|
{
|
||||||
|
return mPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated server port number.
|
||||||
|
*/
|
||||||
|
void SetPort(int port)
|
||||||
|
{
|
||||||
|
Invalid();
|
||||||
|
// Is there a valid port?
|
||||||
|
if (port < 0 || port > 65535)
|
||||||
|
{
|
||||||
|
STHROWF("Invalid port number: {0} < 0 || {0} > 65535", port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mPort = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated server port number.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ApplyPort(int port)
|
||||||
|
{
|
||||||
|
SetPort(port);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated SSL status.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD bool GetSecure() const
|
||||||
|
{
|
||||||
|
return mSecure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated SSL status.
|
||||||
|
*/
|
||||||
|
void SetSecure(bool secure)
|
||||||
|
{
|
||||||
|
Invalid();
|
||||||
|
mSecure = secure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated SSL status.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ApplySecure(bool secure)
|
||||||
|
{
|
||||||
|
SetSecure(secure);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated data callback.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD Function & GetOnData()
|
||||||
|
{
|
||||||
|
return mOnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated data callback.
|
||||||
|
*/
|
||||||
|
void SetOnData(Function & cb)
|
||||||
|
{
|
||||||
|
mOnData = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated data callback.
|
||||||
|
*/
|
||||||
|
WebSocketClient & BindOnData(Function & cb)
|
||||||
|
{
|
||||||
|
mOnData = cb;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the associated close callback.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD Function & GetOnClose()
|
||||||
|
{
|
||||||
|
return mOnClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated close callback.
|
||||||
|
*/
|
||||||
|
void SetOnClose(Function & cb)
|
||||||
|
{
|
||||||
|
mOnClose = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the associated close callback.
|
||||||
|
*/
|
||||||
|
WebSocketClient & BindOnClose(Function & cb)
|
||||||
|
{
|
||||||
|
mOnClose = cb;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Connect to a web-socket as a client.
|
||||||
|
*/
|
||||||
|
WebSocketClient & Connect();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Connect to a web-socket as a client with specific extensions.
|
||||||
|
*/
|
||||||
|
WebSocketClient & ConnectExt();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Close client connection.
|
||||||
|
*/
|
||||||
|
void Close()
|
||||||
|
{
|
||||||
|
mg_close_connection(Valid());
|
||||||
|
// Prevent further use
|
||||||
|
mHandle = nullptr;
|
||||||
|
// Process pending events
|
||||||
|
Process(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Sends the contents of the given buffer through the socket as a single frame.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD SQInteger SendOpCode(SqBuffer & buf, SQInteger opcode)
|
||||||
|
{
|
||||||
|
return mg_websocket_client_write(Valid(), static_cast< int >(opcode), nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Sends the contents of the given buffer through the socket as a single frame.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD SQInteger SendBuffer(SqBuffer & buf, SQInteger opcode)
|
||||||
|
{
|
||||||
|
return mg_websocket_client_write(Valid(), static_cast< int >(opcode), buf.Valid().Data(), buf.Valid().Position());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Sends the contents of the given string through the socket as a single frame.
|
||||||
|
*/
|
||||||
|
SQMOD_NODISCARD SQInteger SendString(SQInteger opcode, StackStrF & str)
|
||||||
|
{
|
||||||
|
return mg_websocket_client_write(Valid(), static_cast< int >(opcode), str.mPtr, static_cast< size_t >(str.mLen));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Process received data.
|
||||||
|
*/
|
||||||
|
void Process(bool force = false)
|
||||||
|
{
|
||||||
|
// Is there a valid connection?
|
||||||
|
if (mHandle == nullptr && !force)
|
||||||
|
{
|
||||||
|
return; // No point in going forward
|
||||||
|
}
|
||||||
|
FramePtr frame;
|
||||||
|
// See if connection is closing
|
||||||
|
const bool closing = mClosing.load();
|
||||||
|
// Is the connection closing?
|
||||||
|
if (closing)
|
||||||
|
{
|
||||||
|
mHandle = nullptr; // Prevent further use
|
||||||
|
}
|
||||||
|
// Retrieve each frame individually and process it
|
||||||
|
for (size_t count = mQueue.size_approx(), n = 0; n <= count; ++n)
|
||||||
|
{
|
||||||
|
// Try to get a frame from the queue
|
||||||
|
if (mQueue.try_dequeue(frame) && !mOnData.IsNull())
|
||||||
|
{
|
||||||
|
// Obtain a buffer from the frame
|
||||||
|
Buffer b(frame->mData, frame->mSize, frame->mSize, Buffer::OwnIt{});
|
||||||
|
// Backup the frame size before forgetting about it
|
||||||
|
const SQInteger size = static_cast< SQInteger >(frame->mSize);
|
||||||
|
// Take ownership of the memory
|
||||||
|
frame->ForgetBuffer();
|
||||||
|
// Transform the buffer into a script object
|
||||||
|
LightObj obj(SqTypeIdentity< SqBuffer >{}, SqVM(), std::move(b));
|
||||||
|
// Forward the event to the callback
|
||||||
|
mOnData.Execute(obj, size, frame->mFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Is the server closing the connection?
|
||||||
|
if (closing && !mOnClose.IsNull())
|
||||||
|
{
|
||||||
|
mOnClose.Execute(); // Let the user know
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used internally to release script resources, if any. The VM is about to be closed.
|
||||||
|
* If you don't close the connection yourself don't care about what is received after this.
|
||||||
|
*/
|
||||||
|
void Terminate()
|
||||||
|
{
|
||||||
|
// Process pending data
|
||||||
|
Process(true);
|
||||||
|
// Release callbacks
|
||||||
|
mOnData.Release();
|
||||||
|
mOnClose.Release();
|
||||||
|
// Release user data
|
||||||
|
mData.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Callback for handling data received from the server
|
||||||
|
*/
|
||||||
|
int DataHandler(int flags, char * data, size_t data_len) noexcept;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Callback for handling a close message received from the server.
|
||||||
|
*/
|
||||||
|
void CloseHandler() noexcept;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Proxy for DataHandler()
|
||||||
|
*/
|
||||||
|
static int DataHandler_(struct mg_connection * SQ_UNUSED_ARG(c), int f, char * d, size_t n, void * u) noexcept
|
||||||
|
{
|
||||||
|
return reinterpret_cast< WebSocketClient * >(u)->DataHandler(f, d, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Proxy for CloseHandler();
|
||||||
|
*/
|
||||||
|
static void CloseHandler_(const struct mg_connection * SQ_UNUSED_ARG(c), void * u) noexcept
|
||||||
|
{
|
||||||
|
reinterpret_cast< WebSocketClient * >(u)->CloseHandler();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // Namespace:: SqMod
|
@ -40,8 +40,9 @@ using Poco::StreamCopier;
|
|||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
* Helper utility that can be used to announce the server to a master-list.
|
* Helper utility that can be used to announce the server to a master-list.
|
||||||
*/
|
*/
|
||||||
struct SqAnnouncer : SqChainedInstances< SqAnnouncer >
|
struct SqAnnouncer : public SqChainedInstances< SqAnnouncer >
|
||||||
{
|
{
|
||||||
|
using Base = SqChainedInstances< SqAnnouncer >;
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Announcer status.
|
* Announcer status.
|
||||||
*/
|
*/
|
||||||
@ -114,7 +115,7 @@ struct SqAnnouncer : SqChainedInstances< SqAnnouncer >
|
|||||||
* Explicit constructor.
|
* Explicit constructor.
|
||||||
*/
|
*/
|
||||||
SqAnnouncer(SQInteger interval, StackStrF & uri)
|
SqAnnouncer(SQInteger interval, StackStrF & uri)
|
||||||
: mRun(false), mLog(true)
|
: Base(), mRun(false), mLog(true)
|
||||||
, mCount(0)
|
, mCount(0)
|
||||||
, mSuccess(0)
|
, mSuccess(0)
|
||||||
, mFailures(0)
|
, mFailures(0)
|
||||||
@ -125,8 +126,7 @@ struct SqAnnouncer : SqChainedInstances< SqAnnouncer >
|
|||||||
, mURI(uri.mPtr)
|
, mURI(uri.mPtr)
|
||||||
, mMtx(), mThread()
|
, mMtx(), mThread()
|
||||||
{
|
{
|
||||||
// Remember this instance
|
ChainInstance(); // Remember this instance
|
||||||
ChainInstance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
@ -18,10 +18,12 @@ static bool g_Reload = false;
|
|||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//extern void InitExports();
|
//extern void InitExports();
|
||||||
|
extern void InitializeNet();
|
||||||
extern void InitializePocoDataConnectors();
|
extern void InitializePocoDataConnectors();
|
||||||
extern void ProcessRoutines();
|
extern void ProcessRoutines();
|
||||||
extern void ProcessTasks();
|
extern void ProcessTasks();
|
||||||
extern void ProcessThreads();
|
extern void ProcessThreads();
|
||||||
|
extern void ProcessNet();
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
* Will the scripts be reloaded at the end of the current event?
|
* Will the scripts be reloaded at the end of the current event?
|
||||||
@ -168,6 +170,8 @@ static void OnServerFrame(float elapsed_time)
|
|||||||
ProcessTasks();
|
ProcessTasks();
|
||||||
// Process threads
|
// Process threads
|
||||||
ProcessThreads();
|
ProcessThreads();
|
||||||
|
// Process network
|
||||||
|
ProcessNet();
|
||||||
// Process log messages from other threads
|
// Process log messages from other threads
|
||||||
Logger::Get().ProcessQueue();
|
Logger::Get().ProcessQueue();
|
||||||
// See if a reload was requested
|
// See if a reload was requested
|
||||||
@ -991,6 +995,7 @@ SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs * funcs, PluginCallback
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// External plugs that need to happen (once) before initialization
|
// External plugs that need to happen (once) before initialization
|
||||||
|
InitializeNet();
|
||||||
InitializePocoDataConnectors();
|
InitializePocoDataConnectors();
|
||||||
// Proceed with plug-in initialization
|
// Proceed with plug-in initialization
|
||||||
if (!Core::Get().Initialize())
|
if (!Core::Get().Initialize())
|
||||||
|
@ -17,9 +17,8 @@ void TerminatePocoNet()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================================================
|
// ================================================================================================
|
||||||
void Register_POCO_Net(HSQUIRRELVM vm, Table &)
|
void Register_POCO_Net(HSQUIRRELVM vm, Table & ns)
|
||||||
{
|
{
|
||||||
Table ns(vm);
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
ns.Bind(_SC("WsClient"),
|
ns.Bind(_SC("WsClient"),
|
||||||
Class< WsClient, NoCopy< WsClient > >(ns.GetVM(), SqWsClient::Str)
|
Class< WsClient, NoCopy< WsClient > >(ns.GetVM(), SqWsClient::Str)
|
||||||
@ -47,8 +46,6 @@ void Register_POCO_Net(HSQUIRRELVM vm, Table &)
|
|||||||
.CbFunc(_SC("RecvStringFrameIn"), &WsClient::RecvStringFrameIn)
|
.CbFunc(_SC("RecvStringFrameIn"), &WsClient::RecvStringFrameIn)
|
||||||
);
|
);
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
RootTable(vm).Bind(_SC("SqNet"), ns);
|
|
||||||
// --------------------------------------------------------------------------------------------
|
|
||||||
ConstTable(vm).Enum(_SC("SqWsFrameFlags"), Enumeration(vm)
|
ConstTable(vm).Enum(_SC("SqWsFrameFlags"), Enumeration(vm)
|
||||||
.Const(_SC("FIN"), static_cast< SQInteger >(Poco::Net::WebSocket::FRAME_FLAG_FIN))
|
.Const(_SC("FIN"), static_cast< SQInteger >(Poco::Net::WebSocket::FRAME_FLAG_FIN))
|
||||||
.Const(_SC("RSV1"), static_cast< SQInteger >(Poco::Net::WebSocket::FRAME_FLAG_RSV1))
|
.Const(_SC("RSV1"), static_cast< SQInteger >(Poco::Net::WebSocket::FRAME_FLAG_RSV1))
|
||||||
|
@ -31,7 +31,6 @@ namespace SqMod {
|
|||||||
*/
|
*/
|
||||||
struct WsClient
|
struct WsClient
|
||||||
{
|
{
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Flags received in the last call to Recv[String]Frame() (will be overwritten on next call).
|
* Flags received in the last call to Recv[String]Frame() (will be overwritten on next call).
|
||||||
*/
|
*/
|
||||||
@ -47,17 +46,17 @@ struct WsClient
|
|||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Receiving buffer instance.
|
* Receiving buffer instance.
|
||||||
*/
|
*/
|
||||||
Poco::Buffer< char > mBuffer;
|
Poco::Buffer< char > mBuffer{0};
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* User tag associated with this instance.
|
* User tag associated with this instance.
|
||||||
*/
|
*/
|
||||||
String mTag;
|
String mTag{};
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* User data associated with this instance.
|
* User data associated with this instance.
|
||||||
*/
|
*/
|
||||||
LightObj mData;
|
LightObj mData{};
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* HTTP client session instance.
|
* HTTP client session instance.
|
||||||
|
@ -37,6 +37,7 @@ extern void Register_Format(HSQUIRRELVM vm);
|
|||||||
extern void Register_IO(HSQUIRRELVM vm);
|
extern void Register_IO(HSQUIRRELVM vm);
|
||||||
extern void Register_JSON(HSQUIRRELVM vm);
|
extern void Register_JSON(HSQUIRRELVM vm);
|
||||||
extern void Register_MMDB(HSQUIRRELVM vm);
|
extern void Register_MMDB(HSQUIRRELVM vm);
|
||||||
|
extern void Register_Net(HSQUIRRELVM vm);
|
||||||
extern void Register_Numeric(HSQUIRRELVM vm);
|
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);
|
||||||
@ -102,6 +103,7 @@ bool RegisterAPI(HSQUIRRELVM vm)
|
|||||||
Register_IO(vm);
|
Register_IO(vm);
|
||||||
Register_JSON(vm);
|
Register_JSON(vm);
|
||||||
Register_MMDB(vm);
|
Register_MMDB(vm);
|
||||||
|
Register_Net(vm);
|
||||||
Register_Numeric(vm);
|
Register_Numeric(vm);
|
||||||
Register_String(vm);
|
Register_String(vm);
|
||||||
Register_System(vm);
|
Register_System(vm);
|
||||||
|
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)
|
||||||
|
47
vendor/CivetWeb/CMakeLists.txt
vendored
Normal file
47
vendor/CivetWeb/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Create the CivetWeb library
|
||||||
|
add_library(CivetWeb STATIC
|
||||||
|
include/civetweb.h civetweb.c
|
||||||
|
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 PUBLIC USE_TIMERS=1 USE_WEBSOCKET=1 USE_IPV6=1 USE_HTTP2=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 PUBLIC "OPENSSL_API_${OPENSSL_VERSION_MAJOR}_${OPENSSL_VERSION_MINOR}")
|
||||||
|
message(STATUS "CivetWeb: OPENSSL_API_${OPENSSL_VERSION_MAJOR}_${OPENSSL_VERSION_MINOR}")
|
||||||
|
else()
|
||||||
|
target_compile_definitions(CivetWeb PUBLIC 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 PUBLIC USE_ZLIB=1)
|
||||||
|
endif()
|
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
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