Adapting SpiderMonkey to work with SteamNetworkingSockets

I’ve hit a dilemma where I cannot fully use Steam’s matchmaking and hosting functionality because I am not using their Networking API. So that means I would have to rewrite my entire networking code if I want some of Steam’s useful networking features to work. I’m hoping it is possible to make a fork of SpiderMonkey that can act as a wrapper of some sort for the steamsockets API when a boolean is true, and works normally without going through steam’s sockets when false.


To give more information why I need to do this:

My game has client/server based multiplayer modes that will last about 10 minute per match, and I plan to host the match on one of the player’s computers during my game’s Early Access phase, because paying for dedicated servers is not a viable option at this point.

And even if I do get dedicated servers, it is still useful to let players host local and custom matches with friends on their own machine so that the dedicated servers can be cleared up for matchmade games that are more competitive and expected to be secure and cheat/hack free.

But when using SpiderMonkey, the only way a player can host a match on their machine is if they have port-forwarded the proper port- something that not many normal users are willing or able to do. (I’m also not even sure if Steam will allow me to list my game as multiplayer if I require players to port forward, based on other things they’ve been picky about so far)

So to get around this, Steam’s support told me I need to use this API and that it will handle all the advanced stuff to get around the need to port forward (I believe Steam uses a relay server to do this and to offer extra security for its users).

The steamworks API looks very similar to SpiderMonkey, so I hope it’s possible to setup a version of SpiderMonkey that converts messages to the steam equivalent before sending them, and back to SpiderMonkey messages upon receival - or something like that so it is effectively using the same code to go through steam’s networking sockets instead.

https://partner.steamgames.com/doc/api/ISteamNetworkingSockets

I will be putting in a lot of work to do this, because letting players host matches locally without needing to port forward or have dedicated servers is a very high priority issue for me. But I will likely need a lot of guidance to get started and to make sure that what I want to do here is possible.

Any help or insight on this idea is greatly appreciated :slightly_smiling_face:

2 Likes

Steam has also mentioned something about a dedicated server program for devs thats in beta:

To participate in Valve’s dedicated server hosting program, use of this API is required. (This program is in beta – contact us if you’d like to participate.)

I can’t find more info yet, but if there’s even a chance that steam is going to offer free/cheaper dedicated servers for their partners, then I definitely want to be using their netowrking API so I can take advantage of it, as it will likely also be easier than setting up dedicated servers on my own.

1 Like

Does steamworks have a Java API?

1 Like

Yes there is thankfully this Steamworks wrapper for java that appears to be actively used and updated still.

Although I haven’t used much of steamworks features yet, just basic stuff, so I’m hoping it will continue to be as reliable as it has been so far.

2 Likes

I am not using Steam API but here are my two cents!

I am going to hit this issue as well.

Consider me dumb on this topic, but is UPnP a thing to consider? From what I read it is very easy to set up than manual port forwarding. Also found a bunch of Java libraries for using this.

for example

Besides it, I found these services also interesting. Looks like they act as a relay server like you said.

This a video tutorial I found for Minecraft

Looks like they all have free plans.

I never heard of it before, but from a bit of quick research it sounds like it would indeed work, but I’m not exactly sure how; it sounds like Id need to put this on all the players computers for it to work, and would just save them the hassle of going into their router settings to port forward. But it also doesn’t sound quite as secure as it would be to go through steam, since Steam uses a relay server and this UPnP sounds like it still just opens the ports

It looks like these would all be a good solution for minecraft-like games where you let the player build their own world and then they run a server to host that world to friends or the public

In that case, it would be their responsibility to pay for the better plan if they want to host a bigger server with more players (or they can still host a server on their own machine if they know how to port-forward). And then you can just have a public server list where you let players post their server IP to so everyone can join each others servers, and you never pay a dime for hosting.

But since my game’s multiplayer mode isn’t world based and is of a competitive style, the only players that have incentive to download a server and set things up to be a host usually have malicious intentions, since there’s no other benefit to hosting a server if its just for a short 10v10 capture the flag match, and the world resets every time.

So my hope is to set things up with Steam’s networking API so that any player is able to be the host, and then I can silently pick the best and most trusted host out of all the players in that match. At least until I scale up to larger dedicated servers.

1 Like

