diff --git a/src/char/char.c b/src/char/char.c index 20d4574915a..99f06774a12 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -50,6 +50,7 @@ #include "common/HPM.h" #include "common/apipackets.h" #include "common/cbasetypes.h" +#include "common/charloginpackets.h" #include "common/chunked.h" #include "common/conf.h" #include "common/console.h" @@ -5298,10 +5299,11 @@ static int char_send_accounts_tologin_sub(union DBKey key, struct DBData *data, { struct online_char_data* character = DB->data2ptr(data); int* i = va_arg(ap, int*); + int* accounts = va_arg(ap, int *); nullpo_ret(character); if (character->mapserver_connection == OCS_CONNECTED) { - WFIFOL(chr->login_fd,8+(*i)*4) = character->account_id; + accounts[*i] = character->account_id; (*i)++; return 1; } @@ -5310,18 +5312,24 @@ static int char_send_accounts_tologin_sub(union DBKey key, struct DBData *data, static int char_send_accounts_tologin(int tid, int64 tick, int id, intptr_t data) { - if (chr->login_fd > 0 && sockt->session[chr->login_fd]) - { + if (chr->login_fd > 0 && sockt->session[chr->login_fd] != NULL) { // send account list to login server int users = chr->online_char_db->size(chr->online_char_db); int i = 0; - WFIFOHEAD(chr->login_fd,8+users*4); - WFIFOW(chr->login_fd,0) = 0x272d; - chr->online_char_db->foreach(chr->online_char_db, chr->send_accounts_tologin_sub, &i, users); - WFIFOW(chr->login_fd,2) = 8+ i*4; - WFIFOL(chr->login_fd,4) = i; - WFIFOSET(chr->login_fd,WFIFOW(chr->login_fd,2)); + struct PACKET_CHARLOGIN_ONLINE_ACCOUNTS *p; + int len = sizeof(struct PACKET_CHARLOGIN_ONLINE_ACCOUNTS) + sizeof(*p->accounts) * users; + + WFIFOHEAD(chr->login_fd, len); + p = WFIFOP(chr->login_fd, 0); + p->packetType = HEADER_CHARLOGIN_ONLINE_ACCOUNTS; + + chr->online_char_db->foreach(chr->online_char_db, chr->send_accounts_tologin_sub, &i, p->accounts); + + p->packetLength = sizeof(struct PACKET_CHARLOGIN_ONLINE_ACCOUNTS) + sizeof(*p->accounts) * i; + p->list_length = i; + + WFIFOSET(chr->login_fd, len); } return 0; } diff --git a/src/common/Makefile.in b/src/common/Makefile.in index ed7baebcfa1..136fe456e53 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -62,7 +62,7 @@ COMMON_H = atomic.h cbasetypes.h base62.h conf.h console.h core.h db.h des.h ers grfio.h hercules.h HPM.h HPMi.h memmgr.h memmgr_inc.h mapindex.h \ md5calc.h mmo.h mutex.h nullpo.h packets.h packets_len.h packets_struct.h random.h \ showmsg.h socket.h spinlock.h sql.h strlib.h sysinfo.h thread.h \ - timer.h utils.h winapi.h api.h charmappackets.h mapcharpackets.h \ + timer.h utils.h winapi.h api.h charloginpackets.h charmappackets.h mapcharpackets.h \ chunked/rfifo.h chunked/wfifo.h config/defc.h config/emblems.h config/undefc.h \ ../plugins/HPMHooking.h COMMON_PH = diff --git a/src/common/charloginpackets.h b/src/common/charloginpackets.h new file mode 100644 index 00000000000..bdfda7c7d1f --- /dev/null +++ b/src/common/charloginpackets.h @@ -0,0 +1,45 @@ +/** + * This file is part of Hercules. + * http://herc.ws - http://github.com/HerculesWS/Hercules + * + * Copyright (C) 2012-2024 Hercules Dev Team + * Copyright (C) Athena Dev Teams + * + * Hercules is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef COMMON_CHARLOGINPACKETS_H +#define COMMON_CHARLOGINPACKETS_H + +// Packets sent by Char-Server to Login-Server + +#include "common/hercules.h" + +/* Packets Structs */ +#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute +#pragma pack(push, 1) +#endif // not NetBSD < 6 / Solaris + +struct PACKET_CHARLOGIN_ONLINE_ACCOUNTS { + int16 packetType; + uint16 packetLength; + uint32 list_length; + int accounts[]; +} __attribute__((packed)); +DEFINE_PACKET_ID(CHARLOGIN_ONLINE_ACCOUNTS, 0x272d) + +#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute +#pragma pack(pop) +#endif // not NetBSD < 6 / Solaris + +#endif /* COMMON_CHARLOGINPACKETS_H */ diff --git a/src/login/login.c b/src/login/login.c index 8a4458bd857..20ad72d7d33 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -32,6 +32,7 @@ #include "common/HPM.h" #include "common/apipackets.h" #include "common/cbasetypes.h" +#include "common/charloginpackets.h" #include "common/conf.h" #include "common/core.h" #include "common/db.h" @@ -675,17 +676,17 @@ static void login_fromchar_parse_account_offline(int fd) static void login_fromchar_parse_online_accounts(int fd, int id) { - uint32 i, users; login->online_db->foreach(login->online_db, login->online_db_setoffline, id); //Set all chars from this char-server offline first - users = RFIFOW(fd,4); - for (i = 0; i < users; i++) { - int aid = RFIFOL(fd,6+i*4); - struct online_login_data *p = idb_ensure(login->online_db, aid, login->create_online_user); - p->char_server = id; - if (p->waiting_disconnect != INVALID_TIMER) - { - timer->delete(p->waiting_disconnect, login->waiting_disconnect_timer); - p->waiting_disconnect = INVALID_TIMER; + + const struct PACKET_CHARLOGIN_ONLINE_ACCOUNTS *p = RFIFOP(fd, 0); + for (uint32 i = 0; i < p->list_length; i++) { + int aid = p->accounts[i]; + struct online_login_data *login_data = idb_ensure(login->online_db, aid, login->create_online_user); + login_data->char_server = id; + + if (login_data->waiting_disconnect != INVALID_TIMER) { + timer->delete(login_data->waiting_disconnect, login->waiting_disconnect_timer); + login_data->waiting_disconnect = INVALID_TIMER; } } } @@ -950,7 +951,7 @@ static int login_parse_fromchar(int fd) login->fromchar_parse_account_offline(fd); break; - case 0x272d: // Receive list of all online accounts. [Skotlex] + case HEADER_CHARLOGIN_ONLINE_ACCOUNTS: // Receive list of all online accounts. [Skotlex] if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; {