OSDN Git Service

Merge branch 'wdoor-stable'
[shogi-server/shogi-server.git] / webserver
1 #!/usr/bin/ruby
2
3 ## Copyright (C) 2007-2012 Daigo Moriwaki <daigo at debian dot org>
4 ##
5 ## This program is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 2 of the License, or
8 ## (at your option) any later version.
9 ##
10 ## This program is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 ## GNU General Public License for more details.
14 ##
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program; if not, write to the Free Software
17 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19 require 'getoptlong'
20 require 'timeout'
21 require 'thread'
22 require 'webrick'
23 require 'socket'
24 require 'fileutils'
25
26 def write_pid_file(file)
27   open(file, "w") do |fh|
28     fh.puts "#{$$}"
29   end
30 end
31
32 class ShogiClient
33   CLIENT_NAME     = "web"
34   CLIENT_PASSWORD = "web1235"
35
36   def initialize(config = {})
37     @@mutex = Mutex.new
38     config[:host] ||= "localhost"
39     config[:port] ||= 4081
40     @socket = TCPSocket.open(config[:host], config[:port])
41   end
42
43   def login
44     @socket.puts "LOGIN #{CLIENT_NAME} #{CLIENT_PASSWORD} x1"
45     gets_ok do |s|
46       /OK x1/ =~ s
47     end
48   end
49
50   def logout
51     @socket.puts "LOGOUT"
52     gets_ok
53   end
54
55   def who
56     @@mutex.synchronize do
57       @socket.puts "%%WHO"
58       gets_ok
59     end
60   end
61
62   def list
63     @@mutex.synchronize do
64       @socket.puts "%%LIST"
65       gets_ok
66     end
67   end
68
69   private
70
71   def gets_ok
72     buf = ""
73     timeout(5) do
74       loop do
75         s = @socket.gets
76         break unless s
77         buf << s
78         if block_given?
79           break if yield(s)
80         else
81           break if /OK$/ =~ s
82         end
83       end
84     end
85     return buf
86   rescue Timeout::Error
87     return buf
88   end
89 end
90
91
92 class ListServlet < WEBrick::HTTPServlet::AbstractServlet
93   def do_GET(req, res)
94     res.body = $client.list
95     res['Content-Type'] = "text/plain"
96   end
97 end
98
99 class WhoServlet < WEBrick::HTTPServlet::AbstractServlet
100   def do_GET(req, res)
101     res.body = $client.who
102     res['Content-Type'] = "text/plain"
103   end
104 end
105
106 def usage
107   $stderr.puts <<-EOF
108 USAGE: #{$0} [--daemon dir] [--port port] [--pid-file file]
109   --daemon dir    Run as a daemon. Log files are put in dir
110   --port port     Listening port for HTTP server (default 4080) 
111   --pid-file file Write the process id to the file
112   EOF
113 end
114
115 def parse_command_line
116   options = Hash::new
117   parser = GetoptLong.new( ["--daemon",   GetoptLong::REQUIRED_ARGUMENT],
118                            ["--port",     GetoptLong::REQUIRED_ARGUMENT],
119                            ["--pid-file", GetoptLong::REQUIRED_ARGUMENT])
120   parser.quiet = true
121   begin
122     parser.each_option do |name, arg|
123       name.sub!(/^--/, '')
124       options[name] = arg.dup
125     end
126   rescue
127     usage
128     raise parser.error_message
129   end
130
131   dir = options["daemon"]
132   dir = File.expand_path(dir) if dir
133   if dir && ! File.exist?(dir)
134     FileUtils.mkdir(dir)
135   end
136   options["dir"] = dir || File.dirname(__FILE__)
137   options["port"] ||= 4080
138   options["port"] = options["port"].to_i
139   options["pid-file"] = File.expand_path(options["pid-file"]) if options["pid-file"]
140
141   return options
142 end
143
144
145 def main
146   $options = parse_command_line
147
148   $client = ShogiClient.new
149   $client.login
150
151   http_log_file            = File.join($options["dir"], "shogi-server-httpd.log")
152   http_access_log_file     = File.join($options["dir"], "shogi-server-access.log")
153   http_config = {}
154   http_config[:BindAddress] = "0.0.0.0"
155   http_config[:Port]       = $options["port"]
156   http_config[:ServerType] = WEBrick::Daemon if $options["daemon"]
157   http_config[:Logger]     = WEBrick::Log.new(http_log_file)
158   http_config[:AccessLog]  = 
159           [[ WEBrick::Log.new(http_access_log_file), WEBrick::AccessLog::COMMON_LOG_FORMAT ]]
160   if $options["pid-file"]
161     http_config[:StartCallback] = Proc.new do
162       write_pid_file($options["pid-file"])
163     end
164     http_config[:StopCallback] = Proc.new do
165       FileUtils.rm($options["pid-file"], :force => true)
166     end
167   end
168
169   
170   
171   server = WEBrick::HTTPServer.new(http_config)
172   ["INT", "TERM"].each {|signal| trap(signal){ server.shutdown; $client.logout } }
173   server.mount("/list", ListServlet)
174   server.mount("/who",  WhoServlet)
175   server.start
176 end
177
178 if __FILE__ == $0
179   TCPSocket.do_not_reverse_lookup = true
180   main
181 end