diff options
-rw-r--r-- | conf/map/battle/client.conf | 9 | ||||
-rw-r--r-- | src/common/socket.c | 7 | ||||
-rw-r--r-- | src/common/socket.h | 1 | ||||
-rw-r--r-- | src/map/battle.c | 2 | ||||
-rw-r--r-- | src/map/battle.h | 3 | ||||
-rw-r--r-- | src/map/clif.c | 51 | ||||
-rw-r--r-- | src/map/clif.h | 4 | ||||
-rw-r--r-- | src/map/packets.h | 4 | ||||
-rw-r--r-- | src/map/packets_struct.h | 14 |
9 files changed, 93 insertions, 2 deletions
diff --git a/conf/map/battle/client.conf b/conf/map/battle/client.conf index b7d4ac781..24b1c8157 100644 --- a/conf/map/battle/client.conf +++ b/conf/map/battle/client.conf @@ -189,3 +189,12 @@ mvp_exp_reward_message: false // character has 0 HP when dead. // Default: true (Official behavior) display_fake_hp_when_dead: true + +// Send ping timer +// For clients 20190320 Re+ +// Interval in seconds for each timer invoke. +ping_timer_inverval: 30 + +// Send packets timeout in seconds before ping packet can be sent. +// For clients 20190320 Re+ +ping_time: 20 diff --git a/src/common/socket.c b/src/common/socket.c index faf57f412..dc5b06da0 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -488,11 +488,12 @@ static int send_from_fifo(int fd) return 0; } - if( len > 0 ) + if (len > 0) { + sockt->session[fd]->wdata_tick = sockt->last_tick; // some data could not be transferred? // shift unsent data to the beginning of the queue - if( (size_t)len < sockt->session[fd]->wdata_size ) + if ((size_t)len < sockt->session[fd]->wdata_size) memmove(sockt->session[fd]->wdata, sockt->session[fd]->wdata + len, sockt->session[fd]->wdata_size - len); sockt->session[fd]->wdata_size -= len; @@ -649,6 +650,7 @@ static int make_listen_bind(uint32 ip, uint16 port) create_session(fd, sockt->connect_client, null_send, null_parse); sockt->session[fd]->client_addr = 0; // just listens sockt->session[fd]->rdata_tick = 0; // disable timeouts on this socket + sockt->session[fd]->wdata_tick = 0; return fd; } @@ -731,6 +733,7 @@ static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseF sockt->session[fd]->func_send = func_send; sockt->session[fd]->func_parse = func_parse; sockt->session[fd]->rdata_tick = sockt->last_tick; + sockt->session[fd]->wdata_tick = sockt->last_tick; sockt->session[fd]->session_data = NULL; sockt->session[fd]->hdata = NULL; return 0; diff --git a/src/common/socket.h b/src/common/socket.h index 193b22645..b20b0b07e 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -130,6 +130,7 @@ struct socket_data { size_t rdata_pos; uint32 last_head_size; time_t rdata_tick; // time of last recv (for detecting timeouts); zero when timeout is disabled + time_t wdata_tick; // time of last send (for detecting timeouts); RecvFunc func_recv; SendFunc func_send; diff --git a/src/map/battle.c b/src/map/battle.c index c65b32132..fe7a64b51 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7415,6 +7415,8 @@ static const struct battle_data { { "display_fake_hp_when_dead", &battle_config.display_fake_hp_when_dead, 1, 0, 1, }, { "magicrod_type", &battle_config.magicrod_type, 0, 0, 1, }, { "features/enable_achievement_system", &battle_config.feature_enable_achievement, 1, 0, 1, }, + { "ping_timer_inverval", &battle_config.ping_timer_interval, 30, 0, 99999999, }, + { "ping_time", &battle_config.ping_time, 20, 0, 99999999, }, }; static bool battle_set_value_sub(int index, int value) diff --git a/src/map/battle.h b/src/map/battle.h index 7e03f0a8e..723a86874 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -580,6 +580,9 @@ struct Battle_Config { int magicrod_type; int feature_enable_achievement; + + int ping_timer_interval; + int ping_time; }; /* criteria for battle_config.idletime_critera */ diff --git a/src/map/clif.c b/src/map/clif.c index baf9abec7..85e1a192b 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -22152,6 +22152,47 @@ static void clif_parse_clientVersion(int fd, struct map_session_data *sd) #endif } +static void clif_parse_ping(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +static void clif_parse_ping(int fd, struct map_session_data *sd) +{ + // do nothing, any packet update client tick +} + +static void clif_ping(struct map_session_data *sd) +{ +#if PACKETVER_MAIN_NUM >= 20190213 || PACKETVER_RE_NUM >= 20190213 || PACKETVER_ZERO_NUM >= 20190130 + nullpo_retv(sd); + struct PACKET_ZC_PING p; + p.packetType = HEADER_ZC_PING; + clif->send(&p, sizeof(p), &sd->bl, SELF); +#endif +} + +static int clif_pingTimer(int tid, int64 tick, int id, intptr_t data) +{ + map->foreachpc(clif->pingTimerSub, time(NULL)); + return 0; +} + +static int clif_pingTimerSub(struct map_session_data *sd, va_list ap) +{ + nullpo_ret(sd); + const int fd = sd->fd; + + if (!sockt->session_is_active(fd)) + { + return 0; + } + + time_t tick = va_arg(ap, time_t); + + if (sockt->session[fd]->wdata_tick + battle_config.ping_time < tick) + { + clif->ping(sd); + } + return 0; +} + /*========================================== * Main client packet processing function *------------------------------------------*/ @@ -22433,6 +22474,12 @@ static int do_init_clif(bool minimal) clif->delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); clif->delayed_damage_ers = ers_new(sizeof(struct cdelayed_damage),"clif.c::delayed_damage_ers",ERS_OPT_CLEAR); +#if PACKETVER_MAIN_NUM >= 20190403 || PACKETVER_RE_NUM >= 20190320 + timer->add_func_list(clif->pingTimer, "clif_pingTimer"); + if (battle_config.ping_timer_interval != 0) + timer->add_interval(timer->gettick() + battle_config.ping_timer_interval * 1000, clif->pingTimer, 0, 0, battle_config.ping_timer_interval * 1000); +#endif + return 0; } @@ -23335,4 +23382,8 @@ void clif_defaults(void) clif->pNPCBarterClosed = clif_parse_NPCBarterClosed; clif->pNPCBarterPurchase = clif_parse_NPCBarterPurchase; clif->pClientVersion = clif_parse_clientVersion; + clif->pPing = clif_parse_ping; + clif->ping = clif_ping; + clif->pingTimer = clif_pingTimer; + clif->pingTimerSub = clif_pingTimerSub; } diff --git a/src/map/clif.h b/src/map/clif.h index 6b501477c..a9413465b 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -1581,6 +1581,10 @@ struct clif_interface { void (*pNPCBarterClosed) (int fd, struct map_session_data *sd); void (*pNPCBarterPurchase) (int fd, struct map_session_data *sd); void (*pClientVersion) (int fd, struct map_session_data *sd); + void (*pPing) (int fd, struct map_session_data *sd); + void (*ping) (struct map_session_data *sd); + int (*pingTimer) (int tid, int64 tick, int id, intptr_t data); + int (*pingTimerSub) (struct map_session_data *sd, va_list ap); }; #ifdef HERCULES_CORE diff --git a/src/map/packets.h b/src/map/packets.h index 50784f09a..279c19d93 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -1931,4 +1931,8 @@ packet(0x96e,clif->ackmergeitems); packet(0x0b12,clif->pNPCBarterClosed); #endif +#if PACKETVER_MAIN_NUM >= 20190403 || PACKETVER_RE_NUM >= 20190320 + packet(0x0b1c,clif->pPing); +#endif + #endif /* MAP_PACKETS_H */ diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 42b11b718..b12193997 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -3160,6 +3160,20 @@ struct PACKET_CZ_CLIENT_VERSION { DEFINE_PACKET_HEADER(CZ_CLIENT_VERSION, 0x044a); #endif +#if PACKETVER_MAIN_NUM >= 20190227 || PACKETVER_RE_NUM >= 20190220 || PACKETVER_ZERO_NUM >= 20190220 +struct PACKET_CZ_PING { + int16 packetType; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(CZ_PING, 0x0b1c); +#endif + +#if PACKETVER_MAIN_NUM >= 20190213 || PACKETVER_RE_NUM >= 20190213 || PACKETVER_ZERO_NUM >= 20190130 +struct PACKET_ZC_PING { + int16 packetType; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_PING, 0x0b1d); +#endif + #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 |