work on ServerModule
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cassert>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "pch.hpp"
|
#include "pch.hpp"
|
||||||
#include "utils/Module/Module.h"
|
#include "utils/Module/Module.h"
|
||||||
|
#include "utils/Events/Event.h"
|
||||||
|
|
||||||
namespace Archimedes {
|
namespace Archimedes {
|
||||||
|
|
||||||
@@ -55,9 +56,22 @@ namespace Archimedes {
|
|||||||
|
|
||||||
bool isDone() const { return done; }
|
bool isDone() const { return done; }
|
||||||
|
|
||||||
std::unordered_map<std::string, unsigned int> getEventTypes() const { return eventTypes; }
|
void emitEvent(Event* e) { events.push_back(e); }
|
||||||
|
|
||||||
void addEventType(std::string type) { eventTypes[type] = nextEventType++; }
|
unsigned int getEventType(std::string event) { return eventTypes[event]; }
|
||||||
|
|
||||||
|
void addEventType(std::string type) {
|
||||||
|
//only add each type once
|
||||||
|
if(eventTypes.find(type) == eventTypes.end())
|
||||||
|
eventTypes[type] = nextEventType++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeEventType(std::string type) {
|
||||||
|
//only erase registered types
|
||||||
|
auto it = eventTypes.find(type);
|
||||||
|
if(it != eventTypes.end())
|
||||||
|
eventTypes.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -73,10 +87,25 @@ namespace Archimedes {
|
|||||||
std::unordered_map<std::string, Module*> modules;
|
std::unordered_map<std::string, Module*> modules;
|
||||||
std::unordered_map<std::string, unsigned int> eventTypes;
|
std::unordered_map<std::string, unsigned int> eventTypes;
|
||||||
|
|
||||||
|
std::list<Event*> events;
|
||||||
|
|
||||||
std::list<std::string> runOrder;
|
std::list<std::string> runOrder;
|
||||||
|
|
||||||
std::list<std::string> toClose;
|
std::list<std::string> toClose;
|
||||||
std::list<std::variant<std::string, Module*>> toOpen;
|
std::list<std::variant<std::string, Module*>> toOpen;
|
||||||
|
|
||||||
|
void handleEvents() {
|
||||||
|
while(!events.empty()) {
|
||||||
|
for(auto it = runOrder.rbegin(); it != runOrder.rend(); it++) {
|
||||||
|
if(modules[*it]->onEvent(*events.front())) {
|
||||||
|
Event* e = events.front();
|
||||||
|
events.pop_front();
|
||||||
|
delete e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual Module* dynamicLoad(std::string lib) {
|
virtual Module* dynamicLoad(std::string lib) {
|
||||||
|
|
||||||
@@ -169,18 +198,12 @@ namespace Archimedes {
|
|||||||
|
|
||||||
if(modules.find(name) == modules.end())
|
if(modules.find(name) == modules.end())
|
||||||
return;
|
return;
|
||||||
/*
|
|
||||||
//unload modules that depend on the one we are unloading
|
|
||||||
for(std::string s : runOrder) {
|
|
||||||
if(modules[s]->deps.find(name) != modules[s]->deps.end()) {
|
|
||||||
unload(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
Module* m = modules[name];
|
Module* m = modules[name];
|
||||||
void* h = m->getHandle();
|
void* h = m->getHandle();
|
||||||
|
|
||||||
modules[name] = nullptr;
|
modules[name] = nullptr;
|
||||||
|
modules.erase(name);
|
||||||
|
|
||||||
runOrder.remove(name);
|
runOrder.remove(name);
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ namespace Archimedes {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
unsigned int type;
|
virtual ~Event() {}
|
||||||
|
|
||||||
|
virtual operator std::string() const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,59 @@
|
|||||||
#include "Archimedes.h"
|
#include "Archimedes.h"
|
||||||
|
|
||||||
struct Client {
|
#include <steam/steamnetworkingsockets.h>
|
||||||
unsigned int id;
|
#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;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -5,10 +5,19 @@ ServerModule::ServerModule(Archimedes::App* a, void* h) : Archimedes::Module(a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ServerModule::~ServerModule() {
|
ServerModule::~ServerModule() {
|
||||||
|
app->removeEventType(SMEvent::DataRecievedEvent());
|
||||||
|
app->removeEventType(SMEvent::DataSentEvent());
|
||||||
|
app->removeEventType(SMEvent::ConnectionStatusChangedEvent());
|
||||||
|
|
||||||
GameNetworkingSockets_Kill();
|
GameNetworkingSockets_Kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerModule::onLoad() {
|
void ServerModule::onLoad() {
|
||||||
|
|
||||||
|
app->addEventType(SMEvent::DataRecievedEvent());
|
||||||
|
app->addEventType(SMEvent::DataSentEvent());
|
||||||
|
app->addEventType(SMEvent::ConnectionStatusChangedEvent());
|
||||||
|
|
||||||
SteamDatagramErrMsg errMsg;
|
SteamDatagramErrMsg errMsg;
|
||||||
|
|
||||||
if ( !GameNetworkingSockets_Init( nullptr, errMsg ) ) {
|
if ( !GameNetworkingSockets_Init( nullptr, errMsg ) ) {
|
||||||
@@ -51,3 +60,132 @@ void ServerModule::run() {
|
|||||||
port = -1; //just in case
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,22 @@ class ServerModule : public Archimedes::Module {
|
|||||||
void startServer(int);
|
void startServer(int);
|
||||||
void stopServer();
|
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:
|
private:
|
||||||
|
//handle all events by default
|
||||||
|
unsigned int eventsToHandle = SMEventEnum::ConnectionStatusChanged | SMEventEnum::DataSent | SMEventEnum::DataRecieved;
|
||||||
|
|
||||||
bool running = false;
|
bool running = false;
|
||||||
|
|
||||||
int port = -1;
|
int port = -1;
|
||||||
@@ -36,9 +51,8 @@ class ServerModule : public Archimedes::Module {
|
|||||||
void OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t *pInfo );
|
void OnSteamNetConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t *pInfo );
|
||||||
|
|
||||||
|
|
||||||
std::map<HSteamNetConnection, Client> clients;
|
std::map<HSteamNetConnection, unsigned int> clients;
|
||||||
|
|
||||||
void PollIncomingMessages();
|
|
||||||
void PollConnectionStateChanges();
|
void PollConnectionStateChanges();
|
||||||
void PollLocalUserInput();
|
void PollLocalUserInput();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user