Issues writing to config (ini) files from multiple servers

Discussions about Coding and Scripting
User avatar
Dizzy
Experienced
Posts: 109
Joined: Tue May 21, 2013 3:57 pm
Personal rank: Oaf
Contact:

Issues writing to config (ini) files from multiple servers

Post by Dizzy »

I have multiple UT servers running on the same physical host. They each run a mod called BTPlusPlus which uses an external config file (BTRecords.ini) to hold records about flag capture times on maps.

Ideally, all of the servers would share a single BTRecords.ini file and records would therefore be consistent across all servers.

However in practice this is not possible because when one server writes data to the file (for example when a new record is made or when the server changes maps), it overwrites the changes made by the previous server. It's my assumption that this is because of the way UT handles reading and writing config files - I'm guessing that it holds a copy of the config in memory and then every time a change is written, it dumps the whole thing out (instead of intepreting and editing the file on-the-fly).

Does anyone wiser than me know if the above is correct, and if so, if there's anything I can do about it short of creating a messy workaround using external scripts or something?
Join the BunnyTrack.net Discord chat server: https://www.bunnytrack.net/discord
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Issues writing to config (ini) files from multiple serve

Post by nogardilaref »

The engine doesn't actually persist the ini file itself in memory, it just loads it once, and only once (when the class is loaded in some way), and by doing so the file is parsed at that time only and all of its values are assigned to the defaults of the class, then it just disappears as all the values are now loaded into the class itself.

Then on save, it simply overwrites the file with all the current class default values (StaticSaveConfig) or the current class instance values (SaveConfig).
You can read all about it here: https://wiki.beyondunreal.com/Legacy:Co ... .Ini_Files

I think, however, that on map change the ini is reloaded as packages are unloaded and loaded back again, but don't quote me on this as I might be utterly mistaken.

If this holds to be true though, I think the only thing you can do is to build a mod, in which you can have a main class and 3 subclasses, each one with their own ini file, one for each server.
Then in each server you only write to one of them, but read from all 3 on map change.

From there, in the same mod, you can have yet another class, which is going to serve as a server actor, which acts as the driver to transfer data from BT to your other classes and vice-versa.
These 3 classes will act as a sharded database, and whenever you need to load things up, to just have to sum them, average them, check the maximum or minimum, whichever operations make sense to you in the kind of data you're loading, merging and saving.

This way, regardless of what and where BT itself saves stuff becomes irrelevant, as the info is sharded by 3 different other ini files in your own control.


Another, cleaner but more complicated, way, is to do something similar, but instead of loading and saving into local ini files, you can build a web server and have your mod communicating with it.
This way you can have as many servers as you want, but it requires you to look into how UT handles HTTP requests (it's not hard really) and to build a web server somehow in another language (maybe PHP, Java, C#, Javascript, Lua, or something else entirely).
It all goes down to what you already feel comfortable with and what you want to pursue. :)
User avatar
Dizzy
Experienced
Posts: 109
Joined: Tue May 21, 2013 3:57 pm
Personal rank: Oaf
Contact:

Re: Issues writing to config (ini) files from multiple serve

Post by Dizzy »

Thank you @nogardilaref. I'm very interested in storing the config remotely as you suggest (I'm a web programmer) but haven't had time to fully investigate yet.

Two questions:

1. Is LibHTTP the library to use for HTTP requests?
2. Does it support HTTPS?
Join the BunnyTrack.net Discord chat server: https://www.bunnytrack.net/discord
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Issues writing to config (ini) files from multiple serve

Post by nogardilaref »

Dizzy wrote: 1. Is LibHTTP the library to use for HTTP requests?
I don't know, I never tried to use a lib before in UT.
Doing HTTP requests from UT is rather easy though. Not as easy as you would find in other languages, and maybe the lib you mentioned actually makes it easier, but still easy nonetheless.

All you have to do is to look into the UBrowserHTTPClient class.
The requests are asynchronous (as they should be), so you have a method to make the request (Browse, I think), then 2 other methods which are events fired when you receive the response (HTTPReceivedData and HTTPError).

