#include "inetworkserver.h" #include "inetworkclient.h" #include "tier0/lib.h" #include "tier1/utlmutex.h" #include "tier1/utlvector.h" #ifdef STEAM #include "steam/steam_gameserver.h" #endif #include "steam/isteamnetworkingsockets.h" class CSteamNetworkServer: public INetworkBase { public: CSteamNetworkServer( uint16_t uPort ); virtual ~CSteamNetworkServer() override; virtual void NetThink() override; virtual void SetCallback( NetCallbackFn fnCallback ) override; virtual uint32_t BHasUpdates() override; virtual NetPacket_t PeekPacket() override; virtual NetPacket_t RecievePacket() override; virtual void SendPacket( NetPacket_t stPacket ) override; virtual bool BIsActive() override; virtual uint64_t GetSteamID() override; virtual const char *GetIP() override; virtual uint16_t GetPort() override; ISteamNetworkingSockets *m_pInterface; HSteamListenSocket m_hSocket; NetCallbackFn m_fnCallback; HSteamNetPollGroup m_hPollGroup; uint64_t m_uSteamId; CUtlVector m_hConnections; STEAM_GAMESERVER_CALLBACK(CSteamNetworkServer, ClientConnected, SteamNetConnectionStatusChangedCallback_t); STEAM_GAMESERVER_CALLBACK(CSteamNetworkServer, SteamNetAuthenticated, SteamNetAuthenticationStatus_t); }; CSteamNetworkServer::CSteamNetworkServer( uint16_t uPort ) { m_pInterface = SteamGameServerNetworkingSockets(); m_hSocket = m_pInterface->CreateListenSocketP2P(0, 0, NULL); m_hPollGroup = m_pInterface->CreatePollGroup(); } CSteamNetworkServer::~CSteamNetworkServer() { } void CSteamNetworkServer::NetThink() { } void CSteamNetworkServer::SetCallback( NetCallbackFn fnCallback ) { m_fnCallback = fnCallback; } uint32_t CSteamNetworkServer::BHasUpdates() { return 0; } NetPacket_t CSteamNetworkServer::PeekPacket() { } NetPacket_t CSteamNetworkServer::RecievePacket() { } void CSteamNetworkServer::SendPacket( NetPacket_t stPacket ) { if ( stPacket.m_uOwner == 0 ) { for ( auto c: m_hConnections ) { if (stPacket.m_eArrival == PACKET_MAY_ARRIVE) m_pInterface->SendMessageToConnection(c, stPacket.pData, stPacket.uSize, k_nSteamNetworkingSend_Unreliable, 0); if (stPacket.m_eArrival == PACKET_MUST_ARRIVE) m_pInterface->SendMessageToConnection(c, stPacket.pData, stPacket.uSize, k_nSteamNetworkingSend_Reliable, 0); } } } bool CSteamNetworkServer::BIsActive() { return true; } uint64_t CSteamNetworkServer::GetSteamID() { return 0; } const char *CSteamNetworkServer::GetIP() { return NULL; } uint16_t CSteamNetworkServer::GetPort() { return 0; } void CSteamNetworkServer::ClientConnected( SteamNetConnectionStatusChangedCallback_t *pParam ) { uint32_t uResult; NetCallback_t callback = {}; switch (pParam->m_info.m_eState) { case k_ESteamNetworkingConnectionState_Connecting: callback.m_eType = NET_TRYING_TO_CONNECT; callback.m_ullUserID = pParam->m_info.m_identityRemote.GetSteamID64(); break; case k_ESteamNetworkingConnectionState_Connected: callback.m_eType = NET_CONNECTED; callback.m_ullUserID = pParam->m_info.m_identityRemote.GetSteamID64(); m_pInterface->SetConnectionPollGroup(pParam->m_hConn, m_hPollGroup); m_hConnections.AppendTail(pParam->m_hConn); break; default: break; } V_printf("%p\n", m_fnCallback); if (m_fnCallback) uResult = m_fnCallback(&callback); else uResult = 0; switch (pParam->m_info.m_eState) { case k_ESteamNetworkingConnectionState_Connecting: if (uResult != 0) m_pInterface->AcceptConnection(pParam->m_hConn); else m_pInterface->CloseConnection(pParam->m_hConn, 0, "Connection denied", 0); break; default: break; } } void CSteamNetworkServer::SteamNetAuthenticated( SteamNetAuthenticationStatus_t *pParam ) { NetCallback_t callback = {}; callback.m_eType = NET_SERVER_READY_TO_USE; if ( pParam->m_eAvail != k_ESteamNetworkingAvailability_Current ) return; if (m_fnCallback) m_fnCallback(&callback); } class CSteamNetworkClient: public INetworkBase { public: CSteamNetworkClient( uint64_t uID, uint16_t uPort ); virtual ~CSteamNetworkClient() override; virtual void NetThink() override; virtual void SetCallback( NetCallbackFn fnCallback ) override; virtual uint32_t BHasUpdates() override; virtual NetPacket_t PeekPacket() override; virtual NetPacket_t RecievePacket() override; virtual void SendPacket( NetPacket_t stPacket ) override; virtual bool BIsActive() override; virtual uint64_t GetSteamID() override; virtual const char *GetIP() override; virtual uint16_t GetPort() override; ISteamNetworkingSockets *m_pInterface; HSteamNetConnection m_hConnection; CUtlVector m_incomingPackets = {}; CUtlVector m_incomingSteamPackets = {}; CUtlVector m_freeSteamPackets = {}; CUtlLock m_lock; }; CSteamNetworkClient::CSteamNetworkClient( uint64_t uID, uint16_t uPort ) { m_pInterface = SteamNetworkingSockets(); SteamNetworkingIdentity id = {}; id.Clear(); id.SetSteamID64(uID); m_hConnection = m_pInterface->ConnectP2P(id, 0, 0, NULL); } CSteamNetworkClient::~CSteamNetworkClient() { } void CSteamNetworkClient::NetThink() { int nReceived = 1; for ( auto p: m_freeSteamPackets ) { p->Release(); } m_freeSteamPackets = {}; while (nReceived) { SteamNetworkingMessage_t *pMessages[64]; nReceived = m_pInterface->ReceiveMessagesOnConnection(m_hConnection, pMessages, 64); for ( int i = 0; i < nReceived; i++ ) { SteamNetConnectionInfo_t info = {}; m_pInterface->GetConnectionInfo(pMessages[i]->GetConnection(), &info); m_incomingSteamPackets.AppendTail(pMessages[i]); NetPacket_t packet = {}; packet.m_uOwner = info.m_identityRemote.GetSteamID64(); packet.uSize = pMessages[i]->GetSize(); packet.pData = (void*)pMessages[i]->GetData(); m_incomingPackets.AppendTail(packet); } } } void CSteamNetworkClient::SetCallback( NetCallbackFn fnCallback ) { } uint32_t CSteamNetworkClient::BHasUpdates() { return m_incomingPackets.GetSize(); } NetPacket_t CSteamNetworkClient::PeekPacket() { m_lock.Lock(); if (!BHasUpdates()) return {}; NetPacket_t p = m_incomingPackets[0]; m_lock.Unlock(); return p; } NetPacket_t CSteamNetworkClient::RecievePacket() { m_lock.Lock(); if (!BHasUpdates()) return {}; NetPacket_t p = m_incomingPackets[0]; m_freeSteamPackets.AppendTail(m_incomingSteamPackets[0]); m_incomingSteamPackets.RemoveHead(1); m_incomingPackets.RemoveHead(1); m_lock.Unlock(); return p; } void CSteamNetworkClient::SendPacket( NetPacket_t stPacket ) { } bool CSteamNetworkClient::BIsActive() { return true; } uint64_t CSteamNetworkClient::GetSteamID() { return 0; } const char *CSteamNetworkClient::GetIP() { return 0; } uint16_t CSteamNetworkClient::GetPort() { return 0; } INetworkBase *LaunchServerAtSteamRelay( uint16_t uPort ) { INetworkBase *pBase = new CSteamNetworkServer(uPort); return pBase; } INetworkBase *ConnectBySteamID( uint64_t uID, uint16_t uPort ) { CSteamNetworkClient *pBase = new CSteamNetworkClient(uID, uPort); if (pBase->m_hConnection == k_HSteamNetConnection_Invalid) { delete pBase; return NULL; } return pBase; }