ip in servers.cfg

Archive of the older Feature Request Forum Posts

Moderator: POL Developer

Locked
innominabile
Adept Poster
Posts: 85
Joined: Wed Aug 30, 2006 5:24 pm

ip in servers.cfg

Post by innominabile »

I have a pol server test on dynamic ip.
When router change ip or provider force change, POL remains up but is not reachable.
An autoupdate ip address in servers.cfg ?
Or load a domain in servers.cfg an not ip?
Lagoon
Grandmaster Poster
Posts: 118
Joined: Sun Mar 05, 2006 7:25 am

Post by Lagoon »

use a virtual dns provider, which tracks your dynamic ip and lets you connect to POL using the provided dns
I know only this one, but I'm sure there are plenty
http://www.dyndns.com/
innominabile
Adept Poster
Posts: 85
Joined: Wed Aug 30, 2006 5:24 pm

Post by innominabile »

Yes.... I have my own DNS fixed, but already I can use in in servers.cfg instead of ip number?
innominabile
Adept Poster
Posts: 85
Joined: Wed Aug 30, 2006 5:24 pm

Post by innominabile »

In manual is written I can only use IP.
Xandros
Expert Poster
Posts: 76
Joined: Fri Feb 17, 2006 12:25 pm

Post by Xandros »

Yes, I had the same problem. Turned out that the manual is misleading,
you can use DNS names in that file.

Xandros
Lagoon
Grandmaster Poster
Posts: 118
Joined: Sun Mar 05, 2006 7:25 am

Post by Lagoon »

you should be allowed to use a dns
Marilla

Post by Marilla »

I posted about this in another thread somewhat recently... I forget where...

You can, in fact, put a host name in servers.cfg. However, there's a BIG but - a big enough but that I'm fairly sure it's the reason the docs say you can't use a host name...


Basically, POL will accept a host name. However, we have to look at the packet in question; The one that the login server has to send the client to tell it where to connect to get connected to the game server chosen: The packet in question does NOT permit a host name. It, in fact, has four bytes set aside for the IP address, only. (this packet would obviously need to be changed for IPv6, assuming UO lasts that long :P )

This means that no matter what you put into servers.cfg, when POL sends the connect to server packet to the client, telling it where to connect to, it is sending an IP address... NOT a host name.

So far, no trouble here. When you do this, it works. Clearly, POL is able to resolve that host name into an IP, and send that IP to the client.

Here's the BUT, though:

POL only gets that information once, and stores that result, while running. So, if your IP changes, even if your Dynamic DNS info is updated, POL still has the old IP address value stored, and keeps sending it. It appears it never checks to see if the host name in question still resolves to the same IP.


(Incidentally, I seriously do not recommend running a production server off any sort of dynamic connection, no matter how you get it to work. If nothing else, it's annoying to your players to all lose connection at once when your IP changes - even if you do what I will describe below to 'fix' the problem...)


The ultimate fix for this would be for POL to either periodically, or on-demand, re-check the DNS information for the host names in servers.cfg, so that it sends current info.

Until then, however, POL 096+ can fix this, but it requires a few extra steps, and an external program or script.


Basically, you would need to hook the 0x8C packet outgoing from the server. This packet needs to be altered to make sure it is sending the correct IP address each time. Following is my test server's connect.src, which is configured to handle 0xC8

Code: Select all

use uo;
use os;

Const IPOffset := 1;
Const PortOffset := 5;
Const BUILD_SERV_PORT := 5052;
Const TEST_SERV_PORT := 5053;

program connect()
	Syslog("Hooking Server Connect Packet");
	return 1;
endprogram

exported function SendConnect(who, byref packet)
	if (!GetGlobalProperty("testing"))
		return 0;
	endif
	if (!GetGlobalProperty("iparray"))
		return 0;
	endif
	var iparray2 := array;
	var iparray := GetGlobalProperty("iparray");
	var i;
	for (i := 1; i <= 4; i := i + 1)
		iparray2[i] := Packet.GetInt8(i);
	endfor
	if (iparray2[1] == 1)
		for (i := 1; i <= 4; i := i + 1)
			Packet.SetInt8(i, cint(iparray[i]));
		endfor
		Packet.SetInt16(5, BUILD_SERV_PORT);
	elseif (iparray2[1] == 2)
		for (i := 1; i <= 4; i := i + 1)
			Packet.SetInt8(i, cint(iparray[i]));
		endfor
		Packet.SetInt16(5, TEST_SERV_PORT);
	endif
	return 0;
endfunction
The check for the Global Property "testing" is merely to make sure this code only runs on our test server. Our production server has static IPs from our colocation host, so it does not need to do this.

In our servers.cfg file, we have multiple entries; we actually have multiple 'test' servers; one for building, one for code testing. The IP addresses in the servers.cfg are simply 1.1.1.1 and 2.2.2.2 You can see the test for the first byte in the default packet... if the first byte is 1 or 2 (which would basically be invalid values otherwise), then the packet is altered with the currently set IP, and the appropriate port (the IP is the same either way because we're talking about our public IP here).


If you only had one server, you would not need to do the test of the currently set values... you could just skip to setting the IP.


But then next, what you need is code to actually SET the iparray global property. This part requires an outside program to run and check the current IP now and again, as POL has no mechanism to do this periodically, once running. (actually, it has no script mechanism to resolve host names at all).

One could write a Perl script, or a small program to run periodically and query a certain source for your current public IP address. Then, the program would need to submit that IP address to POL. Due to the ease of implementation, I used a WWW script to do mine (I never expose the WWW interface of POL to public use at all, but instead have only my own administrative programs, such as noted here, or web sites connect and cache information, as appropriate).

Anyway, here's the www script that updates the iparray global property:

Code: Select all

program UpdateIP()
	var iparray := array;
	iparray[1] := cint(QueryParam ("ip1"));
	iparray[2] := cint(QueryParam ("ip2"));
	iparray[3] := cint(QueryParam ("ip3"));
	iparray[4] := cint(QueryParam ("ip4"));
	SetGlobalProperty("iparray", iparray);
	WriteHtml ("set test server IP OK" + cstr(iparray[1]) + "." + cstr(iparray[2]) + "." +cstr(iparray[3]) + "." +cstr(iparray[4]));
endprogram
As you can tell, my program/script simply needs to call the WWW script in question with the ip1, ip2, ip3, and ip4 querystring parameters set to the bytes of the new IP address.



As for that external program itself; I included the functionality in a Windows Service that handles many other aspects of our systems; It's fairly simple code that runs on the thread pool every few minutes, triggerred by a System.Threading.Timer instance; It uses sockets to connect to a well-known resource to gather our current public IP, and then to call the test server's WWW script with the appropriate parameters, as noted above.

I would post the code to that, but it actually does more; Since it makes sense to connect the two things, the code in question also handles updating our Dynamic DNS info too; it actually stores the last IP it got persistently. When it gets the current IP, if it has changed, or if it has been long enough since the last update that our DDNS record is in danger of expiring, it also makes an HTTP request to the DDNS provider to update our info there, and then it does the aforementioned update via the POL WWW script.
Locked