mirror of
https://github.com/ValveSoftware/GameNetworkingSockets.git
synced 2026-05-29 16:20:34 +00:00
Some refactoring to make way for the "Messages" API.
Steam has a higher level UDP-style API, currently called ISteamNetworkingMessages. There are no connection handles, instead you just send a message to a peer. (It still supports reliable messages and messages longer than datagrams, the difference is in how things are addressed at the API layer.) The Messages interface creates connections internally, and those connections are not visible to the app through the normal connections interface. So receiving messages and handling connection state change notifications needs to be dispatched differently. This change introduces hooks in CSteamNetworkConnectionBase to better facilitate this. It happened because, on the Steam side, all such internally created connections used to be a specific derived class. Those hooks could then be accomplished by overriding virtual functions. But I'm changing that to make it so that different connections might be used. For example, you might use the Messages interface with IP address as the peer identity, which would make porting existing UDP much easier. Or if you open up a session to send messages to yourself (or another local identity, say the gameserver when you are the user), we would use a pipe connection. In this situation, basically any connection class could be used by the Messages layer, and using virtual functions as the means of hooking in won't work; hence these changes. (If we were using a dynamic language like Python or Javascript, we could do it, though.)
This commit is contained in:
@@ -96,12 +96,21 @@ CSteamNetworkingMessage *CSteamNetworkingMessage::New( CSteamNetworkConnectionBa
|
||||
// FIXME Should avoid this dynamic memory call with some sort of pooling
|
||||
CSteamNetworkingMessage *pMsg = new CSteamNetworkingMessage;
|
||||
|
||||
pMsg->m_sender = pParent->m_identityRemote;
|
||||
if ( pParent )
|
||||
{
|
||||
pMsg->m_sender = pParent->m_identityRemote;
|
||||
pMsg->m_conn = pParent->m_hConnectionSelf;
|
||||
pMsg->m_nConnUserData = pParent->GetUserData();
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( &pMsg->m_sender, 0, sizeof(pMsg->m_sender) );
|
||||
pMsg->m_conn = k_HSteamNetConnection_Invalid;
|
||||
pMsg->m_nConnUserData = 0;
|
||||
}
|
||||
pMsg->m_pData = malloc( cbSize );
|
||||
pMsg->m_cbSize = cbSize;
|
||||
pMsg->m_nChannel = -1;
|
||||
pMsg->m_conn = pParent->m_hConnectionSelf;
|
||||
pMsg->m_nConnUserData = pParent->GetUserData();
|
||||
pMsg->m_usecTimeReceived = usecNow;
|
||||
pMsg->m_nMessageNumber = nMsgNum;
|
||||
pMsg->m_pfnRelease = CSteamNetworkingMessage::Delete;
|
||||
@@ -344,6 +353,8 @@ CSteamNetworkConnectionBase::CSteamNetworkConnectionBase( CSteamNetworkingSocket
|
||||
m_unConnectionIDRemote = 0;
|
||||
m_pParentListenSocket = nullptr;
|
||||
m_hSelfInParentListenSocketMap = -1;
|
||||
m_pMessagesInterface = nullptr;
|
||||
m_pMessagesSession = nullptr;
|
||||
m_bCertHasIdentity = false;
|
||||
m_bCryptKeysValid = false;
|
||||
memset( m_szAppName, 0, sizeof( m_szAppName ) );
|
||||
@@ -1428,6 +1439,27 @@ void CSteamNetworkConnectionBase::ReceivedMessage( const void *pData, int cbData
|
||||
(long long)nMsgNum,
|
||||
cbData );
|
||||
|
||||
// Special case for internal connections used by Messages interface
|
||||
if ( m_pMessagesInterface )
|
||||
{
|
||||
// Are we still associated with our session?
|
||||
if ( !m_pMessagesSession )
|
||||
{
|
||||
// How did we get here? We should be closed, and once closed,
|
||||
// we should not receive any more messages
|
||||
AssertMsg2( false, "Received message for connection %s associated with Messages interface, but no session. Connection state is %d", GetDescription(), (int)GetState() );
|
||||
}
|
||||
else if ( m_pMessagesSession->m_pConnection != this )
|
||||
{
|
||||
AssertMsg2( false, "Connection/session linkage bookkeeping bug! %s state %d", GetDescription(), (int)GetState() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pMessagesSession->ReceivedMessage( pData, cbData, nMsgNum, usecNow );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a message
|
||||
CSteamNetworkingMessage *pMsg = CSteamNetworkingMessage::New( this, cbData, nMsgNum, usecNow );
|
||||
|
||||
@@ -1450,8 +1482,40 @@ void CSteamNetworkConnectionBase::ConnectionStateChanged( ESteamNetworkingConnec
|
||||
// from the application's perspective, are not relevant
|
||||
ESteamNetworkingConnectionState eOldAPIState = CollapseConnectionStateToAPIState( eOldState );
|
||||
ESteamNetworkingConnectionState eNewAPIState = CollapseConnectionStateToAPIState( GetState() );
|
||||
if ( eOldAPIState != eNewAPIState )
|
||||
PostConnectionStateChangedCallback( eOldAPIState, eNewAPIState );
|
||||
|
||||
// Internal connection used by the higher-level messages interface?
|
||||
if ( m_pMessagesInterface )
|
||||
{
|
||||
// Are we still associated with our session?
|
||||
if ( m_pMessagesSession )
|
||||
{
|
||||
// How did we get here? We should be closed!
|
||||
if ( m_pMessagesSession->m_pConnection != this )
|
||||
{
|
||||
AssertMsg2( false, "Connection/session linkage bookkeeping bug! %s state %d", GetDescription(), (int)GetState() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pMessagesSession->ConnectionStateChanged( eOldState, GetState() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should only detach after being closed or destroyed.
|
||||
AssertMsg2( GetState() == k_ESteamNetworkingConnectionState_FinWait || GetState() == k_ESteamNetworkingConnectionState_Dead || GetState() == k_ESteamNetworkingConnectionState_None,
|
||||
"Connection %s has detatched from messages session, but is in state %d", GetDescription(), (int)GetState() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Ordinary connection. Check for posting callback, if connection state has changed from
|
||||
// an API perspective
|
||||
if ( eOldAPIState != eNewAPIState )
|
||||
{
|
||||
PostConnectionStateChangedCallback( eOldAPIState, eNewAPIState );
|
||||
}
|
||||
}
|
||||
|
||||
// Any time we switch into a state that is closed from an API perspective,
|
||||
// discard any unread received messages
|
||||
@@ -2221,7 +2285,7 @@ void CSteamNetworkConnectionPipe::ConnectionStateChanged( ESteamNetworkingConnec
|
||||
void CSteamNetworkConnectionPipe::PostConnectionStateChangedCallback( ESteamNetworkingConnectionState eOldAPIState, ESteamNetworkingConnectionState eNewAPIState )
|
||||
{
|
||||
// Don't post any callbacks for the initial transitions.
|
||||
if ( eNewAPIState == k_ESteamNetworkingConnectionState_Connected || eNewAPIState == k_ESteamNetworkingConnectionState_Connected )
|
||||
if ( eNewAPIState == k_ESteamNetworkingConnectionState_Connecting || eNewAPIState == k_ESteamNetworkingConnectionState_Connected )
|
||||
return;
|
||||
|
||||
// But post callbacks for these guys
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
|
||||
struct SteamNetConnectionStatusChangedCallback_t;
|
||||
class ISteamNetworkingSocketsSerialized;
|
||||
class CMsgSteamSockets_UDP_ChallengeRequest;
|
||||
class CMsgSteamSockets_UDP_ConnectRequest;
|
||||
class CMsgSteamSockets_UDP_ConnectionClosed;
|
||||
class CMsgSteamSockets_UDP_Stats;
|
||||
|
||||
namespace SteamNetworkingSocketsLib {
|
||||
|
||||
@@ -36,6 +32,7 @@ const SteamNetworkingMicroseconds k_usecFinWaitTimeout = 5*k_nMillion;
|
||||
typedef char ConnectionEndDebugMsg[ k_cchSteamNetworkingMaxConnectionCloseReason ];
|
||||
|
||||
class CSteamNetworkingSockets;
|
||||
class CSteamNetworkingMessages;
|
||||
class CSteamNetworkConnectionBase;
|
||||
class CSharedSocket;
|
||||
struct SteamNetworkingMessageQueue;
|
||||
@@ -146,9 +143,19 @@ struct SteamNetworkingMessageQueue
|
||||
void PurgeMessages();
|
||||
};
|
||||
|
||||
/// Connections created through the "messages" interface are not directly exposed to the app.
|
||||
// They have different mechanisms for notifying of received messages and state changes.
|
||||
class ISteamNetworkingMessagesSession
|
||||
{
|
||||
public:
|
||||
CSteamNetworkConnectionBase *m_pConnection; // active connection, if any. Might be NULL!
|
||||
virtual void ReceivedMessage( const void *pData, int cbData, int64 nMsgNum, SteamNetworkingMicroseconds usecNow ) = 0;
|
||||
virtual void ConnectionStateChanged( ESteamNetworkingConnectionState eOldState, ESteamNetworkingConnectionState eNewState ) = 0;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Abstract base classes
|
||||
// CSteamNetworkListenSocketBase
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -186,6 +193,12 @@ protected:
|
||||
virtual ~CSteamNetworkListenSocketBase(); // hidden destructor, don't call directly. Use Destroy()
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CSteamNetworkConnectionBase
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Abstract interface for a connection to a remote host over any underlying
|
||||
/// transport. Most of the common functionality for implementing reliable
|
||||
/// connections on top of unreliable datagrams, connection quality measurement,
|
||||
@@ -304,6 +317,11 @@ public:
|
||||
/// Our handle in our parent's m_listAcceptedConnections (if we were accepted on a listen socket)
|
||||
int m_hSelfInParentListenSocketMap;
|
||||
|
||||
// Was this connection created as part of the "messages" interface? If so, what interface
|
||||
// owns us, and if so, are we still associated with an active session?
|
||||
CSteamNetworkingMessages *m_pMessagesInterface;
|
||||
ISteamNetworkingMessagesSession *m_pMessagesSession;
|
||||
|
||||
// Linked list of received messages
|
||||
SteamNetworkingMessageQueue m_queueRecvMessages;
|
||||
|
||||
@@ -438,7 +456,7 @@ protected:
|
||||
virtual int SendEncryptedDataChunk( const void *pChunk, int cbChunk, SteamNetworkingMicroseconds usecNow, void *pConnectionContext ) = 0;
|
||||
|
||||
/// Called when we receive a complete message. Should allocate a message object and put it into the proper queues
|
||||
virtual void ReceivedMessage( const void *pData, int cbData, int64 nMsgNum, SteamNetworkingMicroseconds usecNow );
|
||||
void ReceivedMessage( const void *pData, int cbData, int64 nMsgNum, SteamNetworkingMicroseconds usecNow );
|
||||
|
||||
/// Called when the state changes
|
||||
virtual void ConnectionStateChanged( ESteamNetworkingConnectionState eOldState );
|
||||
|
||||
Reference in New Issue
Block a user