PDA

View Full Version : Server Config Setting to Assign Port Ranges Per Zone Server


trevius
04-23-2008, 01:07 AM
The idea is to have a configuration setting to specify which ports to use for which zone server all in the World Server config. This is so the World Server knows which ports to use when loading dynamic or static zones on separate zone server, and so you can define clearly separate port ranges for each.

The new settings would look something like this:

<zones>
<defaultstatus>0</defaultstatus>
<!-- Sets port range for world to use to auto configure zones -->
<ports zonea low="7000" high="7049"/>
<ports zoneb low="7050" high="7100"/>
</zones>

With "zonea" being the name of the zone launcher set in the start.bat file (start eqlaunch.exe zonea) of the world/zone server PC and "zoneb" being the name of the zone launcher set in the zone server PC batch file (start eqlaunch.exe zoneb).

I am not a coder at all, so I don't know how hard it would be to get this change working. I think this would make setting up extra zone servers very simple. As it is now, the only way I can see multiple zone server working without any flaws are if you are running them on 2 completely separate networks with separate internet connections and IPs to allow for overlapping port ranges, or to have zones that never ever crash (unlikely).

My understanding of how ports work with multiple zone servers currently:

Basically, the world server will boot up zones on the first port available as defined in the config on the World Server PC here:

<zones>
<defaultstatus>0</defaultstatus>
<!-- Sets port range for world to use to auto configure zones -->
<ports low="7000" high="7100"/>
</zones>

It boots whatever zones are available from the launcher first. So, if you load up your zone server before loading the world, it will start loading the zones on the zone server starting at port 7000 until it has loaded all static and/or dynamic zones from the zone server. Let say you use 5 statics and 5 dynamics, so it will load the last zone from the zone server onto port 7009 (10 zones). In this case, you will need to have ports 7000 to 7009 forwarded in your router to the zone server PC. Then, you hit the enter key (or any key) in the launcher window on the world server PC to start the zones loading on the world server PC. Let say it is another 10 dynamic zones and these are loaded on ports 7010 to 7019. Again, you will need to have your router forward these ports to the world server.

So, now everything is up and working properly. Everything can work perfectly this way as long as no zones crash. If there is a crash, there is a likely chance that zones will start loading on the wrong ports of the zone and/or world server. This causes the zones to be unavailable to players.

I have a post in the support forum for trying to get this working properly, but I have come to the conclusion that it can't unless you have a separate network or some kind of port spoofing to let both PCs use the same ports.

If anyone can figure out how to make this change, I think it would be very useful. But I would gladly accept any corrections if there is a way to set this up without having issues that I am somehow missing.

trevius
04-24-2008, 01:04 AM
I am definitely no coder, but I am hoping to start learning more about it soon. I normally learn pretty quickly, but it looks like teaching myself how to write source is gonna take a while. Either way, I wanted to post some sections of the source that I think might need to be looked at to make a change in the way ports are loaded to multiple zone servers.

Again, I am not a coder, so this could all be completely irrelevant, but it is the stuff that stands out to me as being related to setting up zones on ports. Note that I only added in the sections from these files that I think might be related, so if it looks like something is missing, it is probably because I didn't know to copy it in here:


EQLConfig.cpp
if (database.RunQuery(query, MakeAnyLenString(&query,
"SELECT dynamics FROM launcher WHERE name='%s'",
namebuf)
, errbuf, &result))
{
while ((row = mysql_fetch_row(result))) {
m_dynamics = atoi(row[0]);
}
mysql_free_result(result);
} else {
LogFile->write(EQEMuLog::Error, "EQLConfig::LoadSettings: %s", errbuf);
}
safe_delete_array(query);

if (database.RunQuery(query, MakeAnyLenString(&query,
"SELECT zone,port FROM launcher_zones WHERE launcher='%s'",
namebuf)
, errbuf, &result))
{
LauncherZone zs;
while ((row = mysql_fetch_row(result))) {
zs.name = row[0];
zs.port = atoi(row[1]);
m_zones[zs.name] = zs;
}
mysql_free_result(result);
} else {
LogFile->write(EQEMuLog::Error, "EQLConfig::LoadSettings: %s", errbuf);
}
safe_delete_array(query);
}


if (!database.RunQuery(query, MakeAnyLenString(&query,
"INSERT INTO launcher_zones (launcher,zone,port) VALUES('%s', '%s', %d)",
namebuf, zonebuf, port), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in BootStaticZone query: %s", errbuf);
safe_delete_array(query);
return false;
}

safe_delete_array(query);

//update our internal state.
LauncherZone lz;
lz.name = short_name;
lz.port = port;
m_zones[lz.name] = lz;

//if the launcher is connected, update it.
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll != NULL) {
ll->BootZone(short_name, port);
}

return(true);
}


if (!database.RunQuery(query, MakeAnyLenString(&query,
"UPDATE launcher_zones SET port=%d WHERE launcher='%s' AND zone='%s'",
port, namebuf, zonebuf), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in ChangeStaticZone query: %s", errbuf);
safe_delete_array(query);
return false;
}
safe_delete_array(query);


//update internal state
res->second.port = port;

LauncherLink.cpp
std::vector<LauncherZone>::iterator cur, end;
cur = result.begin();
end = result.end();
ZoneState zs;
for(; cur != end; cur++) {
zs.port = cur->port;
zs.up = false;
zs.starts = 0;
_log(WORLD__LAUNCH_TRACE, "%s: Loaded zone '%s' on port %d", m_name.c_str(), cur->name.c_str(), zs.port);
m_states[cur->name] = zs;
}


void LauncherLink::BootZone(const char *short_name, uint16 port) {
ZoneState zs;
zs.port = port;
zs.up = false;
zs.starts = 0;
_log(WORLD__LAUNCH_TRACE, "%s: Loaded zone '%s' on port %d", m_name.c_str(), short_name, zs.port);
m_states[short_name] = zs;

StartZone(short_name);
}


void LauncherLink::BootDynamics(uint8 new_count) {
if(m_dynamicCount == new_count)
return;

ZoneState zs;
if(m_dynamicCount < new_count) {
//we are booting more dynamics.

zs.port = 0;
zs.up = false;
zs.starts = 0;

int r;
char nbuf[20];
uint8 index;
//"for each zone we need to boot"
for(r = m_dynamicCount; r < new_count; r++) {
//find an idle ID
for(index = m_dynamicCount+1; index < 255; index++) {
sprintf(nbuf, "dynamic_%02d", index);
if(m_states.find(nbuf) != m_states.end())
continue;
m_states[nbuf] = zs;
StartZone(nbuf);
break;
}
}
m_dynamicCount = new_count;
} else if(new_count == 0) {
//kill all zones...
std::map<std::string, ZoneState>::iterator cur, end;
cur = m_states.begin();
end = m_states.end();
for(; cur != end; cur++) {
StopZone(cur->first.c_str());
}
} else {
//need to get rid of some zones...

//quick and dirty way to do this.. should do better (like looking for idle zones)
int found = 0;
std::map<std::string, ZoneState>::iterator cur, end;
cur = m_states.begin();
end = m_states.end();
for(; cur != end; cur++) {
if(cur->first.find("dynamic_") == 0) {
if(found >= new_count) {
//this zone exceeds the number of allowed booted zones.
StopZone(cur->first.c_str());
} else {
found++;
}
}
}

m_dynamicCount = new_count;
}

}


LauncherLink.h
inline bool HasName() const { return(m_name.length() > 0); }
inline int32 GetIP() const { return tcpc->GetrIP(); }
inline int16 GetPort() const { return tcpc->GetrPort(); }
inline const char * GetName() const { return(m_name.c_str()); }
inline int CountZones() const { return(m_states.size()); }


If any coders get a chance to look through this stuff. It doesn't seem like it would be too hard to either add a new setting in the config xml file on the world server that lets you set ports for all zone server names or to just allow the world server to use the port settings in the config files from the xml in the world as well as in any launchers that connect to it when deciding which ports to use to create static or dynamic zones in on each launcher. As it is now, it seems that the port settings any other zone servers besides the one that the world is running on are completely pointless. But, what do I know about how difficult this would be? :x

trevius
04-26-2008, 05:47 AM
I have spoken with a few of the admins for some of the most popular servers and it seems that the only 1 I know for sure that runs multiple zone servers is PEQ, and they do it on seperate networks to allow the ports to overlap without causing issues.

If there was a way to define which port ranges are used for which zone servers, that would make running multiple zone servers something that anyone could do.

For some reason, it seems that my server is now breaking 120+ during peak times. This is causing some pretty annoying stability issues. I could probably help this by buying some very nice server upgrades, but I can't justify spending the money and I don't want to feel obligated to my players if I ask them for donations. Being able to split the load between my main server and my other PC (which is actually nicer than the server) should increase stability considerably. I tried setting it up that way for 1 night and it seemed to make a huge difference. Unfortunately the first zone to be reset was nexus (my server base) and it was restarted on the wrong port making it unavailable.

I don't want to ask anyone to put alot of time into getting this to work, but if there are any coders out there that see this and think they can make the fix in a reasonable amount of time, I think it would be a great thing for anyone running a server from home when they need it.

I am a network technician, so if there are network related questions to get this working, perhaps I can help with that part.