OSDN Git Service

Fixed a bug that the server failed to start with a permission denied error.
[shogi-server/shogi-server.git] / webserver
1 #!/usr/bin/ruby
2
3 ## Copyright (C) 2007 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
25 class ShogiClient
26   CLIENT_NAME     = "web"
27   CLIENT_PASSWORD = "web1235"
28
29   def initialize(config = {})
30     @@mutex = Mutex.new
31     config[:host] ||= "localhost"
32     config[:port] ||= 4081
33     @socket = TCPSocket.open(config[:host], config[:port])
34   end
35
36   def login
37     @socket.puts "LOGIN #{CLIENT_NAME} #{CLIENT_PASSWORD} x1"
38     gets_ok do |s|
39       /OK x1/ =~ s
40     end
41   end
42
43   def logout
44     @socket.puts "LOGOUT"
45     gets_ok
46   end
47
48   def who
49     @@mutex.synchronize do
50       @socket.puts "%%WHO"
51       gets_ok
52     end
53   end
54
55   def list
56     @@mutex.synchronize do
57       @socket.puts "%%LIST"
58       gets_ok
59     end
60   end
61
62   private
63
64   def gets_ok
65     buf = ""
66     timeout(5) do
67       loop do
68         s = @socket.gets
69         break unless s
70         buf << s
71         if block_given?
72           break if yield(s)
73         else
74           break if /OK$/ =~ s
75         end
76       end
77     end
78     return buf
79   rescue Timeout::Error
80     return buf
81   end
82 end
83
84
85 class ListServlet < WEBrick::HTTPServlet::AbstractServlet
86   def do_GET(req, res)
87     res.body = $client.list
88     res['Content-Type'] = "text/plain"
89   end
90 end
91
92 class WhoServlet < WEBrick::HTTPServlet::AbstractServlet
93   def do_GET(req, res)
94     res.body = $client.who
95     res['Content-Type'] = "text/plain"
96   end
97 end
98
99 def usage
100   $stderr.puts <<-EOF
101 USAGE: #{$0} [--daemon dir] [--port port]
102   --daemon dir    Run as a daemon. Log files are put in dir
103   --port port     Listening port for HTTP server (default 4080) 
104   EOF
105 end
106
107 def parse_command_line
108   options = Hash::new
109   parser = GetoptLong.new( ["--daemon", GetoptLong::REQUIRED_ARGUMENT],
110                            ["--port",   GetoptLong::REQUIRED_ARGUMENT])
111   parser.quiet = true
112   begin
113     parser.each_option do |name, arg|
114       name.sub!(/^--/, '')
115       options[name] = arg.dup
116     end
117   rescue
118     usage
119     raise parser.error_message
120   end
121
122   dir = options["daemon"] || nil
123   dir = File.expand_path(dir) if dir
124   if dir && ! File.exist?(dir)
125     FileUtils.mkdir(dir)
126   end
127   options["dir"] = dir || File.dirname(__FILE__)
128   
129   options["port"] ||= 4080
130   options["port"] = options["port"].to_i
131   
132   return options
133 end
134
135
136 def main
137   $options = parse_command_line
138
139   $client = ShogiClient.new
140   $client.login
141
142   http_log_file            = File.join($options["dir"], "shogi-server-httpd.log")
143   http_access_log_file     = File.join($options["dir"], "shogi-server-access.log")
144   http_config = {}
145   http_config[:Port]       = $options["port"]
146   http_config[:ServerType] = WEBrick::Daemon if $options["daemon"]
147   http_config[:Logger]     = WEBrick::Log.new(http_log_file)
148   http_config[:AccessLog]  = 
149           [[ WEBrick::Log.new(http_access_log_file), WEBrick::AccessLog::COMMON_LOG_FORMAT ]]
150   
151   
152   server = WEBrick::HTTPServer.new(http_config)
153   ["INT", "TERM"].each {|signal| trap(signal){ server.shutdown; $client.logout } }
154   server.mount("/list", ListServlet)
155   server.mount("/who",  WhoServlet)
156   server.start
157 end
158
159 if __FILE__ == $0
160   TCPSocket.do_not_reverse_lookup = true
161   main
162 end