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; } } }
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; }
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; }
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; }