void Client::Handle_SessionReady(const char* data, unsigned int size) { if(status != cs_not_sent_session_ready) { server_log->Log(log_network_error, "Session ready recieved again after already being recieved."); return; } if(size < sizeof(unsigned int)) { server_log->Log(log_network_error, "Session ready was too small."); return; } unsigned int mode = *((unsigned int*)data); if(mode == (unsigned int)lm_from_world) { server_log->Log(log_network, "Session ready indicated logged in from world(unsupported feature), disconnecting."); connection->Close(); return; } status = cs_waiting_for_login; /** * The packets are mostly the same but slightly different between the two versions. */ if(version == cv_sod) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_ChatMessage, 17); outapp->pBuffer[0] = 0x02; outapp->pBuffer[10] = 0x01; outapp->pBuffer[11] = 0x65; if(server.options.IsDumpOutPacketsOn()) { DumpPacket(outapp); } connection->QueuePacket(outapp); delete outapp; } else { const char *msg = "ChatMessage"; EQApplicationPacket *outapp = new EQApplicationPacket(OP_ChatMessage, 16 + strlen(msg)); outapp->pBuffer[0] = 0x02; outapp->pBuffer[10] = 0x01; outapp->pBuffer[11] = 0x65; strcpy((char*)(outapp->pBuffer + 15), msg); if(server.options.IsDumpOutPacketsOn()) { DumpPacket(outapp); } connection->QueuePacket(outapp); delete outapp; } }
bool EmuTCPConnection::SendPacket(EmuTCPNetPacket_Struct* tnps) { if (RemoteID) { return false; } if (!Connected()) { return false; } if (GetMode() != modePacket) { return false; } LockMutex lock(&MState); eTCPMode tmp = GetMode(); if (tmp == modeTransition) { EmuTCPNetPacket_Struct* tnps2 = (EmuTCPNetPacket_Struct*) new uchar[tnps->size]; memcpy(tnps2, tnps, tnps->size); InModeQueuePush(tnps2); return true; } #if TCPN_LOG_PACKETS >= 1 if (tnps && tnps->opcode != 0) { struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Logging outgoing TCP NetPacket. OPCode: 0x" << std::hex << std::setw(4) << std::setfill('0') << tnps->opcode << std::dec << ", size: " << std::setw(5) << std::setfill(' ') << tnps->size << " " << inet_ntoa(in) << ":" << GetrPort(); if (pOldFormat) { std::cout << " (OldFormat)"; } std::cout << std::endl; #if TCPN_LOG_PACKETS == 2 if (tnps->size >= 32) { DumpPacket((uchar*) tnps, 32); } else { DumpPacket((uchar*) tnps, tnps->size); } #endif #if TCPN_LOG_PACKETS >= 3 DumpPacket((uchar*) tnps, tnps->size); #endif } #endif ServerSendQueuePushEnd((const uchar*) tnps, tnps->size); return true; }
DWORD __fastcall RecvHook_WOD(void* thisPTR, void* dummy, void* param1, void* param2, CDataStore* ds, void* param4) { DumpPacket(SMSG, 0, *(DWORD*)ds->buffer, 4, ds->size, ds->buffer); CHECK(hookInfo.recvHookGood, "Recv hook is working.\n"); typedef DWORD(__thiscall *proto)(void*, void*, void*, void*, void*); return reinterpret_cast<proto>(hookInfo.recvDetour)(thisPTR, param1, param2, ds, param4); }
DWORD __fastcall SendHook(void* thisPTR, void* dummy, CDataStore* ds, DWORD connectionId) { DumpPacket(CMSG, connectionId, *(DWORD*)ds->buffer, 4, ds->size, ds->buffer); CHECK(hookInfo.sendHookGood, "Send hook is working.\n"); typedef DWORD(__thiscall *proto)(void*, void*, DWORD); return reinterpret_cast<proto>(hookInfo.sendDetour)(thisPTR, ds, connectionId); }
DWORD __fastcall RecvHook(void* thisPTR, void* /* dummy */, void* param1, CDataStore* dataStore, void* param3) { WORD opcodeSize = buildNumber <= WOW_MOP_16135 ? 2 : 4; // packet dump DumpPacket(SMSG, 0, opcodeSize, dataStore); // unhooks the recv function HookManager::UnHook(recvAddress, defaultMachineCodeRecv); // calls client's function so it can processes the packet DWORD returnValue = 0; if (buildNumber <= WOW_TBC_8606) // different prototype returnValue = RecvProto8606(recvAddress)(thisPTR, param1, dataStore); else returnValue = RecvProto(recvAddress)(thisPTR, param1, dataStore, param3); // hooks again to catch the next incoming packets also HookManager::ReHook(recvAddress, machineCodeHookRecv); if (!recvHookGood) { printf("Recv hook is working.\n"); recvHookGood = true; } return returnValue; }
void ServerManager::SendOldUserToWorldRequest(const char* server_id, unsigned int client_account_id) { list<WorldServer*>::iterator iter = world_servers.begin(); bool found = false; while(iter != world_servers.end()) { if((*iter)->GetRemoteIP() == server_id) { ServerPacket *outapp = new ServerPacket(ServerOP_UsertoWorldReq, sizeof(UsertoWorldRequest_Struct)); UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct*)outapp->pBuffer; utwr->worldid = (*iter)->GetServerListID(); utwr->lsaccountid = client_account_id; (*iter)->GetConnection()->SendPacket(outapp); found = true; if(server.options.IsDumpInPacketsOn()) { DumpPacket(outapp); } delete outapp; } ++iter; } if(!found && server.options.IsTraceOn()) { server_log->Log(log_client_error, "Client requested a user to world but supplied an invalid id of %s.", server_id); } }
int handle_REQ_PERFORM_SUPPLEMENTARY_SERVICE( unsigned char * pkt, unsigned short len ) { perform_supplementary_service_req * prq = ( perform_supplementary_service_req * ) pkt; unsigned char * ssd = ( unsigned char * ) &prq[1]; unsigned short ssd_len = ( len - ( unsigned short ) sizeof( perform_supplementary_service_req ) ); printf( "Debugger request: REQ_PERFORM_SUPPLEMENTARY_SERVICE\n" ); printf( " ID: 0x%.08x", prq->id ); ServiceNameAndId *lookup; for( lookup = services; lookup != NULL; lookup = lookup->next ) { if( prq->id == lookup->service_id ) { printf( " [%s]", lookup->service_name ); break; } } last_service = lookup; printf( "\n" ); if( ssd_len ) { int rc = 0; if( lookup && lookup->service_decode ) rc = lookup->service_decode( 1, ssd, ssd_len ); if( 0 != rc ) { printf( " supplementary service data:\n" ); DumpPacket( ssd, ssd_len, 1 ); } } return 1; }
bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character."); return false; } else if (app->size != sizeof(CharCreate_Struct)) { clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct)); DumpPacket(app); // the previous behavior was essentially returning true here // but that seems a bit odd to me. return true; } CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer; if(OPCharCreate(char_name, cc) == false) { database.DeleteCharacter(char_name); EQApplicationPacket *outapp = new EQApplicationPacket(OP_ApproveName, 1); outapp->pBuffer[0] = 0; QueuePacket(outapp); safe_delete(outapp); } else { SendCharInfo(); } return true; }
int SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet) { DumpPacket(packet); ssize_t sent = send(sock, packet->data, packet->len, 0); printf("SDLNet_UDP_Send Sock Descriptor=%d, Data=%p, Len=%d, Sent=%ld\n" , sock, packet->data, packet->len, sent); return sent; }
int handle_REQ_READ_IO_REPLY( unsigned char * pkt, unsigned short len ) { printf( "Trap reply: REQ_READ_IO\n" ); printf( " Length: 0x%.04x\n", len ); if( len ){ printf( " Data:\n" ); DumpPacket( pkt, len, 1 ); } return 1; }
/*----------------------------------------------------------------------------*/ int ProcessPacket(mtcp_manager_t mtcp, const int ifidx, uint32_t cur_ts, unsigned char *pkt_data, int len) { struct ethhdr *ethh = (struct ethhdr *)pkt_data; u_short ip_proto = ntohs(ethh->h_proto); int ret; #ifdef PKTDUMP DumpPacket(mtcp, (char *)pkt_data, len, "IN", ifidx); #endif #ifdef NETSTAT mtcp->nstat.rx_packets[ifidx]++; mtcp->nstat.rx_bytes[ifidx] += len + 24; #endif /* NETSTAT */ #if 0 /* ignore mac address which is not for current interface */ int i; for (i = 0; i < 6; i ++) { if (ethh->h_dest[i] != CONFIG.eths[ifidx].haddr[i]) { return FALSE; } } #endif if (ip_proto == ETH_P_IP) { /* process ipv4 packet */ ret = ProcessIPv4Packet(mtcp, cur_ts, ifidx, pkt_data, len); } else if (ip_proto == ETH_P_ARP) { ProcessARPPacket(mtcp, cur_ts, ifidx, pkt_data, len); return TRUE; } else { //DumpPacket(mtcp, (char *)pkt_data, len, "??", ifidx); struct ps_packet packet; packet.ifindex = ifidx; packet.len = len; packet.buf = (char *)pkt_data; ps_slowpath_packet(mtcp->ctx->handle, &packet); return TRUE; } #ifdef NETSTAT if (ret < 0) { mtcp->nstat.rx_errors[ifidx]++; } #endif return ret; }
void Client::SendServerListPacket() { EQApplicationPacket *outapp = server.SM->CreateServerListPacket(this); if(server.options.IsDumpOutPacketsOn()) { DumpPacket(outapp); } connection->QueuePacket(outapp); delete outapp; }
bool EmuTCPConnection::SendPacket(ServerPacket* pack, uint32 iDestination) { if (!Connected()) return false; eTCPMode tmp = GetMode(); if (tmp != modePacket && tmp != modeTransition) return false; LockMutex lock(&MState); if (RemoteID) return RelayLink->SendPacket(pack, RemoteID); else if (pOldFormat) { #if TCPN_LOG_PACKETS >= 1 if (pack && pack->opcode != 0) { struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Logging outgoing TCP OldPacket. OPCode: 0x" << hex << setw(4) << setfill('0') << pack->opcode << dec << ", size: " << setw(5) << setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; #if TCPN_LOG_PACKETS == 2 if (pack->size >= 32) DumpPacket(pack->pBuffer, 32); else DumpPacket(pack); #endif #if TCPN_LOG_PACKETS >= 3 DumpPacket(pack); #endif } #endif SPackSendQueue* spsq = MakeOldPacket(pack); ServerSendQueuePushEnd(spsq->buffer, spsq->size); safe_delete_array(spsq); } else { EmuTCPNetPacket_Struct* tnps = MakePacket(pack, iDestination); if (tmp == modeTransition) { InModeQueuePush(tnps); } else { #if TCPN_LOG_PACKETS >= 1 if (pack && pack->opcode != 0) { struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Logging outgoing TCP packet. OPCode: 0x" << hex << setw(4) << setfill('0') << pack->opcode << dec << ", size: " << setw(5) << setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; #if TCPN_LOG_PACKETS == 2 if (pack->size >= 32) DumpPacket(pack->pBuffer, 32); else DumpPacket(pack); #endif #if TCPN_LOG_PACKETS >= 3 DumpPacket(pack); #endif } #endif ServerSendQueuePushEnd((uchar**) &tnps, tnps->size); } } return true; }
void Mob::CreateHorseSpawnPacket(EQApplicationPacket* app, const char* ownername, uint16 ownerid, Mob* ForWho) { app->SetOpcode(OP_NewSpawn); app->pBuffer = new uchar[sizeof(NewSpawn_Struct)]; app->size = sizeof(NewSpawn_Struct); memset(app->pBuffer, 0, sizeof(NewSpawn_Struct)); NewSpawn_Struct* ns = (NewSpawn_Struct*)app->pBuffer; FillSpawnStruct(ns, ForWho); #if (EQDEBUG >= 11) printf("Horse Spawn Packet - Owner: %s\n", ownername); DumpPacket(app); #endif }
int handle_REQ_WRITE_IO( unsigned char * pkt, unsigned short len ) { write_io_req * prq = ( write_io_req * ) pkt; unsigned short to_write = ( len - ( unsigned short ) sizeof( write_io_req ) ); unsigned char * data = ( unsigned char * ) &prq[1]; printf( "Debugger request: REQ_WRITE_IO\n" ); printf( " Address: %.08x\n", prq->IO_offset ); printf( " Length: %.04x\n", to_write ); printf( " Data:\n" ); DumpPacket( data, to_write, 1 ); return 1; }
int handle_REQ_PERFORM_SUPPLEMENTARY_SERVICE_REPLY( unsigned char * pkt, unsigned short len) { int rc = -1; if( last_service ) { if( last_service && last_service->service_decode ) rc = last_service->service_decode( 0, pkt, len ); } if( 0 != rc ) { printf( " supplementary service response:\n" ); DumpPacket( pkt, len, 1 ); } return 1; }
/*----------------------------------------------------------------------------*/ static int psio_flush_pkts(struct mtcp_thread_context *ctx, int nif) { struct ps_chunk_buf *c_buf; mtcp_manager_t mtcp; struct psio_private_context *ppc; int send_cnt, to_send_cnt = 0; int start_idx, i; ppc = (struct psio_private_context *)ctx->io_private_context; c_buf = &ppc->w_chunk_buf[nif]; mtcp = ctx->mtcp_manager; /* if chunk (for writing) is not there... then return */ if (!c_buf) return -1; to_send_cnt = c_buf->cnt; if (to_send_cnt > 0) { STAT_COUNT(mtcp->runstat.rounds_tx_try); start_idx = c_buf->next_to_send; send_cnt = ps_send_chunk_buf(&ppc->handle, c_buf); for (i = 0; i < send_cnt; i++) { #ifdef NETSTAT mtcp->nstat.tx_bytes[nif] += c_buf->info[start_idx].len + 24; #endif #if PKTDUMP DumpPacket(mtcp, c_buf->buf + c_buf->info[start_idx].offset, c_buf->info[start_idx].len, "OUT", nif); #endif start_idx = (start_idx + 1) % ENTRY_CNT; } if (send_cnt < 0) { TRACE_ERROR("ps_send_chunk_buf failed. " "ret: %d, error: %s\n", send_cnt, strerror(errno)); #ifdef NETSTAT } else { mtcp->nstat.tx_packets[nif] += send_cnt; #endif } return send_cnt; } return 0; }
/*--------------------------------------------------------------------*/ int main() { int sd, bytes_read; char data[1024]; sd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); if ( sd < 0 ) PANIC("Snooper socket"); do { bytes_read = recvfrom(sd, data, sizeof(data), 0, 0, 0); if ( bytes_read > 0 ) DumpPacket(data, bytes_read); } while ( bytes_read > 0 ); return 0; }
int handle_REQ_MACHINE_DATA( unsigned char * pkt, unsigned short len ) { machine_data_req * prq = ( machine_data_req * ) pkt; unsigned char * msd = ( unsigned char * ) &prq[1]; unsigned short msd_len = ( len - ( unsigned short ) sizeof( machine_data_req ) ); printf( "Debugger request: REQ_MACHINE_DATA\n" ); printf( " Type: %u\n", prq->info_type ); printf( " Address: %.04x:%.08x\n", prq->addr.segment, prq->addr.offset ); if( msd_len ) { printf( "Machine specific data - to be decoded:\n" ); DumpPacket( msd, msd_len, 1 ); } return 1; }
//sending functions void PerlPacket::SendTo(Client *who) { if(!who || op == OP_Unknown || (len > 0 && packet == NULL)) return; EQApplicationPacket *outapp = new EQApplicationPacket(op, len); if(len > 0) memcpy(outapp->pBuffer, packet, len); #ifndef WIN32 #warning Rewrite this! #endif // printf("Created this packet with PerlPacket: OP: %s\n", ZoneOpcodeManager->EmuToName(op)); DumpPacket(outapp); who->FastQueuePacket(&outapp); }
int handle_REQ_MACHINE_DATA_REPLY( unsigned char * pkt, unsigned short len ) { machine_data_ret * pr = (machine_data_ret * ) pkt; unsigned char * msd = ( unsigned char * ) &pr[1]; unsigned short msd_len = ( len - ( unsigned short ) sizeof( machine_data_ret ) ); printf( "Trap reply: REQ_MACHINE_DATA\n" ); printf( " Start: %.08x\n", pr->cache_start ); printf( " End: %.08x\n", pr->cache_end ); if( msd_len ){ printf( "Machine specific data - to be decoded:\n" ); DumpPacket( msd, msd_len, 1 ); } return 1; }
VOID DumpPacket2 (const char *prefix, const ETH_HEADER *eth, const unsigned char *data, unsigned int len) { struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE); if (ep) { if (len > DEFAULT_PACKET_LOOKAHEAD) len = DEFAULT_PACKET_LOOKAHEAD; ep->eth = *eth; NdisMoveMemory (ep->payload, data, len); DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len); MemFree (ep, sizeof (struct ethpayload)); } }
void WorldServer::SendClientAuth(unsigned int ip, string account, string key, unsigned int account_id, uint8 version) { ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ServerLSClientAuth)); ServerLSClientAuth* slsca = (ServerLSClientAuth*)outapp->pBuffer; slsca->lsaccount_id = account_id; strncpy(slsca->name, account.c_str(), account.size() > 30 ? 30 : account.size()); strncpy(slsca->key, key.c_str(), 10); slsca->lsadmin = 0; slsca->worldadmin = 0; slsca->ip = ip; slsca->version = version; in_addr in; in.s_addr = ip;connection->GetrIP(); string client_address(inet_ntoa(in)); in.s_addr = connection->GetrIP(); string world_address(inet_ntoa(in)); if(client_address.compare(world_address) == 0) { slsca->local = 1; } else if (client_address.find(db.LoadServerSettings("options", "local_network").c_str()) != string::npos) { slsca->local = 1; } else { slsca->local = 0; } connection->SendPacket(outapp); if (server_log->DumpIn()) { DumpPacket(outapp); } delete outapp; }
DWORD __fastcall SendHook(void* thisPTR, void* /* dummy */, CDataStore* dataStore, void* param2) { // dumps the packet DumpPacket(CMSG, 0, 4, dataStore); // unhooks the send function HookManager::UnHook(sendAddress, defaultMachineCodeSend); // now let's call client's function // so it can send the packet to the server (connection, CDataStore*, 2) DWORD returnValue = SendProto(sendAddress)(thisPTR, dataStore, param2); // hooks again to catch the next outgoing packets also HookManager::ReHook(sendAddress, machineCodeHookSend); if (!sendHookGood) { printf("Send hook is working.\n"); sendHookGood = true; } return 0; }
bool EmuTCPConnection::ProcessReceivedDataAsOldPackets(char* errbuf) { int32 base = 0; int32 size = 4; uchar* buffer; ServerPacket* pack = 0; while ((recvbuf_used - base) >= size) { buffer = &recvbuf[base]; memcpy(&size, &buffer[2], 2); if (size >= MaxTCPReceiveBuffferSize) { #if TCPN_DEBUG_Memory >= 1 std::cout << "TCPConnection[" << GetID() << "]::ProcessReceivedDataAsPackets(): size[" << size << "] >= MaxTCPReceiveBuffferSize" << std::endl; #endif if (errbuf) snprintf(errbuf, TCPConnection_ErrorBufferSize, "EmuTCPConnection::ProcessReceivedDataAsPackets(): size >= MaxTCPReceiveBuffferSize"); return false; } if ((recvbuf_used - base) >= size) { // ok, we got enough data to make this packet! pack = new ServerPacket; memcpy(&pack->opcode, &buffer[0], 2); pack->size = size - 4; /* if () { // TODO: Checksum or size check or something similar // Datastream corruption, get the hell outta here! delete pack; return false; }*/ if (pack->size > 0) { pack->pBuffer = new uchar[pack->size]; memcpy(pack->pBuffer, &buffer[4], pack->size); } if (pack->opcode == 0) { // keepalive, no need to process safe_delete(pack); } else { #if TCPN_LOG_PACKETS >= 1 if (pack && pack->opcode != 0) { struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Logging incoming TCP OldPacket. OPCode: 0x" << hex << setw(4) << setfill('0') << pack->opcode << dec << ", size: " << setw(5) << setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; #if TCPN_LOG_PACKETS == 2 if (pack->size >= 32) DumpPacket(pack->pBuffer, 32); else DumpPacket(pack); #endif #if TCPN_LOG_PACKETS >= 3 DumpPacket(pack); #endif } #endif OutQueuePush(pack); } base += size; size = 4; } } if (base != 0) { if (base >= recvbuf_used) { safe_delete_array(recvbuf); } else { uchar* tmpbuf = new uchar[recvbuf_size - base]; memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base); safe_delete_array(recvbuf); recvbuf = tmpbuf; recvbuf_used -= base; recvbuf_size -= base; } } return true; }
bool TCPConnection::SendData(bool &sent_something, char* errbuf) { if (errbuf) errbuf[0] = 0; /************ Get first send packet on queue and send it! ************/ uchar* data = 0; int32 size = 0; int status = 0; if (ServerSendQueuePop(&data, &size)) { #ifdef _WINDOWS status = send(connection_socket, (const char *) data, size, 0); #else status = send(connection_socket, data, size, MSG_NOSIGNAL); if(errno==EPIPE) status = SOCKET_ERROR; #endif if (status >= 1) { #if TCPN_LOG_RAW_DATA_OUT >= 1 struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Wrote " << status << " bytes to network. " << inet_ntoa(in) << ":" << GetrPort(); std::cout << std::endl; #if TCPN_LOG_RAW_DATA_OUT == 2 int32 tmp = status; if (tmp > 32) tmp = 32; DumpPacket(data, status); #elif TCPN_LOG_RAW_DATA_OUT >= 3 DumpPacket(data, status); #endif #endif sent_something = true; if (status < (signed)size) { #if TCPN_LOG_RAW_DATA_OUT >= 1 struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Pushed " << (size - status) << " bytes back onto the send queue. " << inet_ntoa(in) << ":" << GetrPort(); std::cout << std::endl; #endif // If there's network congestion, the number of bytes sent can be less than // what we tried to give it... Push the extra back on the queue for later ServerSendQueuePushFront(&data[status], size - status); } else if (status > (signed)size) { return false; } // else if (status == size) {} } else { ServerSendQueuePushFront(data, size); } safe_delete_array(data); if (status == SOCKET_ERROR) { #ifdef _WINDOWS if (WSAGetLastError() != WSAEWOULDBLOCK) #else if (errno != EWOULDBLOCK) #endif { if (errbuf) { #ifdef _WINDOWS snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %i", WSAGetLastError()); #else snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %s", strerror(errno)); #endif } //if we get an error while disconnecting, just jump to disconnected MState.lock(); if(pState == TCPS_Disconnecting) pState = TCPS_Disconnected; MState.unlock(); return false; } } } return true; }
bool TCPConnection::ProcessReceivedData(char* errbuf) { if (errbuf) errbuf[0] = 0; if (!recvbuf) return true; #if TCPN_DEBUG_Console >= 4 if (recvbuf_used) { std::cout << "Starting Processing: recvbuf=" << recvbuf_used << std::endl; DumpPacket(recvbuf, recvbuf_used); } #endif for (int i=0; i < recvbuf_used; i++) { if (GetEcho() && i >= recvbuf_echo) { Send(&recvbuf[i], 1); recvbuf_echo = i + 1; } switch(recvbuf[i]) { case 0: { // 0 is the code for clear buffer if (i==0) { recvbuf_used--; recvbuf_echo--; memmove(recvbuf, &recvbuf[1], recvbuf_used); i = -1; } else { if (i == recvbuf_used) { safe_delete_array(recvbuf); i = -1; } else { uchar* tmpdel = recvbuf; recvbuf = new uchar[recvbuf_size]; memcpy(recvbuf, &tmpdel[i+1], recvbuf_used-i); recvbuf_used -= i + 1; recvbuf_echo -= i + 1; safe_delete_array(tmpdel); i = -1; } } #if TCPN_DEBUG_Console >= 5 std::cout << "Removed 0x00" << std::endl; if (recvbuf_used) { std::cout << "recvbuf left: " << recvbuf_used << std::endl; DumpPacket(recvbuf, recvbuf_used); } else std::cout << "recbuf left: None" << std::endl; #endif m_previousLineEnd = false; break; } case 10: case 13: // newline marker { char *line = nullptr; if (i==0) { // empty line if(!m_previousLineEnd) { //char right before this was NOT a CR, report the empty line. line = new char[1]; line[0] = '\0'; m_previousLineEnd = true; } else { m_previousLineEnd = false; } recvbuf_used--; recvbuf_echo--; memcpy(recvbuf, &recvbuf[1], recvbuf_used); i = -1; } else { line = new char[i+1]; memset(line, 0, i+1); memcpy(line, recvbuf, i); #if TCPN_DEBUG_Console >= 3 std::cout << "Line Out: " << std::endl; DumpPacket((uchar*) line, i); #endif //line[i] = 0; uchar* tmpdel = recvbuf; recvbuf = new uchar[recvbuf_size]; recvbuf_used -= i+1; recvbuf_echo -= i+1; memcpy(recvbuf, &tmpdel[i+1], recvbuf_used); #if TCPN_DEBUG_Console >= 5 std::cout << "i+1=" << i+1 << std::endl; if (recvbuf_used) { std::cout << "recvbuf left: " << recvbuf_used << std::endl; DumpPacket(recvbuf, recvbuf_used); } else std::cout << "recbuf left: None" << std::endl; #endif safe_delete_array(tmpdel); i = -1; m_previousLineEnd = true; } if(line != nullptr) { bool finish_proc = false; finish_proc = LineOutQueuePush(line); if(finish_proc) return(true); //break early as requested by LineOutQueuePush } break; } case 8: // backspace { if (i==0) { // nothin to backspace recvbuf_used--; recvbuf_echo--; memmove(recvbuf, &recvbuf[1], recvbuf_used); i = -1; } else { uchar* tmpdel = recvbuf; recvbuf = new uchar[recvbuf_size]; memcpy(recvbuf, tmpdel, i-1); memcpy(&recvbuf[i-1], &tmpdel[i+1], recvbuf_used-i); recvbuf_used -= 2; recvbuf_echo -= 2; safe_delete_array(tmpdel); i -= 2; } break; m_previousLineEnd = false; } default: m_previousLineEnd = false; } } if (recvbuf_used < 0) safe_delete_array(recvbuf); return true; }
bool TCPConnection::RecvData(char* errbuf) { if (errbuf) errbuf[0] = 0; if (!Connected()) { return false; } int status = 0; if (recvbuf == 0) { recvbuf = new uchar[5120]; recvbuf_size = 5120; recvbuf_used = 0; recvbuf_echo = 0; } else if ((recvbuf_size - recvbuf_used) < 2048) { uchar* tmpbuf = new uchar[recvbuf_size + 5120]; memcpy(tmpbuf, recvbuf, recvbuf_used); recvbuf_size += 5120; safe_delete_array(recvbuf); recvbuf = tmpbuf; if (recvbuf_size >= MaxTCPReceiveBuffferSize) { if (errbuf) snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): recvbuf_size >= MaxTCPReceiveBuffferSize"); return false; } } status = recv(connection_socket, (char *) &recvbuf[recvbuf_used], (recvbuf_size - recvbuf_used), 0); if (status >= 1) { #if TCPN_LOG_RAW_DATA_IN >= 1 struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Read " << status << " bytes from network. (recvbuf_used = " << recvbuf_used << ") " << inet_ntoa(in) << ":" << GetrPort(); std::cout << std::endl; #if TCPN_LOG_RAW_DATA_IN == 2 int32 tmp = status; if (tmp > 32) tmp = 32; DumpPacket(&recvbuf[recvbuf_used], status); #elif TCPN_LOG_RAW_DATA_IN >= 3 DumpPacket(&recvbuf[recvbuf_used], status); #endif #endif recvbuf_used += status; if (!ProcessReceivedData(errbuf)) return false; } else if (status == SOCKET_ERROR) { #ifdef _WINDOWS if (!(WSAGetLastError() == WSAEWOULDBLOCK)) { if (errbuf) snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Error: %i", WSAGetLastError()); return false; } #else if (!(errno == EWOULDBLOCK)) { if (errbuf) snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Error: %s", strerror(errno)); return false; } #endif } else if (status == 0) { snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Connection closed"); return false; } return true; }
bool EmuTCPConnection::ProcessReceivedDataAsPackets(char* errbuf) { if (errbuf) errbuf[0] = 0; int32 base = 0; int32 size = 7; uchar* buffer; ServerPacket* pack = 0; while ((recvbuf_used - base) >= size) { EmuTCPNetPacket_Struct* tnps = (EmuTCPNetPacket_Struct*) &recvbuf[base]; buffer = tnps->buffer; size = tnps->size; if (size >= MaxTCPReceiveBuffferSize) { #if TCPN_DEBUG_Memory >= 1 std::cout << "TCPConnection[" << GetID() << "]::ProcessReceivedDataAsPackets(): size[" << size << "] >= MaxTCPReceiveBuffferSize" << std::endl; DumpPacket(&recvbuf[base], 16); #endif if (errbuf) snprintf(errbuf, TCPConnection_ErrorBufferSize, "EmuTCPConnection::ProcessReceivedDataAsPackets(): size >= MaxTCPReceiveBuffferSize"); return false; } if ((recvbuf_used - base) >= size) { // ok, we got enough data to make this packet! pack = new ServerPacket; pack->size = size - sizeof(EmuTCPNetPacket_Struct); // read headers pack->opcode = tnps->opcode; if (tnps->flags.compressed) { pack->compressed = true; pack->InflatedSize = *((int32*)buffer); pack->size -= 4; buffer += 4; } if (tnps->flags.destination) { pack->destination = *((int32*)buffer); pack->size -= 4; buffer += 4; } // end read headers if (pack->size > 0) { if (tnps->flags.compressed) { // Lets decompress the packet here pack->compressed = false; pack->pBuffer = new uchar[pack->InflatedSize]; pack->size = InflatePacket(buffer, pack->size, pack->pBuffer, pack->InflatedSize); } else { pack->pBuffer = new uchar[pack->size]; memcpy(pack->pBuffer, buffer, pack->size); } } if (pack->opcode == 0) { if (pack->size) { #if TCPN_DEBUG >= 2 std::cout << "Received TCP Network layer packet" << std::endl; #endif ProcessNetworkLayerPacket(pack); } #if TCPN_DEBUG >= 5 else { std::cout << "Received TCP keepalive packet. (opcode=0)" << std::endl; } #endif // keepalive, no need to process safe_delete(pack); } else { #if TCPN_LOG_PACKETS >= 1 if (pack && pack->opcode != 0) { struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Logging incoming TCP packet. OPCode: 0x" << hex << setw(4) << setfill('0') << pack->opcode << dec << ", size: " << setw(5) << setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << std::endl; #if TCPN_LOG_PACKETS == 2 if (pack->size >= 32) DumpPacket(pack->pBuffer, 32); else DumpPacket(pack); #endif #if TCPN_LOG_PACKETS >= 3 DumpPacket(pack); #endif } #endif if (RelayServer && Server && pack->destination) { EmuTCPConnection* con = Server->FindConnection(pack->destination); if (!con) { #if TCPN_DEBUG >= 1 std::cout << "Error relaying packet: con = 0" << std::endl; #endif safe_delete(pack); } else con->OutQueuePush(pack); } else OutQueuePush(pack); } base += size; size = 7; } } if (base != 0) { if (base >= recvbuf_used) { safe_delete_array(recvbuf); } else { uchar* tmpbuf = new uchar[recvbuf_size - base]; memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base); safe_delete_array(recvbuf); recvbuf = tmpbuf; recvbuf_used -= base; recvbuf_size -= base; } } return true; }
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; }