Skip to content

Commit

Permalink
net: Add initial relay support
Browse files Browse the repository at this point in the history
  • Loading branch information
IonAgorria committed Jan 5, 2024
1 parent e8f223d commit d0bf4ff
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 41 deletions.
15 changes: 12 additions & 3 deletions Source/Network/NetConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,11 @@ int NetConnection::send_raw(const void* buffer, uint32_t len) {
return sent;
}

int NetConnection::send(const XBuffer& data) {
return send(reinterpret_cast<const uint8_t*>(data.buf), data.length());
int NetConnection::send(const XBuffer& data, NETID destination) {
return send(reinterpret_cast<const uint8_t*>(data.buf), data.length(), destination);
}

int NetConnection::send(const uint8_t* buffer, uint32_t len) {
int NetConnection::send(const uint8_t* buffer, uint32_t len, NETID destination) {
if (buffer == nullptr) {
ErrH.Abort("Got null buffer in send");
}
Expand All @@ -169,6 +169,12 @@ int NetConnection::send(const uint8_t* buffer, uint32_t len) {
}
}

//Destination NETID info
if (destination != NETID_NONE) {
flags |= PERIMETER_MESSAGE_FLAG_NETID;
len += sizeof(NETID);
}

//Calculate message size
int msg_size = static_cast<int>(len + sizeof(NC_HEADER_MAGIC));
if (msg_size > PERIMETER_MESSAGE_MAX_SIZE) {
Expand All @@ -185,6 +191,9 @@ int NetConnection::send(const uint8_t* buffer, uint32_t len) {
xbuf.set(3);
xbuf < len;
xbuf.set(8);
if (flags & PERIMETER_MESSAGE_FLAG_NETID) {
xbuf < destination;
}
xbuf.write(sending_buffer, len);

int sent = send_raw(xbuf.buf, msg_size);
Expand Down
16 changes: 13 additions & 3 deletions Source/Network/NetConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const uint32_t PERIMETER_MESSAGE_MAX_SIZE = 32 * 1024 * 1024;
const uint32_t PERIMETER_MESSAGE_COMPRESSION_SIZE = 128*1024;
///Specifies this message contains compressed payload
const uint16_t PERIMETER_MESSAGE_FLAG_COMPRESSED = 1 << 0;
///Specifies this message contains NETID that is intended for
const uint16_t PERIMETER_MESSAGE_FLAG_NETID = 1 << 1;
///How many milliseconds extra to wait for the data part once getting header
const int RECV_DATA_AFTER_HEADER_TIMEOUT = 10000;
///How many milliseconds to wait for handshake to be sent/recv
Expand All @@ -17,6 +19,7 @@ const int CONNECTION_HANDSHAKE_TIMEOUT = 10000;
//Special IDs
const uint64_t NETID_NONE = 0;
const uint64_t NETID_HOST = 1;
const uint64_t NETID_RELAY = -2;
const uint64_t NETID_ALL = -1;

//Used to identify player connection
Expand Down Expand Up @@ -139,19 +142,21 @@ class NetConnection {
* Closes connection upon error
*
* @param buffer data to send into connection
* @param netid destination NETID to send this data, can be NETID_NONE
* @return amount of bytes sent, <0 if error or closed
*/
int send(const XBuffer& data);
int send(const XBuffer& data, NETID destination);

/**
* Writes data to connection
* Closes connection upon error
*
* @param buffer pointer of data to send into connection
* @param netid destination NETID to send this data, can be NETID_NONE
* @param len amount of data to send
* @return amount of bytes sent, <0 if error or closed
*/
int send(const uint8_t* buffer, uint32_t len);
int send(const uint8_t* buffer, uint32_t len, NETID destination);

/**
* Receives data from connection if any
Expand All @@ -177,10 +182,14 @@ class NetConnectionHandler {
PNetCenter* net_center = nullptr;
TCPsocket accept_socket = nullptr;
std::unordered_map<NETID, NetConnection*> connections;
//Special connection dedicated to relay
NetConnection* relayConnection;

void stopListening();
void stopRelay();
void stopConnections();
NetConnection* newConnectionFromSocket(TCPsocket socket, bool host);

NetConnection* newConnectionFromSocket(TCPsocket socket, NETID netid);

public:
explicit NetConnectionHandler(PNetCenter* center);
Expand Down Expand Up @@ -209,6 +218,7 @@ class NetConnectionHandler {

//Host related functions
bool startListening(uint16_t port);
bool startRelay();

//Single client connection
NetConnection* startConnection(NetAddress* address);
Expand Down
74 changes: 57 additions & 17 deletions Source/Network/NetConnectionHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ NetConnectionHandler::~NetConnectionHandler() {

void NetConnectionHandler::reset() {
stopListening();
stopRelay();
stopConnections();
}

Expand All @@ -28,19 +29,20 @@ NETID NetConnectionHandler::acceptConnection() {
NetConnection* incoming = nullptr;

//Find any closed connection in array
bool reused = false;
for (auto& entry : connections) {
if (entry.second->is_closed()) {
incoming = entry.second;
incoming->set_socket(incoming_socket);
reused = true;
break;
}
}

//Check if we can add it
if (!reused) {
incoming = newConnectionFromSocket(incoming_socket, false);
//Couldn't find any connection to reuse, create new
if (incoming == nullptr) {
incoming = newConnectionFromSocket(
incoming_socket,
NETID_HOST + connections.size() + 1
);
}

//incoming may be deallocated if index is not available, so get it before
Expand Down Expand Up @@ -137,6 +139,49 @@ void NetConnectionHandler::stopListening() {
}
}

bool NetConnectionHandler::startRelay() {
reset();


#if defined(PERIMETER_DEBUG) && 1
const char* relay_address = "127.0.0.1:8877";
#else
const char* relay_address = nullptr; //"relay.kdlab.com";
#endif

if (!relay_address) {
fprintf(stderr, "No relay available!\n");
return false;
}

NetAddress relay_addr;
bool resolveFailed = !NetAddress::resolve(relay_addr, relay_address);
if (!resolveFailed) {
return false;
}

TCPsocket socket = SDLNet_TCP_Open(&relay_addr.addr);
if (!socket) {
fprintf(stderr, "TCP socket open failed address %s error %s\n", relay_addr.getString().c_str(), SDLNet_GetError());
return false;
}

max_connections = 0;
relayConnection = newConnectionFromSocket(socket, NETID_RELAY);

//TODO do presentation to relay telling the game type and own data?

return true;
}

void NetConnectionHandler::stopRelay() {
if (relayConnection) {
LogMsg("Relay connection closed\n");
relayConnection->close();
relayConnection = nullptr;
}
}

NetConnection* NetConnectionHandler::startConnection(NetAddress* address) {
reset();

Expand All @@ -159,29 +204,22 @@ NetConnection* NetConnectionHandler::startConnection(NetAddress* address) {
}
}

NetConnection* NetConnectionHandler::newConnectionFromSocket(TCPsocket socket, bool host) {
NetConnection* NetConnectionHandler::newConnectionFromSocket(TCPsocket socket, NETID netid) {
NetConnection* connection = new NetConnection(socket);
if (connections.size() < max_connections) {
NETID netid;
if (host) {
netid = NETID_HOST;
} else {
netid = NETID_HOST + connections.size() + 1;
}
connection->netid = netid;
connections.insert_or_assign(netid, connection);
}
return connection;
}


size_t SendBufferToConnection(const uint8_t* buffer, size_t size, NetConnection* connection) {
size_t SendBufferToConnection(const uint8_t* buffer, size_t size, NetConnection* connection, NETID destination) {
int retries = 5;
if (!connection || !connection->is_active()) {
return 0;
}
while (0 < retries) {
int sent = connection->send(buffer, size);
int sent = connection->send(buffer, size, destination);
if (0 < sent) {
return size;
} else if (!connection->is_active()) {
Expand All @@ -199,12 +237,14 @@ size_t NetConnectionHandler::sendToNETID(const uint8_t* buffer, size_t size, NET
size_t sent = 0;
if (destination == NETID_NONE) {
fprintf(stderr, "Discarding sending to NETID_NONE\n");
} else if (relayConnection) {
sent = SendBufferToConnection(buffer, size, relayConnection, destination);
} else if (destination == NETID_ALL) {
for (auto& conn : connections) {
sent += SendBufferToConnection(buffer, size, conn.second);
sent += SendBufferToConnection(buffer, size, conn.second, NETID_NONE);
}
} else {
sent = SendBufferToConnection(buffer, size, getConnection(destination));
sent = SendBufferToConnection(buffer, size, getConnection(destination), NETID_NONE);
}

return sent;
Expand Down
9 changes: 6 additions & 3 deletions Source/Network/P2P_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,8 @@ struct sPNCInterfaceCommand {
};

enum e_PNCInternalCommand{
PNC_COMMAND__START_HOST_AND_CREATE_GAME_AND_STOP_FIND_HOST,
PNC_COMMAND__START_HOST_AND_CREATE_GAME_AND_STOP_FIND_HOST,
PNC_COMMAND__CONNECT_RELAY_AND_CREATE_GAME_AND_STOP_FIND_HOST,

//PNCC_START_FIND_HOST,
PNC_COMMAND__CONNECT_2_HOST_AND_STOP_FIND_HOST,
Expand Down Expand Up @@ -436,7 +437,9 @@ class PNetCenter {
bool ExecuteInternalCommand(e_PNCInternalCommand ic, bool waitExecution);
bool ExecuteInterfaceCommand(e_PNCInterfaceCommands ic, std::unique_ptr<LocalizedText> text = nullptr);

void CreateGame(const NetAddress& connection, const std::string& gameName, MissionDescription* mission, const std::string& playerName, const std::string& password="");
void CreateGame(bool isPublicGame, const NetAddress& connection,
const std::string& gameName, MissionDescription* mission,
const std::string& playerName, const std::string& password);

void JoinGame(const NetAddress& connection, const std::string& playerName, const std::string& password="");

Expand Down Expand Up @@ -523,7 +526,7 @@ class PNetCenter {
void StartFindHost();

bool Init();
bool ServerStart();
bool ServerStart(bool);
void SetConnectionTimeout(int ms);
void RemovePlayer(NETID netid);

Expand Down
17 changes: 13 additions & 4 deletions Source/Network/P2P_interface1Th.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,11 @@ int PNetCenter::getHostPort() {
//////////////////////////////////////////////
/// New network game creation or joining

void PNetCenter::CreateGame(const NetAddress& connection, const std::string& gameName, MissionDescription* mission, const std::string& playerName, const std::string& password)
{
void PNetCenter::CreateGame(
bool isPublicGame, const NetAddress& connection,
const std::string& gameName, MissionDescription* mission,
const std::string& playerName, const std::string& password
) {
LogMsg("Create Game\n");
clientPause=false;
clientInPacketPause=false;
Expand All @@ -252,11 +255,17 @@ void PNetCenter::CreateGame(const NetAddress& connection, const std::string& gam
xassert(mission);
hostMissionDescription = mission;

//Argument PNC_COMMAND__START_HOST_AND_CREATE_GAME_AND_STOP_FIND_HOST
//Arguments for:
// PNC_COMMAND__START_HOST_AND_CREATE_GAME_AND_STOP_FIND_HOST
// PNC_COMMAND__CONNECT_RELAY_AND_CREATE_GAME_AND_STOP_FIND_HOST

m_GameName = gameName;
m_PlayerName = playerName;
ExecuteInternalCommand(PNC_COMMAND__START_HOST_AND_CREATE_GAME_AND_STOP_FIND_HOST, true);
ExecuteInternalCommand(
isPublicGame ? PNC_COMMAND__CONNECT_RELAY_AND_CREATE_GAME_AND_STOP_FIND_HOST
: PNC_COMMAND__START_HOST_AND_CREATE_GAME_AND_STOP_FIND_HOST,
true
);

gameShell->callBack_CreateGameReturnCode(isConnected() ? GameShell::CG_RC_OK : GameShell::CG_RC_CREATE_HOST_ERR);
}
Expand Down
5 changes: 3 additions & 2 deletions Source/Network/P2P_interface2Th.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ bool PNetCenter::SecondThread()
}
break;
case PNC_COMMAND__START_HOST_AND_CREATE_GAME_AND_STOP_FIND_HOST:
case PNC_COMMAND__CONNECT_RELAY_AND_CREATE_GAME_AND_STOP_FIND_HOST:
{
flag_LockIputPacket=0;
flag_SkipProcessingGameCommand=0;
Expand All @@ -148,8 +149,8 @@ bool PNetCenter::SecondThread()

LogMsg("starting server...\n");
if(!isConnected()) {
//m_pConnection->Init();
if (ServerStart()) {
bool isPrivate = curInternalCommand == PNC_COMMAND__START_HOST_AND_CREATE_GAME_AND_STOP_FIND_HOST;
if (ServerStart(isPrivate)) {
LogMsg("...started OK\n");
}
}
Expand Down
14 changes: 9 additions & 5 deletions Source/Network/P2P_interface2Th_NetConn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ bool PNetCenter::Init()
return true;
}

bool PNetCenter::ServerStart()
{
bool PNetCenter::ServerStart(bool publicServer)
{
m_hostNETID = m_localNETID = NETID_NONE;
flag_connected = connectionHandler.startListening(hostConnection.port());
if (publicServer) {
flag_connected = connectionHandler.startRelay();
} else {
flag_connected = connectionHandler.startListening(hostConnection.port());
}
if (!flag_connected) {
fprintf(stderr, "Error listening on port %d\n", hostConnection.port());
} else {
Expand Down Expand Up @@ -89,7 +93,7 @@ bool PNetCenter::Connect() {
connectInfo.set(currentShortVersion, gamePassword.c_str(), terGameContentSelect, m_PlayerName.c_str());
XBuffer buffer(256, true);
connectInfo.write(buffer);
connection->send(buffer);
connection->send(buffer, NETID_HOST);

//Get the response and pass it to interface command
int ret = connection->receive(buffer, CONNECTION_HANDSHAKE_TIMEOUT);
Expand Down Expand Up @@ -267,7 +271,7 @@ void PNetCenter::handleIncomingClientConnection(NetConnection* connection) {
if (response.connectResult != NetConnectionInfoResponse::CR_NONE) {
XBuffer responseBuffer(256, true);
response.write(responseBuffer);
ret = connection->send(responseBuffer);
ret = connection->send(responseBuffer, connection->netid);
}

//Close connection if result was not OK
Expand Down
7 changes: 4 additions & 3 deletions Source/UserInterface/Menu/MultiplayerHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ int creatingHostDialogQuant(float, float ) {
std::string gameName = gameNameInput->getText();
CEditWindow* passwordInput = dynamic_cast<CEditWindow*>(_shellIconManager.GetWnd(SQSH_MM_MULTIPLAYER_HOST_PASSWORD_INPUT));
std::string password = passwordInput->getText();
CComboWindow* hostTypeCombo = dynamic_cast<CComboWindow*>(_shellIconManager.GetWnd(SQSH_MM_MULTIPLAYER_HOST_TYPE_COMBO));
bool isPublic = hostTypeCombo->pos != 0;

putStringSettings("HostName", gameName);
putStringSettings("HostPort", std::to_string(conn.port()));
Expand All @@ -87,7 +89,7 @@ int creatingHostDialogQuant(float, float ) {
mission = new MissionDescription(missionName.c_str(), GT_MULTI_PLAYER_CREATE);
}

gameShell->getNetClient()->CreateGame(conn, gameName, mission, playerName, password);
gameShell->getNetClient()->CreateGame(isPublic, conn, gameName, mission, playerName, password);
}
return 0;
}
Expand All @@ -100,8 +102,7 @@ void onMMMultiplayerHostTypeCombo(CShellWindow* pWnd, InterfaceEventCode code, i
CComboWindow *pCombo = (CComboWindow*) pWnd;
if (code == EVENT_CREATEWND) {
pCombo->Array.emplace_back(getItemTextFromBase("Private Server").c_str() );
//TODO enable this once implemented the public listing
//pCombo->Array.emplace_back(getItemTextFromBase("Public Server").c_str() );
pCombo->Array.emplace_back(getItemTextFromBase("Public Server").c_str() );
pCombo->size = pCombo->Array.size();
pCombo->pos = 0;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/UserInterface/Menu/MultiplayerList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ int startCmdlineQuant(float, float ) {
mission->loadIntoMemory();
}
_shellIconManager.initialMenu = SQSH_MM_MULTIPLAYER_LOBBY_SCR;
gameShell->getNetClient()->CreateGame(conn, gameName, mission, cmdLineData.playerName, cmdLineData.password);
gameShell->getNetClient()->CreateGame(cmdLineData.publicHost, conn, gameName, mission, cmdLineData.playerName, cmdLineData.password);
showMessageBoxButtons();
}
} else {
Expand Down

0 comments on commit d0bf4ff

Please sign in to comment.