OSDN Git Service

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