class DRbService

A base class for DRb-based services. Concrete subclasses must define the service API by declaring public methods. By default, any public methods are hidden until the client authenticates. You can optionally declare a subset of its API that is # accessible before authentication by wrapping them in an ‘unguarded’ block. # See DRbService::unguarded for more details.

Constants

DEFAULT_CERTNAME

The default path to the service cert, relative to the current directory

DEFAULT_CONFIG

The default values for the drbservice config hash

DEFAULT_IP

The default IP address to listen on

DEFAULT_KEYNAME

The default path to the service key, relative to the current directory

DEFAULT_PORT

The default port to listen on

REVISION

Version-control revision

VERSION

Library version

Attributes

real_methods[R]
unguarded_mode[RW]

The unguarded mode flag – instance methods defined while this flag is set will not be hidden

Public Class Methods

inherited( subclass ) click to toggle source

Inheritance callback: Add a per-class ‘unguarded mode’ flag to subclasses.

Calls superclass method
# File lib/drbservice.rb, line 105
def self::inherited( subclass )
        self.log.debug "Setting @unguarded_mode in %p" % [ subclass ]
        subclass.instance_variable_set( :@unguarded_mode, false )
        super
end
method_added( meth ) click to toggle source

Method-addition callback: Obscure the method meth unless unguarded mode is enabled.

Calls superclass method
# File lib/drbservice.rb, line 86
def self::method_added( meth )
        super

        unless self == ::DRbService || meth.to_sym == :initialize
                if !self.public_instance_methods.collect( &:to_sym ).include?( meth )
                        DRbService.log.debug "Not obsuring %p#%s: not a public method" % [ self, meth ]
                elsif self.unguarded_mode
                        DRbService.log.debug "Not obscuring %p#%s: unguarded mode." % [ self, meth ]
                else
                        DRbService.log.debug "Obscuring %p#%s." % [ self, meth ]
                        @real_methods ||= {}
                        @real_methods[ meth.to_sym ] = self.instance_method( meth )
                        remove_method( meth )
                end
        end
end
new( config={} ) click to toggle source

Create a new instance of the service. Raises a ScriptError if DRbService is instantiated directly.

# File lib/drbservice.rb, line 146
def initialize( config={} )
        raise ScriptError,
                "can't instantiate #{self.class} directly: please subclass it instead" if
                self.class == DRbService
        @authenticated = false
end
start( config={} ) click to toggle source

Start the DRbService, using the ip, port, and cert information from the given config hash.

:ip

the ip to bind to

:port

the port to listen on

:certfile

the name of the server’s SSL certificate file

:keyfile

the name of the server’s SSL key file

# File lib/drbservice.rb, line 61
def self::start( config={} )
        config = DEFAULT_CONFIG.merge( config )

        frontobj = self.new( config )
        uri = "drbssl://%s:%d" % config.values_at( :ip, :port )

        cert = OpenSSL::X509::Certificate.new( File.read(config[:certfile]) )
        key  = OpenSSL::PKey::RSA.new( File.read(config[:keyfile]) )

        config = {
                :safe_level     => 1,
                :verbose        => true,
        :SSLCertificate => cert,
        :SSLPrivateKey  => key,
        }

        DRbService.log.info "Starting %p as a DRbService at %s" % [ self, uri ]
        server = DRb::DRbServer.new( uri, frontobj, config )
        DRbService.log.debug "  started. Joining the DRb thread."
        $0 = "%s %s" % [ self.name, uri ]
        server.thread.join
end
unguarded() { || ... } click to toggle source

Declare some service methods that can be called without authentication in the provided block.

# File lib/drbservice.rb, line 114
def self::unguarded
        self.unguarded_mode = true
        yield
ensure
        self.unguarded_mode = false
end
version_string( include_buildnum=false ) click to toggle source

Return the library’s version string

# File lib/drbservice.rb, line 123
def self::version_string( include_buildnum=false )
        vstring = "%s %s" % [ self.name, VERSION ]
        vstring << " (build %s)" % [ REVISION[/.*: ([[:xdigit:]]+)/, 1] || '0' ] if include_buildnum
        return vstring
end

Public Instance Methods

authenticate( *args ) click to toggle source

Default authentication implementation – always fails. You’ll need to include one of the authentication modules or provide your own authenticate method in your subclass.

# File lib/drbservice.rb, line 182
def authenticate( *args )
        self.log.error "authentication failure (fallback method)"
        raise SecurityError, "authentication failure"
end
authenticated?() click to toggle source

Returns true if the client has successfully authenticated.

# File lib/drbservice.rb, line 165
def authenticated?
        return @authenticated ? true : false
end
authorized?() click to toggle source

Returns true if the client has successfully authenticated and is authorized to use the service. By default, authentication is sufficient for authorization; to specify otherwise, override this method in your service’s subclass or include an auth mixin that provides one.

# File lib/drbservice.rb, line 174
def authorized?
        return self.authenticated?
end
inspect() click to toggle source

Return a human-readable representation of the object.

# File lib/drbservice.rb, line 159
def inspect
        return "#<%s:0x%0x>" % [ self.class, self.__id__ * 2 ]
end

Protected Instance Methods

method_missing( sym, *args ) click to toggle source

Handle calls to guarded methods by requiring the authentication flag be set if there is a password set.

Calls superclass method
# File lib/drbservice.rb, line 194
def method_missing( sym, *args )
        return super unless body = self.class.real_methods[ sym ]

        if self.authorized?
                return body.clone.bind( self ).call( *args )
        else
                self.log.error "Guarded method %p called without authentication!" % [ sym ]
                raise SecurityError, "not authenticated"
        end
end