Ticket #40821

対局中に空行などを定期的に送信するクライアントの指し手放置時間切れを検知できない

Open Date: 2020-10-01 21:25 Last Update: 2020-12-06 18:52

Reporter:
Owner:
(None)
Type:
Status:
Closed
Component:
(None)
MileStone:
(None)
Priority:
5 - Medium
Severity:
5 - Medium
Resolution:
None
File:
None

Details

将棋所テスト版4 のような、定期的に無意味な文字列を対局中に送信するクライアントの場合、指し手放置の時間切れを検知出来ず、対局が何時までも閉じられなくなる可能性があります。

shogi-serverにて、クライアントからの入力が一定時間無かった時(:timeout)にしか指し手放置時間切れの検知処理を行っていなかったのが原因と見られます。

  1. # Return
  2. # - a received string
  3. # - :timeout
  4. # - :exception
  5. # - nil when a socket is closed
  6. #
  7. def gets_safe(socket, timeout=nil)
  8. if r = select([socket], nil, nil, timeout)
  9. return r[0].first.gets
  10. else
  11. return :timeout
  12. end
  13. rescue Exception => ex
  14. log_error("gets_safe: #{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}")
  15. return :exception
  16. end

* 解決案1: 検知間隔を充分に短くする

  1. ------------------------------- shogi_server.rb -------------------------------
  2. @@ -46,7 +46,7 @@ require 'shogi_server/buoy'
  3. module ShogiServer # for a namespace
  4. Max_Identifier_Length = 32
  5. -Default_Timeout = 60 # for single socket operation
  6. +Default_Timeout = 28 # for single socket operation
  7. Default_Game_Name = "default-1500-0"
  8. Default_Max_Moves = 256
  9. Default_Least_Time_Per_Move = 0

* 解決案2: KeepAliveCommand / SpaceCommand の実行時にも時間切れの検知を行う

https://osdn.net/users/mizar/pf/shogi-server/scm/commits/a128e96f671e3a2dcf38eb80b4a00b628069e1c5

  1. --------------------------- shogi_server/command.rb ---------------------------
  2. @@ -157,6 +157,10 @@ module ShogiServer
  3. def call
  4. @player.write_safe("\n")
  5. + if (@player.status == "game")
  6. + s = @player.game.handle_one_move(:keepalive, @player, @time)
  7. + return :return if (s && @player.protocol == LoginCSA::PROTOCOL)
  8. + end
  9. return :continue
  10. end
  11. end
  12. @@ -685,6 +689,10 @@ module ShogiServer
  13. def call
  14. ## ignore null string
  15. + if (@player.status == "game")
  16. + s = @player.game.handle_one_move(:space, @player, @time)
  17. + return :return if (s && @player.protocol == LoginCSA::PROTOCOL)
  18. + end
  19. return :continue
  20. end
  21. end
  22. ----------------------------- shogi_server/game.rb -----------------------------
  23. @@ -248,7 +248,7 @@ class Game
  24. # class Game
  25. def handle_one_move(str, player, end_time)
  26. unless turn?(player)
  27. - return false if str == :timeout
  28. + return false if (str == :timeout || str == :keepalive || str == :space)
  29. @fh.puts("'Deferred %s" % [str])
  30. log_warning("Deferred a move [%s] scince it is not %s 's turn." %
  31. @@ -263,7 +263,7 @@ class Game
  32. if (@time_clock.timeout?(@current_player, @start_time, @end_time))
  33. status = :timeout
  34. - elsif (str == :timeout)
  35. + elsif (str == :timeout || str == :keepalive || str == :space)
  36. return false # time isn't expired. players aren't swapped. continue game
  37. else
  38. t = @time_clock.process_time(@current_player, @start_time, @end_time)

Ticket History (3/6 Histories)

2020-10-01 21:25 Updated by: mizar
  • New Ticket "対局中に空行などを定期的に送信するクライアントの指し手放置時間切れを検知できない" created
2020-10-01 21:42 Updated by: mizar
Comment
(This comment has been deleted)
2020-10-02 01:06 Updated by: mizar
  • Details Updated
2020-10-02 01:44 Updated by: mizar
  • Details Updated
2020-10-04 23:31 Updated by: mizar
Comment

将棋所4.7.1テスト版4 ではアプリケーションレベルでのkeepaliveが半角空白(SP)+改行(LF)文字の送信にて1分おきに行われているため、単に改行(LF)文字が送信されていることを想定した shogi-server 20201004 での修正 https://osdn.net/projects/shogi-server/scm/git/shogi-server/commits/8d5884aa82cc5b0b31ca115cfea891ba37ad6fe3 では不十分です。

追加的に、以下のような修正が必要になると思われます。

https://osdn.net/users/mizar/pf/shogi-server/scm/commits/7cd512b50be019cee0d9c000716be2277d50743f

  1. --------------------------- shogi_server/command.rb ---------------------------
  2. @@ -28,7 +28,7 @@ module ShogiServer
  3. def Command.factory(str, player, time=Time.now)
  4. cmd = nil
  5. case str
  6. - when "", /^%[^%]/, :timeout
  7. + when "", /^\s*$/, /^%[^%]/, :timeout
  8. cmd = SpecialCommand.new(str, player)
  9. when /^[\+\-][^%]/
  10. cmd = MoveCommand.new(str, player)
  11. @@ -108,8 +108,6 @@ module ShogiServer
  12. new_buoy_game = nil
  13. nth_move = nil
  14. cmd = ForkCommand.new(str, player, source_game, new_buoy_game, nth_move)
  15. - when /^\s*$/
  16. - cmd = SpaceCommand.new(str, player)
  17. when /^%%%[^%]/
  18. # TODO: just ignore commands specific to 81Dojo.
  19. # Need to discuss with 81Dojo people.
  20. @@ -172,7 +170,7 @@ module ShogiServer
  21. end
  22. end
  23. - # Command like "%TORYO", :timeout, or keep alive
  24. + # Command like "%TORYO", :timeout, space, or keep alive
  25. #
  26. # Keep Alive is an application-level protocol. Whenever the server receives
  27. # an LF, it sends back an LF. Note that the 30 sec rule (client may not send
  28. @@ -191,6 +189,9 @@ module ShogiServer
  29. @player.write_safe("\n")
  30. # Fall back to :timeout to check the game gets timed up
  31. @str = :timeout
  32. + elsif /^\s+$/ =~ @str
  33. + # Fall back to :timeout to check the game gets timed up
  34. + @str = :timeout
  35. end
  36. if (@player.status == "game")
  37. @@ -673,19 +674,6 @@ module ShogiServer
  38. end
  39. end
  40. - # Command for a space
  41. - #
  42. - class SpaceCommand < Command
  43. - def initialize(str, player)
  44. - super
  45. - end
  46. -
  47. - def call
  48. - ## ignore null string
  49. - return :continue
  50. - end
  51. - end
  52. -
  53. # Command for an error
  54. #
  55. class ErrorCommand < Command
(Edited, 2020-10-05 00:29 Updated by: mizar)
2020-12-06 18:52 Updated by: beatles
  • Status Update from Open to Closed

Attachment File List

No attachments

Edit

You are not logged in. I you are not logged in, your comment will be treated as an anonymous post. » Login