int32 map_close_session(uint32 tick, map_session_data_t* map_session_data) { if (map_session_data != nullptr && map_session_data->server_packet_data != nullptr && map_session_data->PChar != nullptr) { charutils::SavePlayTime(map_session_data->PChar); //clear accounts_sessions if character is logging out (not when zoning) if (map_session_data->shuttingDown == 1) { Sql_Query(SqlHandle, "DELETE FROM accounts_sessions WHERE charid = %u", map_session_data->PChar->id); } uint64 port64 = map_session_data->client_port; uint64 ipp = map_session_data->client_addr; ipp |= port64 << 32; map_session_data->PChar->StatusEffectContainer->SaveStatusEffects(map_session_data->shuttingDown == 1); aFree(map_session_data->server_packet_data); delete map_session_data->PChar; delete map_session_data; map_session_data = nullptr; map_session_list.erase(ipp); return 0; } ShowError(CL_RED"map_close_session: cannot close session, session not found\n" CL_RESET); return 1; }
int32 map_close_session(uint32 tick, CTaskMgr::CTask* PTask) { map_session_data_t* map_session_data = (map_session_data_t*)PTask->m_data; if (map_session_data != NULL && map_session_data->server_packet_data != NULL && // bad pointer crashed here, might need dia to look at this one map_session_data->PChar != NULL) // crash occured when both server_packet_data & PChar were NULL { charutils::SavePlayTime(map_session_data->PChar); Sql_Query(SqlHandle, "DELETE FROM accounts_sessions WHERE charid = %u", map_session_data->PChar->id); uint64 port64 = map_session_data->client_port; uint64 ipp = map_session_data->client_addr; ipp |= port64<<32; map_session_data->PChar->StatusEffectContainer->SaveStatusEffects(); aFree(map_session_data->server_packet_data); delete map_session_data->PChar; delete map_session_data; map_session_data = NULL; map_session_list.erase(ipp); ShowDebug(CL_CYAN"map_close_session: session closed\n" CL_RESET); return 0; } ShowError(CL_RED"map_close_session: cannot close session, session not found\n" CL_RESET); return 1; }
int32 map_cleanup(uint32 tick, CTaskMgr::CTask* PTask) { map_session_list_t::iterator it = map_session_list.begin(); while(it != map_session_list.end()) { map_session_data_t* map_session_data = it->second; if( (time(NULL) - map_session_data->last_update) > (map_config.max_time_lastupdate/1000) ) { if (map_session_data->PChar) { ShowWarning("map_cleanup: "CL_WHITE"%s"CL_RESET" timed out, session closed\n",map_session_data->PChar->GetName()); map_session_data->PChar->status = STATUS_SHUTDOWN; PacketParcer[0x00D](map_session_data, map_session_data->PChar, 0); } else { ShowWarning("map_cleanup: "CL_WHITE"WHITHOUT CHAR"CL_RESET" timed out, session closed\n"); const int8* fmtQuery = "DELETE FROM accounts_sessions WHERE client_addr = %u AND client_port = %u"; Sql_Query(SqlHandle,fmtQuery,map_session_data->client_addr,map_session_data->client_port); aFree(map_session_data->server_packet_data); delete map_session_data; map_session_list.erase(it++); continue; } } ++it; } return 0; }
int32 map_close_session(uint32 tick, CTaskMgr::CTask* PTask) { map_session_data_t* map_session_data = (map_session_data_t*)PTask->m_data; if (map_session_data != NULL) { Sql_Query(SqlHandle,"DELETE FROM accounts_sessions WHERE charid = %u",map_session_data->PChar->id); uint64 port64 = map_session_data->client_port; uint64 ipp = map_session_data->client_addr; ipp |= port64<<32; map_session_data->PChar->StatusEffectContainer->SaveStatusEffects(); aFree(map_session_data->server_packet_data); delete map_session_data->PChar; delete map_session_data; map_session_list.erase(ipp); ShowDebug(CL_CYAN"map_close_session: session closed\n"CL_RESET); return 0; } ShowError(CL_RED"map_close_session: cannot close session, session not found\n"CL_RESET); return 1; }
int32 map_cleanup(uint32 tick, CTaskMgr::CTask* PTask) { map_session_list_t::iterator it = map_session_list.begin(); while (it != map_session_list.end()) { map_session_data_t* map_session_data = it->second; CCharEntity* PChar = map_session_data->PChar; if ((time(nullptr) - map_session_data->last_update) > 5) { if (PChar != nullptr && !(PChar->nameflags.flags & FLAG_DC)) { PChar->nameflags.flags |= FLAG_DC; PChar->updatemask |= UPDATE_HP; if (PChar->status == STATUS_NORMAL) { PChar->loc.zone->SpawnPCs(PChar); } } if ((time(nullptr) - map_session_data->last_update) > map_config.max_time_lastupdate) { if (PChar != nullptr) { if (map_session_data->shuttingDown == 0) { //[Alliance] fix to stop server crashing: //if a party within an alliance only has 1 char (that char will be party leader) //if char then disconnects we need to tell the server about the alliance change if (PChar->PParty != nullptr && PChar->PParty->m_PAlliance != nullptr && PChar->PParty->GetLeader() == PChar) { if (PChar->PParty->members.size() == 1) { if (PChar->PParty->m_PAlliance->partyList.size() == 1) { PChar->PParty->m_PAlliance->dissolveAlliance(); } else { PChar->PParty->m_PAlliance->removeParty(PChar->PParty); } } } // uncharm pet if player d/c if (PChar->PPet != nullptr && PChar->PPet->objtype == TYPE_MOB) { petutils::DespawnPet(PChar); } PChar->StatusEffectContainer->SaveStatusEffects(true); ShowDebug(CL_CYAN"map_cleanup: %s timed out, closing session\n" CL_RESET, PChar->GetName()); PChar->status = STATUS_SHUTDOWN; PacketParser[0x00D](map_session_data, PChar, 0); } else { map_session_data->PChar->StatusEffectContainer->SaveStatusEffects(true); Sql_Query(SqlHandle, "DELETE FROM accounts_sessions WHERE charid = %u;", map_session_data->PChar->id); aFree(map_session_data->server_packet_data); delete map_session_data->PChar; delete map_session_data; map_session_data = nullptr; map_session_list.erase(it++); continue; } } else if (map_session_data->shuttingDown == 0) { ShowWarning(CL_YELLOW"map_cleanup: WHITHOUT CHAR timed out, session closed\n" CL_RESET); const int8* Query = "DELETE FROM accounts_sessions WHERE client_addr = %u AND client_port = %u"; Sql_Query(SqlHandle, Query, map_session_data->client_addr, map_session_data->client_port); aFree(map_session_data->server_packet_data); map_session_list.erase(it++); delete map_session_data; continue; } } } else if (PChar != nullptr && (PChar->nameflags.flags & FLAG_DC)) { PChar->nameflags.flags &= ~FLAG_DC; PChar->updatemask |= UPDATE_HP; PChar->pushPacket(new CCharUpdatePacket(PChar)); if (PChar->status == STATUS_NORMAL) { PChar->loc.zone->SpawnPCs(PChar); } charutils::SaveCharStats(PChar); } ++it; } return 0; }
int32 do_sockets(fd_set* rfd, int32 next) { struct timeval timeout; int32 ret; memcpy(rfd, &readfds, sizeof(*rfd)); timeout.tv_sec = next / 1000; timeout.tv_usec = next % 1000 * 1000; ret = sSelect(fd_max, rfd, nullptr, nullptr, &timeout); if (ret == SOCKET_ERROR) { if (sErrno != S_EINTR) { ShowFatalError("do_sockets: select() failed, error code %d!\n", sErrno); do_final(EXIT_FAILURE); } return 0; // interrupted by a signal, just loop and try again } last_tick = time(nullptr); if (sFD_ISSET(map_fd, rfd)) { struct sockaddr_in from; socklen_t fromlen = sizeof(from); int32 ret = recvudp(map_fd, g_PBuff, map_config.buffer_size, 0, (struct sockaddr*)&from, &fromlen); if (ret != -1) { // find player char # ifdef WIN32 uint32 ip = ntohl(from.sin_addr.S_un.S_addr); # else uint32 ip = ntohl(from.sin_addr.s_addr); # endif uint64 port = ntohs(from.sin_port); uint64 ipp = ip; ipp |= port << 32; map_session_data_t* map_session_data = mapsession_getbyipp(ipp); if (map_session_data == nullptr) { map_session_data = mapsession_createsession(ip, ntohs(from.sin_port)); if (map_session_data == nullptr) { map_session_list.erase(ipp); return -1; } } map_session_data->last_update = time(nullptr); size_t size = ret; if (recv_parse(g_PBuff, &size, &from, map_session_data) != -1) { // если предыдущий пакет был потерян, то мы не собираем новый, // а отправляем предыдущий пакет повторно if (!parse(g_PBuff, &size, &from, map_session_data)) { send_parse(g_PBuff, &size, &from, map_session_data); } ret = sendudp(map_fd, g_PBuff, size, 0, (const struct sockaddr*)&from, fromlen); int8* data = g_PBuff; g_PBuff = map_session_data->server_packet_data; map_session_data->server_packet_data = data; map_session_data->server_packet_size = size; } if (map_session_data->shuttingDown > 0) { map_close_session(gettick(), map_session_data); } } } return 0; }