Skip to content

Commit ae52d2d

Browse files
committed
Refactor custom signaling
Removed the word "custom" from the namesofinterfacesthatwerealreadyverylong. Added k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling, which is a mechanism for connections that require signaling to be iniated locally. This is used by ISteamnetwrokingSockets::ConnectP2P and connections created using the ISteamNetworkingMessages interface....which has been added. These changes address issue ValveSoftware#137 and bring the opensource code more in line with Steamworks version. Delete the define STEAMNETWORKINGSOCKETS_HAS_DEFAULT_P2P_SIGNALING. "Default signaling" is a thing that can exist on any platform, and can only be determined at runtime. Most places that were using this actually should have been checking STEAMNETWORKINGSOCKETS_ENABLE_STEAMNETWORKINGMESSAGES anyway, and those two defines were equivalent in practice. STEAMNETWORKINGSOCKETS_ENABLE_STEAMNETWORKINGMESSAGES will be defined by default. I could add a mechanism to disable it if anybody is relaly concerned about code size. (Also started some refactoring of the P2P listen sockets, to merge them with hosted dedicated server listen sockets. The goal is to enable a way to connected to hosted dedicated servers without tickets. That is a work in progress, and also not relevant to the opensource code.)
1 parent 952a7b9 commit ae52d2d

18 files changed

+1332
-115
lines changed

examples/trivial_signaling_client.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "trivial_signaling_client.h"
1313
#include <steam/isteamnetworkingsockets.h>
1414
#include <steam/isteamnetworkingutils.h>
15+
#include <steam/steamnetworkingcustomsignaling.h>
1516

1617
#ifdef POSIX
1718
#include <unistd.h>
@@ -57,7 +58,7 @@ class CTrivialSignalingClient : public ITrivialSignalingClient
5758

5859
// This is the thing we'll actually create to send signals for a particular
5960
// connection.
60-
struct ConnectionSignaling : ISteamNetworkingConnectionCustomSignaling
61+
struct ConnectionSignaling : ISteamNetworkingConnectionSignaling
6162
{
6263
CTrivialSignalingClient *const m_pOwner;
6364
std::string const m_sPeerIdentity; // Save off the string encoding of the identity we're talking to
@@ -69,7 +70,7 @@ class CTrivialSignalingClient : public ITrivialSignalingClient
6970
}
7071

7172
//
72-
// Implements ISteamNetworkingConnectionCustomSignaling
73+
// Implements ISteamNetworkingConnectionSignaling
7374
//
7475

7576
// This is called from SteamNetworkingSockets to send a signal. This could be called from any thread,
@@ -197,12 +198,8 @@ class CTrivialSignalingClient : public ITrivialSignalingClient
197198
sockMutex.unlock();
198199
}
199200

