From 55bf169b2c544de89143260b89ab55ed528d59fb Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 27 Sep 2005 14:28:59 +0000 Subject: [PATCH] Implemented protocol parts: * Added exceptions for all protocol errors (4xx, 5xx). * Implement commands: help, quit, adda, dela, updt, list. * Added Backend#prot_msg_body, let Backend#prot_msg do the outputting. * Added Server::Backend and Server::Account (empty stub implementations). git-svn-id: svn+ssh://svn.luon.net/svn/ildus/trunk@4 65a33f86-aa00-0410-91be-cd1bf5efb309 --- lib/ildus/server.rb | 7 +- lib/ildus/server/account.rb | 53 ++++++++++++++ lib/ildus/server/backend.rb | 47 +++++++++++++ lib/ildus/server/handler.rb | 136 ++++++++++++++++++++++++++++++------ 4 files changed, 219 insertions(+), 24 deletions(-) create mode 100644 lib/ildus/server/account.rb create mode 100644 lib/ildus/server/backend.rb diff --git a/lib/ildus/server.rb b/lib/ildus/server.rb index 77c8e25..bd17523 100644 --- a/lib/ildus/server.rb +++ b/lib/ildus/server.rb @@ -10,8 +10,6 @@ require 'gserver' require 'yaml' -require 'ildus/server/handler' - module Ildus class Server < GServer @@ -72,3 +70,8 @@ module Ildus end # class Server end # module Ildus + +# Require the rest of the server library. +require 'ildus/server/account' +require 'ildus/server/backend' +require 'ildus/server/handler' diff --git a/lib/ildus/server/account.rb b/lib/ildus/server/account.rb new file mode 100644 index 0000000..179b6de --- /dev/null +++ b/lib/ildus/server/account.rb @@ -0,0 +1,53 @@ +# = ildus/server/account - server account library +# +# Copyright (C) 2005 Paul van Tilburg +# +# 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. + +require 'yaml' + +module Ildus + + class Server + + class Account + + attr_reader :user, :pass + + def self.register_account(user, pass) + end + + def self.unregister_account(user, pass) + end + + def initialize + @user = nil + @pass = nil + @auth = false + end + + def user=(username) + raise Handler::AlreadyAuthError if @auth + @user = username + end + + def pass=(password) + raise Handler::AlreadyAuthError if @auth + @pass = password + ## STUB + @auth = rand(2).zero? + ## + end + + def authenticated? + @auth + end + + end # class Account + + end # class Server + +end # module Ildus diff --git a/lib/ildus/server/backend.rb b/lib/ildus/server/backend.rb new file mode 100644 index 0000000..5dcdc0b --- /dev/null +++ b/lib/ildus/server/backend.rb @@ -0,0 +1,47 @@ +# = ildus/server/backend - generic server backend library +# +# Copyright (C) 2005 Paul van Tilburg +# +# 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. + +require 'singleton' + +module Ildus + + class Server + + class Backend + include Singleton + + def hostnames_of(user) + raise Handler::NotImplementedError + end + + def add_hostname(user) + raise Handler::NotImplementedError + end + + def remove_hostname(user) + raise Handler::NotImplementedError + end + + def update_hostname(user, host, addr) + raise Handler::NotImplementedError + end + + def add_alias(user, new_alias, host) + raise Handler::NotImplementedError + end + + def remove_alias(user, old_alias, host) + raise Handler::NotImplementedError + end + + end # class Backend + + end # class Server + +end # module Ildus diff --git a/lib/ildus/server/handler.rb b/lib/ildus/server/handler.rb index f4572c2..1f42053 100644 --- a/lib/ildus/server/handler.rb +++ b/lib/ildus/server/handler.rb @@ -13,12 +13,20 @@ module Ildus 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 + class ProtocolException < StandardError; end + + class HandlerExit < ProtocolException; end # 221 + + class HostNotFoundError < ProtocolException; end # 425 + class RecordNotFoundError < ProtocolException; end # 426 + + class CmdUnknownError < ProtocolException; end # 500 + class ArgsSyntaxError < ProtocolException; end # 501 + class NotImplementedError < ProtocolException; end # 502 + class TooManyUnknownError < ProtocolException; end # 503 + class AlreadyAuthError < ProtocolException; end # 504 + class BackendError < ProtocolException; end # 506 + class NotAuthError < ProtocolException; end # 530 MaxCmdErrs = 3 @@ -49,35 +57,46 @@ module Ildus 530 => "Not authenticated!" } - def intialize(server, io) - @server = server - @io = io + def initialize(server, io) + @server = server + @io = io + @account = Account.new + @backend = Backend.instance end def handle_client - io.puts prot_msg(220, "localhost", Program, Version, Time.now.to_s) + prot_msg 220, "localhost", Program, Version, Time.now.to_s cmd_errs = 0 - io.each_line do |line| + @io.each_line do |line| begin - cmd, *args = line.split /\s+/ - handle_command(io, cmd, args) + cmd, *args = line.split + handle_command(cmd, args) + rescue HandlerExit + prot_msg 221, "localhost" + break rescue CmdUnknownError # 500 raise TooManyUnknownError if cmd_errs > MaxCmdErrs - io.puts prot_msg(500, cmd) cmd_errs = cmd_errs + 1 + prot_msg 500, cmd rescue ArgsSyntaxError # 501 - io.puts prot_msg(501) + raise TooManyUnknownError if cmd_errs > MaxCmdErrs + cmd_errs = cmd_errs + 1 + prot_msg 501 rescue NotImplementedError # 502 - io.puts prot_msg(502) + prot_msg 502 rescue AlreadyAuthError # 504 - io.puts prot_msg(504) + prot_msg 504 + rescue BackendError => msg # 506 + prot_msg 506, msg + rescue NotAuthError # 530 + prot_msg 530 end end rescue TooManyUnknownError # 503 - io.puts prot_msg(503) + prot_msg 503 rescue RuntimeError => msg # 505 - io.puts prot_msg(505, msg) + prot_msg 505, msg raise end @@ -85,16 +104,89 @@ module Ildus private ######### - def handle_command(io, cmd, args) + def handle_command(cmd, args) method_name = cmd.downcase + "_cmd" meth = method(method_name) meth.call(*args) - rescue NameError + rescue ArgumentError + raise ArgsSyntaxError + rescue NameError => e + $stderr.puts "#{e.class}: #{e}" + $stderr.puts e.backtrace raise CmdUnknownError end def prot_msg(code, *args) - code.to_s << " " << ProtocolCodeMapping[code] % args + msg = code.to_s + " " + (ProtocolCodeMapping[code] % args) + @io.puts msg + end + + def prot_msg_with_body(code, body, *args) + @io.print code.to_s, "-", body + prot_msg(code, *args) + end + + ################## + # Commands methods + + def user_cmd(username) + @account.user = username + prot_msg 331 + end + + def pass_cmd(password) + @account.pass = password + if @account.authenticated? + prot_msg 230, @account.user + else + raise NotAuthError + end + end + + def updt_cmd(hostname, addr) + raise NotAuthError unless @account.authenticated? + @backend.update_hostname(@account.user, hostname, addr) + rescue HostNotFoundError + prot_msg 425, hostname + rescue RecordNotFoundError + prot_msg 426, type, hostname + else + prot_msg 240, hostname, addr + end + + def adda_cmd(hostname, new_alias) + raise NotImplementedError + end + + def dela_cmd(hostname, old_alias) + raise NotImplementedError + end + + def list_cmd + raise NotAuthError unless @account.authenticated? + user = @account.user + #list = @backend.hostnames_of(user) + prot_msg_with_body 215, + "Listing of hosts (and aliases) for user #{user}\n" + end + + def help_cmd + prot_msg_with_body 214, + <<-EOT, "ildus-admin@localhost" +The following commands are recognized: + HELP\t\t\tshow this help + QUIT\t\t\tclose connection + USER \t\tsupply username + PASS \t\tgive password + LIST\t\t\tlist hostnames (and aliases)\t[auth. required] + UPDT \tupdate ip for host\t\t[auth. required] + ADDA \tadd alias to host\t\t[auth. required] + DELA \tdelete alias from host\t\t[auth. required] + EOT + end + + def quit_cmd + raise HandlerExit end end # class Handler