예제 #1
0
void Clientlist::Process() {

	EQStream *eqs;

	while((eqs = mailsf->Pop())) {

		struct in_addr  in;

		in.s_addr = eqs->GetRemoteIP();

		_log(MAIL__CLIENT, "New Client UDP Mail connection from %s:%d", inet_ntoa(in), ntohs(eqs->GetRemotePort()));

		eqs->SetOpcodeManager(&MailOpMgr);

		Client *c = new Client(eqs);

		ClientMailConnections.push_back(c);
	}

	list<Client*>::iterator Iterator;

	for(Iterator = ClientMailConnections.begin(); Iterator != ClientMailConnections.end(); Iterator++) {

		if((*Iterator)->ClientStream->CheckClosed()) {

			struct in_addr  in;

			in.s_addr = (*Iterator)->ClientStream->GetRemoteIP();

			_log(MAIL__CLIENT, "Client connection from %s:%d closed.", inet_ntoa(in),
										   ntohs((*Iterator)->ClientStream->GetRemotePort()));
			
			safe_delete((*Iterator));

			Iterator = ClientMailConnections.erase(Iterator);

			if(Iterator == ClientMailConnections.end())
				break;

			continue;
		}

		EQApplicationPacket *app = 0;

		bool KeyValid = true;

		while( KeyValid && (app = (EQApplicationPacket *)(*Iterator)->ClientStream->PopPacket())) {

			_pkt(MAIL__PACKETS, app);

			EmuOpcode opcode = app->GetOpcode();

			switch(opcode) {

				case OP_MailLogin: {

					char *PacketBuffer = (char *)app->pBuffer;

					char MailBox[64];

					char Key[64];

					VARSTRUCT_DECODE_STRING(MailBox, PacketBuffer);

					// Check to see if we are running with a version of world that inserts a Connection Type
					// indicator at the start of the mailkey, and skip past it if so.
					if(strlen(PacketBuffer) == 9)
						PacketBuffer++;

					VARSTRUCT_DECODE_STRING(Key, PacketBuffer);

					string MailBoxString = MailBox, CharacterName;

					// Strip off the SOE.EQ.<shortname>.
					//
					string::size_type LastPeriod = MailBoxString.find_last_of(".");

					if(LastPeriod == string::npos)
						CharacterName = MailBoxString;
					else
						CharacterName = MailBoxString.substr(LastPeriod + 1);

					_log(MAIL__TRACE, "Received login for mailbox %s with key %s", MailBox, Key);

					if(!database.VerifyMailKey(CharacterName, (*Iterator)->ClientStream->GetRemoteIP(), Key)) {

						_log(MAIL__ERROR, "Mail Key for %s does not match, closing connection.", MailBox);

						KeyValid = false;

						break;
					}

					database.FindAccount(CharacterName.c_str(), (*Iterator));

					(*Iterator)->SendMailBoxes();

					CheckForStaleConnections((*Iterator));

					break;
				}

				case OP_Mail: {
					const char *inbuf = (const char*)app->pBuffer;

					if((app->size >= 11) && !strncmp(inbuf, "getheaders", 10)) { // getheaders

						database.SendHeaders((*Iterator));

					}
					else if((app->size >= 8) && !strncmp(inbuf, "getbody", 7)) {

							string GetBodyCommand = inbuf;

							database.SendBody((*Iterator), atoi(GetBodyCommand.substr(8).c_str()));
					}
					else if((app->size >= 7) && !strncmp(inbuf, "mailto", 6)) {

							ProcessMailTo((*Iterator), inbuf);
					}
					else if((app->size >= 17) && !strncmp(inbuf, "setmessagestatus", 16)) {

						int MessageNumber;

						int Status;

						string SetMessageCommand = inbuf;

						switch(SetMessageCommand[17]) {

							case 'R': // READ
								Status = 3;
								break;

							case 'T': // TRASH
								Status = 4;
								break;

							default: // DELETE
								Status = 0;

						}
						string::size_type NumStart = SetMessageCommand.find_first_of("123456789", 18);

						while(NumStart != string::npos) {

							string::size_type NumEnd = SetMessageCommand.find_first_of(" ", NumStart);

							if(NumEnd == string::npos) {

								MessageNumber = atoi(SetMessageCommand.substr(NumStart).c_str());

								database.SetMessageStatus(MessageNumber, Status);

								break;
							}

							MessageNumber = atoi(SetMessageCommand.substr(NumStart, NumEnd-NumStart).c_str());

							database.SetMessageStatus(MessageNumber, Status);

							NumStart = SetMessageCommand.find_first_of("123456789", NumEnd);
						}
					}
					else if((app->size >= 14) && !strncmp(inbuf, "selectmailbox", 13)) {

						string SelectMailBoxCommand = inbuf;

						string::size_type NumStart = SelectMailBoxCommand.find_first_of("0123456789", 13);

						int MailBoxNumber = atoi(SelectMailBoxCommand.substr(NumStart).c_str());

						_log(MAIL__TRACE, "%s Change to mailbox %i", (*Iterator)->MailBoxName().c_str(), MailBoxNumber);

						(*Iterator)->SetMailBox(MailBoxNumber);

						_log(MAIL__TRACE, "New mailbox is %s", (*Iterator)->MailBoxName().c_str());
						
						EQApplicationPacket *outapp = new EQApplicationPacket(OP_MailboxChange, 2);

						char *buf = (char *)outapp->pBuffer;

						VARSTRUCT_ENCODE_INTSTRING(buf, MailBoxNumber);
						
						_pkt(MAIL__PACKETS, outapp);

						(*Iterator)->QueuePacket(outapp);

						safe_delete(outapp);
					}
					else if((app->size >= 18) && !strncmp(inbuf, "setmailforwarding", 17)) {
						// This is sent to turn mail forwarding to your Station email account on/off
						// Not implemented.
						_log(MAIL__TRACE, "Unimplemented command: %s", inbuf);
					}
					else
						_log(MAIL__ERROR, "Unhandled OP_Mail command: %s", inbuf);

					break;
				}

				default: {
					_log(MAIL__ERROR, "Unhandled mail opcode %8X", opcode);
					break;
				}
			}
			safe_delete(app);

		}
		if(!KeyValid) {
			(*Iterator)->ClientStream->Close();

			safe_delete((*Iterator));

			Iterator = ClientMailConnections.erase(Iterator);

			if(Iterator == ClientMailConnections.end())
				break;
		}

	}

}
예제 #2
0
파일: Client.cpp 프로젝트: Vaion/Server
bool Client::Process()
{
	EQApplicationPacket *app = connection->PopPacket();
	while(app)
	{
		if(server.options.IsTraceOn())
		{
			server_log->Log(log_network, "Application packet recieved from client (size %u)", app->Size());
		}

		if(server.options.IsDumpInPacketsOn())
		{
			DumpPacket(app);
		}

		switch(app->GetOpcode())
		{
		case OP_SessionReady:
			{
				if(server.options.IsTraceOn())
				{
					server_log->Log(log_network, "Session ready recieved from client.");
				}
				Handle_SessionReady((const char*)app->pBuffer, app->Size());
				break;
			}
		case OP_Login:
			{
				if(app->Size() < 20)
				{
					server_log->Log(log_network_error, "Login recieved but it is too small, discarding.");
					break;
				}

				if(server.options.IsTraceOn())
				{
					server_log->Log(log_network, "Login recieved from client.");
				}

				Handle_Login((const char*)app->pBuffer, app->Size());
				break;
			}
		case OP_ServerListRequest:
			{
				if(server.options.IsTraceOn())
				{
					server_log->Log(log_network, "Server list request recieved from client.");
				}

				SendServerListPacket();
				break;
			}
		case OP_PlayEverquestRequest:
			{
				if(app->Size() < sizeof(PlayEverquestRequest_Struct))
				{
					server_log->Log(log_network_error, "Play recieved but it is too small, discarding.");
					break;
				}

				Handle_Play((const char*)app->pBuffer);
				break;
			}
		default:
			{
				char dump[64];
				app->build_header_dump(dump);
				server_log->Log(log_network_error, "Recieved unhandled application packet from the client: %s.", dump);
			}
		}

		delete app;
		app = connection->PopPacket();
	}

	return true;
}
예제 #3
0
void StructStrategy::ErrorEncoder(EQApplicationPacket **in_p, EQStreamInterface *dest, bool ack_req) {
	EQApplicationPacket *p = *in_p;
	*in_p = nullptr;

	Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Error encoding opcode %s: no encoder provided. Dropping.", OpcodeManager::EmuToName(p->GetOpcode()));

	delete p;
}
예제 #4
0
void StructStrategy::ErrorEncoder(EQApplicationPacket **in_p, EQStream *dest, bool ack_req) {
	EQApplicationPacket *p = *in_p;
	*in_p = nullptr;

	_log(NET__STRUCTS, "Error encoding opcode %s: no encoder provided. Dropping.", OpcodeManager::EmuToName(p->GetOpcode()));

	delete p;
}