Probably there are other ways to do HTTP requests in UT, given that there are other classes to establish remote connections, but this was the first one that came to mind.
It works fairly well also, and in terms of the usual limits UT has, I think my last experiment (several years ago) has shown that you could retrieve a response of up to around 16KB, but I am not sure about the number anymore (I tried gigantic JSON responses back then to check where it would cut off).
Dizzy wrote: 2. Does it support HTTPS?
I don't know that either for sure, however it's very unlikely that it does.
At most, you can make HTTPS requests, but internally they will just fallback to regular HTTP ones, specially since HTTPS wasn't really a thing until later in the 2000's.

Even if it does support it, it's even more unlikely that it uses anything newer than SSLv3, since TLS1.0 was only specified in the same year the game came out, and a lot of the engine is still the same as when they released Unreal back when only SSL existed.
Even Android smartphones released up to 2011 didn't support TLS for HTTPS.
And even if it does use SSL, it's completely useless anyway to protect you from man-in-the-middle attacks, given the POODLE exploit found in it back in 2014, which made nearly every service disable the support for up to SSLv3 immediately after it was found.

Therefore I think you can forget about proper HTTPS support, at least without involving some native coding where you can use stuff like cURL and OpenSSL.

But, I don't think you need a great deal of security for something like this. It's an almost 20-year old game, without many players left, and you're just going to store statistics in a hidden fashion from the player anyway.
At most, you just need to setup a secret key in both the web server and your servers, to validate the requests between the servers, so even if someone guesses your endpoint, they cannot do anything with it.

If you think that you must absolutely have as much security as you possibly can anyway, without resorting to native modding, it's possible although you would have a some work to do.
In this case you could implement both HMAC and RSA using UScript.
Then you could generate a private key that would be in your web server and store the public one in your UT servers, this way you would get the same level of security as you would get from a SSH connection, which would be pretty much equivalent to an HTTPS connection (RSA part).
Then you could also set up a secret key to use for the HMAC generation for the data you're going to send back and forth, so that way you get authentication and data integrity checks at the same time. A common way of doing this nowadays is using a format called JWT (JSON Web Token), which boils down to a simple and uniform way of using HMAC.

I don't think you can get it more secure than this, but I think it would be overkill for what you want to do.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Issues writing to config (ini) files from multiple serve

Post by JackGriffin »

Diz, I'm telling you from experience that hooking multiple UT servers to a remote webserver is possible but it's a real headache. The engine does not handle it well which isn't surprising. It was made during the days of dial up. No one had any idea homes could have the speeds they do today. The webserver can easily flood the game server with requests and cause it to die. I had ideas of making a DayZ type game that used a remote webserver to track player data, allowing a persistent experience if you left the game and came back. I had the mod fleshed out but trying to handshake with a webserver was a real pain in the ass. Now admittedly this is at the fringe of my ability and someone with more experience could likely work it out better but to me it's obvious that recoding your mod is the better idea. Just have it store the data in such a way that each server is identified within the ini like this:

BestTimes(0):7777,23.11
BestTimes(1):7797,24.31
BestTimes(2):7767,25.25
BestTimes(3):7787,26.02

...where the first part is the port number of your reporting server. You could use anything here as long as it use unique, in fact it may be easier to add an identifier into the mod itself that you could use as the variable. The second part is the actual value you want to save. It would be easy to ignore the first part and reorder the ini using the second value.

As an aside you still have enough people playing to need multiple servers? I'd figured the game would be just dead as a doornail by now.
So long, and thanks for all the fish
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Issues writing to config (ini) files from multiple serve

Post by sektor2111 »

