Ejemplo n.º 1
0
bool ClientList::SendPacket(const char* to, ServerPacket* pack) {
	if (to == 0 || to[0] == 0) {
		zoneserver_list.SendPacket(pack);
		return true;
	}
	else if (to[0] == '*') {
		// Cant send a packet to a console....
		return false;
	}
	else {
		ClientListEntry* cle = FindCharacter(to);
		if (cle != nullptr) {
			if (cle->Server() != nullptr) {
				cle->Server()->SendPacket(pack);
				return true;
			}
			return false;
		} else {
			ZoneServer* zs = zoneserver_list.FindByName(to);
			if (zs != nullptr) {
				zs->SendPacket(pack);
				return true;
			}
			return false;
		}
	}
	return false;
}
Ejemplo n.º 2
0
void handle_rc_relay(const std::string &method, const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &params) {
	std::string error;
	std::map<std::string, std::string> res;
	uint32 zone_id = 0;
	uint32 instance_id = 0;
	ZoneServer *zs = nullptr;
	
	if(params.size() < 2) {
		error = "Missing zone relay params";
		RemoteCallResponse(connection_id, request_id, res, error);
		return;
	}
	
	zone_id = (uint32)atoi(params[0].c_str());
	instance_id = (uint32)atoi(params[1].c_str());
	if(!zone_id && !instance_id) {
		error = "Zone not booted";
		RemoteCallResponse(connection_id, request_id, res, error);
		return;
	}
	
	
	if(instance_id) {
		zs = zoneserver_list.FindByInstanceID(instance_id);
	} else {
		zs = zoneserver_list.FindByZoneID(zone_id);
	}
	
	if(!zs) {
		error = "Zone server not found";
		RemoteCallResponse(connection_id, request_id, res, error);
		return;
	}
	
	uint32 sz = (uint32)(request_id.size() + connection_id.size() + method.size() + 3 + 16);
	uint32 p_sz = (uint32)params.size() - 2;
	for(uint32 i = 0; i < p_sz; ++i) {
		auto &param = params[i + 2];
		sz += (uint32)param.size();
		sz += 5;
	}
	
	ServerPacket *pack = new ServerPacket(ServerOP_WIRemoteCall, sz);
	pack->WriteUInt32((uint32)request_id.size());
	pack->WriteString(request_id.c_str());
	pack->WriteUInt32((uint32)connection_id.size());
	pack->WriteString(connection_id.c_str());
	pack->WriteUInt32((uint32)method.size());
	pack->WriteString(method.c_str());
	pack->WriteUInt32(p_sz);
	
	for(uint32 i = 0; i < p_sz; ++i) {
		auto &param = params[i + 2];
		pack->WriteUInt32((uint32)param.size());
		pack->WriteString(param.c_str());
	}
	
	zs->SendPacket(pack);
	safe_delete(pack);
}
Ejemplo n.º 3
0
void Adventure::SetStatus(AdventureStatus new_status)
{
	if(new_status == AS_WaitingForPrimaryEndTime)
	{
		status = new_status;
		safe_delete(current_timer);
		current_timer = new Timer(adventure_template->duration * 1000);
		database.SetInstanceDuration(instance_id, adventure_template->duration + 60);
		ServerPacket *pack = new ServerPacket(ServerOP_InstanceUpdateTime, sizeof(ServerInstanceUpdateTime_Struct));
		ServerInstanceUpdateTime_Struct *ut = (ServerInstanceUpdateTime_Struct*)pack->pBuffer;
		ut->instance_id = instance_id;
		ut->new_duration = adventure_template->duration + 60;

		pack->Deflate();
		zoneserver_list.SendPacket(0, instance_id, pack);
		safe_delete(pack);
	}
	else if(new_status == AS_WaitingForSecondaryEndTime)
	{
		status = new_status;
		safe_delete(current_timer);
		current_timer = new Timer(1800000);
		database.SetInstanceDuration(instance_id, 1860);
		ServerPacket *pack = new ServerPacket(ServerOP_InstanceUpdateTime, sizeof(ServerInstanceUpdateTime_Struct));
		ServerInstanceUpdateTime_Struct *ut = (ServerInstanceUpdateTime_Struct*)pack->pBuffer;
		ut->instance_id = instance_id;
		ut->new_duration = 1860;

		pack->Deflate();
		zoneserver_list.SendPacket(0, instance_id, pack);
		safe_delete(pack);
	}
	else if(new_status == AS_Finished)
	{
		status = new_status;
		safe_delete(current_timer);
		current_timer = new Timer(1800000);
		database.SetInstanceDuration(instance_id, 1800);
		ServerPacket *pack = new ServerPacket(ServerOP_InstanceUpdateTime, sizeof(ServerInstanceUpdateTime_Struct));
		ServerInstanceUpdateTime_Struct *ut = (ServerInstanceUpdateTime_Struct*)pack->pBuffer;
		ut->instance_id = instance_id;
		ut->new_duration = 1860;

		pack->Deflate();
		zoneserver_list.SendPacket(0, instance_id, pack);
		safe_delete(pack);
	}
	else
	{
		return;
	}

	list<string>::iterator iter = players.begin();
	while(iter != players.end())
	{
		adventure_manager.GetAdventureData((*iter).c_str());
		iter++;
	}
}
Ejemplo n.º 4
0
map<string,string> EQW::GetZoneDetails(Const_char *zone_ref) {
	map<string,string> res;
	
	ZoneServer *zs = zoneserver_list.FindByID(atoi(zone_ref));
	if(zs == NULL) {
		res["error"] = "Invalid zone.";
		return(res);
	}
	
	res["type"] = zs->IsStaticZone()?"static":"dynamic";
	res["zone_id"] = itoa(zs->GetZoneID());
	res["launch_name"] = zs->GetLaunchName();
	res["launched_name"] = zs->GetLaunchedName();
	res["short_name"] = zs->GetZoneName();
	res["long_name"] = zs->GetZoneLongName();
	res["port"] = itoa(zs->GetCPort());
	res["player_count"] = itoa(zs->NumPlayers());
	
	//this isnt gunna work for dynamic zones...
	res["launcher"] = "";
	if(zs->GetZoneID() != 0) {
		LauncherLink *ll = launcher_list.FindByZone(zs->GetLaunchName());
		if(ll != NULL)
			res["launcher"] = ll->GetName();
	}
	
	return(res);
}
Ejemplo n.º 5
0
void ZoneServer::SendGroupIDs() {
	ServerPacket* pack = new ServerPacket(ServerOP_GroupIDReply, sizeof(ServerGroupIDReply_Struct));
	ServerGroupIDReply_Struct* sgi = (ServerGroupIDReply_Struct*)pack->pBuffer;
	zoneserver_list.NextGroupIDs(sgi->start, sgi->end);
	SendPacket(pack);
	delete pack;
}
Ejemplo n.º 6
0
void handle_rc_get_zone_info(const std::string &method, const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &params) {
	std::string error;
	std::map<std::string, std::string> res;
	if(params.size() != 1) {
		error = "Expected only one zone_id.";
		RemoteCallResponse(connection_id, request_id, res, error);
		return;
	}

	ZoneServer *zs = zoneserver_list.FindByID(atoi(params[0].c_str()));
	if(zs == nullptr) {
		error = "Invalid zone";
		RemoteCallResponse(connection_id, request_id, res, error);
		return;
	}

	res["type"] = zs->IsStaticZone() ? "static" : "dynamic";
	res["zone_id"] = itoa(zs->GetZoneID());
	res["instance_id"] = itoa(zs->GetInstanceID());
	res["launch_name"] = zs->GetLaunchName();
	res["launched_name"] = zs->GetLaunchedName();
	res["short_name"] = zs->GetZoneName();
	res["long_name"] = zs->GetZoneLongName();
	res["port"] = itoa(zs->GetCPort());
	res["player_count"] = itoa(zs->NumPlayers());
	RemoteCallResponse(connection_id, request_id, res, error);
}
Ejemplo n.º 7
0
void WorldGuildManager::SendGuildDelete(uint32 guild_id) {
	Log(Logs::Detail, Logs::Guilds, "Broadcasting guild delete for guild %d to world", guild_id);
	auto pack = new ServerPacket(ServerOP_DeleteGuild, sizeof(ServerGuildID_Struct));
	ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer;
	s->guild_id = guild_id;
	zoneserver_list.SendPacket(pack);
	safe_delete(pack);
}
Ejemplo n.º 8
0
void ZoneServer::ChangeWID(uint32 iCharID, uint32 iWID) {
	ServerPacket* pack = new ServerPacket(ServerOP_ChangeWID, sizeof(ServerChangeWID_Struct));
	ServerChangeWID_Struct* scw = (ServerChangeWID_Struct*) pack->pBuffer;
	scw->charid = iCharID;
	scw->newwid = iWID;
	zoneserver_list.SendPacket(pack);
	delete pack;
}
Ejemplo n.º 9
0
void WorldGuildManager::SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid) {
	Log(Logs::Detail, Logs::Guilds, "Broadcasting char refresh for %d from guild %d to world", charid, guild_id);
	auto pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct));
	ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer;
	s->guild_id = guild_id;
	s->old_guild_id = old_guild_id;
	s->char_id = charid;
	zoneserver_list.SendPacket(pack);
	safe_delete(pack);
}
Ejemplo n.º 10
0
void ClientList::SendOnlineGuildMembers(uint32 FromID, uint32 GuildID)
{
	int PacketLength = 8;

	uint32 Count = 0;
	ClientListEntry* from = this->FindCLEByCharacterID(FromID);

	if(!from)
	{
		_log(WORLD__CLIENT_ERR,"Invalid client. FromID=%i GuildID=%i", FromID, GuildID);
		return;
	}

	LinkedListIterator<ClientListEntry*> Iterator(clientlist);

	Iterator.Reset();

	while(Iterator.MoreElements())
	{
		ClientListEntry* CLE = Iterator.GetData();

		if(CLE && (CLE->GuildID() == GuildID))
		{
			PacketLength += (strlen(CLE->name()) + 5);
			++Count;
		}

		Iterator.Advance();

	}

	Iterator.Reset();

	ServerPacket* pack = new ServerPacket(ServerOP_OnlineGuildMembersResponse, PacketLength);

	char *Buffer = (char *)pack->pBuffer;

	VARSTRUCT_ENCODE_TYPE(uint32, Buffer, FromID);
	VARSTRUCT_ENCODE_TYPE(uint32, Buffer, Count);

	while(Iterator.MoreElements())
	{
		ClientListEntry* CLE = Iterator.GetData();

		if(CLE && (CLE->GuildID() == GuildID))
		{
			VARSTRUCT_ENCODE_STRING(Buffer, CLE->name());
			VARSTRUCT_ENCODE_TYPE(uint32, Buffer, CLE->zone());
		}

		Iterator.Advance();
	}
	zoneserver_list.SendPacket(from->zone(), from->instance(), pack);
	safe_delete(pack);
}
Ejemplo n.º 11
0
void WorldGuildManager::SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation) {
	Log(Logs::Detail, Logs::Guilds, "Broadcasting guild refresh for %d, changes: name=%d, motd=%d, rank=d, relation=%d", guild_id, name, motd, rank, relation);
	auto pack = new ServerPacket(ServerOP_RefreshGuild, sizeof(ServerGuildRefresh_Struct));
	ServerGuildRefresh_Struct *s = (ServerGuildRefresh_Struct *) pack->pBuffer;
	s->guild_id = guild_id;
	s->name_change = name;
	s->motd_change = motd;
	s->rank_change = rank;
	s->relation_change = relation;
	zoneserver_list.SendPacket(pack);
	safe_delete(pack);
}
Ejemplo n.º 12
0
void handle_rc_list_zones(const std::string &method, const std::string &connection_id, const std::string &request_id, const std::vector<std::string> &params) {
	std::vector<uint32> zones;
	zoneserver_list.GetZoneIDList(zones);

	std::map<std::string, std::string> res;
	uint32 sz = (uint32)zones.size();
	for(uint32 i = 0; i < sz; ++i) {
		res[itoa(i)] = (itoa(zones[i]));
	}
	
	std::string error;
	RemoteCallResponse(connection_id, request_id, res, error);
}
Ejemplo n.º 13
0
//returns an array of zone_refs (opaque)
vector<string> EQW::ListBootedZones() {
	vector<string> res;
	
	vector<int32> zones;
	zoneserver_list.GetZoneIDList(zones);
	
	vector<int32>::iterator cur, end;
	cur = zones.begin();
	end = zones.end();
	for(; cur != end; cur++) {
		res.push_back(itoa(*cur));
	}
	
	return(res);
}
Ejemplo n.º 14
0
ZoneServer::ZoneServer(EmuTCPConnection* itcpc) 
: WorldTCPConnection(), tcpc(itcpc), ls_zboot(5000) {
	ID = zoneserver_list.GetNextID();
	memset(zone_name, 0, sizeof(zone_name));
	memset(compiled, 0, sizeof(compiled));
	zoneID = 0;
	instanceID = 0;

	memset(clientaddress, 0, sizeof(clientaddress));
	clientport = 0;
	BootingUp = false;
	authenticated = false;
	staticzone = false;
	pNumPlayers = 0;
}
Ejemplo n.º 15
0
//Account Limiting Code to limit the number of characters allowed on from a single account at once.
void ClientList::EnforceSessionLimit(int32 iLSAccountID) {

	ClientListEntry* ClientEntry = 0;

	LinkedListIterator<ClientListEntry*> iterator(clientlist, BACKWARD);

	int CharacterCount = 0;

	iterator.Reset();

	while(iterator.MoreElements()) {

		ClientEntry = iterator.GetData();

		if ((ClientEntry->LSAccountID() == iLSAccountID) &&
		    ((ClientEntry->Admin() <= (RuleI(World, ExemptAccountLimitStatus))) || (RuleI(World, ExemptAccountLimitStatus) < 0))) {

			CharacterCount++;

			if (CharacterCount >= (RuleI(World, AccountSessionLimit))){
				// If we have a char name, they are in a zone, so send a kick to the zone server
				if(strlen(ClientEntry->name())) 
				
				{				
					
					ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
					ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer;
					strcpy(skp->adminname, "SessionLimit");
					strcpy(skp->name, ClientEntry->name());
					skp->adminrank = 255;
					zoneserver_list.SendPacket(pack);
					safe_delete(pack);
					
				}
				
				ClientEntry->SetOnline(CLE_Status_Offline);

				iterator.RemoveCurrent();

				continue;
			}
		}
		iterator.Advance();
	}
}
Ejemplo n.º 16
0
void Adventure::SendAdventureMessage(uint32 type, const char *msg)
{
	ServerPacket *pack = new ServerPacket(ServerOP_EmoteMessage, sizeof(ServerEmoteMessage_Struct) + strlen(msg) + 1);
	ServerEmoteMessage_Struct *sms = (ServerEmoteMessage_Struct*)pack->pBuffer;
	sms->type = type;
	strcpy(sms->message, msg);
	list<string>::iterator iter = players.begin();
	while(iter != players.end())
	{
		ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
		if(current)
		{
			strcpy(sms->to, (*iter).c_str());
			zoneserver_list.SendPacket(current->zone(), current->instance(), pack);
		}
		iter++;
	}
	delete pack;
}
Ejemplo n.º 17
0
bool LoginServer::Connect() {
	char tmp[25];
	if(database.GetVariable("loginType",tmp,sizeof(tmp)) && strcasecmp(tmp,"MinILogin") == 0){
		minilogin = true;
		_log(WORLD__LS, "Setting World to MiniLogin Server type");
	}
	else
		minilogin = false;

	if (minilogin && WorldConfig::get()->WorldAddress.length()==0) {
		_log(WORLD__LS_ERR, "**** For minilogin to work, you need to set the <address> element in the <world> section.");
		return false;
	}

	char errbuf[TCPConnection_ErrorBufferSize];
	if ((LoginServerIP = ResolveIP(LoginServerAddress, errbuf)) == 0) {
		_log(WORLD__LS_ERR, "Unable to resolve '%s' to an IP.",LoginServerAddress);
		return false;
	}

	if (LoginServerIP == 0 || LoginServerPort == 0) {
		_log(WORLD__LS_ERR, "Connect info incomplete, cannot connect: %s:%d",LoginServerAddress,LoginServerPort);
		return false;
	}

	if (tcpc->ConnectIP(LoginServerIP, LoginServerPort, errbuf)) {
		_log(WORLD__LS, "Connected to Loginserver: %s:%d",LoginServerAddress,LoginServerPort);
		if (minilogin)
			SendInfo();
		else
			SendNewInfo();
		SendStatus();
		zoneserver_list.SendLSZones();
		return true;
	}
	else {
		_log(WORLD__LS_ERR, "Could not connect to login server: %s:%d %s",LoginServerAddress,LoginServerPort,errbuf);
		return false;
	}
}
Ejemplo n.º 18
0
void ClientList::SendGuildPacket(uint32 guild_id, ServerPacket* pack) {
	std::set<uint32> zone_ids;

	LinkedListIterator<ClientListEntry*> iterator(clientlist);

	iterator.Reset();
	while(iterator.MoreElements()) {
		if (iterator.GetData()->GuildID() == guild_id) {
			zone_ids.insert(iterator.GetData()->zone());
		}
		iterator.Advance();
	}

	//now we know all the zones, send it to each one... this is kinda a shitty way to do this
	//since its basically O(n^2)
	std::set<uint32>::iterator cur, end;
	cur = zone_ids.begin();
	end = zone_ids.end();
	for(; cur != end; cur++) {
		zoneserver_list.SendPacket(*cur, pack);
	}
}
Ejemplo n.º 19
0
void ClientList::DisconnectByIP(uint32 iIP) {
	ClientListEntry* countCLEIPs = 0;
	LinkedListIterator<ClientListEntry*> iterator(clientlist);
	iterator.Reset();

	while(iterator.MoreElements()) {
		countCLEIPs = iterator.GetData();
		if ((countCLEIPs->GetIP() == iIP)) {
			if(strlen(countCLEIPs->name())) {
				ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
				ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer;
				strcpy(skp->adminname, "SessionLimit");
				strcpy(skp->name, countCLEIPs->name());
				skp->adminrank = 255;
				zoneserver_list.SendPacket(pack);
				safe_delete(pack);
			}
			countCLEIPs->SetOnline(CLE_Status_Offline);
			iterator.RemoveCurrent();
		}
		iterator.Advance();
	}
}
Ejemplo n.º 20
0
void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) {
	switch(pack->opcode) {

	case ServerOP_RefreshGuild: {
		if(pack->size != sizeof(ServerGuildRefresh_Struct)) {
			Log(Logs::Detail, Logs::Guilds, "Received ServerOP_RefreshGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildRefresh_Struct));
			return;
		}
		ServerGuildRefresh_Struct *s = (ServerGuildRefresh_Struct *) pack->pBuffer;
		Log(Logs::Detail, Logs::Guilds, "Received and broadcasting guild refresh for %d, changes: name=%d, motd=%d, rank=d, relation=%d", s->guild_id, s->name_change, s->motd_change, s->rank_change, s->relation_change);

		//broadcast this packet to all zones.
		zoneserver_list.SendPacket(pack);

		//preform a local refresh.
		if(!RefreshGuild(s->guild_id)) {
			Log(Logs::Detail, Logs::Guilds, "Unable to preform local refresh on guild %d", s->guild_id);
			//can we do anything?
		}

		break;
	}

	case ServerOP_GuildCharRefresh: {
		if(pack->size != sizeof(ServerGuildCharRefresh_Struct)) {
			Log(Logs::Detail, Logs::Guilds, "Received ServerOP_RefreshGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildCharRefresh_Struct));
			return;
		}
		ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer;
		Log(Logs::Detail, Logs::Guilds, "Received and broadcasting guild member refresh for char %d to all zones with members of guild %d", s->char_id, s->guild_id);

		//preform the local update
		client_list.UpdateClientGuild(s->char_id, s->guild_id);

		//broadcast this update to any zone with a member in this guild.
		//client_list.SendGuildPacket(s->guild_id, pack);
		//because im sick of this not working, sending it to all zones, just spends a bit more bandwidth.
		zoneserver_list.SendPacket(pack);

		break;
	}

	case ServerOP_DeleteGuild: {
		if(pack->size != sizeof(ServerGuildID_Struct)) {
			Log(Logs::Detail, Logs::Guilds, "Received ServerOP_DeleteGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildID_Struct));
			return;
		}
		ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer;
		Log(Logs::Detail, Logs::Guilds, "Received and broadcasting guild delete for guild %d", s->guild_id);

		//broadcast this packet to all zones.
		zoneserver_list.SendPacket(pack);

		//preform a local refresh.
		if(!LocalDeleteGuild(s->guild_id)) {
			Log(Logs::Detail, Logs::Guilds, "Unable to preform local delete on guild %d", s->guild_id);
			//can we do anything?
		}

		break;
	}

	case ServerOP_GuildMemberUpdate: {
		if(pack->size != sizeof(ServerGuildMemberUpdate_Struct))
		{
			Log(Logs::Detail, Logs::Guilds, "Received ServerOP_GuildMemberUpdate of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildMemberUpdate_Struct));
			return;
		}

		zoneserver_list.SendPacket(pack);

		break;
	}

	default:
		Log(Logs::Detail, Logs::Guilds, "Unknown packet 0x%x received from zone??", pack->opcode);
		break;
	}
}
Ejemplo n.º 21
0
void ClientList::SendClientVersionSummary(const char *Name)
{
	uint32 Client62Count = 0;
	uint32 ClientTitaniumCount = 0;
	uint32 ClientSoFCount = 0;
	uint32 ClientSoDCount = 0;
	uint32 ClientUnderfootCount = 0;
	uint32 ClientRoFCount = 0;

	LinkedListIterator<ClientListEntry*> Iterator(clientlist);

	Iterator.Reset();

	while(Iterator.MoreElements())
	{
		ClientListEntry* CLE = Iterator.GetData();

		if(CLE && CLE->zone())
		{
			switch(CLE->GetClientVersion())
			{
				case 1:
				{
					++Client62Count;
					break;
				}
				case 2:
				{
					++ClientTitaniumCount;
					break;
				}
				case 3:
				{
					++ClientSoFCount;
					break;
				}
				case 4:
				{
					++ClientSoDCount;
					break;
				}
				case 5:
				{
					++ClientUnderfootCount;
					break;
				}
				case 6:
				{
					++ClientRoFCount;
					break;
				}
				default:
					break;
			}
		}

		Iterator.Advance();

	}

	zoneserver_list.SendEmoteMessage(Name, 0, 0, 13, "There are %i 6.2, %i Titanium, %i SoF, %i SoD, %i UF, %i RoF clients currently connected.",
					Client62Count, ClientTitaniumCount, ClientSoFCount, ClientSoDCount, ClientUnderfootCount, ClientRoFCount);
}
Ejemplo n.º 22
0
void Client::Clearance(int8 response)
{
	ZoneServer* zs = nullptr;
	if(instanceID > 0)
	{
		zs = zoneserver_list.FindByInstanceID(instanceID);
	}
	else
	{
		zs = zoneserver_list.FindByZoneID(zoneID);
	}

	if(zs == 0 || response == -1 || response == 0)
	{
		if (zs == 0)
		{
			clog(WORLD__CLIENT_ERR,"Unable to find zoneserver in Client::Clearance!!");
		} else {
			clog(WORLD__CLIENT_ERR, "Invalid response %d in Client::Clearance", response);
		}

		ZoneUnavail();
		return;
	}

	EQApplicationPacket* outapp;

	if (zs->GetCAddress() == nullptr) {
		clog(WORLD__CLIENT_ERR, "Unable to do zs->GetCAddress() in Client::Clearance!!");
		ZoneUnavail();
		return;
	}

	if (zoneID == 0) {
		clog(WORLD__CLIENT_ERR, "zoneID is nullptr in Client::Clearance!!");
		ZoneUnavail();
		return;
	}

	const char* zonename = database.GetZoneName(zoneID);
	if (zonename == 0) {
		clog(WORLD__CLIENT_ERR, "zonename is nullptr in Client::Clearance!!");
		ZoneUnavail();
		return;
	}

	// @bp This is the chat server
	/*
	char packetData[] = "64.37.148.34.9876,MyServer,Testchar,23cd2c95";
	outapp = new EQApplicationPacket(OP_0x0282, sizeof(packetData));
	strcpy((char*)outapp->pBuffer, packetData);
	QueuePacket(outapp);
	delete outapp;
	*/

	// Send zone server IP data
	outapp = new EQApplicationPacket(OP_ZoneServerInfo, sizeof(ZoneServerInfo_Struct));
	ZoneServerInfo_Struct* zsi = (ZoneServerInfo_Struct*)outapp->pBuffer;
	const char *zs_addr=zs->GetCAddress();
	if (!zs_addr[0]) {
		if (cle->IsLocalClient()) {
			struct in_addr in;
			in.s_addr = zs->GetIP();
			zs_addr=inet_ntoa(in);
			if (!strcmp(zs_addr,"127.0.0.1"))
				zs_addr=WorldConfig::get()->LocalAddress.c_str();
		} else {
			zs_addr=WorldConfig::get()->WorldAddress.c_str();
		}
	}
	strcpy(zsi->ip, zs_addr);
	zsi->port =zs->GetCPort();
	clog(WORLD__CLIENT,"Sending client to zone %s (%d:%d) at %s:%d",zonename,zoneID,instanceID,zsi->ip,zsi->port);
	QueuePacket(outapp);
	safe_delete(outapp);

	if (cle)
		cle->SetOnline(CLE_Status_Zoning);
}
Ejemplo n.º 23
0
void ClientList::SendClientVersionSummary(const char *Name)
{
	uint32 ClientUnusedCount = 0;
	uint32 ClientPCCount = 0;
	uint32 ClientIntelCount = 0;
	uint32 ClientPPCCount = 0;
	uint32 ClientEvolutionCount = 0;

	LinkedListIterator<ClientListEntry*> Iterator(clientlist);

	Iterator.Reset();

	while(Iterator.MoreElements())
	{
		ClientListEntry* CLE = Iterator.GetData();

		if(CLE && CLE->zone())
		{
			switch(CLE->GetClientVersion())
			{
				case 1:
				{
					++ClientUnusedCount;
					break;
				}
				case 2:
				{
					switch(CLE->GetMacClientVersion())
					{
						case 2:
						{
							++ClientPCCount;
							break;
						}
						case 4:
						{
							++ClientIntelCount;
							break;
						}
						case 8:
						{
							++ClientPPCCount;
							break;
						}
					}
					break;
				}
				case 3:
				{
					++ClientEvolutionCount;
					break;
				}
				default:
					break;
			}
		}

		Iterator.Advance();

	}

	zoneserver_list.SendEmoteMessage(Name, 0, 0, 13, "There are %i Unused, %i PC, %i Intel, %i PPC, %i Evolution clients currently connected.",
					ClientUnusedCount, ClientPCCount, ClientIntelCount, ClientPPCCount, ClientEvolutionCount);
}
Ejemplo n.º 24
0
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {

	if (GetAccountID() == 0) {
		clog(WORLD__CLIENT_ERR,"Enter world with no logged in account");
		eqs->Close();
		return true;
	}

	if(GetAdmin() < 0)
	{
		clog(WORLD__CLIENT,"Account banned or suspended.");
		eqs->Close();
		return true;
	}

	if (RuleI(World, MaxClientsPerIP) >= 0) {
		client_list.GetCLEIP(this->GetIP()); //Check current CLE Entry IPs against incoming connection
	}

	EnterWorld_Struct *ew=(EnterWorld_Struct *)app->pBuffer;
	strn0cpy(char_name, ew->name, 64);

	EQApplicationPacket *outapp;
	uint32 tmpaccid = 0;
	charid = database.GetCharacterInfo(char_name, &tmpaccid, &zoneID, &instanceID);
	if (charid == 0 || tmpaccid != GetAccountID()) {
		clog(WORLD__CLIENT_ERR,"Could not get CharInfo for '%s'",char_name);
		eqs->Close();
		return true;
	}

	// Make sure this account owns this character
	if (tmpaccid != GetAccountID()) {
		clog(WORLD__CLIENT_ERR,"This account does not own the character named '%s'",char_name);
		eqs->Close();
		return true;
	}

	if(!pZoning && ew->return_home && !ew->tutorial)
	{
		CharacterSelect_Struct* cs = new CharacterSelect_Struct;
		memset(cs, 0, sizeof(CharacterSelect_Struct));
		database.GetCharSelectInfo(GetAccountID(), cs);
		bool home_enabled = false;

		for(int x = 0; x < 10; ++x)
		{
			if(strcasecmp(cs->name[x], char_name) == 0)
			{
				if(cs->gohome[x] == 1)
				{
					home_enabled = true;
					break;
				}
			}
		}
		safe_delete(cs);

		if(home_enabled)
		{
			zoneID = database.MoveCharacterToBind(charid,4);
		}
		else
		{
			clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name);
			database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
			eqs->Close();
			return true;
		}
	}

	if(!pZoning && (RuleB(World, EnableTutorialButton) && (ew->tutorial || StartInTutorial))) {
		CharacterSelect_Struct* cs = new CharacterSelect_Struct;
		memset(cs, 0, sizeof(CharacterSelect_Struct));
		database.GetCharSelectInfo(GetAccountID(), cs);
		bool tutorial_enabled = false;

		for(int x = 0; x < 10; ++x)
		{
			if(strcasecmp(cs->name[x], char_name) == 0)
			{
				if(cs->tutorial[x] == 1)
				{
					tutorial_enabled = true;
					break;
				}
			}
		}
		safe_delete(cs);

		if(tutorial_enabled)
		{
			zoneID = RuleI(World, TutorialZoneID);
			database.MoveCharacterToZone(charid, database.GetZoneName(zoneID));
		}
		else
		{
			clog(WORLD__CLIENT_ERR,"'%s' is trying to go to tutorial but are not allowed...",char_name);
			database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
			eqs->Close();
			return true;
		}
	}

	if (zoneID == 0 || !database.GetZoneName(zoneID)) {
		// This is to save people in an invalid zone, once it's removed from the DB
		database.MoveCharacterToZone(charid, "arena");
		clog(WORLD__CLIENT_ERR, "Zone not found in database zone_id=%i, moveing char to arena character:%s", zoneID, char_name);
	}

	if(instanceID > 0)
	{
		if(!database.VerifyInstanceAlive(instanceID, GetCharID()))
		{
			zoneID = database.MoveCharacterToBind(charid);
			instanceID = 0;
		}
		else
		{
			if(!database.VerifyZoneInstance(zoneID, instanceID))
			{
				zoneID = database.MoveCharacterToBind(charid);
				instanceID = 0;
			}
		}
	}

	if(!pZoning) {
		database.SetGroupID(char_name, 0, charid);
		database.SetFirstLogon(charid, 1);

		if (RuleB(World, AnnounceJoinQuits) == true) //this is having an issue, its not taking a true false swap, only takes default.
		{
			zoneserver_list.SendEmoteMessage(0, 0, 0, 15, "%s is logging on!", GetCharName());
			clog(WORLD__CLIENT_ERR, "Character is logging on: %s", GetCharName());
		}
	}
	else{
		uint32 groupid=database.GetGroupID(char_name);
		if(groupid>0){
			char* leader=0;
			char leaderbuf[64]={0};
			if((leader=database.GetGroupLeaderForLogin(char_name,leaderbuf)) && strlen(leader)>1){
				EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct));
				GroupJoin_Struct* gj=(GroupJoin_Struct*)outapp3->pBuffer;
				gj->action=8;
				strcpy(gj->yourname,char_name);
				strcpy(gj->membername,leader);
				QueuePacket(outapp3);
				safe_delete(outapp3);
			}
		}
	}

	outapp = new EQApplicationPacket(OP_MOTD);
	char tmp[500] = {0};
	if (database.GetVariable("MOTD", tmp, 500)) {
		outapp->size = strlen(tmp)+1;
		outapp->pBuffer = new uchar[outapp->size];
		memset(outapp->pBuffer,0,outapp->size);
		strcpy((char*)outapp->pBuffer, tmp);

	} else {
		// Null Message of the Day. :)
		outapp->size = 1;
		outapp->pBuffer = new uchar[outapp->size];
		outapp->pBuffer[0] = 0;
	}
	QueuePacket(outapp);
	safe_delete(outapp);

	int MailKey = MakeRandomInt(1, INT_MAX);

	database.SetMailKey(charid, GetIP(), MailKey);

	char ConnectionType;

	ConnectionType = 'C';

	EQApplicationPacket *outapp2 = new EQApplicationPacket(OP_SetChatServer);
	char buffer[112];

	const WorldConfig *Config = WorldConfig::get();

	sprintf(buffer,"%s,%i,%s.%s,%c%08X",
		Config->ChatHost.c_str(),
		Config->ChatPort,
		Config->ShortName.c_str(),
		this->GetCharName(), ConnectionType, MailKey
	);
	outapp2->size=strlen(buffer)+1;
	outapp2->pBuffer = new uchar[outapp2->size];
	memcpy(outapp2->pBuffer,buffer,outapp2->size);
	QueuePacket(outapp2);
	safe_delete(outapp2);

	EnterWorld();

	return true;
}
Ejemplo n.º 25
0
void Client::EnterWorld(bool TryBootup) {
	if (zoneID == 0)
		return;

	ZoneServer* zs = nullptr;
	if(instanceID > 0)
	{
		if(database.VerifyInstanceAlive(instanceID, GetCharID()))
		{
			if(database.VerifyZoneInstance(zoneID, instanceID))
			{
				zs = zoneserver_list.FindByInstanceID(instanceID);
			}
			else
			{
				instanceID = 0;
				zs = nullptr;
				database.MoveCharacterToBind(GetCharID());
				ZoneUnavail();
				return;
			}
		}
		else
		{
			instanceID = 0;
			zs = nullptr;
			database.MoveCharacterToBind(GetCharID());
			ZoneUnavail();
			return;
		}
	}
	else
		zs = zoneserver_list.FindByZoneID(zoneID);


	const char *zone_name=database.GetZoneName(zoneID, true);
	if (zs) {
		// warn the world we're comming, so it knows not to shutdown
		zs->IncommingClient(this);
	}
	else {
		if (TryBootup) {
			clog(WORLD__CLIENT,"Attempting autobootup of %s (%d:%d)",zone_name,zoneID,instanceID);
			autobootup_timeout.Start();
			pwaitingforbootup = zoneserver_list.TriggerBootup(zoneID, instanceID);
			if (pwaitingforbootup == 0) {
				clog(WORLD__CLIENT_ERR,"No zoneserver available to boot up.");
				ZoneUnavail();
			}
			return;
		}
		else {
			clog(WORLD__CLIENT_ERR,"Requested zone %s is no running.",zone_name);
			ZoneUnavail();
			return;
		}
	}
	pwaitingforbootup = 0;

	cle->SetChar(charid, char_name);
	database.UpdateLiveChar(char_name, GetAccountID());
	clog(WORLD__CLIENT,"%s %s (%d:%d)",seencharsel ? "Entering zone" : "Zoning to",zone_name,zoneID,instanceID);
//	database.SetAuthentication(account_id, char_name, zone_name, ip);

	if (seencharsel) {
		if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zoneID)) {
			clog(WORLD__CLIENT_ERR,"Enter world failed. Zone is locked.");
			ZoneUnavail();
			return;
		}

		ServerPacket* pack = new ServerPacket;
		pack->opcode = ServerOP_AcceptWorldEntrance;
		pack->size = sizeof(WorldToZone_Struct);
		pack->pBuffer = new uchar[pack->size];
		memset(pack->pBuffer, 0, pack->size);
		WorldToZone_Struct* wtz = (WorldToZone_Struct*) pack->pBuffer;
		wtz->account_id = GetAccountID();
		wtz->response = 0;
		zs->SendPacket(pack);
		delete pack;
	}
	else {	// if they havent seen character select screen, we can assume this is a zone
			// to zone movement, which should be preauthorized before they leave the previous zone
		Clearance(1);
	}
}
Ejemplo n.º 26
0
bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
	if (app->size != sizeof(LoginInfo_Struct)) {
		return false;
	}

	LoginInfo_Struct *li=(LoginInfo_Struct *)app->pBuffer;

	// Quagmire - max len for name is 18, pass 15
	char name[19] = {0};
	char password[16] = {0};
	strn0cpy(name, (char*)li->login_info,18);
	strn0cpy(password, (char*)&(li->login_info[strlen(name)+1]), 15);

	if (strlen(password) <= 1) {
		// TODO: Find out how to tell the client wrong username/password
		clog(WORLD__CLIENT_ERR,"Login without a password");
		return false;
	}

	pZoning=(li->zoning==1);

