Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SteamHelper: Add helper app which can use the Steamworks SDK on behalf of Dolphin #11833

Closed

Conversation

OatmealDome
Copy link
Member

@OatmealDome OatmealDome commented May 21, 2023

Because the Steamworks SDK uses a non-free license, we are unable to link to it directly in Dolphin. However, there is a (slightly complicated) workaround.

We can create a helper app under a more permissive license (in this case, the 3-clause BSD license), and have it link to the Steamworks SDK. This app is launched in the background during Dolphin's start up. When Dolphin wants to do something with the Steamworks SDK, it uses IPC to send a message to the helper app and it does the operation on behalf of Dolphin.

Because the helper app can't contain anything licensed under the GPL, I am limited to just using stuff from the STL in its code since the vast majority of Dolphin is GPL-licensed.

As of now, this PR doesn't actually do anything visible (unless you open Task Manager or equivalent and look for "SteamHelper.exe" or "dolphin-steam-helper"), but I will introduce PRs that actually make use of the helper app in the future.

If anyone wants to try this PR out, switch to the steamworks-integration beta in Steam. It should change your current status on Steam to the current game that you're playing. If you do not have access to Dolphin on Steam, ping me on IRC or Discord.

This PR takes design inspiration from icculus's steamshim and libretro's mist, but does not contain any actual code from either of them.

@OatmealDome OatmealDome force-pushed the steamworks-gpl-compliant branch 7 times, most recently from 912cdf8 to 2bf4dc1 Compare May 21, 2023 03:27
@OatmealDome OatmealDome force-pushed the steamworks-gpl-compliant branch from 2bf4dc1 to a20df11 Compare May 21, 2023 06:07
@OatmealDome OatmealDome force-pushed the steamworks-gpl-compliant branch from a20df11 to f951505 Compare May 21, 2023 07:50
@OatmealDome OatmealDome force-pushed the steamworks-gpl-compliant branch from f951505 to 17a20f3 Compare May 21, 2023 08:03
@AdmiralCurtiss
Copy link
Contributor

I'm not sure how I feel about having non-GPL code inside the Dolphin repository itself. How much work would it be to split that out into a second repository?

@CasualPokePlayer
Copy link
Contributor

I'm curious, does this actually workaround GPL? For both GPLv2 and GPLv3 (given Dolphin is GPLv2+ and might be GPLv3 in the final binary depending on libraries used). It would sound like an open book for anyone to just go "sure Dolphin is GPL but I can use it in any non-GPL (probably closed source) fashion in whatever fork as long as the non-GPL part is a separate program that the GPL code comms with IPC!" Which itself sounds like a bad reason to even try this.

This clause in GPLv2 seems to be relevant in this regard:

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

So for GPLv2, it seems it would at least depend on the definition of "modules" in this context. Does the other IPC program count as a "module" of the overall Dolphin executable? Whether or not it is a separate executable in itself sounds like more an implementation detail, considering it is unintended to be launched directly (and so is explicitly intended to be ran with another program), and even more damning, this PR makes it required that this IPC is active, making this non-GPL compliant executable a required component (or I guess, "module") of a GPL executable. (Granted, it's probably easy enough to make it so Dolphin won't just immediately exit when the steam helper is not around or can't be executed for whatever reason)

This definition in GPLv3 seems to be relevant and more damning in this regard:

The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

So for GPLv3, the fact that this IPC'd program is required to run the application would end up running afoul the licence, as this non-GPL compliant program ends up required to run the GPL program, and thus its source code (which can't be provided given closed source components) falls under the "corresponding source" of Dolphin as a whole.

Another clause seems to also imply even if it was made optional, that the IPC'd program would end up running afoul GPLv3

A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

The IPC'd program could possibly be reasonably be said that by its nature it is an extension of Dolphin itself ("can't be launched directly, go launch Dolphin in Steam"), and thus "which are not by their nature extensions of the covered work" would end up not applying to this IPC'd program and thus the combination of the Dolphin exe and the SteamHelper exe cannot be said to an "aggregate" but rather SteamHelper is part of the covered work (Dolphin) itself.

I'm curious to know in any case what legal basis if any steamshim and mist used to justify that what they do is not a violation of GPL when used by GPL programs. Whether or not it's using dynamic linking or IPC seems at best to be an implementation detail, the most you can really say these don't violate GPL is with GPLv2 if they don't count as a "module" of the executable work, and GPLv3 you are most likely running afoul the licence regardless of what you do. And of course, you just open the door to anyone using IPC to bypass Dolphin's GPL in any way they want.

@OatmealDome
Copy link
Member Author

@AdmiralCurtiss

I'm not sure how I feel about having non-GPL code inside the Dolphin repository itself. How much work would it be to split that out into a second repository?

I can look into that if we decide to proceed with this approach.


@CasualPokePlayer

I'm curious to know in any case what legal basis if any steamshim and mist used to justify that what they do is not a violation of GPL when used by GPL programs.

As far as I'm aware, icculus and libretro have chosen to interpret their helper apps as being separate works.

The FSF FAQ has this to say:

Where's the line between two separate programs, and one program with two parts? This is a legal question, which ultimately judges will decide. We believe that a proper criterion depends both on the mechanism of communication (exec, pipes, rpc, function calls within a shared address space, etc.) and the semantics of the communication (what kinds of information are interchanged).