8) The same physical host here running 4 servers (not all at once but is doable by setting up ports - I don't need all at once) but having different MapVote config (two running DM CTF - two running MH MH2 MA) by example, using... the same MapVote type and even package file. Is that hard if you have control over entire machine ? Nope, is easy as a pie.
I'm speaking about a "shared" structure having everything in common except... INI INT DLL EXE locations which are separate in 4 folders, each is located in its own place but using the same UnrealShare UnrealI, Botpack, generally all stock files except, ignition related files.
So to speak UT is very capable of reading stock needs from OUTSIDE of "Sand-Box" and also logs are written in the same way out of Sand-Box in web sharing place, so I can access chat-logs even if I'm not at home - but I don't need to do this.

If you want the same INI this means your mod has ONLY to read that and not writing/saving it or else will affect ALL servers and/or will interfere with the rest of serves handling the same INI. File opened is protected to prevent data corruption if two things are trying to save a different setup. I think is not a good idea to have ONE INI used in 4 servers - I go for multiple INI files but used by the same Package - this is doable and safe and it take less disk space. Each INI being dedicated to a single purpose allowing you to have 2 different settings.
User avatar
Sp0ngeb0b
Adept
Posts: 376
Joined: Wed Feb 13, 2008 9:16 pm
Location: Cologne
Contact:

Re: Issues writing to config (ini) files from multiple serve

Post by Sp0ngeb0b »

I would suggest holding the record data (if that's what you are talking about) inside a sql database, which can be accessed by the gameservers via a simple http request and a php script. You need to make sure to keep it in sync though - so fetch the events in game (new record for example) and push it to the database and access the data you need during the game (that would be one record for the current map for example). You could even use UT's webserver features to provide syncing in the other direction, so that the php script pushes the updated entry to the other gameservers.
Website, Forum & UTStats

Image
******************************************************************************
Nexgen Server Controller || My plugins & mods on GitHub
******************************************************************************
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Issues writing to config (ini) files from multiple serve

Post by sektor2111 »

In shared structure there is not needed any PHP, everything goes too simple. I'm not even using any WebServer actor.

Post Note: Entire structure might have a backup on a single USB stick - this is what I have.
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Issues writing to config (ini) files from multiple serve

Post by nogardilaref »

JackGriffin wrote:Diz, I'm telling you from experience that hooking multiple UT servers to a remote webserver is possible but it's a real headache. The engine does not handle it well which isn't surprising. It was made during the days of dial up. No one had any idea homes could have the speeds they do today. The webserver can easily flood the game server with requests and cause it to die. I had ideas of making a DayZ type game that used a remote webserver to track player data, allowing a persistent experience if you left the game and came back. I had the mod fleshed out but trying to handshake with a webserver was a real pain in the ass.
Actually it doesn't really matter how many years passed by, HTTP is still HTTP, it still works pretty much the same way it worked ages ago, with just new features nowadays.
The increase in speed/bandwidth or the decrease in latency has no barring in how things work, even because I imagine this sort of thing to have been tested first pointing towards the developer's own machine (localhost), just like any web developer always did even at that time.

As for the part I bolded in your quote, I cannot really understand how that would even be possible at all.
You're probably misunderstanding what a webserver actually is and is supposed to do, and maybe even misused it.
You don't receive requests from a webserver, you make requests to it, it's a completely different direction of communication here.
At most, your problem would be flooding the webserver itself from the actual game server, and not the other way around.

The only problem I can imagine happening when making HTTP requests from UT is what the actual webserver expects and what it responds.
But, if the webserver is yours, you're in complete control of what it does and how it does something, so there shouldn't be any problem at all.

Some years ago I did an experiment as I mentioned above, using only the classes UT itself still currently offers, where I made requests to all sorts of services and domains, one of them being google itself for instance, and another to my own localhost and even to public APIs that I made for the company I work for.
It always worked flawlessly in all of my experiments, including when I requested a rather huge JSON file.

The only problem I found was: when it exceeds a certain size, UT simply cuts off the response at one point, which I imagine it's when it exceeds the max buffer size of what it expects, and here yes, the speeds from back then compared to today certainly influenced how large this buffer would be. But it's still quite big, and it's not a show stopper in my opinion.
There is another limitation such as not getting access to the response body if the HTTP status code is of an error (4xx and 5xx), which means you cannot implement RESTful communication as "by the book", but you can still work around it.

This leads me to believe that, if set up correctly, you can actually make UT to work with a webserver rather smoothly.

EDIT: Scratch the red part, I just checked the HTTP class again, and you can customize it to behave differently when dealing with errors, so that's not a problem either.
It considers anything different than a 200 HTTP status code as an error, which is stupid, as only 4xx and 5xx codes are errors, but this can be overridden and handled differently too it seems.
Last edited by nogardilaref on Wed Jul 26, 2017 7:27 pm, edited 2 times in total.
User avatar
Sp0ngeb0b
Adept
Posts: 376
Joined: Wed Feb 13, 2008 9:16 pm
Location: Cologne
Contact:

Re: Issues writing to config (ini) files from multiple serve

Post by Sp0ngeb0b »

sektor2111 wrote:In shared structure there is not needed any PHP, everything goes too simple. I'm not even using any WebServer actor.

Post Note: Entire structure might have a backup on a single USB stick - this is what I have.
It appears to me that you misunderstood Dizzy's goal here; it's not about efficient resource sharing, but about one central database (he asked for a single .ini file, I suggest an external sql one) which the gameservers can read and write to simultaneously. As stated by nogardilaref, this is not possible via the .ini file due to the way the UnrealEngine handles config reads and writes.

@nogardilaref:
There exist quite a lot of mods out there who are pairing up with a Webserver via HTTP requests. IpToCountry, UTStats in-game viewer, and UniversalUnreal just to name a few.
Website, Forum & UTStats

Image
******************************************************************************
Nexgen Server Controller || My plugins & mods on GitHub
******************************************************************************
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Issues writing to config (ini) files from multiple serve

Post by sektor2111 »

Then apology if I miss-understood title of thread, because I gave a sample of 1 U package file reading 4 INIs not 4 U package files reading 1 INI file. For me is way spending to host 4 the same Botpack since a single Botpack can be loaded for multiple servers.
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Issues writing to config (ini) files from multiple serve

Post by JackGriffin »

@nog:
Dude, I'm completely sure you know way more than I do especially when it comes to remote database linking. I'm just a mailman who happened to like scripting and never did formal training. Of course I fucked some things up (and enjoyed every minute!). I'm just telling you what our experience was in getting UTrustedPlayer off the ground and stable. Having the server poll a remote db after a match is over or before the server completely loads is no big deal. However when you try to access as the game is running it can easily crash the server. We had to build timeouts into the uscript to allow the transfer of information because it just doesn't work consistently and stably if you try to go on the fly. You'll have to excuse that I'm trying to pull memories from before treatment so it's all sketchy at best but IIRC if uscript requested data from the db and did not get some sort of return it would crash the server. Dane said that it couldn't have a null value return because the engine could not account for that. He had to build in safeguard returns to trigger in place of failed queries to prevent any problems. It never worked right 100% of the time and so we were never really satisfied no matter what we tried.

Mind you we were using a very simple interface as there only needed to be a player check to see if they matched any entries in the database. That single returned value was handled then by the mod code, good or bad. I'm not sure how it could have gotten any more streamlined than that but it was just never right.

I have no idea how UTStats or those other programs do their thing. I'm just relaying how we tried to work it out and what we encountered as we went along.
So long, and thanks for all the fish
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Issues writing to config (ini) files from multiple serve

Post by nogardilaref »

@JackGriffin: I hope you're not misunderstanding my own attitude towards what you said.
I am not trying to say that I know more or less than you, what I am attempting to do here is to try to find out why you're saying that it simply doesn't work well, and why you are so strongly discouraging Dizzy from using this approach.
I apologize if I came across the wrong way.

The fact that you're a mailman and I happen to be a web programmer, doesn't detract at all from the fact that we can actually have a very productive exchange of information here so we can both understand what went wrong.
In my life, I have met a ton of enthusiasts who are better programmers than many professionals will ever be (plus, I never had any "real" formal training either, the vast majority of my current knowledge came from experience and self-learning too, but I happened to actually be able to do it for a living), and although I don't know that yet, you might as well even be one of them too. :wink:

Case in point, based on your explanation alone, it seems to me that you guys went the wrong way about dealing with webservers in the first place, specially when you mentioned that the webserver itself would cause the game server to crash by just flooding it with requests, and one of the first things I tried to highlight is that that's not how a webserver is even supposed to work, a webserver doesn't make requests, it only receives them.

When you said this, it gave me a clue that you guys might have done the wrong setup. Or maybe you did it right and are simply mixing things up right now by how long ago you last looked into it (which happens to me as well), or maybe it's me who's really missing something here.
But I would like to get the bottom of this, so, if possible at all, could you share the source code of what you guys attempted to do?


Looking at the class itself I experimented with years ago, from UT itself, it seems that you actually are able to have complete control of what is sent to any server and how you receive it.
All UT itself does is to build the HTTP request from the ground up, using UScript alone, which is awesome since it means we can build our own HTTP client from ground up, and it's not hard at all to do it.
It also means that we could go as far as implementing things like HTTPS, and even other protocols to communicate directly with stuff like SMTP for sending mails, or even communicate directly with a local Redis for shared memory.

But there's a catch: it seems that UT has predefined ways of how it expects the communication to be made, and one of the things which must be defined is if you expect binary communication or text-based communication.
However, UT represents the most raw form of data through strings, just like many languages, however unlike them, the strings in this engine are NULL-terminated, meaning that the moment you put a NULL character in the middle of the string, it will either just discard the rest of the string, or might even crash through segmentation faults, or even have a memory leak which ends up crashing the whole thing as well.

In other words, it might be possible for a webserver to crash a server by sending a NULL character somewhere in its response, and you won't be able to see the bastard.
But in case binary data is required to be sent back and forth, you can simply encode the data into Base64. It will make the data bigger, but it will be text alone so it's fine.
Or even JSON, which escapes all binary sequences, and which would turn NULL into "\x00", but this would be even larger than Base64.

Sp0ngeb0b wrote: @nogardilaref:
There exist quite a lot of mods out there who are pairing up with a Webserver via HTTP requests. IpToCountry, UTStats in-game viewer, and UniversalUnreal just to name a few.
Yeah, I knew about IpToCountry and UTStats, didn't know about UniversalUnreal. Thanks for the info. :tu:
JackGriffin
Godlike
Posts: 3774
Joined: Fri Jan 14, 2011 1:53 pm
Personal rank: -Retired-

Re: Issues writing to config (ini) files from multiple serve

Post by JackGriffin »

I have the source code on a backup drive, I'll see if I can dig up the relevant class this weekend.

I'm not sure how we could have gone the wrong direction. The setup was as simple as having a remote DB with a list of players sorted according to ACE identification. Joining players were checked against the list and it returned whether the player matched against any entries. If they did not then the player saw nothing and continued on. If the return was a positive then the player was prevented from being able to join. The DB also returned a ban number if the person matched and this number was sent to the rejected player via console. This allowed for an appeal/explanation process as well as allowing for temporary bans.

The flooding part happened when a match would begin in a packed server. If you got 12 people all getting ACE checks then having those get submitted all at once to the remote DB, well as you already know the DB can handle that. The server can't and it would often crash from trying to handle the incoming information. When we stopped pursuing UTP we were in the process of trying to do the requests in order, one at a time over time. The entire project was stopped because ACE cannot clearly identify someone despite what the common consensus is about it's ability. Tools exist that can easily spoof all the identifying information that ACE gathers so UTP became a pointless exercise.

I've seen what you are talking about, that people can field test a server and get these really nice returns from a remote host and it all seems good. What I'd really be impressed with is seeing those same test occurring on a server with 10 other players while a game is going on. It was my experience that it's hugely different and the engine becomes more sensitive by an order of magnitude.

I know others use this method for banning and I'd be curious what their experience with it is too. I compared notes and code with a couple of other admins as we were working this out and they also had the same experiences.

You know, Smirf would be someone to really chime in on this as he did a lot of work on the interface for Unreal 227 to make it more stable. He could probably line out the limitations pretty well.
So long, and thanks for all the fish
User avatar
Sp0ngeb0b
Adept
Posts: 376
Joined: Wed Feb 13, 2008 9:16 pm
Location: Cologne
Contact:

Re: Issues writing to config (ini) files from multiple serve

Post by Sp0ngeb0b »

Just adding a small note regarding communication with remote servers: Remeber that UT has build-in UDP- and TCP-Link Classes which can be used as well. Although I remember people complaining about them, and I believe there has been a completely overworked native TCP-Link version (inside ACE iirc), I personally have used the default UBrowserBufferedTcpLink class for communication with Teamspeak 3 servers without any further issues. This also worked for lots of commands sent on game start, I implemented a simple queue to handle the communication. Of course, this requires some attention syncronizing the data flow inside the UScript mod, but it is definitly possible with default UT netcode.
Website, Forum & UTStats

Image
******************************************************************************
Nexgen Server Controller || My plugins & mods on GitHub
******************************************************************************
Post Reply