+2020-10-04 Daigo Moriwaki <daigo at debian dot org>
+
+ * [shogi-server] Improve timed-up detection.
+ Previously, the server checked if a game got timed up when a player
+ in turn sent no message for a certain amount of time mainly defined
+ by Default_Timeout. If the player sent keep alive frequently, the
+ timed-up detection could be quite delayed.
+ This issue has been addressed. The server now checks timed up with
+ keep alive received as well. Players are notified with TIME_UP not
+ long before games gets timed up.
+
2018-08-25 Daigo Moriwaki <daigo at debian dot org>
* [shogi-server] Support a graceful shutdown.
#
def Command.factory(str, player, time=Time.now)
cmd = nil
- case str
- when ""
- cmd = KeepAliveCommand.new(str, player)
+ case str
+ when "", /^%[^%]/, :timeout
+ cmd = SpecialCommand.new(str, player)
when /^[\+\-][^%]/
cmd = MoveCommand.new(str, player)
- when /^%[^%]/, :timeout
- cmd = SpecialCommand.new(str, player)
when :exception
cmd = ExceptionCommand.new(str, player)
when /^REJECT/
end
end
- # Application-level protocol for Keep-Alive.
- # If the server receives an LF, it sends back an LF. Note that the 30 sec
- # rule (client may not send LF again within 30 sec) is not implemented
- # yet.
- #
- class KeepAliveCommand < Command
- def initialize(str, player)
- super
- end
-
- def call
- @player.write_safe("\n")
- return :continue
- end
- end
-
# Command of moving a piece.
#
class MoveCommand < Command
end
end
- # Command like "%TORYO" or :timeout
+ # Command like "%TORYO", :timeout, or keep alive
+ #
+ # Keep Alive is an application-level protocol. Whenever the server receives
+ # an LF, it sends back an LF. Note that the 30 sec rule (client may not send
+ # LF again within 30 sec) is not implemented yet.
#
class SpecialCommand < Command
def initialize(str, player)
def call
rc = :continue
+
+ if @str == "" # keep alive
+ log_debug("received keep alive from #{@player.name}")
+ @player.write_safe("\n")
+ # Fall back to :timeout to check the game gets timed up
+ @str = :timeout
+ end
+
if (@player.status == "game")
rc = in_game_status()
elsif ["agree_waiting", "start_waiting"].include?(@player.status)