mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-08-18 01:44:28 +08:00
651 lines
20 KiB
C++
651 lines
20 KiB
C++
/***********************************************************************
|
|
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
|
|
DEVELOPER: Zihan Chen(vczh)
|
|
***********************************************************************/
|
|
#include "VlppOS.h"
|
|
#include "Vlpp.h"
|
|
|
|
/***********************************************************************
|
|
.\ASYNCSOCKET\ASYNCSOCKET.WINDOWS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
|
|
Windows implementation of IAsyncSocket(Server|Client)
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_INTERPROCESS_ASYNCSOCKET_WINDOWS
|
|
#define VCZH_INTERPROCESS_ASYNCSOCKET_WINDOWS
|
|
|
|
// Winsock must precede every include that can include windows.h.
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <WinSock2.h>
|
|
#include <MSWSock.h>
|
|
#define _WINSOCKAPI_
|
|
#include <Windows.h>
|
|
|
|
|
|
namespace vl::inter_process::async_tcp_socket::windows_socket
|
|
{
|
|
class AsyncSocketServer : public Object, public virtual IAsyncSocketServer
|
|
{
|
|
private:
|
|
class Impl;
|
|
Impl* impl = nullptr;
|
|
|
|
public:
|
|
AsyncSocketServer(vint port);
|
|
~AsyncSocketServer();
|
|
|
|
vint GetPort() override;
|
|
void Start(IAsyncSocketServerCallback* callback) override;
|
|
void Stop() override;
|
|
bool IsStopped() override;
|
|
};
|
|
|
|
class AsyncSocketClient : public Object, public virtual IAsyncSocketClient
|
|
{
|
|
private:
|
|
class Impl;
|
|
Impl* impl = nullptr;
|
|
|
|
public:
|
|
AsyncSocketClient(vint port);
|
|
~AsyncSocketClient();
|
|
|
|
vint GetPort() override;
|
|
Ptr<IAsyncSocketClient> CreateSameEndpointClient() override;
|
|
IAsyncSocketConnection* GetConnection() override;
|
|
void WaitForServer() override;
|
|
ClientStatus GetStatus() override;
|
|
};
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\WINDOWS\NETWORKPROTOCOL.WINDOWS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
|
|
Interfaces:
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_INTERPROCESS_WINDOWS_NETWORKPROTOCOL
|
|
#define VCZH_INTERPROCESS_WINDOWS_NETWORKPROTOCOL
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#define _WINSOCKAPI_
|
|
#include <windows.h>
|
|
#include <http.h>
|
|
#define RPC_USE_NATIVE_WCHAR
|
|
#include <rpc.h>
|
|
#include <winhttp.h>
|
|
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\WINDOWS\HTTPCLIENTAPI.WINDOWS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
|
|
Interfaces:
|
|
HttpClientApi
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_INTERPROCESS_WINDOWS_HTTPCLIENTAPI
|
|
#define VCZH_INTERPROCESS_WINDOWS_HTTPCLIENTAPI
|
|
|
|
|
|
namespace vl::inter_process::windows_http
|
|
{
|
|
|
|
/// <summary>A Windows-only async HTTP client for a single host and port.</summary>
|
|
class HttpClientApi : public Object
|
|
{
|
|
static constexpr vint32_t HttpRespondBodyStep = 65536;
|
|
|
|
class HttpRequestContext : public Object
|
|
{
|
|
public:
|
|
HttpClientApi* api = nullptr;
|
|
HINTERNET httpRequest = NULL;
|
|
Func<void(Variant<HttpResponse, HttpError>)> callback;
|
|
collections::Array<char> requestBody;
|
|
HttpResponse response;
|
|
DWORD bodyBufferWriting = 0;
|
|
DWORD bodyBufferWritingAvailable = 0;
|
|
bool keepAliveOnStop = false;
|
|
bool completed = false;
|
|
bool closing = false;
|
|
SpinLock lockContext;
|
|
};
|
|
|
|
WString server;
|
|
vint port = 0;
|
|
HINTERNET httpSession = NULL;
|
|
HINTERNET httpConnection = NULL;
|
|
|
|
SpinLock lockActiveRequests;
|
|
collections::List<Ptr<HttpRequestContext>> activeRequests;
|
|
bool stopping = false;
|
|
atomic_vint pendingCallbacks = 0;
|
|
EventObject eventPendingCallbacks;
|
|
|
|
static void CALLBACK HttpStatusCallback(HINTERNET httpRequest, DWORD_PTR context, DWORD status, LPVOID statusInformation, DWORD statusInformationLength);
|
|
static HttpError MakeError(const WString& operation, DWORD errorCode);
|
|
|
|
bool IsStopping();
|
|
void BeginPendingCallback();
|
|
void EndPendingCallback();
|
|
void AttachRequestUnsafe(Ptr<HttpRequestContext> context);
|
|
void RemoveRequestUnsafe(Ptr<HttpRequestContext> context);
|
|
void CloseRequest(Ptr<HttpRequestContext> context);
|
|
void OnRequestHandleClosing(Ptr<HttpRequestContext> context);
|
|
void CompleteRequest(Ptr<HttpRequestContext> context, HttpResponse&& response);
|
|
void CompleteRequest(Ptr<HttpRequestContext> context, HttpError&& error);
|
|
void CompleteRequestWithLastError(Ptr<HttpRequestContext> context, const WString& operation, DWORD errorCode);
|
|
|
|
public:
|
|
HttpClientApi(const WString& _server, vint _port);
|
|
~HttpClientApi();
|
|
|
|
HttpClientApi(const HttpClientApi&) = delete;
|
|
HttpClientApi(HttpClientApi&&) = delete;
|
|
HttpClientApi& operator=(const HttpClientApi&) = delete;
|
|
HttpClientApi& operator=(HttpClientApi&&) = delete;
|
|
|
|
void HttpQuery(const HttpRequest& request, Func<void(Variant<HttpResponse, HttpError>)> callback);
|
|
void Stop();
|
|
|
|
static WString UrlEncodeQuery(const WString& query);
|
|
static WString UrlDecodeQuery(const WString& query);
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\WINDOWS\HTTPCLIENT.WINDOWS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
|
|
Interfaces:
|
|
HttpClient
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_INTERPROCESS_WINDOWS_HTTPCLIENT
|
|
#define VCZH_INTERPROCESS_WINDOWS_HTTPCLIENT
|
|
|
|
|
|
namespace vl::inter_process::windows_http
|
|
{
|
|
|
|
class HttpClient : public Object, public virtual INetworkProtocolConnection, public virtual INetworkProtocolClient
|
|
{
|
|
protected:
|
|
static constexpr vint HttpRequestMaxAttempts = 3;
|
|
|
|
enum class State
|
|
{
|
|
Ready,
|
|
WaitForServerConnection,
|
|
Running,
|
|
Stopping,
|
|
};
|
|
|
|
State state = State::Ready;
|
|
INetworkProtocolCallback* callback = nullptr;
|
|
WString baseUrl;
|
|
Ptr<HttpClientApi> httpClientApi;
|
|
WString urlConnect;
|
|
WString urlRequest;
|
|
WString urlResponse;
|
|
SpinLock lockState;
|
|
|
|
/***********************************************************************
|
|
HttpClient (Reading)
|
|
***********************************************************************/
|
|
|
|
protected:
|
|
void RaiseLocalError(WString errorMessage, bool fatal);
|
|
bool IsStopping();
|
|
public:
|
|
|
|
void BeginReadingLoopUnsafe() override;
|
|
|
|
/***********************************************************************
|
|
HttpClient (WaitForServer)
|
|
***********************************************************************/
|
|
|
|
protected:
|
|
|
|
EventObject eventWaitForServer;
|
|
SpinLock lockConnectResult;
|
|
bool connectCompleted = false;
|
|
WString connectResponse;
|
|
WString connectError;
|
|
void CompleteConnectRequest(const WString& response, const WString& error);
|
|
|
|
public:
|
|
|
|
INetworkProtocolConnection* GetConnection() override;
|
|
void WaitForServer() override;
|
|
ClientStatus GetStatus() override;
|
|
|
|
/***********************************************************************
|
|
HttpClient (Writing)
|
|
***********************************************************************/
|
|
|
|
protected:
|
|
enum class HttpRequestType
|
|
{
|
|
Connect,
|
|
Request,
|
|
Response,
|
|
};
|
|
|
|
bool SendHttpRequest(HttpRequestType requestType, const WString& url, const WString& body, vint attempt = 1);
|
|
void OnHttpRequestCompleted(HttpRequestType requestType, WString body, vint attempt, Variant<HttpResponse, HttpError> result);
|
|
void OnHttpRequestFailed(HttpRequestType requestType, const WString& body, vint attempt, const WString& errorMessage);
|
|
|
|
public:
|
|
|
|
void SendString(const WString& str) override;
|
|
|
|
/***********************************************************************
|
|
HttpClient
|
|
***********************************************************************/
|
|
|
|
public:
|
|
HttpClient(const WString _baseUrl, vint port);
|
|
~HttpClient();
|
|
|
|
void InstallCallback(INetworkProtocolCallback* _callback) override;
|
|
void Stop() override;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\WINDOWS\HTTPSERVERAPI.WINDOWS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
|
|
Interfaces:
|
|
HttpServerApi
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_INTERPROCESS_WINDOWS_HTTPSERVERAPI
|
|
#define VCZH_INTERPROCESS_WINDOWS_HTTPSERVERAPI
|
|
|
|
|
|
namespace vl::inter_process::windows_http
|
|
{
|
|
|
|
/// <summary>A response to be sent by <see cref="HttpServerApi"/>.</summary>
|
|
struct HttpServerResponse
|
|
{
|
|
vint statusCode = 200;
|
|
WString reason;
|
|
WString body;
|
|
WString contentType;
|
|
};
|
|
|
|
/// <summary>A Windows-only async HTTP server for a single URL prefix.</summary>
|
|
class HttpServerApi : public Object
|
|
{
|
|
static constexpr vint32_t HttpRequestBufferInitSize = 1024;
|
|
|
|
protected:
|
|
enum class State
|
|
{
|
|
Ready,
|
|
Running,
|
|
Stopping,
|
|
};
|
|
|
|
WString urlPrefix;
|
|
bool respondToOptions = false;
|
|
|
|
HANDLE httpRequestQueue = INVALID_HANDLE_VALUE;
|
|
HTTP_SERVER_SESSION_ID httpSessionId = HTTP_NULL_ID;
|
|
HTTP_URL_GROUP_ID httpUrlGroupId = HTTP_NULL_ID;
|
|
|
|
State state = State::Ready;
|
|
|
|
collections::Array<BYTE> bufferRequest;
|
|
HANDLE hWaitHandleRequest = INVALID_HANDLE_VALUE;
|
|
OVERLAPPED overlappedRequest;
|
|
HANDLE hEventRequest = INVALID_HANDLE_VALUE;
|
|
EventObject eventPendingCallbacks;
|
|
atomic_vint pendingCallbacks = 0;
|
|
|
|
void OnHttpConnectionBrokenUnsafe();
|
|
void OnHttpRequestReceivedUnsafe(PHTTP_REQUEST pRequest);
|
|
ULONG ListenToHttpRequest_Init(OVERLAPPED* overlapped);
|
|
ULONG ListenToHttpRequest_InitMoreData(ULONG* bytesReturned);
|
|
ULONG ListenToHttpRequest_OverlappedMoreData(vint expectedBufferSize);
|
|
void ListenToHttpRequest();
|
|
void BeginPendingCallback();
|
|
void EndPendingCallback();
|
|
|
|
virtual void OnHttpRequestReceived(PHTTP_REQUEST pRequest) = 0;
|
|
virtual void OnHttpServerStopping();
|
|
|
|
static void SendOptionsResponse(HANDLE httpRequestQueue, HTTP_REQUEST_ID requestId);
|
|
|
|
public:
|
|
HttpServerApi(const WString& _urlPrefix, bool _respondToOptions);
|
|
~HttpServerApi();
|
|
|
|
HttpServerApi(const HttpServerApi&) = delete;
|
|
HttpServerApi(HttpServerApi&&) = delete;
|
|
HttpServerApi& operator=(const HttpServerApi&) = delete;
|
|
HttpServerApi& operator=(HttpServerApi&&) = delete;
|
|
|
|
void Start();
|
|
void Stop();
|
|
bool IsStopped();
|
|
HANDLE GetHttpRequestQueue() const;
|
|
|
|
Nullable<WString> GetUtf8Body(PHTTP_REQUEST pRequest);
|
|
static ULONG SendResponse(HANDLE httpRequestQueue, HTTP_REQUEST_ID requestId, const HttpServerResponse& response);
|
|
static void SendResponseUtf8(HANDLE httpRequestQueue, HTTP_REQUEST_ID requestId, WString body);
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\WINDOWS\HTTPSERVER.WINDOWS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
|
|
Interfaces:
|
|
HttpServer
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_INTERPROCESS_WINDOWS_HTTPSERVER
|
|
#define VCZH_INTERPROCESS_WINDOWS_HTTPSERVER
|
|
|
|
|
|
namespace vl::inter_process::windows_http
|
|
{
|
|
|
|
class HttpServer;
|
|
|
|
class HttpServerConnection : public Object, public virtual INetworkProtocolConnection
|
|
{
|
|
friend class HttpServer;
|
|
protected:
|
|
HttpServer* server = nullptr;
|
|
WString guid;
|
|
INetworkProtocolCallback* callback = nullptr;
|
|
|
|
SpinLock lockQueuedStrings;
|
|
collections::List<WString> queuedStrings;
|
|
|
|
SpinLock pendingRequestLock;
|
|
HTTP_REQUEST_ID httpPendingRequestId = HTTP_NULL_ID;
|
|
collections::List<WString> pendingRequestsToSend;
|
|
bool submittingResponse = false;
|
|
collections::List<WString> responsesToSubmit;
|
|
|
|
// All following functions must be called inside SPIN_LOCK(pendingRequestLock)
|
|
void OnCancelCurrentHttpRequestForPendingRequest();
|
|
void OnNewHttpRequestForPendingRequest(HTTP_REQUEST_ID httpRequestId);
|
|
|
|
WString SubmitResponse(PHTTP_REQUEST pRequest);
|
|
|
|
public:
|
|
void InstallCallback(INetworkProtocolCallback* _callback) override;
|
|
void BeginReadingLoopUnsafe() override;
|
|
void SendString(const WString& str) override;
|
|
void Stop() override;
|
|
|
|
static WString GenerateNewGuid();
|
|
};
|
|
|
|
class HttpServer : public HttpServerApi, public virtual INetworkProtocolServer
|
|
{
|
|
friend class HttpServerConnection;
|
|
using ConnectionMap = collections::Dictionary<WString, Ptr<HttpServerConnection>>;
|
|
protected:
|
|
WString baseUrl;
|
|
WString urlConnect;
|
|
WString urlRequestPrefix;
|
|
WString urlResponsePrefix;
|
|
|
|
// covers connections
|
|
SpinLock lockConnections;
|
|
ConnectionMap connections;
|
|
|
|
/***********************************************************************
|
|
HttpServer (BeginReadingLoopUnsafe)
|
|
***********************************************************************/
|
|
|
|
protected:
|
|
|
|
|
|
/***********************************************************************
|
|
HttpServer (HttpServerApi)
|
|
***********************************************************************/
|
|
|
|
protected:
|
|
|
|
void OnHttpRequestReceived(PHTTP_REQUEST pRequest) override;
|
|
void OnHttpServerStopping() override;
|
|
|
|
/***********************************************************************
|
|
HttpServer
|
|
***********************************************************************/
|
|
|
|
public:
|
|
HttpServer(const WString _baseUrl, vint port);
|
|
~HttpServer();
|
|
|
|
WaitForClientResult OnClientConnected(INetworkProtocolConnection* connection) override;
|
|
void Start() override;
|
|
void Stop() override;
|
|
bool IsStopped() override;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\WINDOWS\NAMEDPIPE.WINDOWS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Vczh Library++ 3.0
|
|
Developer: Zihan Chen(vczh)
|
|
|
|
Interfaces:
|
|
NamedPipeServer
|
|
NamedPipeClient
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_INTERPROCESS_WINDOWS_NAMEDPIPE
|
|
#define VCZH_INTERPROCESS_WINDOWS_NAMEDPIPE
|
|
|
|
|
|
namespace vl::inter_process::named_pipe
|
|
{
|
|
|
|
class NamedPipeServer;
|
|
|
|
class NamedPipeConnection : public Object, public virtual INetworkProtocolConnection
|
|
{
|
|
friend class NamedPipeServer;
|
|
// -----------------------------------------------------------------------
|
|
// Reading
|
|
// -----------------------------------------------------------------------
|
|
|
|
private:
|
|
class ReadWaitContext;
|
|
|
|
bool firstRead = true;
|
|
atomic_vint stopped = 0;
|
|
collections::Array<BYTE> bufferReadFile;
|
|
stream::MemoryStream streamReadFile;
|
|
std::atomic<ReadWaitContext*> readWaitContext = nullptr;
|
|
OVERLAPPED overlappedReadFile;
|
|
HANDLE hEventReadFile = INVALID_HANDLE_VALUE;
|
|
atomic_vint pendingCallbacks = 0;
|
|
EventObject eventPendingCallbacks;
|
|
|
|
void BeginReadingUnsafe();
|
|
void SubmitReadBufferUnsafe(vint bytes);
|
|
void EndReadingUnsafe();
|
|
void BeginPendingCallback();
|
|
void EndPendingCallback();
|
|
|
|
public:
|
|
void BeginReadingLoopUnsafe() override;
|
|
|
|
// -----------------------------------------------------------------------
|
|
// Writing
|
|
// -----------------------------------------------------------------------
|
|
private:
|
|
SpinLock lockWrite;
|
|
stream::MemoryStream streamWriteFile;
|
|
OVERLAPPED overlappedWriteFile;
|
|
HANDLE hEventWriteFile = INVALID_HANDLE_VALUE;
|
|
|
|
vint32_t WriteInt32ToStream(vint32_t number);
|
|
vint32_t WriteStringToStream(const WString& str);
|
|
void BeginSendStream();
|
|
void EndSendStream(vint32_t bytes);
|
|
|
|
protected:
|
|
void SendString(const WString& str) override;
|
|
|
|
// -----------------------------------------------------------------------
|
|
// Connection
|
|
// -----------------------------------------------------------------------
|
|
|
|
protected:
|
|
// NamedPipe doesn't support a single message that is larger than 64K
|
|
static constexpr vint32_t MaxMessageSize = 65536;
|
|
|
|
NamedPipeServer* server = nullptr;
|
|
INetworkProtocolCallback* callback = nullptr;
|
|
HANDLE hPipe = INVALID_HANDLE_VALUE;
|
|
|
|
void OnLocalError(const WString& errorMessage);
|
|
void OnDisconnected();
|
|
|
|
NamedPipeConnection(HANDLE _hPipe);
|
|
|
|
public:
|
|
~NamedPipeConnection();
|
|
|
|
void InstallCallback(INetworkProtocolCallback* _callback) override;
|
|
void Stop() override;
|
|
};
|
|
|
|
class NamedPipeServer : public Object, public virtual INetworkProtocolServer
|
|
{
|
|
friend class NamedPipeConnection;
|
|
protected:
|
|
class PendingConnection : public Object
|
|
{
|
|
public:
|
|
class ConnectWaitContext;
|
|
|
|
NamedPipeServer* server = nullptr;
|
|
Ptr<NamedPipeConnection> connection;
|
|
std::atomic<ConnectWaitContext*> connectWaitContext = nullptr;
|
|
OVERLAPPED overlappedConnect;
|
|
HANDLE hEventConnect = INVALID_HANDLE_VALUE;
|
|
atomic_vint pendingCallbacks = 0;
|
|
EventObject eventPendingCallbacks;
|
|
|
|
PendingConnection(NamedPipeServer* _server, Ptr<NamedPipeConnection> _connection);
|
|
~PendingConnection();
|
|
|
|
void Stop();
|
|
void BeginPendingCallback();
|
|
void EndPendingCallback();
|
|
};
|
|
|
|
static HANDLE ServerCreatePipe(const WString& pipeName);
|
|
|
|
WString pipeName;
|
|
|
|
// covers started, stopped, connections and pendingConnections
|
|
SpinLock lockConnections;
|
|
bool started = false;
|
|
bool stopped = false;
|
|
collections::List<Ptr< NamedPipeConnection>> connections;
|
|
collections::List<Ptr<PendingConnection>> pendingConnections;
|
|
|
|
void BeginListening();
|
|
void CompletePendingConnection(Ptr<PendingConnection> pendingConnection, bool connected);
|
|
void CompletePendingConnection(PendingConnection* pendingConnection, bool connected);
|
|
|
|
public:
|
|
NamedPipeServer(const WString& _pipeName);
|
|
~NamedPipeServer();
|
|
|
|
WaitForClientResult OnClientConnected(INetworkProtocolConnection* connection) override;
|
|
void Start() override;
|
|
void Stop() override;
|
|
bool IsStopped() override;
|
|
};
|
|
|
|
class NamedPipeClient : public NamedPipeConnection, public virtual INetworkProtocolClient
|
|
{
|
|
protected:
|
|
static HANDLE ClientCreatePipe(const WString& pipeName);
|
|
ClientStatus status = ClientStatus::Ready;
|
|
|
|
public:
|
|
NamedPipeClient(const WString& _pipeName);
|
|
~NamedPipeClient();
|
|
|
|
INetworkProtocolConnection* GetConnection() override;
|
|
void WaitForServer() override;
|
|
ClientStatus GetStatus() override;
|
|
void Stop() override;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
|