work on ServerModule

This commit is contained in:
2025-04-16 01:26:56 -05:00
parent f94cb10412
commit 00ef227128
6 changed files with 228 additions and 36 deletions

View File

@@ -1,45 +1,59 @@
#include "Archimedes.h"
struct Client {
unsigned int id;
};
#include <steam/steamnetworkingsockets.h>
#include <steam/isteamnetworkingutils.h>
class RecievedEvent : public Archimedes::Event {
public:
RecievedEvent(Client c, void* buf, unsigned int s) : client(c), buffer(buf), size(s) {}
namespace SMEvent {
class DataRecievedEvent : public Archimedes::Event {
Client client;
public:
void* buffer;
DataRecievedEvent() : clientID(0), buffer(nullptr), size(0) {}
unsigned int size;
DataRecievedEvent(unsigned int c, void* buf, unsigned int s) : clientID(c), buffer(buf), size(s) {}
};
operator std::string() const { return "DataRecievedEvent"; }
class SentEvent : public Archimedes::Event {
unsigned int clientID;
public:
void* buffer;
SentEvent(Client c, void* buf, unsigned int s) : client(c), buffer(buf), size(s) {}
unsigned int size;
Client client;
};
void* buffer;
class DataSentEvent : public Archimedes::Event {
unsigned int size;
public:
};
DataSentEvent() : clientID(0), buffer(nullptr), size(0) {}
class ConnectionStatusChangedEvent : public Archimedes::Event {
DataSentEvent(unsigned int c, void* buf, unsigned int s) : clientID(c), buffer(buf), size(s) {}
public:
operator std::string() const { return "DataSentEvent"; }
ConnectionStatusChangedEvent(Client c, unsigned int s) : client(c), status(s) {}
unsigned int clientID;
Client client;
void* buffer;
unsigned int size;
};
class ConnectionStatusChangedEvent : public Archimedes::Event {
public:
ConnectionStatusChangedEvent() : info(nullptr) {}
ConnectionStatusChangedEvent(SteamNetConnectionStatusChangedCallback_t* i) : info(i) {}
operator std::string() const { return "ConnectionStatusChangedEvent"; }
SteamNetConnectionStatusChangedCallback_t* info;
};
}
unsigned int status;
};

View File

