test
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,3 +13,4 @@ CMakeUserPresets.json
|
|||||||
|
|
||||||
build/
|
build/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.DS_Store
|
||||||
|
|||||||
@@ -11,10 +11,6 @@
|
|||||||
#include <columnlynx/common/utils.hpp>
|
#include <columnlynx/common/utils.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <openssl/x509.h>
|
|
||||||
#include <openssl/x509_vfy.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/x509v3.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ int main(int argc, char** argv) {
|
|||||||
});
|
});
|
||||||
//ioThread.join();
|
//ioThread.join();
|
||||||
|
|
||||||
log("Client connected to " + host + ":" + port);
|
log("Attempting connection to " + host + ":" + port);
|
||||||
debug("Client connection flag: " + std::to_string(client->isConnected()));
|
debug("Client connection flag: " + std::to_string(client->isConnected()));
|
||||||
debug("Client handshake flag: " + std::to_string(client->isHandshakeComplete()));
|
debug("Client handshake flag: " + std::to_string(client->isHandshakeComplete()));
|
||||||
debug("isDone flag: " + std::to_string(done));
|
debug("isDone flag: " + std::to_string(done));
|
||||||
|
|||||||
@@ -13,13 +13,22 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
if (!ec) {
|
if (!ec) {
|
||||||
asio::async_connect(mSocket, endpoints,
|
asio::async_connect(mSocket, endpoints,
|
||||||
[this, self](asio::error_code ec, const tcp::endpoint&) {
|
[this, self](asio::error_code ec, const tcp::endpoint&) {
|
||||||
if (!NetHelper::isExpectedDisconnect(ec)) {
|
if (!ec) {
|
||||||
mConnected = true;
|
mConnected = true;
|
||||||
Utils::log("Client connected.");
|
Utils::log("Client connected.");
|
||||||
mHandler = std::make_shared<MessageHandler>(std::move(mSocket));
|
mHandler = std::make_shared<MessageHandler>(std::move(mSocket));
|
||||||
mHandler->onMessage([this](AnyMessageType type, const std::string& data) {
|
mHandler->onMessage([this](AnyMessageType type, const std::string& data) {
|
||||||
mHandleMessage(static_cast<ServerMessageType>(MessageHandler::toUint8(type)), data);
|
mHandleMessage(static_cast<ServerMessageType>(MessageHandler::toUint8(type)), data);
|
||||||
});
|
});
|
||||||
|
// Close only after peer FIN to avoid RSTs
|
||||||
|
mHandler->onDisconnect([this](const asio::error_code& ec) {
|
||||||
|
asio::error_code ec2;
|
||||||
|
if (mHandler) {
|
||||||
|
mHandler->socket().close(ec2);
|
||||||
|
}
|
||||||
|
mConnected = false;
|
||||||
|
Utils::log(std::string("Server disconnected: ") + ec.message());
|
||||||
|
});
|
||||||
mHandler->start();
|
mHandler->start();
|
||||||
|
|
||||||
// Init connection handshake
|
// Init connection handshake
|
||||||
@@ -50,7 +59,9 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
|
|
||||||
mStartHeartbeat();
|
mStartHeartbeat();
|
||||||
} else {
|
} else {
|
||||||
Utils::error("Client connect failed: " + ec.message());
|
if (!NetHelper::isExpectedDisconnect(ec)) {
|
||||||
|
Utils::error("Client connect failed: " + ec.message());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -81,18 +92,14 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
asio::error_code ec;
|
asio::error_code ec;
|
||||||
mHeartbeatTimer.cancel();
|
mHeartbeatTimer.cancel();
|
||||||
|
|
||||||
mHandler->socket().shutdown(tcp::socket::shutdown_both, ec);
|
// Half-close: stop sending, keep reading until peer FIN
|
||||||
|
mHandler->socket().shutdown(tcp::socket::shutdown_send, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
Utils::error("Error during socket shutdown: " + ec.message());
|
Utils::error("Error during socket shutdown: " + ec.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
mHandler->socket().close(ec);
|
// Do not close immediately; rely on onDisconnect to finalize
|
||||||
if (ec) {
|
Utils::log("Client initiated graceful disconnect (half-close).");
|
||||||
Utils::error("Error during socket close: " + ec.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
mConnected = false;
|
|
||||||
Utils::log("Client disconnected.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,13 +43,19 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
auto self = shared_from_this();
|
auto self = shared_from_this();
|
||||||
asio::async_read(mSocket, asio::buffer(mHeader),
|
asio::async_read(mSocket, asio::buffer(mHeader),
|
||||||
[this, self](asio::error_code ec, std::size_t) {
|
[this, self](asio::error_code ec, std::size_t) {
|
||||||
if (!NetHelper::isExpectedDisconnect(ec)) {
|
if (!ec) {
|
||||||
mCurrentType = decodeMessageType(mHeader[0]);
|
mCurrentType = decodeMessageType(mHeader[0]);
|
||||||
|
|
||||||
uint16_t len = (mHeader[1] << 8) | mHeader[2];
|
uint16_t len = (mHeader[1] << 8) | mHeader[2];
|
||||||
mReadBody(len);
|
mReadBody(len);
|
||||||
} else {
|
} else {
|
||||||
Utils::error("Header read failed: " + ec.message());
|
if (!NetHelper::isExpectedDisconnect(ec)) {
|
||||||
|
Utils::error("Header read failed: " + ec.message());
|
||||||
|
}
|
||||||
|
// Connection closed, trigger disconnect handler
|
||||||
|
if (mOnDisconnect) {
|
||||||
|
mOnDisconnect(ec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -61,7 +67,7 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
|
|
||||||
asio::async_read(mSocket, asio::buffer(mBody),
|
asio::async_read(mSocket, asio::buffer(mBody),
|
||||||
[this, self](asio::error_code ec, std::size_t) {
|
[this, self](asio::error_code ec, std::size_t) {
|
||||||
if (!NetHelper::isExpectedDisconnect(ec)) {
|
if (!ec) {
|
||||||
std::string payload(mBody.begin(), mBody.end());
|
std::string payload(mBody.begin(), mBody.end());
|
||||||
|
|
||||||
// Dispatch based on message type
|
// Dispatch based on message type
|
||||||
@@ -71,8 +77,10 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
|
|
||||||
mReadHeader(); // Keep listening
|
mReadHeader(); // Keep listening
|
||||||
} else {
|
} else {
|
||||||
Utils::error("Body read failed: " + ec.message());
|
if (!NetHelper::isExpectedDisconnect(ec)) {
|
||||||
|
Utils::error("Body read failed: " + ec.message());
|
||||||
|
}
|
||||||
|
// Connection closed, trigger disconnect handler
|
||||||
if (mOnDisconnect) {
|
if (mOnDisconnect) {
|
||||||
mOnDisconnect(ec);
|
mOnDisconnect(ec);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,20 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
});
|
});
|
||||||
|
|
||||||
mHandler->onDisconnect([this](const asio::error_code& ec) {
|
mHandler->onDisconnect([this](const asio::error_code& ec) {
|
||||||
Utils::log("Client disconnected: " + mHandler->socket().remote_endpoint().address().to_string() + " - " + ec.message());
|
// Peer has closed; finalize locally without sending RST
|
||||||
disconnect();
|
std::string ip = mHandler->socket().remote_endpoint().address().to_string();
|
||||||
|
Utils::log("Client disconnected: " + ip + " - " + ec.message());
|
||||||
|
asio::error_code ec2;
|
||||||
|
mHandler->socket().close(ec2);
|
||||||
|
|
||||||
|
SessionRegistry::getInstance().erase(mConnectionSessionID);
|
||||||
|
SessionRegistry::getInstance().deallocIP(mConnectionSessionID);
|
||||||
|
|
||||||
|
Utils::log("Closed connection to " + ip);
|
||||||
|
|
||||||
|
if (mOnDisconnect) {
|
||||||
|
mOnDisconnect(shared_from_this());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mHandler->start();
|
mHandler->start();
|
||||||
@@ -40,24 +52,13 @@ namespace ColumnLynx::Net::TCP {
|
|||||||
}
|
}
|
||||||
mHeartbeatTimer.cancel();
|
mHeartbeatTimer.cancel();
|
||||||
asio::error_code ec;
|
asio::error_code ec;
|
||||||
mHandler->socket().shutdown(asio::ip::tcp::socket::shutdown_both, ec);
|
// Half-close: stop sending, keep reading until peer FIN
|
||||||
|
mHandler->socket().shutdown(asio::ip::tcp::socket::shutdown_send, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
Utils::error("Error during socket shutdown: " + ec.message());
|
Utils::error("Error during socket shutdown: " + ec.message());
|
||||||
}
|
}
|
||||||
|
// Do not close immediately; final cleanup happens in onDisconnect
|
||||||
mHandler->socket().close(ec);
|
Utils::log("Initiated graceful disconnect (half-close) to " + ip);
|
||||||
if (ec) {
|
|
||||||
Utils::error("Error during socket close: " + ec.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
SessionRegistry::getInstance().erase(mConnectionSessionID);
|
|
||||||
SessionRegistry::getInstance().deallocIP(mConnectionSessionID);
|
|
||||||
|
|
||||||
Utils::log("Closed connection to " + ip);
|
|
||||||
|
|
||||||
if (mOnDisconnect) {
|
|
||||||
mOnDisconnect(shared_from_this());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TCPConnection::getSessionID() const {
|
uint64_t TCPConnection::getSessionID() const {
|
||||||
|
|||||||
Reference in New Issue
Block a user