Implemented parts of the server and protocol handler.
git-svn-id: svn+ssh://svn.luon.net/svn/ildus/trunk@3 65a33f86-aa00-0410-91be-cd1bf5efb309
This commit is contained in:
parent
cb0cf672bd
commit
50062f3b9f
|
@ -8,23 +8,65 @@
|
||||||
# any later version.
|
# any later version.
|
||||||
|
|
||||||
require 'gserver'
|
require 'gserver'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
require 'ildus/server/handler'
|
||||||
|
|
||||||
module Ildus
|
module Ildus
|
||||||
|
|
||||||
class Server < GServer
|
class Server < GServer
|
||||||
|
|
||||||
|
# The interface to listen specified default by the hostname.
|
||||||
|
DEFAULT_HOST = '::'
|
||||||
|
|
||||||
|
# The maximal number of connections.
|
||||||
|
MAX_CONNECTIONS = 20
|
||||||
|
|
||||||
|
# The server configuration.
|
||||||
|
attr_reader :config
|
||||||
|
|
||||||
# Create a Ildus server instance that is a derivate of a generic
|
# Create a Ildus server instance that is a derivate of a generic
|
||||||
# server. Accepts an alternative _config_file_ as optional argument.
|
# server. Accepts an alternative _config_file_ as optional argument.
|
||||||
def initialize(config_file=nil)
|
def initialize(config_file=nil)
|
||||||
|
@config = nil
|
||||||
|
parse_config(config_file)
|
||||||
|
|
||||||
|
super(config['port'], DEFAULT_HOST, 20, $stderr, true, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def serve(io)
|
||||||
|
hdl = Handler.new(self, io)
|
||||||
|
hdl.handle_client
|
||||||
|
rescue => e
|
||||||
|
$stderr.puts "#{e.class}: #{e}"
|
||||||
|
$stderr.puts e.backtrace
|
||||||
end
|
end
|
||||||
|
|
||||||
# Start the Ildus server.
|
# Start the Ildus server.
|
||||||
def start
|
def start
|
||||||
|
super
|
||||||
|
join
|
||||||
end
|
end
|
||||||
|
|
||||||
# Stop and shutdown the Ildus server. An _status_ code (defaults to 0)
|
# Stop and shutdown the Ildus server. An _status_ code (defaults to 0)
|
||||||
# can be used as an optional argument.
|
# can be used as an optional argument.
|
||||||
def shutdown(status=0)
|
def shutdown(status=0)
|
||||||
|
super()
|
||||||
|
exit(status)
|
||||||
|
end
|
||||||
|
|
||||||
|
#########
|
||||||
|
private
|
||||||
|
#########
|
||||||
|
|
||||||
|
# Parses the configuration file _filename_ and stores the parsed
|
||||||
|
# contents.
|
||||||
|
def parse_config(filename)
|
||||||
|
raise ArgumentError unless FileTest.exists? filename
|
||||||
|
|
||||||
|
File.open(filename, "r") do |io|
|
||||||
|
@config = YAML.load(io)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end # class Server
|
end # class Server
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
# = ildus/server/handler - Ildus server command handler
|
||||||
|
#
|
||||||
|
# Copyright (C) 2005 Paul van Tilburg <paul@luon.net>
|
||||||
|
#
|
||||||
|
# Ildus 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.
|
||||||
|
|
||||||
|
module Ildus
|
||||||
|
|
||||||
|
class Server < GServer
|
||||||
|
|
||||||
|
class Handler
|
||||||
|
|
||||||
|
class ProtocolException < StandardError; end
|
||||||
|
class CmdUnknownError < ProtocolException; end
|
||||||
|
class ArgsSyntaxError < ProtocolException; end
|
||||||
|
class NotImplementedError < ProtocolException; end
|
||||||
|
class AlreadyAuthError < ProtocolException; end
|
||||||
|
class TooManyUnknownError < ProtocolException; end
|
||||||
|
|
||||||
|
MaxCmdErrs = 3
|
||||||
|
|
||||||
|
ProtocolCodeMapping = {
|
||||||
|
200 => "Command OK.",
|
||||||
|
# 210, 211, 212, 213
|
||||||
|
214 => "Direct comments to %s.",
|
||||||
|
215 => "Listing done.",
|
||||||
|
220 => "%s %s %s %s, welcome.",
|
||||||
|
221 => "%s closed connection, goodbye!",
|
||||||
|
230 => "User %s authenticated, proceed.",
|
||||||
|
240 => "Updated host %s to IP %s.",
|
||||||
|
# 330
|
||||||
|
331 => "User name OK, need password.",
|
||||||
|
# 420
|
||||||
|
421 => "%s forcibly closed connection.",
|
||||||
|
422 => "connection timed out, %s forcibly closed connection.",
|
||||||
|
# 423, 424
|
||||||
|
425 => "Can't find host %s.",
|
||||||
|
426 => "Can't find %s-record of host %s.",
|
||||||
|
500 => "Syntax error, command `%s' unrecognized.",
|
||||||
|
501 => "Syntax error in arguments.",
|
||||||
|
502 => "Command not implemented.",
|
||||||
|
503 => "Too many unrecognized commands!",
|
||||||
|
504 => "You are already authenticated!",
|
||||||
|
505 => "Server error: %s!",
|
||||||
|
506 => "Server error, update failed: %s",
|
||||||
|
530 => "Not authenticated!"
|
||||||
|
}
|
||||||
|
|
||||||
|
def intialize(server, io)
|
||||||
|
@server = server
|
||||||
|
@io = io
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_client
|
||||||
|
io.puts prot_msg(220, "localhost", Program, Version, Time.now.to_s)
|
||||||
|
|
||||||
|
cmd_errs = 0
|
||||||
|
io.each_line do |line|
|
||||||
|
begin
|
||||||
|
cmd, *args = line.split /\s+/
|
||||||
|
handle_command(io, cmd, args)
|
||||||
|
rescue CmdUnknownError # 500
|
||||||
|
raise TooManyUnknownError if cmd_errs > MaxCmdErrs
|
||||||
|
io.puts prot_msg(500, cmd)
|
||||||
|
cmd_errs = cmd_errs + 1
|
||||||
|
rescue ArgsSyntaxError # 501
|
||||||
|
io.puts prot_msg(501)
|
||||||
|
rescue NotImplementedError # 502
|
||||||
|
io.puts prot_msg(502)
|
||||||
|
rescue AlreadyAuthError # 504
|
||||||
|
io.puts prot_msg(504)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue TooManyUnknownError # 503
|
||||||
|
io.puts prot_msg(503)
|
||||||
|
rescue RuntimeError => msg # 505
|
||||||
|
io.puts prot_msg(505, msg)
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
|
||||||
|
#########
|
||||||
|
private
|
||||||
|
#########
|
||||||
|
|
||||||
|
def handle_command(io, cmd, args)
|
||||||
|
method_name = cmd.downcase + "_cmd"
|
||||||
|
meth = method(method_name)
|
||||||
|
meth.call(*args)
|
||||||
|
rescue NameError
|
||||||
|
raise CmdUnknownError
|
||||||
|
end
|
||||||
|
|
||||||
|
def prot_msg(code, *args)
|
||||||
|
code.to_s << " " << ProtocolCodeMapping[code] % args
|
||||||
|
end
|
||||||
|
|
||||||
|
end # class Handler
|
||||||
|
|
||||||
|
end # class Server
|
||||||
|
|
||||||
|
end # module Ildus
|
Reference in New Issue