#ifdef IPBASED_AUTH_HACK
	struct in_addr tmpip;
	tmpip.s_addr = ip;
#endif
	uint32 id=0;
	bool minilogin = loginserverlist.MiniLogin();
	if(minilogin){
		struct in_addr miniip;
		miniip.s_addr = ip;
		id = database.GetMiniLoginAccount(inet_ntoa(miniip));
	}
	else if(strncasecmp(name, "LS#", 3) == 0)
		id=atoi(&name[3]);
	else
		id=atoi(name);
#ifdef IPBASED_AUTH_HACK
	if ((cle = zoneserver_list.CheckAuth(inet_ntoa(tmpip), password)))
#else
	if (loginserverlist.Connected() == false && !pZoning) {
		clog(WORLD__CLIENT_ERR,"Error: Login server login while not connected to login server.");
		return false;
	}
	if(minilogin)
	client_list.CLEAdd(id, name, password, 0, ip, true);

	if ((minilogin && (cle = client_list.CheckAuth(id,password,ip))) || (cle = client_list.CheckAuth(id, password)))
#endif
	{
		if (cle->AccountID() == 0 || (!minilogin && cle->LSID()==0)) {
			clog(WORLD__CLIENT_ERR,"ID is 0. Is this server connected to minilogin?");
			if(!minilogin)
				clog(WORLD__CLIENT_ERR,"If so you forget the minilogin variable...");
			else
				clog(WORLD__CLIENT_ERR,"Could not find a minilogin account, verify ip address logging into minilogin is the same that is in your account table.");
			return false;
		}

		cle->SetOnline();

		clog(WORLD__CLIENT,"Logged in. Mode=%s",pZoning ? "(Zoning)" : "(CharSel)");

		if(minilogin){
			WorldConfig::DisableStats();
			clog(WORLD__CLIENT,"MiniLogin Account #%d",cle->AccountID());
		}
		else {
			clog(WORLD__CLIENT,"LS Account #%d",cle->LSID());
		}

		const WorldConfig *Config=WorldConfig::get();

		if(Config->UpdateStats){
			ServerPacket* pack = new ServerPacket;
			pack->opcode = ServerOP_LSPlayerJoinWorld;
			pack->size = sizeof(ServerLSPlayerJoinWorld_Struct);
			pack->pBuffer = new uchar[pack->size];
			memset(pack->pBuffer,0,pack->size);
			ServerLSPlayerJoinWorld_Struct* join =(ServerLSPlayerJoinWorld_Struct*)pack->pBuffer;
			strcpy(join->key,GetLSKey());
			join->lsaccount_id = GetLSID();
			loginserverlist.SendPacket(pack);
			safe_delete(pack);
		}

		expansion = database.GetExpansion(cle->AccountID());

		if(ClientVersionBit == 1)
		{		
			SendApproveWorld();
			SendEnterWorld(cle->name());
			SendExpansionInfo();
			SendCharInfo();
		}
		else
		{
			if (!pZoning && ClientVersionBit != 0)
				SendGuildList();
				SendLogServer();
				SendApproveWorld();
				SendEnterWorld(cle->name());
			if (!pZoning) {
				SendExpansionInfo();
				SendCharInfo();
				database.LoginIP(cle->AccountID(), long2ip(GetIP()).c_str());
			}
		}

	}
	else {
		// TODO: Find out how to tell the client wrong username/password
		clog(WORLD__CLIENT_ERR,"Bad/Expired session key '%s'",name);
		return false;
	}

	if (!cle)
		return true;

	cle->SetIP(GetIP());
	return true;
}
Ejemplo n.º 27
0
bool LoginServer::Process() {
	const WorldConfig *Config=WorldConfig::get();

	if (statusupdate_timer.Check()) {
		this->SendStatus();
	}
    
	/************ Get all packets from packet manager out queue and process them ************/
	ServerPacket *pack = 0;
	while((pack = tcpc->PopPacket()))
	{
		_log(WORLD__LS_TRACE,"Recevied ServerPacket from LS OpCode 0x04x",pack->opcode);
		_hex(WORLD__LS_TRACE,pack->pBuffer,pack->size);

		switch(pack->opcode) {
		case 0:
			break;
		case ServerOP_KeepAlive: {
			// ignore this
			break;
		}
		case ServerOP_UsertoWorldReq: {
			UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*) pack->pBuffer;	
			uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid);
			int16 status = database.CheckStatus(id);

			ServerPacket* outpack = new ServerPacket;
			outpack->opcode = ServerOP_UsertoWorldResp;
			outpack->size = sizeof(UsertoWorldResponse_Struct);
			outpack->pBuffer = new uchar[outpack->size];
			memset(outpack->pBuffer, 0, outpack->size);
			UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*) outpack->pBuffer;
			utwrs->lsaccountid = utwr->lsaccountid;
			utwrs->ToID = utwr->FromID;

			if(Config->Locked == true)
			{
				if((status == 0 || status < 100) && (status != -2 || status != -1))
					utwrs->response = 0;
				if(status >= 100)
					utwrs->response = 1;
			}
			else {
				utwrs->response = 1;
			}

			int32 x = Config->MaxClients;
			if( (int32)numplayers >= x && x != -1 && x != 255 && status < 80)
				utwrs->response = -3;

			if(status == -1)
				utwrs->response = -1;
			if(status == -2)
				utwrs->response = -2;

			utwrs->worldid = utwr->worldid;
			SendPacket(outpack);
			delete outpack;
			break;
		}
		case ServerOP_LSClientAuth: {
			ServerLSClientAuth* slsca = (ServerLSClientAuth*) pack->pBuffer;

			if (RuleI(World, AccountSessionLimit) >= 0) {
				// Enforce the limit on the number of characters on the same account that can be 
				// online at the same time.
				client_list.EnforceSessionLimit(slsca->lsaccount_id); 
			}

			client_list.CLEAdd(slsca->lsaccount_id, slsca->name, slsca->key, slsca->worldadmin, slsca->ip, slsca->local);
			break;
		}
		case ServerOP_LSFatalError: {
#ifndef IGNORE_LS_FATAL_ERROR
			WorldConfig::DisableLoginserver();
			_log(WORLD__LS_ERR, "Login server responded with FatalError. Disabling reconnect.");
#else
		_log(WORLD__LS_ERR, "Login server responded with FatalError.");
#endif
			if (pack->size > 1) {
				_log(WORLD__LS_ERR, "     %s",pack->pBuffer);
			}
			break;
		}
		case ServerOP_SystemwideMessage: {
			ServerSystemwideMessage* swm = (ServerSystemwideMessage*) pack->pBuffer;
			zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
			break;
		}
		case ServerOP_LSRemoteAddr: {
			if (!Config->WorldAddress.length()) {
				WorldConfig::SetWorldAddress((char *)pack->pBuffer);
				_log(WORLD__LS, "Loginserver provided %s as world address",pack->pBuffer);
			}
			break;
		}
		case ServerOP_LSAccountUpdate: {
			_log(WORLD__LS, "Received ServerOP_LSAccountUpdate packet from loginserver");
			CanAccountUpdate = true;
			break;
		}
		default:
		{
			_log(WORLD__LS_ERR, "Unknown LSOpCode: 0x%04x size=%d",(int)pack->opcode,pack->size);
DumpPacket(pack->pBuffer, pack->size);
			break;
		}
		}

		delete pack;
	}

	return true;
}
Ejemplo n.º 28
0
int main(int argc, char** argv) {
	// Load server configuration
	_log(WORLD__INIT, "Loading server configuration..");
	if (!WorldConfig::LoadConfig()) {
		_log(WORLD__INIT_ERR, "Loading server configuration failed.");
		return(1);
	}
	const WorldConfig *Config=WorldConfig::get();

	if(!load_log_settings(Config->LogSettingsFile.c_str()))
		_log(WORLD__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str());
	else
		_log(WORLD__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str());


	_log(WORLD__INIT, "CURRENT_WORLD_VERSION:%s", CURRENT_WORLD_VERSION);
	
	#ifdef _DEBUG
		_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	#endif
	
	if (signal(SIGINT, CatchSignal) == SIG_ERR)	{
		_log(WORLD__INIT_ERR, "Could not set signal handler");
		return 0;
	}
	if (signal(SIGTERM, CatchSignal) == SIG_ERR)	{
		_log(WORLD__INIT_ERR, "Could not set signal handler");
		return 0;
	}
	#ifndef WIN32
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)	{
		_log(WORLD__INIT_ERR, "Could not set signal handler");
		return 0;
	}
	#endif
	
	_log(WORLD__INIT, "Connecting to MySQL...");
	if (!database.Connect(
		Config->DatabaseHost.c_str(),
		Config->DatabaseUsername.c_str(),
		Config->DatabasePassword.c_str(),
		Config->DatabaseDB.c_str(),
		Config->DatabasePort)) {
		_log(WORLD__INIT_ERR, "Cannot continue without a database connection.");
		return(1);
	}
	dbasync = new DBAsync(&database);
	guild_mgr.SetDatabase(&database);
	
	if (argc >= 2) {
		char tmp[2];
		if (strcasecmp(argv[1], "help") == 0 || strcasecmp(argv[1], "?") == 0 || strcasecmp(argv[1], "/?") == 0 || strcasecmp(argv[1], "-?") == 0 || strcasecmp(argv[1], "-h") == 0 || strcasecmp(argv[1], "-help") == 0) {
			cout << "Worldserver command line commands:" << endl;
			cout << "adduser username password flag    - adds a user account" << endl;
			cout << "flag username flag    - sets GM flag on the account" << endl;
			cout << "startzone zoneshortname    - sets the starting zone" << endl;
			cout << "-holdzones    - reboots lost zones" << endl;
			return 0;
		}
		else if (strcasecmp(argv[1], "-holdzones") == 0) {
			cout << "Reboot Zones mode ON" << endl;
			holdzones = true;
		}
		else if (database.GetVariable("disablecommandline", tmp, 2)) {
			if (strlen(tmp) == 1) {
				if (tmp[0] == '1') {
					cout << "Command line disabled in database... exiting" << endl;
					return 0;
				}
			}
		}
		else if (strcasecmp(argv[1], "adduser") == 0) {
			if (argc == 5) {
				if (Seperator::IsNumber(argv[4])) {
					if (atoi(argv[4]) >= 0 && atoi(argv[4]) <= 255) {
						if (database.CreateAccount(argv[2], argv[3], atoi(argv[4])) == 0)
							cout << "database.CreateAccount failed." << endl;
						else
							cout << "Account created: Username='******', Password='******', status=" << argv[4] << endl;
						return 0;
					}
				}
			}
			cout << "Usage: world adduser username password flag" << endl;
			cout << "flag = 0, 1 or 2" << endl;
			return 0;
		}
		else if (strcasecmp(argv[1], "flag") == 0) {
			if (argc == 4) {
				if (Seperator::IsNumber(argv[3])) {

					if (atoi(argv[3]) >= 0 && atoi(argv[3]) <= 255) {
						if (database.SetAccountStatus(argv[2], atoi(argv[3])))
							cout << "Account flagged: Username='******', status=" << argv[3] << endl;
						else
							cout << "database.SetAccountStatus failed." << endl;
						return 0;
					}
				}
			}
			cout << "Usage: world flag username flag" << endl;
			cout << "flag = 0-200" << endl;
			return 0;
		}
		else if (strcasecmp(argv[1], "startzone") == 0) {
			if (argc == 3) {
				if (strlen(argv[2]) < 3) {
					cout << "Error: zone name too short" << endl;
				}
				else if (strlen(argv[2]) > 15) {
					cout << "Error: zone name too long" << endl;
				}
				else {
					if (database.SetVariable("startzone", argv[2]))
						cout << "Starting zone changed: '" << argv[2] << "'" << endl;
					else
						cout << "database.SetVariable failed." << endl;
				}
				return 0;
			}
			cout << "Usage: world startzone zoneshortname" << endl;
			return 0;
		}
		else {
			cout << "Error, unknown command line option" << endl;
			return 0;
		}
	}
	srand(time(NULL));
	
	if(Config->WorldHTTPEnabled) {
		_log(WORLD__INIT, "Starting HTTP world service...");
		http_server.Start(Config->WorldHTTPPort, Config->WorldHTTPMimeFile.c_str());
	} else {
		_log(WORLD__INIT, "HTTP world service disabled.");
	}
	
	_log(WORLD__INIT, "Loading variables..");
	database.LoadVariables();
	_log(WORLD__INIT, "Loading zones..");
	database.LoadZoneNames();
	_log(WORLD__INIT, "Clearing groups..");
	database.ClearGroup();
	_log(WORLD__INIT, "Clearing raids..");
	database.ClearRaid();
	database.ClearRaidDetails();
	_log(WORLD__INIT, "Loading items..");
	if (!database.LoadItems()) {
		_log(WORLD__INIT_ERR, "Error: Could not load item data.  But ignoring");
	}
	_log(WORLD__INIT, "Loading guilds..");
	guild_mgr.LoadGuilds();
	//rules:
	{
		char tmp[64];
		if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) {
			_log(WORLD__INIT, "Loading rule set '%s'", tmp);
			if(!rules->LoadRules(&database, tmp)) {
				_log(WORLD__INIT_ERR, "Failed to load ruleset '%s', falling back to defaults.", tmp);
			}
		} else {
			if(!rules->LoadRules(&database, "default")) {
				_log(WORLD__INIT, "No rule set configured, using default rules");
			} else {
				_log(WORLD__INIT, "Loaded default rule set 'default'", tmp);
			}
		}
	}
	if(RuleB(World, ClearTempMerchantlist)){
        _log(WORLD__INIT, "Clearing temporary merchant lists..");
		database.ClearMerchantTemp();
      }
	_log(WORLD__INIT, "Loading EQ time of day..");
	if (!zoneserver_list.worldclock.loadFile(Config->EQTimeFile.c_str()))
		_log(WORLD__INIT_ERR, "Unable to load %s", Config->EQTimeFile.c_str());
	_log(WORLD__INIT, "Loading launcher list..");
	launcher_list.LoadList();
	
	char tmp[20];
	tmp[0] = '\0';
	database.GetVariable("holdzones",tmp, 20);	
	if ((strcasecmp(tmp, "1") == 0)) {
		holdzones = true;
	}
	_log(WORLD__INIT, "Reboot zone modes %s",holdzones ? "ON" : "OFF");
	
	_log(WORLD__INIT, "Deleted %i stale player corpses from database", database.DeleteStalePlayerCorpses());
	_log(WORLD__INIT, "Deleted %i stale player backups from database", database.DeleteStalePlayerBackups());

	_log(WORLD__INIT, "Purging expired instances");
	database.PurgeExpiredInstances();
	Timer PurgeInstanceTimer(450000);
	PurgeInstanceTimer.Start(450000);

	char errbuf[TCPConnection_ErrorBufferSize];
	if (tcps.Open(Config->WorldTCPPort, errbuf)) {
		_log(WORLD__INIT,"Zone (TCP) listener started.");
	} else {
		_log(WORLD__INIT_ERR,"Failed to start zone (TCP) listener on port %d:",Config->WorldTCPPort);
		_log(WORLD__INIT_ERR,"        %s",errbuf);
		return 1;
	}
	if (eqsf.Open()) {
		_log(WORLD__INIT,"Client (UDP) listener started.");
	} else {
		_log(WORLD__INIT_ERR,"Failed to start client (UDP) listener (port 9000)");
		return 1;
	}

	//ItemInst a((SharedDatabase *)&database,(uint32)17354,0);
	//ItemInst b((SharedDatabase *)&database,(uint32)26885,0);
	//ItemInst c((SharedDatabase *)&database,(uint32)41075,0);
	//ItemInst d((SharedDatabase *)&database,(uint32)29041,0);
	//d.PutAugment(&database,0,41006);
	//a.PutItem(0,b);
	//a.PutItem(1,c);
	//a.PutItem(2,d);
	//_log(WORLD__INIT,"%s\n",Client62::SerializeItem(&a,30,0));
	
	//register all the patches we have avaliable with the stream identifier.
	EQStreamIdentifier stream_identifier;
	RegisterAllPatches(stream_identifier);
	
	
	zoneserver_list.shutdowntimer=new Timer(60000);
	zoneserver_list.shutdowntimer->Disable();
	zoneserver_list.reminder = new Timer(20000);
	zoneserver_list.reminder->Disable();
	Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect
	InterserverTimer.Trigger();
	EQStream* eqs;
	EmuTCPConnection* tcpc;
	EQStreamInterface *eqsi;
	
	while(RunLoops) {
		Timer::SetCurrentTime();
		
		//check the factory for any new incoming streams.
		while ((eqs = eqsf.Pop())) {
			//pull the stream out of the factory and give it to the stream identifier
			//which will figure out what patch they are running, and set up the dynamic
			//structures and opcodes for that patch.
			struct in_addr	in;
			in.s_addr = eqs->GetRemoteIP();
			_log(WORLD__CLIENT, "New connection from %s:%d", inet_ntoa(in),ntohs(eqs->GetRemotePort()));
			stream_identifier.AddStream(eqs);	//takes the stream
		}
		
		//give the stream identifier a chance to do its work....
		stream_identifier.Process();
		
		//check the stream identifier for any now-identified streams
		while((eqsi = stream_identifier.PopIdentified())) {
			//now that we know what patch they are running, start up their client object
			struct in_addr	in;
			in.s_addr = eqsi->GetRemoteIP();
 			if (RuleB(World, UseBannedIPsTable)){ //Lieka:  Check to see if we have the responsibility for blocking IPs.
				_log(WORLD__CLIENT, "Checking inbound connection %s against BannedIPs table", inet_ntoa(in));
 				if (!database.CheckBannedIPs(inet_ntoa(in))){ //Lieka:  Check inbound IP against banned IP table.
 					_log(WORLD__CLIENT, "Connection %s PASSED banned IPs check.  Processing connection.", inet_ntoa(in));
 					Client* client = new Client(eqsi);
 					// @merth: client->zoneattempt=0;
 					client_list.Add(client);
 				} else {
 					_log(WORLD__CLIENT, "Connection from %s FAILED banned IPs check.  Closing connection.", inet_ntoa(in));
 					eqsi->Close(); //Lieka:  If the inbound IP is on the banned table, close the EQStream.
 				}
 			}
 			if (!RuleB(World, UseBannedIPsTable)){
 					_log(WORLD__CLIENT, "New connection from %s:%d, processing connection", inet_ntoa(in), ntohs(eqsi->GetRemotePort()));
 					Client* client = new Client(eqsi);
 					// @merth: client->zoneattempt=0;
 					client_list.Add(client);
 			}
		}
		
		client_list.Process();
		
		while ((tcpc = tcps.NewQueuePop())) {
			struct in_addr in;
			in.s_addr = tcpc->GetrIP();
			_log(WORLD__ZONE, "New TCP connection from %s:%d", inet_ntoa(in),tcpc->GetrPort());
			console_list.Add(new Console(tcpc));
		}

		if(PurgeInstanceTimer.Check())
		{
			database.PurgeExpiredInstances();
		}
		
		//check for timeouts in other threads
		timeout_manager.CheckTimeouts();
		
		loginserver.Process();
		
		console_list.Process();
		
		zoneserver_list.Process();
		
		launcher_list.Process();

		LFPGroupList.Process();
		
		if (InterserverTimer.Check()) {
			InterserverTimer.Start();
			database.ping();
			AsyncLoadVariables(dbasync, &database);
			if (Config->LoginHost.length() && loginserver.Connected() == false) {
#ifdef WIN32
				_beginthread(AutoInitLoginServer, 0, NULL);
#else
				pthread_t thread;
				pthread_create(&thread, NULL, &AutoInitLoginServer, NULL);
#endif
			}
		}
		if (numclients == 0) {
			Sleep(50);
			continue;
		}
		Sleep(20);
	}
	_log(WORLD__SHUTDOWN,"World main loop completed.");
	_log(WORLD__SHUTDOWN,"Shutting down console connections (if any).");
	console_list.KillAll();
	_log(WORLD__SHUTDOWN,"Shutting down zone connections (if any).");
	zoneserver_list.KillAll();
	_log(WORLD__SHUTDOWN,"Zone (TCP) listener stopped.");
	tcps.Close();
	_log(WORLD__SHUTDOWN,"Client (UDP) listener stopped.");
	eqsf.Close();
	_log(WORLD__SHUTDOWN,"Signaling HTTP service to stop...");
	http_server.Stop();
