示例#1
0
bool WorldServer::Process()
{
	ServerPacket *app = nullptr;
	while(app = connection->PopPacket())
	{
		server_log->WorldTrace("Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size);

		if (server_log->DumpIn())
		{
			DumpPacket(app);
		}

		switch(app->opcode)
		{
		case ServerOP_NewLSInfo:
			{
				if(app->size < sizeof(ServerNewLSInfo_Struct))
				{
					server_log->Log(log_network_error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
						"but was too small. Discarded to avoid buffer overrun.");
					break;
				}

				server_log->WorldTrace("New Login Info Received.");
				ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)app->pBuffer;
				Handle_NewLSInfo(info);
				break;
			}
		case ServerOP_LSStatus:
			{
				if(app->size < sizeof(ServerLSStatus_Struct))
				{
					server_log->Log(log_network_error, "Received application packet from server that had opcode ServerOP_LSStatus, "
						"but was too small. Discarded to avoid buffer overrun.");
					break;
				}

				server_log->WorldTrace("World Server Status Received.");

				ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)app->pBuffer;
				Handle_LSStatus(ls_status);
				break;
			}
		case ServerOP_LSZoneInfo:
		case ServerOP_LSZoneShutdown:
		case ServerOP_LSZoneStart:
		case ServerOP_LSZoneBoot:
		case ServerOP_LSZoneSleep:
		case ServerOP_LSPlayerLeftWorld:
		case ServerOP_LSPlayerJoinWorld:
		case ServerOP_LSPlayerZoneChange:
			{
				//Not logging these to cut down on spam until we implement them
				break;
			}

		case ServerOP_UsertoWorldResp:
			{
				if(app->size < sizeof(UsertoWorldResponse_Struct))
				{
					server_log->Log(log_network_error, "Received application packet from server that had opcode ServerOP_UsertoWorldResp, "
						"but was too small. Discarded to avoid buffer overrun.");
					break;
				}

				//I don't use world trace for this and here is why:
				//Because this is a part of the client login procedure it makes tracking client errors
				//While keeping world server spam with multiple servers connected almost impossible.
				server_log->Trace("User-To-World Response received.");

				UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)app->pBuffer;
				server_log->Log(log_client, "Trying to find client with user id of %u.", utwr->lsaccountid);
				Client *c = server.CM->GetClient(utwr->lsaccountid);
				if(c && c->GetClientVersion() == cv_old)
				{
					if(utwr->response > 0)
					{
						SendClientAuth(c->GetConnection()->GetRemoteIP(), c->GetAccountName(), c->GetKey(), c->GetAccountID(), c->GetMacClientVersion());
					}

					switch(utwr->response)
					{
						case 1:
							break;
						case 0:
							c->FatalError("\nError 1020: Your chosen World Server is DOWN.\n\nPlease select another.");
							break;
						case -1:
							c->FatalError("You have been suspended from the worldserver.");
							break;
						case -2:
							c->FatalError("You have been banned from the worldserver.");
							break;
						case -3:
							c->FatalError("That server is full.");
							break;
						case -4:
							c->FatalError("Error 1018: You currently have an active character on that EverQuest Server, please allow a minute for synchronization and try again.");
							break;
						case -5:
							c->FatalError("Error IP Limit Exceeded: \n\nYou have exceeded the maximum number of allowed IP addresses for this account.");
							break;
					}
					server_log->Log(log_client, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
					EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestRequest, 17);
					strncpy((char*) &outapp->pBuffer[1], c->GetKey().c_str(), c->GetKey().size());

					c->SendPlayResponse(outapp);
				}
				else if(c)
				{
					server_log->Log(log_client, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
					EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
					PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
					per->Sequence = c->GetPlaySequence();
					per->ServerNumber = c->GetPlayServerID();
					server_log->Log(log_client, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
					server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);

					if (utwr->response > 0)
					{
						per->Allowed = 1;
						SendClientAuth(c->GetConnection()->GetRemoteIP(), c->GetAccountName(), c->GetKey(), c->GetAccountID());
					}

					switch (utwr->response)
					{
					case 1:
						per->Message = 101;
						break;
					case 0:
						per->Message = 326;
						break;
					case -1:
						per->Message = 337;
						break;
					case -2:
						per->Message = 338;
						break;
					case -3:
						per->Message = 303;
						break;
					case -4:
						per->Message = 111;
						break;
					case -5:
						per->Message = 198;
						break;
					}

					server_log->Trace("Sending play response to client.");
					server_log->TracePacket((const char*)outapp->pBuffer, outapp->size);

					if (server_log->DumpOut())
					{
						DumpPacket(outapp);
					}
					c->SendPlayResponse(outapp);
					delete outapp;
				}
				else
				{
					server_log->Log(log_client_error, "Received User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
				}
				break;
			}
		case ServerOP_LSAccountUpdate:
			{
				if(app->size < sizeof(ServerLSAccountUpdate_Struct))
				{
					server_log->Log(log_network_error, "Received application packet from server that had opcode ServerLSAccountUpdate_Struct, "
						"but was too small. Discarded to avoid buffer overrun.");
					break;
				}
			
				server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
				ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)app->pBuffer;
				if(trusted)
				{
					server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
					string name;
					string password;
					string email;
					name.assign(lsau->useraccount);
					password.assign(lsau->userpassword);
					email.assign(lsau->useremail);
					db.CreateLSAccount(name, password, email, 0, "", "");
				}
				break;
			}
		default:
			{
				server_log->Log(log_network_error, "Received application packet from server that had an unknown operation code 0x%.4X.", app->opcode);
			}
		}
		delete app;
		app = nullptr;
	}
	return true;
}