X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=shogi-server;h=abbb4d7fde3384b50c115aa65e7ebde217f650b3;hb=25248369f66d22285460bfec6547b40dc5764099;hp=906fe10ef973911cbf89f4e8d5d0ec9b4384a7a3;hpb=3102c866b85e11fab83a1a785f8a061a44d18bb5;p=shogi-server%2Fshogi-server.git diff --git a/shogi-server b/shogi-server index 906fe10..abbb4d7 100755 --- a/shogi-server +++ b/shogi-server @@ -24,6 +24,8 @@ require 'socket' require 'yaml' require 'yaml/store' require 'digest/md5' +require 'webrick' +require 'fileutils' class TCPSocket @@ -89,9 +91,14 @@ class League @games = Hash::new @players = Hash::new @event = nil - @db = YAML::Store.new( File.join(File.dirname(__FILE__), "players.yaml") ) + @dir = File.dirname(__FILE__) + end + attr_accessor :players, :games, :event, :dir + + # this should be called just after instanciating a League object. + def setup_players_database + @db = YAML::Store.new(File.join(@dir, "players.yaml")) end - attr_accessor :players, :games, :event def add(player) self.load(player) if player.id @@ -128,6 +135,7 @@ class League def search(id) hash = nil @db.transaction do + break unless @db["players"] @db["players"].each do |group, players| hash = players[id] break if hash @@ -139,6 +147,7 @@ class League def rated_players players = [] @db.transaction(true) do + break unless @db["players"] @db["players"].each do |group, players_hash| players << players_hash.keys end @@ -375,7 +384,7 @@ class Player < BasicPlayer # TODO you should confirm that there is no message in the queue. Thread::kill(@writer_thread) if @writer_thread begin - @socket.close if (! @socket.closed?) +# @socket.close if (! @socket.closed?) rescue log_message(sprintf("user %s finish failed", @name)) end @@ -607,7 +616,9 @@ class Player < BasicPlayer when /^\s*$/ ## ignore null string else - write_safe(sprintf("##[ERROR] unknown command %s\n", str)) + msg = "##[ERROR] unknown command %s\n" % [str] + write_safe(msg) + log_error(msg) end ensure $mutex.unlock @@ -1271,6 +1282,7 @@ class Board return true end + # sente is nil only if tests in test_board run def handle_one_move(str, sente=nil) if (str =~ /^([\+\-])(\d)(\d)(\d)(\d)([A-Z]{2})/) sg = $1 @@ -1299,11 +1311,14 @@ class Board return :illegal end + if (sg == "+") - sente = true + sente = true if sente == nil # deprecated + return :illegal unless sente == true # black player's move must be black hands = @sente_hands else - sente = false + sente = false if sente == nil # deprecated + return :illegal unless sente == false # white player's move must be white hands = @gote_hands end @@ -1463,7 +1478,7 @@ class Game @id = sprintf("%s+%s+%s+%s+%s", LEAGUE.event, @game_name, @sente.name, @gote.name, issue_current_time) - @logfile = @id + ".csa" + @logfile = File.join(LEAGUE.dir, @id + ".csa") LEAGUE.games[@id] = self @@ -1914,7 +1929,7 @@ NAME shogi-server - server for CSA server protocol SYNOPSIS - shogi-server event_name port_number + shogi-server [OPTIONS] event_name port_number DESCRIPTION server for CSA server protocol @@ -1922,6 +1937,8 @@ DESCRIPTION OPTIONS --pid-file file specify filename for logging process ID + --daemon dir + run as a daemon. Log files will be put in dir. LICENSE this file is distributed under GPL version2 and might be compiled by Exerb @@ -1929,33 +1946,31 @@ LICENSE SEE ALSO RELEASE - #{Release} + #{ShogiServer::Release} REVISION - #{Revision} + #{ShogiServer::Revision} EOM end def log_message(str) - printf("%s message: %s\n", Time::new.to_s, str) + $logger.info(str) end def log_warning(str) - printf("%s warning: %s\n", Time::new.to_s, str) + $logger.warn(str) end def log_error(str) - printf("%s error: %s\n", Time::new.to_s, str) + $logger.error(str) end def parse_command_line options = Hash::new - parser = GetoptLong.new - parser.ordering = GetoptLong::REQUIRE_ORDER - parser.set_options( - ["--pid-file", GetoptLong::REQUIRED_ARGUMENT]) - + parser = GetoptLong.new( ["--daemon", GetoptLong::REQUIRED_ARGUMENT], + ["--pid-file", GetoptLong::REQUIRED_ARGUMENT] + ) parser.quiet = true begin parser.each_option do |name, arg| @@ -2012,12 +2027,27 @@ def main write_pid_file($options["pid-file"]) if ($options["pid-file"]) - server = TCPserver.open(port) + dir = $options["daemon"] || nil + if dir && ! File.exist?(dir) + FileUtils.mkdir(dir) + end + log_file = dir ? File.join(dir, "shogi-server.log") : STDOUT + $logger = WEBrick::Log.new(log_file) + + LEAGUE.dir = dir || File.dirname(__FILE__) + LEAGUE.setup_players_database + + config = {} + config[:Port] = port + config[:ServerType] = WEBrick::Daemon if $options["daemon"] + config[:Logger] = $logger + + server = WEBrick::GenericServer.new(config) + ["INT", "TERM"].each {|signal| trap(signal){ server.shutdown } } + $stderr.puts("server started as a deamon") if $options["daemon"] log_message("server started") - while true - Thread::start(server.accept) do |client| - Thread.pass + server.start do |client| client.sync = true player = nil login = nil @@ -2037,8 +2067,11 @@ def main LEAGUE.players[player.name].kill else login.incorrect_duplicated_player(str) - Thread::exit - return + #Thread::exit + #return + # TODO + player = nil + break end end LEAGUE.add(player) @@ -2052,9 +2085,10 @@ def main end end # login loop if (! player) - client.close - Thread::exit - return + #client.close + #Thread::exit + #return + next end log_message(sprintf("user %s login", player.name)) login.process @@ -2070,7 +2104,6 @@ def main ensure $mutex.unlock end - end end end @@ -2080,7 +2113,7 @@ if ($0 == __FILE__) STDERR.sync = true TCPSocket.do_not_reverse_lookup = true Thread.abort_on_exception = true - + LEAGUE = ShogiServer::League::new main end