#if 0
#if defined(SHAREMEM) && !defined(WIN32)
		for (int ipc_files = 0; ipc_files <= 4; ipc_files++) {
			key_t share_key;
			switch (ipc_files) {
				// Item
				case 0: share_key = ftok(".", 'I'); break;
				// Npctype
				case 1: share_key = ftok(".", 'N'); break;
				// Door
				case 2: share_key = ftok(".", 'D'); break;
				// Spell
				case 3: share_key = ftok(".", 'S'); break;
				// Faction
				case 4: share_key = ftok(".", 'F'); break;
				// ERROR Fatal
				default: cerr<<"Opps!"<<endl; share_key = 0xFF; break;
			}
			
			int share_id = shmget(share_key, 0, IPC_NOWAIT|0400);
			if (share_id <= 0) {
				cerr<<"exiting could not check user count on shared memory ipcs mem leak!!!!!!!! id="<<share_id<<" key:"<<share_key<<endl;
				exit(1);
			}
			struct shmid_ds mem_users;
			if ((shmctl(share_id, IPC_STAT, &mem_users)) != 0) {
				cerr<<"exiting error checking user count on shared memory, marking for deletion!!!!!id="<<share_id<<" key:"<<share_key<<endl;
				shmctl(share_id, IPC_RMID, 0);
				exit(1);
			}
			if (mem_users.shm_nattch == 0) {
				//cerr<<"exiting stale share marked for deletion!id="<<share_id<<" key:"<<share_key<<endl;
				shmctl(share_id, IPC_RMID, 0);
			}
			else if (mem_users.shm_nattch == 1) {
				//cerr<<"mem_users = 1"<<endl;
				// Detatch and delete shared mem here
				EMuShareMemDLL.Unload();
				shmctl(share_id, IPC_RMID, 0);
			}

		}