SpiderMonkey was designed to support different transports at the low level. I don’t know what it would take to support Steam’s API as I haven’t looked into it.

Is it just a way to pop through NAT or does it actually relay all network traffic? What about UDP?

1 Like

Just relay servers, their documentation says:

  • Supports relayed connections through the Valve network. This prevents IP addresses from being revealed, protecting your players and gameservers from attack. NAT punching is not attempted.

https://partner.steamgames.com/doc/features/multiplayer/steamdatagramrelay

It sounds like they still support UDP in the form of un-reliable message types, if I’m understanding these points from their documentation correctly:

  • It’s a connection-oriented API (like TCP, not UDP). When sending and receiving messages, the peer is identified using a connection handle.

  • But unlike TCP, it’s message-oriented, not stream-oriented. (The boundaries between the messages are maintained by the API.)

  • Both reliable and unreliable messages are supported.

The architecture of SpiderMonkey was built with the idea that transports could be swapped out. The specific mechanisms of message passing are completely abstracted at most levels.

However, because there were zero or limited examples of other transports, I did not include a built-in mechanism for swapping them out when I rewrote SpiderMonkey. (It’s hard to write code without use-cases.)

So the Network.* static convenience methods would definitely have to be side-stepped. (Which is common enough anyway.)

It’s also possible that the DefaultServer and DefaultClient implementations have some TCP assumptions. In that case, those classes would have to be forked until we figure out how to refactor them (after having some examples). But everything below DefaultServer and DefaultClient should be transport agnostic.

Given that the basic reliable and unreliable kernels are passed to DefaultServer, I suspect it would only be adding new channels that requires some forking. Pass in Kernels that delegate to the steam transports and the default channels should “just work”.

1 Like

I will have to take some time to study the SpiderMonkey code so I am more familiar with it, and also the code for using Steam’s sockets at the lower level.

However I might have already encountered a road-block, as I’m not sure the java wrapper for Steamworks supports the SteamNetworkingSockets API yet.

They support steam’s deprecated networking api that’s just called SteamNetworking, but I don’t think that gives you any access to the lower level stuff that we’d need to implement things with SpiderMonkey…

So that seems like it throws a wrench in my plan, especially since the issues been open for a while and no one’s made a PR yet. But then again I think I would need more than just a wrapper for the SteamNetworkingSockets class - it sounds like I would need to make a wrapper for the even lower level classes that make up that whole api?

This is valve’s c++ open source version of the SteamNewtorkingSockets api that I’m guessing I’d be making the wrapper for:

So would I need to make a java wrapper for the whole api? Or just certain classes. I have no experience in the realm of writing a wrapper like this unfortunately.

I wrapped steamworks for spoxel ages ago. I have the code on github:

I’ve done very little to clean it up and haven’t had any time to maintain it, but it may be worth a look for you. This was before they released their new networking API so I haven’t had a chance to check that out.

2 Likes

Sorry if I’m asking dumb questions here about wrapping libraries, I’m still trying to figure things out so I’ve been looking through the steamworks4j repo, and also looked through your steam networking one now as well:

It looks like your wrapper contains all java files, while the steamworks4j one contains a bunch of the original c++ files and java versions with the same names. Are there multiple ways to create a wrapper? Or are these different types of wrappers?

I used steamworks4j to interface with the steam networking stack since their library is c++ based. I wrapped the steamworks code to make it work with spidermonkey. As a result, I could either use default spidermonkey or if the user was logged into steam replace the client / server and not have to change any of the other networking code. There was some weirdness because the steamworks API didn’t handle certain things well (like there is no easy way to handle disconnects… you basically check if the client is still sending you messages and hope they aren’t just timing out).

2 Likes

Thanks I see now, I thought the term wrapper was exclusive for porting code from one language to another but see now it can be between any two libraries/apis.

Do you know if the deprecated SteamNetworking library that your wrapper is based off of uses Steam’s relay servers? Or more importantly, I guess I should ask if using your implementation allows players to host a server without having to port-forward? If so I could get by using that until I manage to wrap the newer API, since that would still be useful for some other new features. But getting around having players port-forward to host a match is the main thing I want to solve.

Yes, it didn’t require port forwarding and would relay through valve’s servers.

1 Like

You can also use Steam P2P to use SpiderMonkey without port forwarding. Every client connects to the server via P2P connection

1 Like