Facepunch / Facepunch.Steamworks

Another fucking c# Steamworks implementation
MIT License
2.88k stars 345 forks source link

Where to get ticket data in OnIncomingConnection? - Dedicated Server - Unity 2019.2.17f1 - Windows 10 #349

Closed MBrown42 closed 4 years ago

MBrown42 commented 4 years ago

Hi, thanks much for facepunch! Good stuff. And thanks in advance for reading; I am somewhat of a noob although not to server/client architecture. The server launches and is shown in the web api as valid, the client launches and sees the server on a LAN server list. I have seen the test code in the repositories but it does not simulate actual networking and a client’s initial connection to a server in separate threads.

Here is my client code snippet which sends the auth ticket, which is executed inside the loop through a LAN serverlist loop – server.SteamID is the steamID of the server it’s looking at (there is only 1)

// attempt to send an auth ticket hopefully to connect to the server ulong steamId64 = m_fpClient.SteamId; Facepunch.Steamworks.Auth.Ticket ticket = m_fpClient.Auth.GetAuthSessionTicket(); byte[] ticketBlob = ticket.Data; m_fpClient.Networking.SendP2PPacket(server.SteamId , ticketBlob, ticketBlob.Length);

Here is how I create the server:

// our primary FacePunch.Steamworks server private Facepunch.Steamworks.Server m_fpServer;

// our FacePunch.Steamworks server options for initialization private Facepunch.Steamworks.ServerInit m_fpServerOptions; // Create the server m_fpServerOptions = new Facepunch.Steamworks.ServerInit("MyGame", "MyGame");

m_fpServerOptions.SteamPort = 7778; m_fpServerOptions.QueryPort = 27016; m_fpServerOptions.GamePort = 27015; m_fpServerOptions.VersionString = m_sVersionID;

m_fpServer = new Facepunch.Steamworks.Server(AppId, m_fpServerOptions); m_fpServer.ServerName = "Test Server"; m_fpServer.MaxPlayers = 6; m_fpServer.Passworded = false; m_fpServer.DedicatedServer = true; m_fpServer.MapName = "boo";

if (!m_fpServer.IsValid) { m_fpServer = null; serverInfoTMPro.text = "Couldnt initialize server"; Debug.LogWarning("Couldn't initialize server"); return; }

m_fpServer.Networking.OnIncomingConnection += OnIncomingConnection; m_fpServer.Networking.OnP2PData += OnP2PData; m_fpServer.Auth.OnAuthChange += OnAuthChange; m_fpServer.LogOnAnonymous();

And here is my incoming connections callback:

// handle incoming connections bool OnIncomingConnection(ulong aSteamID) { serverInfoTMPro.text += ("\nOnIncomingConnection: input: " + aSteamID); Debug.Log(this.gameObject.name + " OnIncomingConnection: input: " + aSteamID);

// I want to call m_fpServer.Auth.StartSession(bytes, aSteamID) // but where do I get the first argument (bytes)?

return true; }

The callback fires but as I tried to code up starting the auth session I realized I have no way to get the first argument – the ticket data. I’ve read the other issues related and seen phrases like “client gets the ticket data to the server somehow”, and “piggyback the connection request with the auth ticket data”.
But how is that accomplished? I’ assuming now that it must be outside of steam completely, as the user is not authenticated and P2P messaging will not yet work, right? I tried to send one and it did not fire the server p2p callback. I’m thinking of just opening a custom low level port on server and client and firing off a custom one-time message per connection initiation with the ticket data and a steamID to map to for later callbacks in the auth process.

If this is so then can you just hijack one of the 3 ports already in use? I haven’t had a chance to code yet but my hunch is calling listen / open on the port in low level code will throw an error that it is already in use by steamworks. If that is true, then I’d need to open a 4th port, which I’m fine with but what happens when I host the dedicated server on steam? Can I just open a port if I want and just tell users to do the same with their routers?

== takes a step back == uses newer FP version ==

At this point I thought perhaps I had run into a limitation of the older FP, so I created a brand new Unity project and added the Github url as a json dependency package. This time the OnIncomingConnection callback never fires, some code snippets below.

Here is the client sending the auth ticket in the newer FP version test project:

.. loop through server found in local LAN server list

// attempt to send an auth ticket hopefully to connect to the server AuthTicket ticket = SteamUser.GetAuthSessionTicket();

byte[] ticketBlob = ticket.Data;

Debug.Log("Client: Sending auth ticket to " + server.SteamId + ": " + server.Name); clientInfoTMPro.text += "\nClient: Sending auth ticket to " + server.SteamId + ": " + server.Name;

if (!SteamNetworking.SendP2PPacket(server.SteamId, ticketBlob, ticketBlob.Length)) { Debug.Log("Client: Failed to send session packet to " + server.SteamId + ": " + server.Name); clientInfoTMPro.text += "\nClient: Failed to send session packet to " + server.SteamId + ": " + server.Name; } else { Debug.Log("Client: Auth ticket sent to " + server.SteamId); clientInfoTMPro.text += "\nClient: Auth ticket sent to " + server.SteamId + ": " + server.Name; }

Here is the server creation and OnIncomingConnection callback in the newer FP version test project:

// Create the server m_fpServerOptions = new SteamServerInit("MyGame", "MyGame");

m_fpServerOptions.SteamPort = 7778; // 8766; // 7778; m_fpServerOptions.QueryPort = 27016; m_fpServerOptions.GamePort = 27015; m_fpServerOptions.VersionString = m_sVersionID; m_fpServerOptions.DedicatedServer = true;

SteamServer.Init(AppId, m_fpServerOptions);

SteamServer.ServerName = "Test Server";

SteamServer.MaxPlayers = 6; SteamServer.Passworded = false; SteamServer.DedicatedServer = true; SteamServer.MapName = "boo"; SteamServer.AutomaticHeartbeats = true; SteamServer.LogOnAnonymous();

SteamServer.OnSteamServersConnected += OnSteamServersConnected; SteamServer.OnValidateAuthTicketResponse += OnValidateAuthTicketResponse; SteamNetworking.OnP2PSessionRequest += OnP2PSessionRequest;

Here is the OnIncomingConnections callback:

// handle incoming connections bool OnIncomingConnection(ulong dalong) { serverInfoTMPro.text += ("\nOnIncomingConnection: input: " + dalong); Debug.Log(this.gameObject.name + " OnIncomingConnection: input: " + dalong);

return true; }

The server and client above with the newer FP version launch and are valid, the server shows up on the web api url and in the client’s LAN server list. Upon the client trying to connect, the server callback OnIncomingConnections above never fires. The only thing I could think of was turning on listening for channel 0, but there are no funcs in FP for it, I ran out of steam (no pun intended) digging into the steamworks api itself and getting a handle to the internal of FP.

SO, I am kinda stuck. I’d rather use the newer FP, but if the callback doesn’t even fire I can’t keep building my game. The older version above fires the callback but now I need a strategy to get the auth ticket data and steamID to the dedicated game server (apparently) outside of steam.

Any advice greatly appreciated,

Thanks much! Matt Brown LifeStamp Games

MBrown42 commented 4 years ago

Update: after calling SetListenChannel(0, true); in my older FP version code, I do get P2P messages detected on the server before authentication. Most people are probably like "duh", but it's the little things... I intend to send a message with the auth ticket data and steamID which will get stuck in pending arrays server side.

I do wish I could understand why the newer version code server receives no messages or callbacks.