#endif
#endif

	CheckEQEMuErrorAndPause();
	return 0;
}
Ejemplo n.º 29
0
int EQW::CountZones() {
	return(zoneserver_list.GetZoneCount());
}
Ejemplo n.º 30
0
int main(int argc, char** argv) {
    RegisterExecutablePlatform(ExePlatformWorld);
    set_exception_handler();

	// Load server configuration
	_log(WORLD__INIT, "Loading server configuration..");
	if (!WorldConfig::LoadConfig()) {
		_log(WORLD__INIT_ERR, "Loading server configuration failed.");
		return(1);
	}
	const WorldConfig *Config=WorldConfig::get();

	if(!load_log_settings(Config->LogSettingsFile.c_str()))
		_log(WORLD__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str());
	else
		_log(WORLD__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str());


	_log(WORLD__INIT, "CURRENT_VERSION: %s", CURRENT_VERSION);
	
	#ifdef _DEBUG
		_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	#endif
	
	if (signal(SIGINT, CatchSignal) == SIG_ERR)	{
		_log(WORLD__INIT_ERR, "Could not set signal handler");
		return 0;
	}
	if (signal(SIGTERM, CatchSignal) == SIG_ERR)	{
		_log(WORLD__INIT_ERR, "Could not set signal handler");
		return 0;
	}
	#ifndef WIN32
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)	{
		_log(WORLD__INIT_ERR, "Could not set signal handler");
		return 0;
	}
	#endif

	// add login server config to list
	if (Config->LoginCount == 0) {
		if (Config->LoginHost.length()) {
			loginserverlist.Add(Config->LoginHost.c_str(), Config->LoginPort, Config->LoginAccount.c_str(), Config->LoginPassword.c_str());
			_log(WORLD__INIT, "Added loginserver %s:%i", Config->LoginHost.c_str(), Config->LoginPort);
		}
	} else {
		LinkedList<LoginConfig*> loginlist=Config->loginlist;
		LinkedListIterator<LoginConfig*> iterator(loginlist);
		iterator.Reset();
		while(iterator.MoreElements()) {
			loginserverlist.Add(iterator.GetData()->LoginHost.c_str(), iterator.GetData()->LoginPort, iterator.GetData()->LoginAccount.c_str(), iterator.GetData()->LoginPassword.c_str());
			_log(WORLD__INIT, "Added loginserver %s:%i", iterator.GetData()->LoginHost.c_str(), iterator.GetData()->LoginPort);
			iterator.Advance();
		}
	}
	
	_log(WORLD__INIT, "Connecting to MySQL...");
	if (!database.Connect(
		Config->DatabaseHost.c_str(),
		Config->DatabaseUsername.c_str(),
		Config->DatabasePassword.c_str(),
		Config->DatabaseDB.c_str(),
		Config->DatabasePort)) {
		_log(WORLD__INIT_ERR, "Cannot continue without a database connection.");
		return(1);
	}
	dbasync = new DBAsync(&database);
	guild_mgr.SetDatabase(&database);
	
	if (argc >= 2) {
		char tmp[2];
		if (strcasecmp(argv[1], "help") == 0 || strcasecmp(argv[1], "?") == 0 || strcasecmp(argv[1], "/?") == 0 || strcasecmp(argv[1], "-?") == 0 || strcasecmp(argv[1], "-h") == 0 || strcasecmp(argv[1], "-help") == 0) {
			cout << "Worldserver command line commands:" << endl;
			cout << "adduser username password flag    - adds a user account" << endl;
			cout << "flag username flag    - sets GM flag on the account" << endl;
			cout << "startzone zoneshortname    - sets the starting zone" << endl;
			cout << "-holdzones    - reboots lost zones" << endl;
			return 0;
		}
		else if (strcasecmp(argv[1], "-holdzones") == 0) {
			cout << "Reboot Zones mode ON" << endl;
			holdzones = true;
		}
		else if (database.GetVariable("disablecommandline", tmp, 2)) {
			if (strlen(tmp) == 1) {
				if (tmp[0] == '1') {
					cout << "Command line disabled in database... exiting" << endl;
					return 0;
				}
			}
		}
		else if (strcasecmp(argv[1], "adduser") == 0) {
			if (argc == 5) {
				if (Seperator::IsNumber(argv[4])) {
					if (atoi(argv[4]) >= 0 && atoi(argv[4]) <= 255) {
						if (database.CreateAccount(argv[2], argv[3], atoi(argv[4])) == 0)
							cout << "database.CreateAccount failed." << endl;
						else
							cout << "Account created: Username='******', Password='******', status=" << argv[4] << endl;
						return 0;
					}
				}
			}
			cout << "Usage: world adduser username password flag" << endl;
			cout << "flag = 0, 1 or 2" << endl;
			return 0;
		}
		else if (strcasecmp(argv[1], "flag") == 0) {
			if (argc == 4) {
				if (Seperator::IsNumber(argv[3])) {

					if (atoi(argv[3]) >= 0 && atoi(argv[3]) <= 255) {
						if (database.SetAccountStatus(argv[2], atoi(argv[3])))
							cout << "Account flagged: Username='******', status=" << argv[3] << endl;
						else
							cout << "database.SetAccountStatus failed." << endl;
						return 0;
					}
				}
			}
			cout << "Usage: world flag username flag" << endl;
			cout << "flag = 0-200" << endl;
			return 0;
		}
		else if (strcasecmp(argv[1], "startzone") == 0) {
			if (argc == 3) {
				if (strlen(argv[2]) < 3) {
					cout << "Error: zone name too short" << endl;
				}
				else if (strlen(argv[2]) > 15) {
					cout << "Error: zone name too long" << endl;
				}
				else {
					if (database.SetVariable("startzone", argv[2]))
						cout << "Starting zone changed: '" << argv[2] << "'" << endl;
					else
						cout << "database.SetVariable failed." << endl;
				}
				return 0;
			}
			cout << "Usage: world startzone zoneshortname" << endl;
			return 0;
		}
		else {
			cout << "Error, unknown command line option" << endl;
			return 0;
		}
	}
	
	if(Config->WorldHTTPEnabled) {
		_log(WORLD__INIT, "Starting HTTP world service...");
		http_server.Start(Config->WorldHTTPPort, Config->WorldHTTPMimeFile.c_str());
	} else {
		_log(WORLD__INIT, "HTTP world service disabled.");
	}
	
	_log(WORLD__INIT, "Loading variables..");
	database.LoadVariables();
	_log(WORLD__INIT, "Loading zones..");
	database.LoadZoneNames();
	_log(WORLD__INIT, "Clearing groups..");
	database.ClearGroup();
	_log(WORLD__INIT, "Clearing raids..");
	database.ClearRaid();
	database.ClearRaidDetails();
	_log(WORLD__INIT, "Loading items..");
	if (!database.LoadItems()) {
		_log(WORLD__INIT_ERR, "Error: Could not load item data.  But ignoring");
	}
	_log(WORLD__INIT, "Loading guilds..");
	guild_mgr.LoadGuilds();
	//rules:
	{
		char tmp[64];
		if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) {
			_log(WORLD__INIT, "Loading rule set '%s'", tmp);
			if(!RuleManager::Instance()->LoadRules(&database, tmp)) {
				_log(WORLD__INIT_ERR, "Failed to load ruleset '%s', falling back to defaults.", tmp);
			}
		} else {
			if(!RuleManager::Instance()->LoadRules(&database, "default")) {
				_log(WORLD__INIT, "No rule set configured, using default rules");
			} else {
				_log(WORLD__INIT, "Loaded default rule set 'default'", tmp);
			}
		}
	}
	if(RuleB(World, ClearTempMerchantlist)){
        _log(WORLD__INIT, "Clearing temporary merchant lists..");
		database.ClearMerchantTemp();
      }
	_log(WORLD__INIT, "Loading EQ time of day..");
	if (!zoneserver_list.worldclock.loadFile(Config->EQTimeFile.c_str()))
		_log(WORLD__INIT_ERR, "Unable to load %s", Config->EQTimeFile.c_str());
	_log(WORLD__INIT, "Loading launcher list..");
	launcher_list.LoadList();
	
	char tmp[20];
	tmp[0] = '\0';
	database.GetVariable("holdzones",tmp, 20);	
	if ((strcasecmp(tmp, "1") == 0)) {
		holdzones = true;
	}
	_log(WORLD__INIT, "Reboot zone modes %s",holdzones ? "ON" : "OFF");
	
	_log(WORLD__INIT, "Deleted %i stale player corpses from database", database.DeleteStalePlayerCorpses());
	if (RuleB(World, DeleteStaleCorpeBackups) == true) {
	_log(WORLD__INIT, "Deleted %i stale player backups from database", database.DeleteStalePlayerBackups());
	}

	_log(WORLD__INIT, "Loading adventures...");
	if(!adventure_manager.LoadAdventureTemplates())
	{
		_log(WORLD__INIT_ERR, "Unable to load adventure templates.");
	}

	if(!adventure_manager.LoadAdventureEntries())
	{
		_log(WORLD__INIT_ERR, "Unable to load adventure templates.");
	}

	adventure_manager.Load();
	adventure_manager.LoadLeaderboardInfo();

	_log(WORLD__INIT, "Purging expired instances");
	database.PurgeExpiredInstances();
	Timer PurgeInstanceTimer(450000);
	PurgeInstanceTimer.Start(450000);

    _log(WORLD__INIT, "Loading char create info...");
    database.LoadCharacterCreateAllocations();
    database.LoadCharacterCreateCombos();

	char errbuf[TCPConnection_ErrorBufferSize];
	if (tcps.Open(Config->WorldTCPPort, errbuf)) {
		_log(WORLD__INIT,"Zone (TCP) listener started.");
	} else {
		_log(WORLD__INIT_ERR,"Failed to start zone (TCP) listener on port %d:",Config->WorldTCPPort);
		_log(WORLD__INIT_ERR,"        %s",errbuf);
		return 1;
	}
	if (eqsf.Open()) {
		_log(WORLD__INIT,"Client (UDP) listener started.");
	} else {
		_log(WORLD__INIT_ERR,"Failed to start client (UDP) listener (port 9000)");
		return 1;
	}

	//register all the patches we have avaliable with the stream identifier.
	EQStreamIdentifier stream_identifier;
	RegisterAllPatches(stream_identifier);
	zoneserver_list.shutdowntimer = new Timer(60000);
	zoneserver_list.shutdowntimer->Disable();
	zoneserver_list.reminder = new Timer(20000);
	zoneserver_list.reminder->Disable();
	Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect
	InterserverTimer.Trigger();
	uint8 ReconnectCounter = 100;
	EQStream* eqs;
	EmuTCPConnection* tcpc;
	EQStreamInterface *eqsi;
	
	while(RunLoops) {
		Timer::SetCurrentTime();
		
		//check the factory for any new incoming streams.
		while ((eqs = eqsf.Pop())) {
			//pull the stream out of the factory and give it to the stream identifier
			//which will figure out what patch they are running, and set up the dynamic
			//structures and opcodes for that patch.
			struct in_addr	in;
			in.s_addr = eqs->GetRemoteIP();
			_log(WORLD__CLIENT, "New connection from %s:%d", inet_ntoa(in),ntohs(eqs->GetRemotePort()));
			stream_identifier.AddStream(eqs);	//takes the stream
		}
		
		//give the stream identifier a chance to do its work....
		stream_identifier.Process();
		
		//check the stream identifier for any now-identified streams
		while((eqsi = stream_identifier.PopIdentified())) {
			//now that we know what patch they are running, start up their client object
			struct in_addr	in;
			in.s_addr = eqsi->GetRemoteIP();
 			if (RuleB(World, UseBannedIPsTable)){ //Lieka:  Check to see if we have the responsibility for blocking IPs.
				_log(WORLD__CLIENT, "Checking inbound connection %s against BannedIPs table", inet_ntoa(in));
 				if (!database.CheckBannedIPs(inet_ntoa(in))){ //Lieka:  Check inbound IP against banned IP table.
 					_log(WORLD__CLIENT, "Connection %s PASSED banned IPs check.  Processing connection.", inet_ntoa(in));
 					Client* client = new Client(eqsi);
 					// @merth: client->zoneattempt=0;
 					client_list.Add(client);
 				} else {
 					_log(WORLD__CLIENT, "Connection from %s FAILED banned IPs check.  Closing connection.", inet_ntoa(in));
 					eqsi->Close(); //Lieka:  If the inbound IP is on the banned table, close the EQStream.
 				}
 			}
 			if (!RuleB(World, UseBannedIPsTable)){
 					_log(WORLD__CLIENT, "New connection from %s:%d, processing connection", inet_ntoa(in), ntohs(eqsi->GetRemotePort()));
 					Client* client = new Client(eqsi);
 					// @merth: client->zoneattempt=0;
 					client_list.Add(client);
 			}
		}
		
		client_list.Process();
		
		while ((tcpc = tcps.NewQueuePop())) {
			struct in_addr in;
			in.s_addr = tcpc->GetrIP();
			_log(WORLD__ZONE, "New TCP connection from %s:%d", inet_ntoa(in),tcpc->GetrPort());
			console_list.Add(new Console(tcpc));
		}

		if(PurgeInstanceTimer.Check())
		{
			database.PurgeExpiredInstances();
		}
		
		//check for timeouts in other threads
		timeout_manager.CheckTimeouts();
		
		loginserverlist.Process();
		
		console_list.Process();
		
		zoneserver_list.Process();
		
		launcher_list.Process();

		UCSLink.Process();
	
		QSLink.Process();

		LFPGroupList.Process();

		adventure_manager.Process();
		
		if (InterserverTimer.Check()) {
			InterserverTimer.Start();
			database.ping();
			AsyncLoadVariables(dbasync, &database);
			ReconnectCounter++;
			if (ReconnectCounter >= 12) { // only create thread to reconnect every 10 minutes. previously we were creating a new thread every 10 seconds
				ReconnectCounter = 0;
				if (loginserverlist.AllConnected() == false) {
#ifdef _WINDOWS
					_beginthread(AutoInitLoginServer, 0, nullptr);
#else
					pthread_t thread;
					pthread_create(&thread, nullptr, &AutoInitLoginServer, nullptr);
#endif
				}
			}
		}
		if (numclients == 0) {
			Sleep(50);
			continue;
		}
		Sleep(20);
	}
	_log(WORLD__SHUTDOWN,"World main loop completed.");
	_log(WORLD__SHUTDOWN,"Shutting down console connections (if any).");
	console_list.KillAll();
	_log(WORLD__SHUTDOWN,"Shutting down zone connections (if any).");
	zoneserver_list.KillAll();
	_log(WORLD__SHUTDOWN,"Zone (TCP) listener stopped.");
	tcps.Close();
	_log(WORLD__SHUTDOWN,"Client (UDP) listener stopped.");
	eqsf.Close();
	_log(WORLD__SHUTDOWN,"Signaling HTTP service to stop...");
	http_server.Stop();

	CheckEQEMuErrorAndPause();
	return 0;
}