If the modules are included in the same executable file, they are definitely combined in one program. If modules are designed to run linked together in a shared address space, that almost surely means combining them into one program.

By contrast, pipes, sockets and command-line arguments are communication mechanisms normally used between two separate programs. So when they are used for communication, the modules normally are separate programs. But if the semantics of the communication are intimate enough, exchanging complex internal data structures, that too could be a basis to consider the two parts as combined into a larger program.

Whether the helper apps can be considered to be "combined into a larger program" is really up to interpretation.

Of course, none of this has been tested in a court of law.

@CasualPokePlayer
Copy link
Contributor

CasualPokePlayer commented May 21, 2023

As a note, the FSF FAQ is that, an FAQ, not the actual license (which they themselves contradict at times), and so at most can be used to judge their intent if anything (although I'm not sure if their intent actually has much meaning here when they are ultimately not the copyright holders in this regard). And even with their interpretation, you probably can argue that this falls the line of not being 2 separate programs (the entire point of the program is to pump complex data from a closed source library into GPL'd Dolphin)... although granted at this stage maybe not given the barebones usage (but with more and more usage with more complex data, like input structures, you end up going to that territory).

Even then, the fact that Dolphin on Steam is requiring that SteamHelper be communicated to seems to me a very clear violation of GPL here, it's not an optional component of Dolphin with this PR, and really therefore I'm not sure how you can argue they are in fact separate works if the GPL program is required to be able to launch the non-GPL program and communicate with it successfully for the GPL program to run (and given that last clause, even if you did make it optional, I could guess that wouldn't be enough for GPL compliance, due to the nature of the program being entirely an extension of Dolphin itself).

Granted of course, a lot of that does go under the assumption that some library in Dolphin would implicitly bump it up from GPLv2 to GPLv3 (I know this is the case for Android, don't know about Windows/MacOS/Linux), and that the other program does not count as a "module" of GPL'd Dolphin, although if that is used as the saving grace, that then means the + in Dolphin's GPLv2+ cannot apply to any of the Steam code and thus cannot apply to Steam builds, and thus any usage of GPLv2 incompatible yet GPLv3 compatible libraries cannot be done for Steam builds.

(And of course, again, doing this is a tacit admission that "we are fine with other people bypassing Dolphin's GPL by using IPC," although tbh that probably wouldn't matter as the people deciding the violate Dolphin's license wouldn't care enough to even try to be clever with said violation)

@AdmiralCurtiss
Copy link
Contributor

AdmiralCurtiss commented May 21, 2023

I have no legal basis on which I base this opinion on, but my two cents...

I think the way this is currently implemented, with Dolphin explicitly launching a second executable and not even starting when that fails, definitely smells fishy under the 'two separate programs' vs 'one singular program' definition, and at the very least breaks the spirit of the law even if not the letter.

Personally, I would do something like this instead: Let Dolphin act as a server for requests that can come from any other process. On boot, Dolphin launches this server component (which can just be part of the Dolphin executable) and then just listens for and replies to requests (as if it were a REST server or something along those lines, but I don't care if this happens via TCP or sockets or pipes or whatever). That way, we're not relying on the shim existing at all -- from the Dolphin end this is similar to a what a scripting API would be, just much more limited.

At this point the shim can be whatever and I think the licensing situation would be a lot more straightforward. In fact, there could even be multiple shims (eg. someone targeting Discord's rich gaming display stuff) and we wouldn't even have to change anything in Dolphin's code itself.

Whether this actually changes anything in regards to the GPL compliance, I'm not sure -- especially if we're shipping the Steam shim together with Dolphin on Steam.

@leo60228
Copy link

leo60228 commented May 22, 2023

For what it's worth, steamshim is used by at least one commercial game with code under GPLv2+ (OneShot).

@leo60228
Copy link

I'm definitely not a lawyer but I also think there'd be a much better case for an existing project like steamshim qualifying as a separate work, compared to a new project specifically tied to Dolphin.

@OatmealDome
Copy link
Member Author

OatmealDome commented May 22, 2023

@AdmiralCurtiss

That way, we're not relying on the shim existing at all

This is a bit problematic. To resolve the concerns brought up in #11459, I need to fetch the person's Steam ID and use it to set the correct User directory. The only way I can find to fetch this is via Steamworks.


Thanks for your comments, everyone. I've had some time to think and I've come up with something that might be viable. Please let me know your thoughts.

  • Split the helper app into a project that exists outside the Dolphin repo. Perhaps it can exist under my personal account.
  • Rewrite the helper app so that it is genericized and not Dolphin-specific. (I am willing to maintain the app for others to use as well. There might be some game devs out there that would be interested in something like this.)
  • Ship the helper app in a separate SteamPipe depot to keep things separate on the backend.
    • Depots are groups of files that can be downloaded by Steam. Which depots are downloaded depends on things like the current OS, owned DLC, etc.
    • Right now, we have one depot for each OS, each containing all of Dolphin's files for that OS.
    • I can add more depots which contain the binaries for the helper app. Steam will automatically download the appropriate one along with the Dolphin depot on installation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants