net7/branches/linux-port/SectorServerManager.cpp
2014-05-11 16:54:16 -04:00

376 lines
9.9 KiB
C++

// SectorServerManager.cpp
//
#include "Net7.h"
#include "SectorServerManager.h"
#include "Connection.h"
#include "UDPConnection.h"
#include "ServerManager.h"
SectorServerManager::SectorServerManager()
{
// Sector servers
m_NumSectorServers = 0;
// Sectors
m_NumSectors = 0;
m_NumUnassignedSectors = 0;
memset(m_SectorAssigned, 0, sizeof(m_SectorAssigned));
memset(m_SectorName, 0, sizeof(m_SectorName));
memset(m_SystemName, 0, sizeof(m_SystemName));
memset(m_ParentSectorName, 0, sizeof(m_ParentSectorName));
m_ServerMgr = NULL;
m_ServerList = NULL;
//LoadSectorList();
LoadSectorServers();
}
SectorServerManager::~SectorServerManager()
{
// Kill all TCP/IP connections and destroy the objects
SectorServer * p = m_ServerList;
SectorServer * next = NULL;
while (p)
{
next = p->next;
//if (p->username)
//{
// delete p->username;
//}
for (short i=0; i < p->max_sectors; i++)
{
if (p->udp_connection[i])
{
delete p->udp_connection[i];
}
}
delete p;
p = next;
}
for (long i=0; i < m_NumSectors; i++)
{
if (m_SectorName[i])
{
delete [] m_SectorName[i];
}
}
}
void SectorServerManager::LoadSectorList()
{
// TODO: Load this data from an XML file
// For now, let's just load the list from a flat text file
char buffer[4096];
char filename[MAX_PATH];
sprintf(filename, "%ssector_list.txt", SERVER_DATABASE_PATH);
FILE * f = fopen(filename, "r");
if (f)
{
while (!feof(f))
{
if (fgets(buffer, sizeof(buffer), f))
{
// strip off any trailing cr/lf
strtok(buffer, "\r\n");
// ignore blank lines and records starting with a semicolon
char c = buffer[0];
if ((c != ';') && (c != 0))
{
strcat(buffer, ",,,,");
char *number = strtok(buffer, ",");
char *name = strtok(NULL, ",");
char *system = strtok(NULL, ",");
char *sector_name = strtok(NULL, ",");
if (name)
{
AddSector(atoi(number), name, system, sector_name);
}
}
}
}
fclose(f);
}
}
bool SectorServerManager::LookupSectorServer(ServerRedirect & redirect)
{
bool success = false;
// Scan through the linked list
SectorServer * server = m_ServerList;
while (server)
{
for (short i=0; i < server->max_sectors; i++)
{
if (server->sector_assigned[i] == (long) ntohl(redirect.sector_id))
{
redirect.ip_address = server->ip_address;
redirect.port = server->port + i;
success = true;
LogMessage("Sending to Port: %d\n",redirect.port);
return (success);
}
}
server = server->next;
}
return (success);
}
void SectorServerManager::AddSector(long sector_id, char *sector_name, char *system_name, char *parent_sector_name)
{
m_SectorID[m_NumSectors] = sector_id;
m_SectorName[m_NumSectors] = new char[strlen(sector_name) + 1];
strcpy(m_SectorName[m_NumSectors], sector_name);
m_SystemName[m_NumSectors] = new char[strlen(system_name) + 1];
strcpy(m_SystemName[m_NumSectors], system_name);
if (parent_sector_name)
{
m_ParentSectorName[m_NumSectors] = new char[strlen(parent_sector_name) + 1];
strcpy(m_ParentSectorName[m_NumSectors], parent_sector_name);
}
else
{
m_ParentSectorName[m_NumSectors] = NULL;
}
m_SectorAssigned[m_NumSectors] = false;
m_NumSectors++;
m_NumUnassignedSectors++;
}
void SectorServerManager::SetServerManager(ServerManager * server_mgr)
{
m_ServerMgr = server_mgr;
}
bool SectorServerManager::RegisterSectorServer(unsigned long ip_address, short port_number, short max_sectors, char *username)
{
bool success = false;
unsigned char * ip = (unsigned char *) &ip_address;
LogMessage("RegisterSectorServer at IP address %d.%d.%d.%d, port %d\n",
ip[0], ip[1], ip[2], ip[3], port_number);
// To register a sector server, the IP address must be in the
// list of authorized servers. This list may be updated by
// the user via a Web Browser using the same IP address as the
// server.
// Scan through the linked list
SectorServer * server = m_ServerList;
while (server)
{
if ((server->ip_address == ip_address) &&
/*(server->port == port_number) &&*/
(strcmp(server->username, username) == 0))
{
if (server->max_sectors != max_sectors)
{
server->max_sectors = max_sectors;
}
//LogMessage("Sector Server authenticated\n");
//success = ConnectBackToSectorServer(server);
success = true;
break;
}
server = server->next;
}
return success;
}
bool SectorServerManager::CheckConnections()
{
bool assignments_complete = true;
// Called by the Main thread in the Main Loop
// Loop through the linked list of connections to Sector Servers
// and remove those that are no longer active.
// Loop through the linked list of connections to Sector Servers
// and see if any have reached the ready state
SectorServer * server = m_ServerList;
while (server)
{
if (server->countdown_to_ready > 0)
{
server->countdown_to_ready -= 100;
if (server->countdown_to_ready <= 0)
{
server->countdown_to_ready = 0;
}
break;
}
server = server->next;
}
//g_Sector_Start = 0;
// Assign a sector to an available server if we have any unassigned sectors
// Scan through the linked list
// Do we have any available servers?
if (m_NumUnassignedSectors > 0)
{
for (long i=0; i < m_NumSectors; i++)
{
if (!m_SectorAssigned[i])
{
if (m_SectorID[i] >= 973)
{
if (AssignSectorToAvailableServer(m_SectorID[i], m_SectorName[i]))
{
//LogMessage("Assigned ID: %d out of %d\n", i, m_NumUnassignedSectors);
m_SectorAssigned[i] = true;
m_NumUnassignedSectors--;
Sleep(100); // wait 100 ms between assignments
assignments_complete = false;
break;
}
else
{
//LogMessage("Cant assign Sector: %d to server\n", m_SectorID[i]);
}
}
}
}
}
return assignments_complete;
}
bool SectorServerManager::AssignSectorToAvailableServer(long sector_id, char *sector_name)
{
//LogMessage("Looking for an available server for sector %d (%s)\n", sector_id, sector_name);
// Loop through the list of servers to find one that is available
SectorServer * server = m_ServerList;
while (server)
{
// Is this server available?
if (server->countdown_to_ready == 0)
{
unsigned char * ip = (unsigned char *) &server->ip_address;
//LogMessage("Max Sectors: %d\n", server->max_sectors);
// Found an available server
for (int i = 0; i < server->max_sectors; i++)
{
if (server->sector_assigned[i] == 0 && sector_id > 1000)
{
//LogMessage("Assigning sector to server at IP address %d.%d.%d.%d, port %d\n",
//ip[0], ip[1], ip[2], ip[3], server->port + i);
short port = server->port + i;
server->sector_assigned[i] = sector_id;
g_ServerMgr->m_UDPMasterConnection->ValidateSectorServer(sector_id, port, server->ip_address);
//server->udp_connection[i]->SendSectorAssignment(sector_id);
return true;
}
}
}
server = server->next;
}
return false;
}
bool SectorServerManager::LoadSectorServers()
{
bool success = false;
// Record format example:
//
// 192.168.1.101,3500,18,VectoR,VectoR.360,Vector.360@gmail.com,VectoR's multi-player sector server
//
// Fields:
// - IP Address
// - First Port
// - Max Number of Sectors
// - Username
// - Toon name to be listed in the credits
// - Email Address,
// - Server Description
// Read the list of usernames and passwords from accounts.txt
SectorServer * last = NULL;
char buffer[256];
char filename[MAX_PATH];
sprintf(filename, "%ssector_servers.txt", SERVER_DATABASE_PATH);
FILE *f = fopen(filename, "r");
if (f)
{
while (!feof(f))
{
if (fgets(buffer, sizeof(buffer), f))
{
// strip off any trailing cr/lf
strtok(buffer, "\r\n");
// ignore blank lines and records starting with a semicolon
char c = buffer[0];
if ((c != ';') && (c != 0))
{
strcat(buffer, ",,,,");
char *ip_address = strtok(buffer, ",");
char *port = strtok(NULL, ",");
char *max_sectors = strtok(NULL, ",");
char *username = strtok(NULL, ",");
char *toon = strtok(NULL, ",");
char *email = strtok(NULL, ",");
char *description = strtok(NULL, ",");
if (ip_address && port && max_sectors && username)
{
// Create a new entry to add to the linked list
SectorServer * server = new SectorServer;
memset(server, 0, sizeof(SectorServer));
server->ip_address = inet_addr(ip_address);
server->port = atoi(port) + 1;
server->max_sectors = atoi(max_sectors);
server->username = new char[strlen(username) + 1];
strcpy(server->username, username);
server->countdown_to_ready = 0;
server->next = NULL;
// Add this server the end of the linked list
if (last)
{
last->next = server;
}
else
{
m_ServerList = server;
}
last = server;
m_NumSectorServers++;
}
}
}
}
}
return success;
}
bool SectorServerManager::SendPacket(long sector_id, short opcode, unsigned char *data, size_t length)
{
SectorServer * server = m_ServerList;
while (server)
{
for (short i=0; i < server->max_sectors; i++)
{
// Is this the correct server?
if ((server->sector_assigned[i] == sector_id) &&
(server->udp_connection[i]))
{
LogMessage("SendPacket -- bad!\n");
//server->udp_connection[i]->SendResponse(opcode, data, length);
return true;
}
}
server = server->next;
}
return false;
}