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

Prefer to grab the server's SDL descriptors. #1450

Merged
merged 2 commits into from
Aug 7, 2023

Conversation

Hoikas
Copy link
Member

@Hoikas Hoikas commented Aug 6, 2023

The impetus for this change is the SDL on MOULa is now progressing, sometimes faster than we can update it due to limited reviewer manpower and the lack of proper reviews taking place on the OU side. This results in SDL DESC PROBLEM for people using our clients. Further, it is known that the MOULa game server does not inspect SDL blobs before propagating them to other players, so it is fairly trivial to make clients error out on MOULa with cryptic messages by taking specially crafted SDLs on that shard. Therefore, we now prefer to use the server's SDL, even in /LocalData.

This removes the singlular /SkipPreload command line argument in favor of two arguments: /LocalPython and /LocalSDL. /LocalData now implies the former but not the latter. The reason for this change is that the SDL is a contract between the server and the client about how exactly an SDL blob is formatted. If SDL blobs don't have the same format between the client and server, this can have fairly bad implications, ranging from remote players being disconnected with an error, the player with the wrong SDL getting an error, or the server crashing.

This removes the singlular `/SkipPreload` command line argument in favor
of two arguments: `/LocalPython` and `/LocalSDL`. `/LocalData` now
implies the former but not the latter. The reason for this change is
that the SDL is a contract between the server and the client about how
exactly an SDL blob is formatted. If SDL blobs don't have the same
format between the client and server, this can have fairly bad
implications, ranging from remote players being disconnected with an
error, the player with the wrong SDL getting an error, or the server
crashing.
Copy link
Contributor

@dgelessus dgelessus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems sensible to me - it will make it much easier to safely use a H'uru client on Cyan's shard. Of course, this can lead to the client using SDL that's incompatible with its local scripts and age data, but that's much less likely to cause remote breakage than SDL mismatches.

To clarify, because I don't fully understand all of the patching logic... does this apply only if the server provides the .sdl files via the auth server/secure preloader, or also if they're provided via the file server? Does this change anything about which of the two sources is preferred?

hsLockGuard(fWorker->fRequestMut);
fWorker->fRequests.emplace_back("SecurePreloader", pfPatcherWorker::Request::kSecurePreloader);
if (NetCliFileQueryConnected()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the other code checks gDataServerLocal directly - or is this condition supposed to check something different?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gDataServer is a variable from plResManager, which I really didn't want to depend on in this case. Instead, what we're really interested in is whether or not a file server is available. If it isn't. then we should fall back to the auth server.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what we're really interested in is whether or not a file server is available. If it isn't. then we should fall back to the auth server.

Ah, I see - that logic makes sense, and in that case I agree the new function is the better choice.

Sources/Plasma/PubUtilLib/plAgeLoader/plResPatcher.cpp Outdated Show resolved Hide resolved
Co-authored-by: dgelessus <dgelessus@users.noreply.github.com>
@Hoikas
Copy link
Member Author

Hoikas commented Aug 6, 2023

Of course, this can lead to the client using SDL that's incompatible with its local scripts and age data, but that's much less likely to cause remote breakage than SDL mismatches.

Yeah, there's really not a good way to fix all of the problems. I'd just like to fix the worst offenders where we can.

To clarify, because I don't fully understand all of the patching logic... does this apply only if the server provides the .sdl files via the auth server/secure preloader, or also if they're provided via the file server? Does this change anything about which of the two sources is preferred?

There should be no change about which of the sources is preferred. The patcher will check the file server first. If the SecurePreloader manifest is missing (or we are not connected to the file server), then we will fall back to the auth server. Ideally, we don't want to use the auth server because files must be redownloaded each time from it because the auth manifests don't include file hashes, preventing any sort of integrity checking.

Copy link
Member

@dpogue dpogue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea sounds great to me.

The code looks okay too, but patcher and netcode is not my area of expertise 😅

hsLockGuard(fWorker->fRequestMut);
fWorker->fRequests.emplace_back("SecurePreloader", pfPatcherWorker::Request::kSecurePreloader);
if (NetCliFileQueryConnected()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what we're really interested in is whether or not a file server is available. If it isn't. then we should fall back to the auth server.

Ah, I see - that logic makes sense, and in that case I agree the new function is the better choice.

Comment on lines +730 to +734
if (NetCliFileQueryConnected()) {
fWorker->fRequests.emplace_back("SecurePreloader", pfPatcherWorker::Request::kSecurePreloader);
} else {
fWorker->EnqueuePreloaderLists();
}
Copy link
Contributor

@dgelessus dgelessus Aug 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regardless of how the condition is spelled, I'm still unsure if this behaves as intended in some corner cases.

Specifically: if /LocalData is specified, but not /LocalSDL, the intended behavior is that .sdl files are fetched from the server and everything else is taken from the local files (without patching) - correct?

This code works that way if the .sdl files are available from the auth server/secure preloader, but not if the .sdl files are only served from the file server. Currently, enabling /LocalData makes the client never connect to the file server, even if one exists - so in that case, this code will only check the auth server and not the file server for .sdl files. The fix would be to change all the conditions for connecting to the file server from if (!gDataServerLocal) to if (!gDataServerLocal || !gSDLLocal) I think.

This might be a purely theoretical problem - I'm not sure. All I know is that DIRTSAND-based servers usually provide the .sdl files via the file server, but I don't know if that also means that they're not available from the auth server anymore.

In any case, it's not a big concern. This fix is primarily meant for Cyan's shard, where .sdl files are available from the auth server, so the code will work correctly there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically: if /LocalData is specified, but not /LocalSDL, the intended behavior is that .sdl files are fetched from the server and everything else is taken from the local files (without patching) - correct?

That's the way it's coded, yes. It could make more sense, in some ways, to only allow /LocalSDL if /LocalData is specified because using the shard's data server but your own bespoke SDL seems a little strange.

This code works that way if the .sdl files are available from the auth server/secure preloader, but not if the .sdl files are only served from the file server. Currently, enabling /LocalData makes the client never connect to the file server, even if one exists - so in that case, this code will only check the auth server and not the file server for .sdl files. The fix would be to change all the conditions for connecting to the file server from if (!gDataServerLocal) to if (!gDataServerLocal && !gSDLLocal) I think.

This might be a purely theoretical problem - I'm not sure. All I know is that DIRTSAND-based servers usually provide the .sdl files via the file server, but I don't know if that also means that they're not available from the auth server anymore.

In any case, it's not a big concern. This fix is primarily meant for Cyan's shard, where .sdl files are available from the auth server, so the code will work correctly there.

Yeah, we never actually wrote down any sort of guidelines about how Python and SDL should be served. In my mind, you really want to serve both Python and SDL from both locations - auth and file server. UruManifest will deploy Python and SDL for both auth and file servers, regardless of server software. To be honest, though, once you start playing around with /LocalData and especially /LocalSDL, you're explicitly turning off the safety valves and saying, "Yeah, I know what I'm doing. If things go badly, it's my fault." This PR is mostly to prevent bad things from happening to other people playing alongside you with some fringe benefits for people using H'uru clients on MOULa.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my mind, you really want to serve both Python and SDL from both locations - auth and file server.

Okay - if that's the preferred/common practice, then this code is fine.

(I made a small logic error above btw: if we were to change the file server connect conditions, they should become if (!gDataServerLocal || !gSDLLocal), with a || rather than && - but that doesn't really matter now.)

@Hoikas Hoikas merged commit 47126dc into H-uru:master Aug 7, 2023
14 checks passed
@Hoikas Hoikas deleted the sdl_contract branch August 7, 2023 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants