feat: update EntityServer connection logic and enhance domain packet parsing
This commit is contained in:
@@ -125,10 +125,8 @@ bool OverteClient::connectAvatarMixer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OverteClient::connectEntityServer() {
|
bool OverteClient::connectEntityServer() {
|
||||||
// Send DomainList request to discover EntityServer endpoint
|
// Entity server connection will be established after DomainList reply
|
||||||
sendDomainListRequest();
|
// For now, create socket and bind to receive packets
|
||||||
|
|
||||||
// Create UDP socket for EntityServer and BIND it to receive packets
|
|
||||||
m_entityFd = ::socket(AF_INET, SOCK_DGRAM, 0);
|
m_entityFd = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (m_entityFd == -1) {
|
if (m_entityFd == -1) {
|
||||||
std::cerr << "[OverteClient] Failed to create EntityServer socket: " << std::strerror(errno) << std::endl;
|
std::cerr << "[OverteClient] Failed to create EntityServer socket: " << std::strerror(errno) << std::endl;
|
||||||
@@ -138,30 +136,24 @@ bool OverteClient::connectEntityServer() {
|
|||||||
// Make non-blocking
|
// Make non-blocking
|
||||||
::fcntl(m_entityFd, F_SETFL, O_NONBLOCK);
|
::fcntl(m_entityFd, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
// Bind to port 40103 to receive entity packets
|
// Bind to ephemeral port (let OS choose) for receiving entity packets
|
||||||
sockaddr_in bindAddr{};
|
sockaddr_in bindAddr{};
|
||||||
bindAddr.sin_family = AF_INET;
|
bindAddr.sin_family = AF_INET;
|
||||||
bindAddr.sin_addr.s_addr = INADDR_ANY; // Listen on all interfaces
|
bindAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
bindAddr.sin_port = htons(m_port + 1); // 40103
|
bindAddr.sin_port = 0; // Let OS assign port
|
||||||
|
|
||||||
if (::bind(m_entityFd, reinterpret_cast<sockaddr*>(&bindAddr), sizeof(bindAddr)) == -1) {
|
if (::bind(m_entityFd, reinterpret_cast<sockaddr*>(&bindAddr), sizeof(bindAddr)) == -1) {
|
||||||
std::cerr << "[OverteClient] Failed to bind EntityServer socket to port " << (m_port + 1)
|
std::cerr << "[OverteClient] Failed to bind EntityServer socket: " << std::strerror(errno) << std::endl;
|
||||||
<< ": " << std::strerror(errno) << std::endl;
|
|
||||||
::close(m_entityFd);
|
::close(m_entityFd);
|
||||||
m_entityFd = -1;
|
m_entityFd = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the target address for sending (if needed)
|
// Get the assigned port
|
||||||
m_entityAddr = {};
|
socklen_t addrLen = sizeof(bindAddr);
|
||||||
sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(&m_entityAddr);
|
if (::getsockname(m_entityFd, reinterpret_cast<sockaddr*>(&bindAddr), &addrLen) == 0) {
|
||||||
addr->sin_family = AF_INET;
|
std::cout << "[OverteClient] EntityServer socket bound to port " << ntohs(bindAddr.sin_port) << std::endl;
|
||||||
addr->sin_port = htons(m_port + 1);
|
}
|
||||||
::inet_pton(AF_INET, m_host.c_str(), &addr->sin_addr);
|
|
||||||
m_entityAddrLen = sizeof(sockaddr_in);
|
|
||||||
|
|
||||||
m_entityServerReady = true;
|
|
||||||
std::cout << "[OverteClient] EntityServer socket bound and listening on port " << (m_port + 1) << std::endl;
|
|
||||||
|
|
||||||
m_entityServer = true;
|
m_entityServer = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -176,21 +168,21 @@ bool OverteClient::connectAudioMixer() {
|
|||||||
void OverteClient::poll() {
|
void OverteClient::poll() {
|
||||||
if (!m_connected) return;
|
if (!m_connected) return;
|
||||||
|
|
||||||
// Try a lightweight UDP ping if ready (placeholder for avatar mixer handshake)
|
// Poll domain UDP socket for domain-level packets
|
||||||
if (m_udpReady && m_udpFd != -1) {
|
if (m_udpReady && m_udpFd != -1) {
|
||||||
const char ping[4] = {'P','I','N','G'};
|
|
||||||
ssize_t s = ::sendto(m_udpFd, ping, sizeof(ping), 0, reinterpret_cast<sockaddr*>(&m_udpAddr), m_udpAddrLen);
|
|
||||||
if (s == -1 && errno != EWOULDBLOCK && errno != EAGAIN) {
|
|
||||||
std::cerr << "[OverteClient] UDP send failed: " << std::strerror(errno) << std::endl;
|
|
||||||
}
|
|
||||||
char buf[1500];
|
char buf[1500];
|
||||||
sockaddr_storage from{}; socklen_t fromlen = sizeof(from);
|
sockaddr_storage from{}; socklen_t fromlen = sizeof(from);
|
||||||
ssize_t r = ::recvfrom(m_udpFd, buf, sizeof(buf), 0, reinterpret_cast<sockaddr*>(&from), &fromlen);
|
ssize_t r = ::recvfrom(m_udpFd, buf, sizeof(buf), 0, reinterpret_cast<sockaddr*>(&from), &fromlen);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
// Parse as potential domain/avatar packets
|
parseDomainPacket(buf, static_cast<size_t>(r));
|
||||||
std::cout << "[OverteClient] Domain UDP packet received (" << r << " bytes, type=0x"
|
}
|
||||||
<< std::hex << (int)(unsigned char)buf[0] << std::dec << ")" << std::endl;
|
|
||||||
parseEntityPacket(buf, static_cast<size_t>(r));
|
// Send periodic ping to domain to keep connection alive
|
||||||
|
static auto lastPing = std::chrono::steady_clock::now();
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
if (std::chrono::duration_cast<std::chrono::seconds>(now - lastPing).count() >= 1) {
|
||||||
|
sendPing(m_udpFd, m_udpAddr, m_udpAddrLen);
|
||||||
|
lastPing = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +217,47 @@ void OverteClient::parseNetworkPackets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverteClient::parseDomainPacket(const char* data, size_t len) {
|
||||||
|
if (len < 1) return;
|
||||||
|
|
||||||
|
unsigned char packetType = static_cast<unsigned char>(data[0]);
|
||||||
|
|
||||||
|
// Domain-level packet types
|
||||||
|
const unsigned char PACKET_TYPE_PING = 0x01;
|
||||||
|
const unsigned char PACKET_TYPE_PING_REPLY = 0x02;
|
||||||
|
const unsigned char PACKET_TYPE_DOMAIN_LIST = 0x03;
|
||||||
|
const unsigned char PACKET_TYPE_DOMAIN_CONNECTION_DENIED = 0x06;
|
||||||
|
const unsigned char PACKET_TYPE_DOMAIN_SERVER_REQUIRE_DT = 0x07;
|
||||||
|
const unsigned char PACKET_TYPE_DOMAIN_CONNECT_ACK = 0x0A;
|
||||||
|
|
||||||
|
std::cout << "[OverteClient] Domain packet type: 0x" << std::hex << (int)packetType << std::dec << std::endl;
|
||||||
|
|
||||||
|
switch (packetType) {
|
||||||
|
case PACKET_TYPE_DOMAIN_LIST:
|
||||||
|
handleDomainListReply(data + 1, len - 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_DOMAIN_CONNECTION_DENIED:
|
||||||
|
handleDomainConnectionDenied(data + 1, len - 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_DOMAIN_CONNECT_ACK:
|
||||||
|
std::cout << "[OverteClient] Domain connection acknowledged!" << std::endl;
|
||||||
|
m_domainConnected = true;
|
||||||
|
// Request domain list after successful connection
|
||||||
|
sendDomainListRequest();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_PING_REPLY:
|
||||||
|
// Keep-alive ping reply
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cout << "[OverteClient] Unknown domain packet type: 0x" << std::hex << (int)packetType << std::dec << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OverteClient::parseEntityPacket(const char* data, size_t len) {
|
void OverteClient::parseEntityPacket(const char* data, size_t len) {
|
||||||
// Overte packet structure (simplified):
|
// Overte packet structure (simplified):
|
||||||
// - Byte 0: PacketType
|
// - Byte 0: PacketType
|
||||||
|
|||||||
Reference in New Issue
Block a user