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
This commit is contained in:
parent
50062f3b9f
commit
55bf169b2c
|
@ -10,8 +10,6 @@
|
||||||
require 'gserver'
|
require 'gserver'
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
|
|
||||||
require 'ildus/server/handler'
|
|
||||||
|
|
||||||
module Ildus
|
module Ildus
|
||||||
|
|
||||||
class Server < GServer
|
class Server < GServer
|
||||||
|
@ -72,3 +70,8 @@ module Ildus
|
||||||
end # class Server
|
end # class Server
|
||||||
|
|
||||||
end # module Ildus
|
end # module Ildus
|
||||||
|
|
||||||
|
# Require the rest of the server library.
|
||||||
|
require 'ildus/server/account'
|
||||||
|
require 'ildus/server/backend'
|
||||||
|
require 'ildus/server/handler'
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
# = ildus/server/account - server account library
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,47 @@
|
||||||
|
# = ildus/server/backend - generic server backend library
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
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
|
|
@ -13,12 +13,20 @@ module Ildus
|
||||||
|
|
||||||
class Handler
|
class Handler
|
||||||
|
|
||||||
class ProtocolException < StandardError; end
|
class ProtocolException < StandardError; end
|
||||||
class CmdUnknownError < ProtocolException; end
|
|
||||||
class ArgsSyntaxError < ProtocolException; end
|
class HandlerExit < ProtocolException; end # 221
|
||||||
class NotImplementedError < ProtocolException; end
|
|
||||||
class AlreadyAuthError < ProtocolException; end
|
class HostNotFoundError < ProtocolException; end # 425
|
||||||
class TooManyUnknownError < ProtocolException; end
|
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
|
MaxCmdErrs = 3
|
||||||
|
|
||||||
|
@ -49,35 +57,46 @@ module Ildus
|
||||||
530 => "Not authenticated!"
|
530 => "Not authenticated!"
|
||||||
}
|
}
|
||||||
|
|
||||||
def intialize(server, io)
|
def initialize(server, io)
|
||||||
@server = server
|
@server = server
|
||||||
@io = io
|
@io = io
|
||||||
|
@account = Account.new
|
||||||
|
@backend = Backend.instance
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_client
|
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
|
cmd_errs = 0
|
||||||
io.each_line do |line|
|
@io.each_line do |line|
|
||||||
begin
|
begin
|
||||||
cmd, *args = line.split /\s+/
|
cmd, *args = line.split
|
||||||
handle_command(io, cmd, args)
|
handle_command(cmd, args)
|
||||||
|
rescue HandlerExit
|
||||||
|
prot_msg 221, "localhost"
|
||||||
|
break
|
||||||
rescue CmdUnknownError # 500
|
rescue CmdUnknownError # 500
|
||||||
raise TooManyUnknownError if cmd_errs > MaxCmdErrs
|
raise TooManyUnknownError if cmd_errs > MaxCmdErrs
|
||||||
io.puts prot_msg(500, cmd)
|
|
||||||
cmd_errs = cmd_errs + 1
|
cmd_errs = cmd_errs + 1
|
||||||
|
prot_msg 500, cmd
|
||||||
rescue ArgsSyntaxError # 501
|
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
|
rescue NotImplementedError # 502
|
||||||
io.puts prot_msg(502)
|
prot_msg 502
|
||||||
rescue AlreadyAuthError # 504
|
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
|
||||||
end
|
end
|
||||||
rescue TooManyUnknownError # 503
|
rescue TooManyUnknownError # 503
|
||||||
io.puts prot_msg(503)
|
prot_msg 503
|
||||||
rescue RuntimeError => msg # 505
|
rescue RuntimeError => msg # 505
|
||||||
io.puts prot_msg(505, msg)
|
prot_msg 505, msg
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -85,16 +104,89 @@ module Ildus
|
||||||
private
|
private
|
||||||
#########
|
#########
|
||||||
|
|
||||||
def handle_command(io, cmd, args)
|
def handle_command(cmd, args)
|
||||||
method_name = cmd.downcase + "_cmd"
|
method_name = cmd.downcase + "_cmd"
|
||||||
meth = method(method_name)
|
meth = method(method_name)
|
||||||
meth.call(*args)
|
meth.call(*args)
|
||||||
rescue NameError
|
rescue ArgumentError
|
||||||
|
raise ArgsSyntaxError
|
||||||
|
rescue NameError => e
|
||||||
|
$stderr.puts "#{e.class}: #{e}"
|
||||||
|
$stderr.puts e.backtrace
|
||||||
raise CmdUnknownError
|
raise CmdUnknownError
|
||||||
end
|
end
|
||||||
|
|
||||||
def prot_msg(code, *args)
|
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 <user>\t\tsupply username
|
||||||
|
PASS <passwd>\t\tgive password
|
||||||
|
LIST\t\t\tlist hostnames (and aliases)\t[auth. required]
|
||||||
|
UPDT <host> <ip>\tupdate ip for host\t\t[auth. required]
|
||||||
|
ADDA <host> <alias>\tadd alias to host\t\t[auth. required]
|
||||||
|
DELA <host> <alias>\tdelete alias from host\t\t[auth. required]
|
||||||
|
EOT
|
||||||
|
end
|
||||||
|
|
||||||
|
def quit_cmd
|
||||||
|
raise HandlerExit
|
||||||
end
|
end
|
||||||
|
|
||||||
end # class Handler
|
end # class Handler
|
||||||
|
|
Reference in New Issue