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:
paul 2005-09-15 14:47:25 +00:00
parent cb0cf672bd
commit 50062f3b9f
2 changed files with 146 additions and 0 deletions

View File

@ -8,23 +8,65 @@
# any later version.
require 'gserver'
require 'yaml'
require 'ildus/server/handler'
module Ildus
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
# server. Accepts an alternative _config_file_ as optional argument.
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
# Start the Ildus server.
def start
super
join
end
# Stop and shutdown the Ildus server. An _status_ code (defaults to 0)
# can be used as an optional argument.
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 # class Server

104
lib/ildus/server/handler.rb Normal file
View File

@ -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