Merge branch 'main' into debugging-client

This commit is contained in:
MihailRis 2025-11-15 13:07:48 +03:00
commit fbc9ceece4
8 changed files with 86 additions and 18 deletions

View File

@ -57,7 +57,10 @@ network.tcp_connect(
-- Function called upon successful connection -- Function called upon successful connection
-- Sending will not work before connection -- Sending will not work before connection
-- Socket is passed as the only argument -- Socket is passed as the only argument
callback: function(Socket) callback: function(Socket),
-- Function called when a connection error occurs
-- Arguments passed: socket and error text
[optional] error_callback: function(Socket, str)
) --> Socket ) --> Socket
``` ```

View File

@ -58,6 +58,9 @@ network.tcp_connect(
-- До подключения отправка работать не будет -- До подключения отправка работать не будет
-- Как единственный аргумент передаётся сокет -- Как единственный аргумент передаётся сокет
callback: function(Socket) callback: function(Socket)
-- Функция, вызываемая при ошибке подключения
-- Как аргументы передаются сокет и текст ошибки
[опционально] error_callback: function(Socket, str)
) --> Socket ) --> Socket
``` ```

View File

@ -70,6 +70,7 @@ local DatagramServerSocket = {__index={
local _tcp_server_callbacks = {} local _tcp_server_callbacks = {}
local _tcp_client_callbacks = {} local _tcp_client_callbacks = {}
local _tcp_client_error_callbacks = {}
local _udp_server_callbacks = {} local _udp_server_callbacks = {}
local _udp_client_datagram_callbacks = {} local _udp_client_datagram_callbacks = {}
@ -116,10 +117,13 @@ network.tcp_open = function (port, handler)
return socket return socket
end end
network.tcp_connect = function(address, port, callback) network.tcp_connect = function(address, port, callback, errorCallback)
local socket = setmetatable({id=0}, Socket) local socket = setmetatable({id=0}, Socket)
socket.id = network.__connect_tcp(address, port) socket.id = network.__connect_tcp(address, port)
_tcp_client_callbacks[socket.id] = function() callback(socket) end _tcp_client_callbacks[socket.id] = function() callback(socket) end
if errorCallback then
_tcp_client_error_callbacks[socket.id] = function(message) errorCallback(socket, message) end
end
return socket return socket
end end
@ -239,6 +243,7 @@ network.__process_events = function()
local CONNECTED_TO_SERVER = 2 local CONNECTED_TO_SERVER = 2
local DATAGRAM = 3 local DATAGRAM = 3
local RESPONSE = 4 local RESPONSE = 4
local CONNECTION_ERROR = 5
local ON_SERVER = 1 local ON_SERVER = 1
local ON_CLIENT = 2 local ON_CLIENT = 2
@ -258,6 +263,11 @@ network.__process_events = function()
if callback then if callback then
callback() callback()
end end
elseif etype == CONNECTION_ERROR then
local callback = _tcp_client_error_callbacks[cid]
if callback then
callback(addr)
end
elseif etype == DATAGRAM then elseif etype == DATAGRAM then
if side == ON_CLIENT then if side == ON_CLIENT then
local callback = _udp_client_datagram_callbacks[cid] local callback = _udp_client_datagram_callbacks[cid]

View File

@ -13,11 +13,13 @@ enum NetworkEventType {
CONNECTED_TO_SERVER, CONNECTED_TO_SERVER,
DATAGRAM, DATAGRAM,
RESPONSE, RESPONSE,
CONNECTION_ERROR,
}; };
struct ConnectionEventDto { struct ConnectionEventDto {
u64id_t server; u64id_t server;
u64id_t client; u64id_t client;
std::string comment {};
}; };
struct ResponseEventDto { struct ResponseEventDto {
@ -283,6 +285,11 @@ static int l_connect_tcp(lua::State* L, network::Network& network) {
CONNECTED_TO_SERVER, CONNECTED_TO_SERVER,
ConnectionEventDto {0, cid} ConnectionEventDto {0, cid}
)); ));
}, [](u64id_t cid, std::string errorMessage) {
push_event(NetworkEvent(
CONNECTION_ERROR,
ConnectionEventDto {0, cid, std::move(errorMessage)}
));
}); });
return lua::pushinteger(L, id); return lua::pushinteger(L, id);
} }
@ -439,7 +446,8 @@ static int l_pull_events(lua::State* L, network::Network& network) {
const auto& event = local_queue[i]; const auto& event = local_queue[i];
switch (event.type) { switch (event.type) {
case CLIENT_CONNECTED: case CLIENT_CONNECTED:
case CONNECTED_TO_SERVER: { case CONNECTED_TO_SERVER:
case CONNECTION_ERROR: {
const auto& dto = std::get<ConnectionEventDto>(event.payload); const auto& dto = std::get<ConnectionEventDto>(event.payload);
lua::pushinteger(L, event.type); lua::pushinteger(L, event.type);
lua::rawseti(L, 1); lua::rawseti(L, 1);
@ -449,6 +457,9 @@ static int l_pull_events(lua::State* L, network::Network& network) {
lua::pushinteger(L, dto.client); lua::pushinteger(L, dto.client);
lua::rawseti(L, 3); lua::rawseti(L, 3);
lua::pushlstring(L, dto.comment);
lua::rawseti(L, 4);
break; break;
} }
case DATAGRAM: { case DATAGRAM: {

View File

@ -16,7 +16,10 @@ namespace network {
std::unique_ptr<Requests> create_curl_requests(); std::unique_ptr<Requests> create_curl_requests();
std::shared_ptr<TcpConnection> connect_tcp( std::shared_ptr<TcpConnection> connect_tcp(
const std::string& address, int port, runnable callback const std::string& address,
int port,
runnable callback,
stringconsumer errorCallback
); );
std::shared_ptr<TcpServer> open_tcp_server( std::shared_ptr<TcpServer> open_tcp_server(
@ -87,12 +90,19 @@ Server* Network::getServer(u64id_t id, bool includePrivate) const {
return found->second.get(); return found->second.get();
} }
u64id_t Network::connectTcp(const std::string& address, int port, consumer<u64id_t> callback) { u64id_t Network::connectTcp(
const std::string& address,
int port,
consumer<u64id_t> callback,
ConnectErrorCallback errorCallback
) {
std::lock_guard lock(connectionsMutex); std::lock_guard lock(connectionsMutex);
u64id_t id = nextConnection++; u64id_t id = nextConnection++;
auto socket = connect_tcp(address, port, [id, callback]() { auto socket = connect_tcp(address, port, [id, callback]() {
callback(id); callback(id);
}, [id, errorCallback](auto errorMessage) {
errorCallback(id, errorMessage);
}); });
connections[id] = std::move(socket); connections[id] = std::move(socket);
return id; return id;

View File

@ -7,7 +7,7 @@ namespace network {
public: public:
~TcpConnection() override = default; ~TcpConnection() override = default;
virtual void connect(runnable callback) = 0; virtual void connect(runnable callback, stringconsumer errorCallback) = 0;
virtual void setNoDelay(bool noDelay) = 0; virtual void setNoDelay(bool noDelay) = 0;
[[nodiscard]] virtual bool isNoDelay() const = 0; [[nodiscard]] virtual bool isNoDelay() const = 0;
@ -88,8 +88,18 @@ namespace network {
[[nodiscard]] Connection* getConnection(u64id_t id, bool includePrivate); [[nodiscard]] Connection* getConnection(u64id_t id, bool includePrivate);
[[nodiscard]] Server* getServer(u64id_t id, bool includePrivate) const; [[nodiscard]] Server* getServer(u64id_t id, bool includePrivate) const;
u64id_t connectTcp(const std::string& address, int port, consumer<u64id_t> callback); u64id_t connectTcp(
u64id_t connectUdp(const std::string& address, int port, const consumer<u64id_t>& callback, ClientDatagramCallback handler); const std::string& address,
int port,
consumer<u64id_t> callback,
ConnectErrorCallback errorCallback
);
u64id_t connectUdp(
const std::string& address,
int port,
const consumer<u64id_t>& callback,
ClientDatagramCallback handler
);
u64id_t openTcpServer(int port, ConnectCallback handler); u64id_t openTcpServer(int port, ConnectCallback handler);
u64id_t openUdpServer(int port, const ServerDatagramCallback& handler); u64id_t openUdpServer(int port, const ServerDatagramCallback& handler);

View File

@ -106,6 +106,7 @@ class SocketTcpConnection : public TcpConnection {
std::vector<char> readBatch; std::vector<char> readBatch;
util::Buffer<char> buffer; util::Buffer<char> buffer;
std::mutex mutex; std::mutex mutex;
std::string errorMessage;
void connectSocket() { void connectSocket() {
state = ConnectionState::CONNECTING; state = ConnectionState::CONNECTING;
@ -115,7 +116,8 @@ class SocketTcpConnection : public TcpConnection {
auto error = handle_socket_error("Connect failed"); auto error = handle_socket_error("Connect failed");
closesocket(descriptor); closesocket(descriptor);
state = ConnectionState::CLOSED; state = ConnectionState::CLOSED;
logger.error() << error.what(); errorMessage = error.what();
logger.error() << errorMessage;
return; return;
} }
logger.info() << "connected to " << to_string(addr); logger.info() << "connected to " << to_string(addr);
@ -182,13 +184,15 @@ public:
thread = std::make_unique<std::thread>([this]() { startListen();}); thread = std::make_unique<std::thread>([this]() { startListen();});
} }
void connect(runnable callback) override { void connect(runnable callback, stringconsumer errorCallback) override {
thread = std::make_unique<std::thread>([this, callback]() { thread = std::make_unique<std::thread>([this, callback, errorCallback]() {
connectSocket(); connectSocket();
if (state == ConnectionState::CONNECTED) { if (state == ConnectionState::CONNECTED) {
callback(); callback();
startListen();
} else {
errorCallback(errorMessage);
} }
startListen();
}); });
} }
@ -263,7 +267,10 @@ public:
} }
static std::shared_ptr<SocketTcpConnection> connect( static std::shared_ptr<SocketTcpConnection> connect(
const std::string& address, int port, runnable callback const std::string& address,
int port,
runnable callback,
stringconsumer errorCallback
) { ) {
addrinfo hints {}; addrinfo hints {};
@ -274,7 +281,11 @@ public:
if (int res = getaddrinfo( if (int res = getaddrinfo(
address.c_str(), nullptr, &hints, &addrinfo address.c_str(), nullptr, &hints, &addrinfo
)) { )) {
throw std::runtime_error(gai_strerror(res)); std::string errorMessage = gai_strerror(res);
if (errorCallback) {
errorCallback(errorMessage);
}
throw std::runtime_error(errorMessage);
} }
sockaddr_in serverAddress; sockaddr_in serverAddress;
@ -284,10 +295,14 @@ public:
SOCKET descriptor = socket(AF_INET, SOCK_STREAM, 0); SOCKET descriptor = socket(AF_INET, SOCK_STREAM, 0);
if (descriptor == -1) { if (descriptor == -1) {
throw std::runtime_error("Could not create socket"); std::string errorMessage = "could not create socket";
if (errorCallback) {
errorCallback(errorMessage);
}
throw std::runtime_error(errorMessage);
} }
auto socket = std::make_shared<SocketTcpConnection>(descriptor, std::move(serverAddress)); auto socket = std::make_shared<SocketTcpConnection>(descriptor, std::move(serverAddress));
socket->connect(std::move(callback)); socket->connect(std::move(callback), std::move(errorCallback));
return socket; return socket;
} }
@ -670,9 +685,14 @@ public:
namespace network { namespace network {
std::shared_ptr<TcpConnection> connect_tcp( std::shared_ptr<TcpConnection> connect_tcp(
const std::string& address, int port, runnable callback const std::string& address,
int port,
runnable callback,
stringconsumer errorCallback
) { ) {
return SocketTcpConnection::connect(address, port, std::move(callback)); return SocketTcpConnection::connect(
address, port, std::move(callback), std::move(errorCallback)
);
} }
std::shared_ptr<TcpServer> open_tcp_server( std::shared_ptr<TcpServer> open_tcp_server(

View File

@ -13,6 +13,7 @@ namespace network {
using OnResponse = std::function<void(std::vector<char>)>; using OnResponse = std::function<void(std::vector<char>)>;
using OnReject = std::function<void(int, std::vector<char>)>; using OnReject = std::function<void(int, std::vector<char>)>;
using ConnectCallback = std::function<void(u64id_t, u64id_t)>; using ConnectCallback = std::function<void(u64id_t, u64id_t)>;
using ConnectErrorCallback = std::function<void(u64id_t, std::string)>;
using ServerDatagramCallback = std::function<void(u64id_t sid, const std::string& addr, int port, const char* buffer, size_t length)>; using ServerDatagramCallback = std::function<void(u64id_t sid, const std::string& addr, int port, const char* buffer, size_t length)>;
using ClientDatagramCallback = std::function<void(u64id_t cid, const char* buffer, size_t length)>; using ClientDatagramCallback = std::function<void(u64id_t cid, const char* buffer, size_t length)>;