200-
//
201-
// Implements ISteamNetworkingCustomSignalingService
202-
//
203-
virtual ISteamNetworkingConnectionCustomSignaling *CreateSignalingForConnection(
201+
ISteamNetworkingConnectionSignaling *CreateSignalingForConnection(
204202
const SteamNetworkingIdentity &identityPeer,
205-
const char *pszRoutingInfo,
206203
SteamNetworkingErrMsg &errMsg
207204
) override {
208205
SteamNetworkingIdentityRender sIdentityPeer( identityPeer );
@@ -310,11 +307,11 @@ class CTrivialSignalingClient : public ITrivialSignalingClient
310307
}
311308

312309
// Setup a context object that can respond if this signal is a connection request.
313-
struct Context : ISteamNetworkingCustomSignalingRecvContext
310+
struct Context : ISteamNetworkingSignalingRecvContext
314311
{
315312
CTrivialSignalingClient *m_pOwner;
316313

317-
virtual ISteamNetworkingConnectionCustomSignaling *OnConnectRequest(
314+
virtual ISteamNetworkingConnectionSignaling *OnConnectRequest(
318315
HSteamNetConnection hConn,
319316
const SteamNetworkingIdentity &identityPeer,
320317
int nLocalVirtualPort
@@ -328,7 +325,7 @@ class CTrivialSignalingClient : public ITrivialSignalingClient
328325
// our envelope that we know how to parse, and we should save it off in this
329326
// context object.
330327
SteamNetworkingErrMsg ignoreErrMsg;
331-
return m_pOwner->CreateSignalingForConnection( identityPeer, nullptr, ignoreErrMsg );
328+
return m_pOwner->CreateSignalingForConnection( identityPeer, ignoreErrMsg );
332329
}
333330

334331
virtual void SendRejectionSignal(

examples/trivial_signaling_client.h

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,19 @@
55
#pragma once
66

77
#include <steam/steamnetworkingcustomsignaling.h>
8-
class ISteamNetworkingSockets;
9-
10-
// FIXME - Eventually I intend to add a mechanism to set the default
11-
// signaling service, so that SteamnetworkingSockets can
12-
// initiate creation of signaling sessions. This will be the
13-
// interface used for that.
14-
/// Interface used to create signaling sessions to particular peers.
15-
/// Typically this represents a connection to some service.
16-
class ISteamNetworkingCustomSignalingService
17-
{
18-
public:
198

20-
/// Setup a session for sending signals for a particular connection.
21-
/// The signals will always be sent to the same peer.
22-
///
23-
/// pszSessionRoutingInfo is reserved for future use, it will always
24-
/// be NULL right now.
25-
///
26-
/// On failure, return NULL
27-
virtual ISteamNetworkingConnectionCustomSignaling *CreateSignalingForConnection(
28-
const SteamNetworkingIdentity &identityPeer,
29-
const char *pszRoutingInfo,
30-
SteamNetworkingErrMsg &errMsg
31-
) = 0;
32-
};
9+
class ISteamNetworkingSockets;
3310

3411
/// Interface to our client.
35-
class ITrivialSignalingClient : public ISteamNetworkingCustomSignalingService
12+
class ITrivialSignalingClient
3613
{
3714
public:
3815

16+
/// Create signaling object for a connection to peer
17+
virtual ISteamNetworkingConnectionSignaling *CreateSignalingForConnection(
18+
const SteamNetworkingIdentity &identityPeer,
19+
SteamNetworkingErrMsg &errMsg ) = 0;
20+
3921
/// Poll the server for incoming signals and dispatch them.
4022
/// We use polling in this example just to keep it simple.
4123
/// You could use a service thread.
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
//====== Copyright Valve Corporation, All rights reserved. ====================
2+
3+
#ifndef ISTEAMNETWORKINGMESSAGES
4+
#define ISTEAMNETWORKINGMESSAGES
5+
#pragma once
6+
7+
#include "steamnetworkingtypes.h"
8+
#include "steam_api_common.h"
9+
10+
//-----------------------------------------------------------------------------
11+
/// The non-connection-oriented interface to send and receive messages
12+
/// (whether they be "clients" or "servers").
13+
///
14+
/// ISteamNetworkingSockets is connection-oriented (like TCP), meaning you
15+
/// need to listen and connect, and then you send messages using a connection
16+
/// handle. ISteamNetworkingMessages is more like UDP, in that you can just send
17+
/// messages to arbitrary peers at any time. The underlying connections are
18+
/// established implicitly.
19+
///
20+
/// Under the hood ISteamNetworkingMessages works on top of the ISteamNetworkingSockets
21+
/// code, so you get the same routing and messaging efficiency. The difference is
22+
/// mainly in your responsibility to explicitly establish a connection and
23+
/// the type of feedback you get about the state of the connection. Both
24+
/// interfaces can do "P2P" communications, and both support both unreliable
25+
/// and reliable messages, fragmentation and reassembly.
26+
///
27+
/// The primary purpose of this interface is to be "like UDP", so that UDP-based code
28+
/// can be ported easily to take advantage of relayed connections. If you find
29+
/// yourself needing more low level information or control, or to be able to better
30+
/// handle failure, then you probably need to use ISteamNetworkingSockets directly.
31+
/// Also, note that if your main goal is to obtain a connection between two peers
32+
/// without concerning yourself with assigning roles of "client" and "server",
33+
/// you may find the symmetric connection mode of ISteamNetworkingSockets useful.
34+
/// (See k_ESteamNetworkingConfig_SymmetricConnect.)
35+
///
36+
class ISteamNetworkingMessages
37+
{
38+
public:
39+
/// Sends a message to the specified host. If we don't already have a session with that user,
40+
/// a session is implicitly created. There might be some handshaking that needs to happen
41+
/// before we can actually begin sending message data. If this handshaking fails and we can't
42+
/// get through, an error will be posted via the callback SteamNetworkingMessagesSessionFailed_t.
43+
/// There is no notification when the operation succeeds. (You should have the peer send a reply
44+
/// for this purpose.)
45+
///
46+
/// Sending a message to a host will also implicitly accept any incoming connection from that host.
47+
///
48+
/// nSendFlags is a bitmask of k_nSteamNetworkingSend_xxx options
49+
///
50+
/// nRemoteChannel is a routing number you can use to help route message to different systems.
51+
/// You'll have to call ReceiveMessagesOnChannel() with the same channel number in order to retrieve
52+
/// the data on the other end.
53+
///
54+
/// Using different channels to talk to the same user will still use the same underlying
55+
/// connection, saving on resources. If you don't need this feature, use 0.
56+
/// Otherwise, small integers are the most efficient.
57+
///
58+
/// It is guaranteed that reliable messages to the same host on the same channel
59+
/// will be be received by the remote host (if they are received at all) exactly once,
60+
/// and in the same order that they were sent.
61+
///
62+
/// NO other order guarantees exist! In particular, unreliable messages may be dropped,
63+
/// received out of order with respect to each other and with respect to reliable data,
64+
/// or may be received multiple times. Messages on different channels are *not* guaranteed
65+
/// to be received in the order they were sent.
66+
///
67+
/// A note for those familiar with TCP/IP ports, or converting an existing codebase that
68+
/// opened multiple sockets: You might notice that there is only one channel, and with
69+
/// TCP/IP each endpoint has a port number. You can think of the channel number as the
70+
/// *destination* port. If you need each message to also include a "source port" (so the
71+
/// recipient can route the reply), then just put that in your message. That is essentially
72+
/// how UDP works!
73+
///
74+
/// Returns:
75+
/// - k_EREsultOK on success.
76+
/// - k_EResultNoConnection will be returned if the session has failed or was closed by the peer,
77+
/// and k_nSteamNetworkingSend_AutoRestartBrokenSession is not used. (You can use
78+
/// GetSessionConnectionInfo to get the details.) In order to acknowledge the broken session
79+
/// and start a new one, you must call CloseSessionWithUser
80+
/// - See ISteamNetworkingSockets::SendMessageToConnection for more possible return values
81+
virtual EResult SendMessageToUser( const SteamNetworkingIdentity &identityRemote, const void *pubData, uint32 cubData, int nSendFlags, int nRemoteChannel ) = 0;
82+
83+
/// Reads the next message that has been sent from another user via SendMessageToUser() on the given channel.
84+
/// Returns number of messages returned into your list. (0 if no message are available on that channel.)
85+
///
86+
/// When you're done with the message object(s), make sure and call SteamNetworkingMessage_t::Release()!
87+
virtual int ReceiveMessagesOnChannel( int nLocalChannel, SteamNetworkingMessage_t **ppOutMessages, int nMaxMessages ) = 0;
88+
89+
/// Call this in response to a SteamNetworkingMessagesSessionRequest_t callback.
90+
/// SteamNetworkingMessagesSessionRequest_t are posted when a user tries to send you a message,
91+
/// and you haven't tried to talk to them first. If you don't want to talk to them, just ignore
92+
/// the request. If the user continues to send you messages, SteamNetworkingMessagesSessionRequest_t
93+
/// callbacks will continue to be posted periodically.
94+
///
95+
/// Returns false if there is no session with the user pending or otherwise. If there is an
96+
/// existing active session, this function will return true, even if it is not pending.
97+
///
98+
/// Calling SendMessageToUser() will implicitly accepts any pending session request to that user.
99+
virtual bool AcceptSessionWithUser( const SteamNetworkingIdentity &identityRemote ) = 0;
100+
101+
/// Call this when you're done talking to a user to immediately free up resources under-the-hood.
102+
/// If the remote user tries to send data to you again, another SteamNetworkingMessagesSessionRequest_t
103+
/// callback will be posted.
104+
///
105+
/// Note that sessions that go unused for a few minutes are automatically timed out.
106+
virtual bool CloseSessionWithUser( const SteamNetworkingIdentity &identityRemote ) = 0;
107+
108+
/// Call this when you're done talking to a user on a specific channel. Once all
109+
/// open channels to a user have been closed, the open session to the user will be
110+
/// closed, and any new data from this user will trigger a
111+
/// SteamSteamNetworkingMessagesSessionRequest_t callback
112+
virtual bool CloseChannelWithUser( const SteamNetworkingIdentity &identityRemote, int nLocalChannel ) = 0;
113+
114+
/// Returns information about the latest state of a connection, if any, with the given peer.
115+
/// Primarily intended for debugging purposes, but can also be used to get more detailed
116+
/// failure information. (See SendMessageToUser and k_nSteamNetworkingSend_AutoRestartBrokenSession.)
117+
///
118+
/// Returns the value of SteamNetConnectionInfo_t::m_eState, or k_ESteamNetworkingConnectionState_None
119+
/// if no connection exists with specified peer. You may pass nullptr for either parameter if
120+
/// you do not need the corresponding details. Note that sessions time out after a while,
121+
/// so if a connection fails, or SendMessageToUser returns k_EResultNoConnection, you cannot wait
122+
/// indefinitely to obtain the reason for failure.
123+
virtual ESteamNetworkingConnectionState GetSessionConnectionInfo( const SteamNetworkingIdentity &identityRemote, SteamNetConnectionInfo_t *pConnectionInfo, SteamNetworkingQuickConnectionStatus *pQuickStatus ) = 0;
124+
};
125+
#define STEAMNETWORKINGMESSAGES_INTERFACE_VERSION "SteamNetworkingMessages002"
126+
127+
//
128+
// Callbacks
129+
//
130+
131+
#pragma pack( push, 1 )
132+
133+
/// Posted when a remote host is sending us a message, and we do not already have a session with them
134+
struct SteamNetworkingMessagesSessionRequest_t
135+
{
136+
enum { k_iCallback = k_iSteamNetworkingMessagesCallbacks + 1 };
137+
SteamNetworkingIdentity m_identityRemote; // user who wants to talk to us
138+
};
139+
140+
/// Posted when we fail to establish a connection, or we detect that communications
141+
/// have been disrupted it an unusual way. There is no notification when a peer proactively
142+
/// closes the session. ("Closed by peer" is not a concept of UDP-style communications, and
143+
/// SteamNetworkingMessages is primarily intended to make porting UDP code easy.)
144+
///
145+
/// Remember: callbacks are asynchronous. See notes on SendMessageToUser,
146+
/// and k_nSteamNetworkingSend_AutoRestartBrokenSession in particular.
147+
///
148+
/// Also, if a session times out due to inactivity, no callbacks will be posted. The only
149+
/// way to detect that this is happening is that querying the session state may return
150+
/// none, connecting, and findingroute again.
151+
struct SteamNetworkingMessagesSessionFailed_t
152+
{
153+
enum { k_iCallback = k_iSteamNetworkingMessagesCallbacks + 2 };
154+
155+
/// Detailed info about the session that failed.
156+
/// SteamNetConnectionInfo_t::m_identityRemote indicates who this session
157+
/// was with.
158+
SteamNetConnectionInfo_t m_info;
159+
};
160+
161+
#pragma pack(pop)
162+
163+
// Global accessors
164+
// Using standalone lib
165+
#ifdef STEAMNETWORKINGSOCKETS_STANDALONELIB
166+
167+
// Standalone lib.
168+
static_assert( STEAMNETWORKINGMESSAGES_INTERFACE_VERSION[25] == '2', "Version mismatch" );
169+
STEAMNETWORKINGSOCKETS_INTERFACE ISteamNetworkingMessages *SteamNetworkingMessages_LibV2();
170+
inline ISteamNetworkingMessages *SteamNetworkingMessages_Lib() { return SteamNetworkingMessages_LibV2(); }
171+
172+
// If running in context of steam, we also define a gameserver instance.
173+
#ifdef STEAMNETWORKINGSOCKETS_STEAM
174+
STEAMNETWORKINGSOCKETS_INTERFACE ISteamNetworkingMessages *SteamGameServerNetworkingMessages_LibV2();
175+
inline ISteamNetworkingMessages *SteamGameServerNetworkingMessages_Lib() { return SteamGameServerNetworkingMessages_LibV2(); }
176+
#endif
177+
178+
#ifndef STEAMNETWORKINGSOCKETS_STEAMAPI
179+
inline ISteamNetworkingMessages *SteamNetworkingMessages() { return SteamNetworkingMessages_LibV2(); }
180+
#ifdef STEAMNETWORKINGSOCKETS_STEAM
181+
inline ISteamNetworkingMessages *SteamGameServerNetworkingMessages() { return SteamGameServerNetworkingMessages_LibV2(); }
182+
#endif
183+
#endif
184+
#endif
185+
186+
// Using Steamworks SDK
187+
#ifdef STEAMNETWORKINGSOCKETS_STEAMAPI
188+
189+
// Steamworks SDK
190+
STEAM_DEFINE_USER_INTERFACE_ACCESSOR( ISteamNetworkingMessages *, SteamNetworkingMessages_SteamAPI, STEAMNETWORKINGMESSAGES_INTERFACE_VERSION );
191+
STEAM_DEFINE_GAMESERVER_INTERFACE_ACCESSOR( ISteamNetworkingMessages *, SteamGameServerNetworkingMessages_SteamAPI, STEAMNETWORKINGMESSAGES_INTERFACE_VERSION );
192+
193+
#ifndef STEAMNETWORKINGSOCKETS_STANDALONELIB
194+
inline ISteamNetworkingMessages *SteamNetworkingMessages() { return SteamNetworkingMessages_SteamAPI(); }
195+
inline ISteamNetworkingMessages *SteamGameServerNetworkingMessages() { return SteamGameServerNetworkingMessages_SteamAPI(); }
196+
#endif
197+
#endif
198+
199+
#endif // ISTEAMNETWORKINGMESSAGES

include/steam/isteamnetworkingsockets.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#include "steam_api_common.h"
99

1010
struct SteamNetAuthenticationStatus_t;
11-
class ISteamNetworkingConnectionCustomSignaling;
12-
class ISteamNetworkingCustomSignalingRecvContext;
11+
class ISteamNetworkingConnectionSignaling;
12+
class ISteamNetworkingSignalingRecvContext;
1313

1414
//-----------------------------------------------------------------------------
1515
/// Lower level networking API.
@@ -106,6 +106,10 @@ class ISteamNetworkingSockets
106106
/// If you need to set any initial config options, pass them here. See
107107
/// SteamNetworkingConfigValue_t for more about why this is preferable to
108108
/// setting the options "immediately" after creation.
109+
///
110+
/// To use your own signaling service, see:
111+
/// - ConnectP2PCustomSignaling
112+
/// - k_ESteamNetworkingConfig_Callback_CreateConnectionSignaling
109113
virtual HSteamNetConnection ConnectP2P( const SteamNetworkingIdentity &identityRemote, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
110114

111115
/// Accept an incoming connection that has been received on a listen socket.
@@ -581,10 +585,10 @@ class ISteamNetworkingSockets
581585
/// This function will immediately construct a connection in the "connecting"
582586
/// state. Soon after (perhaps before this function returns, perhaps in another thread),
583587
/// the connection will begin sending signaling messages by calling
584-
/// ISteamNetworkingConnectionCustomSignaling::SendSignal.
588+
/// ISteamNetworkingConnectionSignaling::SendSignal.
585589
///
586590
/// When the remote peer accepts the connection (See
587-
/// ISteamNetworkingCustomSignalingRecvContext::OnConnectRequest),
591+
/// ISteamNetworkingSignalingRecvContext::OnConnectRequest),
588592
/// it will begin sending signaling messages. When these messages are received,
589593
/// you can pass them to the connection using ReceivedP2PCustomSignal.
590594
///
@@ -599,7 +603,7 @@ class ISteamNetworkingSockets
599603
/// If you need to set any initial config options, pass them here. See
600604
/// SteamNetworkingConfigValue_t for more about why this is preferable to
601605
/// setting the options "immediately" after creation.
602-
virtual HSteamNetConnection ConnectP2PCustomSignaling( ISteamNetworkingConnectionCustomSignaling *pSignaling, const SteamNetworkingIdentity *pPeerIdentity, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
606+
virtual HSteamNetConnection ConnectP2PCustomSignaling( ISteamNetworkingConnectionSignaling *pSignaling, const SteamNetworkingIdentity *pPeerIdentity, int nRemoteVirtualPort, int nOptions, const SteamNetworkingConfigValue_t *pOptions ) = 0;
603607

604608
/// Called when custom signaling has received a message. When your
605609
/// signaling channel receives a message, it should save off whatever
@@ -610,7 +614,7 @@ class ISteamNetworkingSockets
610614
///
611615
/// - If the signal is associated with existing connection, it is dealt
612616
/// with immediately. If any replies need to be sent, they will be
613-
/// dispatched using the ISteamNetworkingConnectionCustomSignaling
617+
/// dispatched using the ISteamNetworkingConnectionSignaling
614618
/// associated with the connection.
615619
/// - If the message represents a connection request (and the request
616620
/// is not redundant for an existing connection), a new connection
@@ -630,7 +634,7 @@ class ISteamNetworkingSockets
630634
///
631635
/// If you expect to be using relayed connections, then you probably want
632636
/// to call ISteamNetworkingUtils::InitRelayNetworkAccess() when your app initializes
633-
virtual bool ReceivedP2PCustomSignal( const void *pMsg, int cbMsg, ISteamNetworkingCustomSignalingRecvContext *pContext ) = 0;
637+
virtual bool ReceivedP2PCustomSignal( const void *pMsg, int cbMsg, ISteamNetworkingSignalingRecvContext *pContext ) = 0;
634638

635639
//
636640
// Certificate provision by the application. On Steam, we normally handle all this automatically

0 commit comments

Comments
 (0)