FlashpointProject / FlashpointProxy

This library sets up a process to connect to the Flashpoint Server via both the HTTP and FTP protocols upon being loaded in the process.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow for configuration of port proxy lives on

clarjon1 opened this issue · comments

I've run into a usecase where Windows itself has decided to listen on port 22500

image

image

image

I have been informed by Nosamu thru the help section in discord that although some components allow for port configuration, the proxy itself has it hardcoded so I'm unable to use this software due to the hardcoded port requirement, and my OS itself holding the port in use.

Preferably, I feel that this should be able to be tied into a feature to be added to the launcher, which would allow an end user to change the port, likely in the Advanced section close to the Server drop down.

As I was writing this up, oblivioncth added this info:

It's strange, it's such an oddball port too. The mounter plugin is also hardcoded to handle the requests over 22501, while that may not be an issue for you specifically if only 22500 is being occupied. If 22500 becomes configurable, then the HTTP/HTTPS ports probably should be reconfigurable as well.

I don't think the ports are actually hardcoded on the proxy's end, there's command line arugments for each of them:
https://github.com/FlashpointProject/FlashpointGameServer/blob/81c46bba2d37646ad0cfb67ccacd9299800eda04/main.go#L83

While I'm sure there's something else I'm forgetting, the main thing would be changing the launcher and mount plugins to read the ports as a proper preference. Currently since they're just part of the launch parameters in services.json there isn't a good way to parse the directly, but of course a regex or the like could be used.

At the very least if the arguments in services were changed to:
"arguments": [
    "-legacyHTDOCSPath=\"Legacy/htdocs\"",
    "-gameRootPath=\"Data/Games\"",
    "-phpCgiPath=\"Legacy/php-cgi.exe\"",
    "-rootPath=\"<fpPath>\"",
    "-proxyPort=22500",
    "-serverHttpPort=22501",
    "-serverHttpsPort=22502"
]

and the mounter extension read the HTTP port by pulling it from the corresponding argument, one could edit the ports within services.json directly and have things work.
If they were to become preferences, then a new macros like might need to be made, such as , etc so that they can be subbed in from preferences.json.

Of course, this leaves out the server port as well (22600) which then would also need to be made configurable since it doesn't really make sense to have only some of the ports configurable.

Using the extra parameters for the proxy in services and un-hardcoding the HTTP port in the mounter extension is probably a good start. Making this happen would probably need to be done in small steps.

That is correct, currently the port is a hardcoded string. The primary difficulty with adding any functionality to Flashpoint Proxy is that it runs on DllMain, so it can't be doing anything too complex because the loader lock is held when it runs. As such, I'd like to avoid any sort of complex parsing of JSON or XML etc. if possible. A simple call to ReadFile to read in a number would work though.

I can foresee one other potential issue which is that the working directory is not necessarily always going to be the same folder that Flashpoint Proxy's DLL is in. Particularly for plugins the working directory would likely be Flashpoint Navigator's folder since the host application is in there, so the config would need to be there, even though that placement is not necessarily intuitive.

