• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!
  • New resources must be posted under Resources tab. A discussion thread will be created automatically, you can't open threads manually anymore.

Feature [TFS 1.0] Solution for Dynamic IP hosters

rsdsebek

C++/LUA coder
Joined
Oct 8, 2008
Messages
128
Reaction score
30
Hi,
When I started hosting my server in my home not long ago, I found out, that I have Dynamic IP and I have to check if I can log in to my server couple times a day. It's well known issue - when your global IP changes, you have to restart your server in order to let other players log in, though. So I started to search for solution, and I wrote small piece of code, that checks IP of your domain (e.g. server.no-ip.org), and if IP is different than IP obtained at server startup, this code save and restarts your server. Works on pre-10.21 TFS 1.0 commits, on newest TFS 1.1 this code is unnecessary, because 10.21 client have ability to resolve host from domain name (in pre-10.21, server is sending resolved ip to client).

So let's go. All modifications are in otserv.cpp:
In otserv.cpp:
Find:
Code:
#include "networkmessage.h"
and under it add:
Code:
uint32_t previousIp = 0; //this variable is used to store your IP from server startup

Find:
Code:
void shutdown()
{
        g_scheduler.shutdown();
        g_dispatcher.shutdown();
}
and under it add:
Code:
void updateGlobalAddress()
{
    std::string ip = g_config.getString(ConfigManager::IP);
    uint32_t resolvedIp = inet_addr(ip.c_str());
    if (resolvedIp == INADDR_NONE) {
        struct hostent* he = gethostbyname(ip.c_str());
        if (!he) {
            std::ostringstream ss;
            ss << "ERROR: Cannot resolve " << ip << "!" << std::endl;
            startupErrorMessage(ss.str());
            return;
        }
        resolvedIp = *(uint32_t*)he->h_addr;
    }
    if (previousIp != resolvedIp) { //we have another IP, let's shutdown (restart) server
        struct in_addr ip_addr;
        ip_addr.s_addr = resolvedIp;
        std::cout << "> IP has changed to: " << inet_ntoa(ip_addr) << std::endl;
        std::cout << "> Restarting!" << std::endl;
        g_game.setGameState(GAME_STATE_SHUTDOWN);
    } else { //we have the same IP, executing updateGlobalAddress in 60 seconds
        g_scheduler.addEvent(createSchedulerTask(60 * 1000, boost::bind(updateGlobalAddress)));
    }
}

Find:
Code:
IpNetMask.first = resolvedIp;
IpNetMask.second = 0;
serverIPs.push_back(IpNetMask);
and add under it:
Code:
previousIp = resolvedIp; //let's store our IP from startup
updateGlobalAddress(); //call our new function

After compiling you have to change your ip in config.lua to your no-ip domain.
And that's it. From now on, if your server finds out, that your domain's IP has changed, it will save and restart itself.

Best
djseban
 
Last edited:
The code you are telling people to find has already been removed from TFS 1.0 (the IpNetMask stuff).

TFS 1.0 allows you to specify a hostname in config.lua for the "ip" config variable, so you can write "myserver.net" instead of the actual IP and if your IP changes too often you just set a low TTL on the DNS.
 
Many people like me, are forced to use protocol 9.81 (since in my project dat editor is essential tool, by this time there isn't any for 10.10+). Unfortunately 9.81 doesn't support passing IP as string to client, so there isn't any possibility to skip IP changing "feature". Anyway, thanks for feedback. I will add note in thread.

Best
Sebastian
 
Back
Top