=begin = net/session.rb version 1.1.3 written by Minero Aoki This library is distributed under the terms of the Ruby license. You can freely distribute/modify this library. =end require 'socket' module Net =begin == Net::Protocol the abstruct class for Internet protocol === Super Class Object === Constants : Version The version of Session class. It is a string like "1.1.3". === Class Methods : new( address = 'localhost', port = nil ) This method Creates a new Session object. : start( address = 'localhost', port = nil, *args ) : start( address = 'localhost', port = nil, *args ){|session| .... } This method creates a new Session object and start session. If you call this method with block, Session object give itself to block and finish session when block returns. : Proxy( address, port ) This method creates a proxy class of its protocol. Arguments are address/port of proxy host. === Methods : address the address of connecting server (FQDN). : port connecting port number : start( *args ) This method start protocol. If you call this method when the protocol is already started, this only returns false without doing anything. '*args' are specified in subclasses. : finish This method ends protocol. If you call this method before protocol starts, it only return false without doing anything. : active? true if session have been started =end class Protocol Version = '1.1.3' class << self def start( address = 'localhost', port = nil, *args ) instance = new( address, port ) if iterator? then instance.start( *args ) { yield instance } else instance.start *args instance end end def Proxy( p_addr, p_port ) klass = Class.new( self ) klass.module_eval %- def initialize( addr, port ) @proxyaddr = '#{p_addr}' @proxyport = '#{p_port}' super @proxyaddr, @proxyport @address = addr @port = port end def connect( addr, port ) super @proxyaddr, @proxyport end private :connect attr :proxyaddr attr :proxyport - def klass.proxy? true end klass end def proxy? false end private def protocol_param( name, val ) module_eval %- def self.#{name.id2name} #{val} end - end end # # sub-class requirements # # protocol_param command_type # protocol_param port # # private method do_start (optional) # private method do_finish (optional) # protocol_param :port, 'nil' protocol_param :command_type, 'nil' protocol_param :socket_type, '::Net::ProtocolSocket' def initialize( addr = nil, port = nil ) @address = addr || 'localhost' @port = port || self.type.port @active = false @pipe = nil @command = nil @socket = nil end attr :address attr :port attr :command attr :socket def start( *args ) return false if active? @active = true begin connect @address, @port do_start *args yield if iterator? ensure finish if iterator? end end def finish if @command then do_finish disconnect end if @socket and not @socket.closed? then @socket.close @socket = nil end if active? then @active = false return true else return false end end def active? @active end def set_pipe( arg ) # un-documented @pipe = arg end private def do_start end def do_finish end def connect( addr, port ) @socket = self.type.socket_type.open( addr, port, @pipe ) @command = self.type.command_type.new( @socket ) end def disconnect @command.quit @command = nil @socket = nil end end Session = Protocol =begin == Net::Command === Super Class Object === Class Methods : new( socket ) This method create new Command object. 'socket' must be ProtocolSocket. This method is abstract class. === Methods : quit This method dispatch command which ends the protocol. =end class Command def initialize( sock ) @socket = sock @error_occured = false end attr :socket, true attr :error_occured def quit if @socket and not @socket.closed? then begin do_quit ensure @socket.close unless @socket.closed? @socket = nil end @error_occured = false end end private def check_reply( *oks ) reply_must( get_reply, *oks ) end def reply_must( rep, *oks ) oks.each do |i| if i === rep then return rep end end @error_occured = true rep.error! @socket.sending end def getok( line, ok = SuccessCode ) @socket.writeline line check_reply ok end end class ProtocolError < StandardError ; end class ProtoSyntaxError < ProtocolError ; end class ProtoFatalError < ProtocolError ; end class ProtoUnknownError < ProtocolError ; end class ProtoServerError < ProtocolError ; end class ProtoAuthError < ProtocolError ; end class ProtoCommandError < ProtocolError ; end class ProtoRetryError < ProtocolError ; end class ReplyCode def initialize( cod, mes ) @code = cod @msg = mes end attr :code attr :msg def error!( sending ) mes = <