@@ -5,10 +5,19 @@ ServerModule::ServerModule(Archimedes::App* a, void* h) : Archimedes::Module(a,
}
ServerModule::~ServerModule() {
app->removeEventType(SMEvent::DataRecievedEvent());
app->removeEventType(SMEvent::DataSentEvent());
app->removeEventType(SMEvent::ConnectionStatusChangedEvent());
GameNetworkingSockets_Kill();
}
void ServerModule::onLoad() {
app->addEventType(SMEvent::DataRecievedEvent());
app->addEventType(SMEvent::DataSentEvent());
app->addEventType(SMEvent::ConnectionStatusChangedEvent());
SteamDatagramErrMsg errMsg;
if ( !GameNetworkingSockets_Init( nullptr, errMsg ) ) {
@@ -51,3 +60,132 @@ void ServerModule::run() {
port = -1; //just in case
}
}
void ServerModule::OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t *pInfo ) {
app->emitEvent(new SMEvent::ConnectionStatusChangedEvent(pInfo));
}
bool ServerModule::onEvent(const Archimedes::Event& event) {
if(eventsToHandle & SMEventEnum::ConnectionStatusChanged && app->getEventType(event) == app->getEventType("ConnectionStatusChangedEvent")) {
SMEvent::ConnectionStatusChangedEvent& e = (SMEvent::ConnectionStatusChangedEvent&) event;
switch(e.info->m_info.m_eState) {
case k_ESteamNetworkingConnectionState_None:
// NOTE: We will get callbacks here when we destroy connections. You can ignore these.
break;
case k_ESteamNetworkingConnectionState_ClosedByPeer:
case k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
{
// Ignore if they were not previously connected. (If they disconnected
// before we accepted the connection.)
if ( e.info->m_eOldState == k_ESteamNetworkingConnectionState_Connected )
{
// Locate the client. Note that it should have been found, because this
// is the only codepath where we remove clients (except on shutdown),
// and connection change callbacks are dispatched in queue order.
auto itClient = clients.find( e.info->m_hConn );
assert( itClient != clients.end() );
// Select appropriate log messages
//const char *pszDebugLogAction;
if ( e.info->m_info.m_eState == k_ESteamNetworkingConnectionState_ProblemDetectedLocally )
{
//pszDebugLogAction = "problem detected locally";
//sprintf( temp, "Alas, %s hath fallen into shadow. (%s)", itClient->second.name.c_str(), e.info->m_info.m_szEndDebug );
}
else
{
// Note that here we could check the reason code to see if
// it was a "usual" connection or an "unusual" one.
//pszDebugLogAction = "closed by peer"; (void)pszDebugLogAction;
//sprintf( temp, "%s hath departed", itClient->second.name.c_str() );
}
// Spew something to our own log. Note that because we put their nick
// as the connection description, it will show up, along with their
// transport-specific data (e.g. their IP address)
/*Printf( "Connection %s %s, reason %d: %s\n",
e.info->m_info.m_szConnectionDescription,
pszDebugLogAction,
e.info->m_info.m_eEndReason,
e.info->m_info.m_szEndDebug
);*/
clients.erase( itClient );
// Send a message so everybody else knows what happened
//SendStringToAllClients( temp );
}
else
{
assert( e.info->m_eOldState == k_ESteamNetworkingConnectionState_Connecting );
}
// Clean up the connection. This is important!
// The connection is "closed" in the network sense, but
// it has not been destroyed. We must close it on our end, too
// to finish up. The reason information do not matter in this case,
// and we cannot linger because it's already closed on the other end,
// so we just pass 0's.
interface->CloseConnection( e.info->m_hConn, 0, nullptr, false );
break;
}
case k_ESteamNetworkingConnectionState_Connecting:
{
// This must be a new connection
assert( clients.find( e.info->m_hConn ) == clients.end() );
//Printf( "Connection request from %s", e.info->m_info.m_szConnectionDescription );
// A client is attempting to connect
// Try to accept the connection.
if ( interface->AcceptConnection( e.info->m_hConn ) != k_EResultOK )
{
// This could fail. If the remote host tried to connect, but then
// disconnected, the connection may already be half closed. Just
// destroy whatever we have on our side.
interface->CloseConnection( e.info->m_hConn, 0, nullptr, false );
//Printf( "Can't accept connection. (It was already closed?)" );
break;
}
// Assign the poll group
if ( !interface->SetConnectionPollGroup( e.info->m_hConn, pollGroup ) )
{
interface->CloseConnection( e.info->m_hConn, 0, nullptr, false );
//Printf( "Failed to set poll group?" );
break;
}
// Add them to the client list, using std::map wacky syntax
clients[ e.info->m_hConn ] = ++numClients;
//SetClientNick( e.info->m_hConn, nick );
break;
}
case k_ESteamNetworkingConnectionState_Connected:
// We will get a callback immediately after accepting the connection.
// Since we are the server, we can ignore this, it's not news to us.
break;
default:
// Silences -Wswitch
break;
}
return true;
} else if(eventsToHandle & SMEventEnum::DataRecieved && app->getEventType(event) == app->getEventType("DataRecievedEvent")) {
return true;
} else if(eventsToHandle & SMEventEnum::DataSent && app->getEventType(event) == app->getEventType("DataSentEvent")) {
return true;
}
return false;
}

View File

@@ -17,7 +17,22 @@ class ServerModule : public Archimedes::Module {
void startServer(int);
void stopServer();
enum SMEventEnum {
None = 0,
ConnectionStatusChanged = 1 << 0,
DataRecieved = 1 << 1,
DataSent = 1 << 2
};
void shouldHandleEvents(unsigned int events) { eventsToHandle = events; }
void sendData() {}
void pollIncomingData();
private:
//handle all events by default
unsigned int eventsToHandle = SMEventEnum::ConnectionStatusChanged | SMEventEnum::DataSent | SMEventEnum::DataRecieved;
bool running = false;
int port = -1;
@@ -36,9 +51,8 @@ class ServerModule : public Archimedes::Module {
void OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t *pInfo );
std::map<HSteamNetConnection, Client> clients;
std::map<HSteamNetConnection, unsigned int> clients;
void PollIncomingMessages();
void PollConnectionStateChanges();
void PollLocalUserInput();
};