Flashpoint Secure Player also uses (a C# port of) Flashpoint Proxy and it's also hardcoded there, so it'd need to be updated as well. I'm working on some other stuff right now but will see about getting around to this later this week.

While being able to change the port at all is a good start, it would be of course be best to be within preferences.json so that one doesn't need to edit the port number in multiple files and user editable configuration remains centralized (and it avoids the Launcher needing to parse/store an additional field outside of its preferences structure.

For the file itself, could you not do a "dumb" parse?

  1. Read all of preferences.json at once
  2. Search for "proxyPort" or whatever the name of the preference is
  3. Search for the comma or linebreak following that position.
  4. Do simple index arithmetic to pull the port between the : and , of the main preferences object (stripping whitespace/quotes as needed)

I don't think this would take too much time. MS docs imply that basic config loading/parsing within DLLMain can be acceptable.

Some initialization tasks cannot be postponed. For example, a DLL that depends on a configuration file should fail to load if the file is malformed or contains garbage. For this type of initialization, the DLL should attempt the action and fail quickly rather than waste resources by completing other work.

While it of course relies on preferences.json to be valid JSON, Flashpoint would have many problems if it wasn't.

As for the problem of locating the file itself due to inconsistent working directory, that is more tricky. Since preferences.json is always at the root of the install, you could traverse parent directories of the current working directory/DLL directory, checking for existence of the file at each depth until you hit the root, though I could see polling the filesystem multiple times like that potentially taking too long for something within DLLMain, though maybe not since its just checking metadata and not file contents.

Alternatively, while this also makes some assumptions, I think it's reasonable as some always need to be made in a situation like this:

All uses of FlashpointProxy.dll are somewhere under FPSoftware. That folder is a staple of the distribution's layout and doesn't seem like it will change any time soon, so in theory one can easily derive the location of preferences.json using that as a landmark. For example:

DLL Location: D:\FP12\FPSoftware\Netscape4\Communicator\Program\Plugins\FlashpointProxy.dll

  1. Get the current working directory or directory of the dll itself
  2. Search for "FPSoftware" within the string
  3. Truncate the string starting at that index, down to D:\FP12\
  4. Append "preferences.json" to get the full path to the file D:\FP12\preferences.json

For the DLL itself I know C# has System.Reflection.Assembly.GetExecutingAssembly(), and it seems like for the C version you can exploit GetModuleHandleEx to figure out the DLL path. Though of course GetCurrentDirectory() is likely sufficient anyway.

Is this all really necessary? The proxy port is already not centralized as it currently stands; both SPR and Flashpoint Navigator store it separately. At a bare minimum changing it Flashpoint-wide requires changing the Firefox configuration, which could be difficult for the Launcher to automate. I certainly don't want to have to modify SPR to read the proxy out of a JSON file from Lingo, which doesn't have so much as support for regex, never mind JSON. (it might be possible if the file could be swapped for XML, which it does have native support for, but I'm guessing that's too much to ask.)

*I'm definitely not going to do a "dumb read" of the JSON, if it is determined that this is absolutely required then I am figuring out a way to do it properly regardless of the loader lock issue. I don't do things halfway. I have up to this point deliberately avoided needing to parse JSON from a C++ program because that just sounds like pain, but if I have to then I will find some library that does it in such a way as to not cause loading issues.

To be fair this is quite a rare issue, so maybe it isn't worth it. Yes right now the port number is set all of the place and not at all centralized. My point was that if the goal is to make the service ports user-configurable, the "right way" is to centralize the ports within preferences.json, despite that undoubtedly requiring significant tweaks to the existing setup.

It would still be beneficial to at least un-hardcode the port here in whatever way you see fit so that the few users that are stuck with a problem like this can work around it, even if they need to root around their install to change the port in multiple places.

I'll I'm saying is that in the long run I think deriving the ports from a single location is the right move, even if it isn't feasible right now. Migrating each component to read from the centralized location one at a time as possible is likely the way forward. Adding the preference for the launcher to use is the easiest part. At first it will be "useless" as it will have to remain set to 22500 due to the other tools being hardcoded, but if we can slowly migrate to using it everywhere then eventually we can achieve centralization.

I'm not saying it's absolutely worth perusing, but it would definitely be the ideal.

*I'm definitely not going to do a "dumb read" of the JSON, if it is determined that this is absolutely required then I am figuring out a way to do it properly regardless of the loader lock issue. I don't do things halfway.

I agree that it's best to do things the proper way when possible, I also hate bodging. I've implemented entire parsers just to tweak a single value in one file and then never really use the parser for anything else; however, the right way in this case is indubitably slower what I suggested. That suggestion was just an idea for if you wanted to prioritize speed over everything else, which sometimes you have to do.

Regardless, I think parsing such a simple JSON file with a lightweight JSON library could still easily be plenty fast. There are many out there. Some that come to mind (1) (2).

If you're open to the idea but question if it's worth your time, I'd be open to PR'ing this if you are, though I'd want to know if @colin969 is open to the idea of trying to move the ports to preferences.json over time in the first place.

EDIT:
Actually even simpler, it may just be possible for the launcher to set the port as an environment variable used when creating all child processes so you can just grab it from the environment.

This was all prompted off this feature request due to the users issue. I was just trying to run with it somewhat, I don't even know if Colin or anyone else other than nosamu is aware yet.

The alteration you suggested for now I think is fine just to get something off the ground so that this user can work around their problem by altering the port; however, you likely missed my last edit since you were looking at this via your email.

Would it not actually be the simplest and most flexible if the Launcher just populated an environment variable with the port in question for all child processes so that you can just pull the port from there via GetEnvironmentVariable()? Then you don't even need a file at all. The launcher already does this for some tooling (possibly only on Linux) by setting an FP_PATH variable with the root of the installation. It would be trivial to add another like FP_PROXY_PORT. I imagine this would greatly simply things for SPR as well.

If for some reason that's a problem, worst case scenario I'm sure that the launcher could be tweaked to update the simple config file you're asking for in response to the preference value changing.

An env var would work good, actually, if that change could be made to the Launcher. Might actually be easier than reading from a file. I could probably add support to SPR also (I think there's an Xtra I could use to get an environment variable there.)

Frankly this just won't happen.

The odds of this happening are already so slim this is the first time it's come up in 5 years.

Making the port configurable means somebody has to write functions to change this for a dozen+ pieces of software across 3 different operating systems.

This would mean env vars, modifying many configs and live patching of executables which any anti virus would demolish us for.

Even if it can't be completely centralized, could the env var still be set for Flashpoint Proxy specifically and whatever else could be trivially made to support it? It would still be sparing us having several TXT files around for every instance where Flashpoint Proxy is used. If the concern is that users will expect that to affect everything then it doesn't have to be exposed in the Config tab, but it would still simplify things for our own development purposes

You can't do it for flash games, that says enough.

Well, alright then. I don't think it would've been bad to have this just be a Flashpoint Proxy specific environment variable, but in that case I'll do this the original way I intended. I'll have Flashpoint Proxy read out of a file in it's working directory. The env vars idea will not be used, and each instance of Flashpoint Proxy can have a text file next to it to change its port number (falling back to the default of 22500 if it's not there.)

Edit: maybe I could just check for both an environment variable and a file, in case you guys ever change your minds? I don't think it would be too slow if it's just checking for a single file's existence. The file could take priority so that the ports for components could be individually overridden, and if neither option is used it'd just fall back to the current behaviour of using port 22050.

I figure I might as well just add it so that it's flexible, and then it's in your guys ballpark to decide whether or not to use it, because reading a file and checking an environment variable is easy and will take very little time to add in

Okay, I've made a couple new commits (still not tested very heavily yet, will do that sometime this week) that add this new feature. Here is how it works:

-it will look for two files, proxy.txt and port.txt, in the current working directory (not necessarily the DLL's directory)
-these files are in the same format as SPR's existing setup - proxy.txt contains 0 or 1, and will disable or enable the proxy. port.txt contains the port number.
-if the file isn't found, it will get the environment variables FP_PROXY and FP_PROXY_PORT. These are expected to contain the same contents as proxy.txt and port.txt respectively: 0 or 1 for FP_PROXY, and a port number for FP_PROXY_PORT.
-if the environment variables aren't found, then it will fall back to the defaults. The proxy will be enabled on port 22500, so this whole system is optional if you guys don't want to use it.

In Flashpoint Secure Player it works slightly differently, instead of searching for a proxy.txt and port.txt it'll expect a tag to be added to FlashpointSecurePlayer.config like this (I've very deliberately avoided using a StreamReader anywhere in Flashpoint Secure Player as AVs tend to heavily flag that, so it has to be in it's config instead)

<flashpointSecurePlayer>
  <flashpointProxy proxy="true" port="22500" />
</flashpointSecurePlayer>

I plan on finishing the new version with this feature either tomorrow or the day after.

I appreciate the effort as at the very least just getting closer to centralizing the value is itself a benefit, and perhaps one day we can get all the way there, even if right now it's a pipe dream.

I have now added a new feature to Flashpoint Proxy to do this which works exactly as previously described. An update to Flashpoint Secure Player will soon follow. Although this is a minor change in the grand scheme of things, Flashpoint Proxy is a heavily used component and this is the most significant change to it in a long time, so I would suggest a slow rollout starting with the smaller plugins rather than putting it on Flash for everyone right away. However it is up to you guys to decide.

The new preferences are entirely optional, so all that is required to upgrade is to replace the FlashpointProxy.dll file in place. Setting the environment variables or creating the text files is not a necessity.

Forgot to close this, but this feature was added in 1.2.