#! /usr/bin/env ruby ## $Id$ ## Copyright (C) 2004 NABEYA Kenichi (aka nanami@2ch) ## Copyright (C) 2007-2008 Daigo Moriwaki (daigo at debian dot org) ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA $:.unshift File.dirname(__FILE__) require 'shogi_server' ################################################# # MAIN # def gets_safe(socket, timeout=nil) if r = select([socket], nil, nil, timeout) return r[0].first.gets else return :timeout end rescue Exception => ex log_error("#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}") return :exception end def usage print <= 4) end ensure $mutex.unlock end end # login loop return [player, login] end def setup_logger(log_file) logger = Logger.new(log_file, 'daily') logger.formatter = ShogiServer::Formatter.new logger.level = Logger::INFO logger.datetime_format = "%Y-%m-%d %H:%M:%S" return logger end def setup_watchdog_for_giant_lock $mutex = Mutex::new Thread::start do Thread.pass mutex_watchdog($mutex, 10) end end def main setup_watchdog_for_giant_lock $options = parse_command_line if (ARGV.length != 2) usage exit 2 end LEAGUE.event = ARGV.shift port = ARGV.shift dir = $options["daemon"] dir = File.expand_path(dir) if dir if dir && ! File.exist?(dir) FileUtils.mkdir(dir) end log_file = dir ? File.join(dir, "shogi-server.log") : STDOUT $logger = setup_logger(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 if $options["pid-file"] pid_file = File.expand_path($options["pid-file"]) config[:StartCallback] = Proc.new do write_pid_file(pid_file) end config[:StopCallback] = Proc.new do FileUtils.rm(pid_file, :force => true) end end server = WEBrick::GenericServer.new(config) ["INT", "TERM"].each do |signal| trap(signal) do LEAGUE.shutdown server.shutdown end end trap("HUP") do LEAGUE.shutdown Dependencies.clear LEAGUE.restart end $stderr.puts("server started as a deamon [Revision: #{ShogiServer::Revision}]") if $options["daemon"] log_message("server started [Revision: #{ShogiServer::Revision}]") server.start do |client| # client.sync = true # this is already set in WEBrick client.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) # Keepalive time can be set by /proc/sys/net/ipv4/tcp_keepalive_time player, login = login_loop(client) # loop next unless player log_message(sprintf("user %s login", player.name)) login.process player.run(login.csa_1st_str) # loop $mutex.lock begin if (player.game) player.game.kill(player) end player.finish # socket has been closed LEAGUE.delete(player) log_message(sprintf("user %s logout", player.name)) ensure $mutex.unlock end end end if ($0 == __FILE__) STDOUT.sync = true STDERR.sync = true TCPSocket.do_not_reverse_lookup = true Thread.abort_on_exception = $DEBUG ? true : false LEAGUE = ShogiServer::League::new main end