tunsafe-clang15/service_pipe_win32.h

112 lines
2.7 KiB
C++

// SPDX-License-Identifier: AGPL-1.0-only
// Copyright (C) 2018 Ludvig Strigeus <info@tunsafe.com>. All Rights Reserved.
#pragma once
#include "tunsafe_threading.h"
#include "network_win32_api.h"
class PipeManager;
// Once a pipe connects, this object is used to facilitate the connection
class PipeConnection {
friend class PipeManager;
public:
class Delegate {
public:
virtual bool HandleMessage(int type, uint8 *data, size_t size) = 0;
virtual void HandleDisconnect() = 0;
};
PipeConnection();
~PipeConnection();
void Configure(PipeManager *manager, int slot);
bool WritePacket(int type, const uint8 *data, size_t data_size);
HANDLE pipe_handle() { return pipe_; }
bool is_connected() { return connection_established_; }
bool VerifyThread();
private:
// -1 = fail, 0 = wait, 1 = conn
int InitializeServerPipeAndConnect();
bool InitializeClientPipe();
void AdvanceStateMachine();
void ClosePipe();
void TrySendNextQueuedWrite();
void HandleWriteComplete();
Delegate *delegate_;
PipeManager *manager_;
HANDLE pipe_;
bool write_overlapped_active_;
bool connection_established_;
enum State {
kStateNone,
kStateStarting,
kStateWaitConnect,
kStateWaitReadLength,
kStateWaitReadPayload,
kStateWaitTimeout,
};
uint8 state_;
uint32 packet_size_;
struct OutgoingPacket {
OutgoingPacket *next;
uint32 size;
uint8 data[0];
};
OutgoingPacket *packets_, **packets_end_;
uint8 *tmp_packet_buf_;
DWORD tmp_packet_size_;
DWORD read_pos_;
OVERLAPPED write_overlapped_, read_overlapped_;
Mutex packets_mutex_;
};
// This class supports multiple PipeConnections and calls HandleNewConnection
// when a new pipe connection is established.
class PipeManager {
friend class PipeConnection;
public:
class Delegate {
public:
// Called when a new connection is established
virtual PipeConnection::Delegate *HandleNewConnection(PipeConnection *handler) = 0;
// Called when a notification event was pushed
virtual void HandleNotify() = 0;
};
PipeManager(const char *pipe_name, bool is_server_pipe, Delegate *delegate);
~PipeManager();
bool StartThread();
void StopThread();
bool VerifyThread();
HANDLE notify_handle() { return events_[0]; }
PipeConnection *GetClientConnection() { return &connections_[0]; }
void TryStartNewListener();
private:
DWORD ThreadMain();
static DWORD WINAPI StaticThreadMain(void *x);
Delegate *delegate_;
HANDLE thread_;
char *pipe_name_;
DWORD thread_id_;
bool is_server_pipe_;
bool exit_thread_;
enum { kMaxConnections = 2 };
HANDLE events_[1 + kMaxConnections * 2];
PipeConnection connections_[kMaxConnections];
};