OSDN Git Service

Bump up revision master
authorDaigo Moriwaki <beatles@sgtpepper.net>
Sun, 4 Oct 2020 02:33:03 +0000 (11:33 +0900)
committerDaigo Moriwaki <beatles@sgtpepper.net>
Sun, 4 Oct 2020 02:33:03 +0000 (11:33 +0900)
changelog
shogi-server
shogi_server.rb
shogi_server/command.rb
shogi_server/player.rb

index b3df157..5ded10a 100644 (file)
--- a/changelog
+++ b/changelog
@@ -1,9 +1,24 @@
+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.
          A file named "STOP" in the base directory prevents the server from
          starting new games including Floodgate matches.
          (Closes #38544)
+       * [shogi-server] Create a directory for a PID file.
+         To put a PID file such as /var/run/shogi-server/shogi-server.pid, if
+         directories do not exist, they will be created recursively.
+         (Closes #38546)
 
 2018-04-07  Daigo Moriwaki <daigo at debian dot org>
 
index 21bc9d1..a436628 100755 (executable)
@@ -34,6 +34,8 @@ require 'shogi_server'
 require 'shogi_server/config'
 require 'shogi_server/util'
 require 'shogi_server/league/floodgate_thread.rb'
+require 'pathname'
+require 'set'
 require 'tempfile'
 
 #################################################
@@ -271,6 +273,8 @@ def check_command_line
 
   if $options["pid-file"] 
     $options["pid-file"] = File.expand_path($options["pid-file"], $topdir)
+    path = Pathname.new($options["pid-file"])
+    path.dirname().mkpath()
     unless ShogiServer::is_writable_file? $options["pid-file"]
       usage
       $stderr.puts "Can not create the pid file: %s" % [$options["pid-file"]]
@@ -432,6 +436,9 @@ def main
 
   $league.dir = $topdir
 
+  # Set of connected players
+  $players = Set.new
+
   config = {}
   config[:BindAddress] = "0.0.0.0"
   config[:Port]       = port
@@ -459,8 +466,9 @@ def main
 
   srand
   server = WEBrick::GenericServer.new(config)
-  ["INT", "TERM"].each do |signal| 
+  ["INT", "TERM"].each do |signal|
     trap(signal) do
+      $players.each {|p| p.kill}
       server.shutdown
       setup_floodgate.kill
     end
@@ -492,6 +500,14 @@ def main
       log_message(sprintf("user %s login", player.name))
       login.process
       player.setup_logger($options["player-log-dir"]) if $options["player-log-dir"]
+
+      $mutex.lock
+      begin
+       $players.add(player)
+      ensure
+        $mutex.unlock
+      end
+
       player.run(login.csa_1st_str) # loop
       $mutex.lock
       begin
@@ -501,6 +517,7 @@ def main
         player.finish
         $league.delete(player)
         log_message(sprintf("user %s logout", player.name))
+       $players.delete(player)
       ensure
         $mutex.unlock
       end
index 536f9c3..df96860 100644 (file)
@@ -53,7 +53,7 @@ Default_Max_Moves = 256
 Default_Least_Time_Per_Move = 0
 One_Time = 10
 Login_Time = 300                # time for LOGIN
-Revision = "20180825"
+Revision = "20201004"
 
 RELOAD_FILES = ["shogi_server/league/floodgate.rb",
                 "shogi_server/league/persistent.rb",
index ad8684d..5fe3cb0 100644 (file)
@@ -27,13 +27,11 @@ module ShogiServer
     #
     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/
@@ -145,22 +143,6 @@ module ShogiServer
     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
@@ -190,7 +172,11 @@ module ShogiServer
     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)
@@ -199,6 +185,14 @@ module ShogiServer
 
     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) 
index c7dc8a4..7a1c303 100644 (file)
@@ -301,7 +301,8 @@ class Player < BasicPlayer
           @socket_buffer << str
           str = @socket_buffer.shift
         end
-        log_debug("%s (%s)" % [str, @socket_buffer.map {|a| String === a ? a.strip : a }.join(",")])
+        log_debug("dump socket buffer: '%s' (%s)" % [String === str ? str.strip : str,
+                                                    @socket_buffer.map {|a| String === a ? a.strip : a }.join(",")])
 
         if (csa_1st_str)
           str = csa_1st_str