class Arachni::RPC::Server::Dispatcher::Service

Base class and namespace for all Dispatcher services.

# RPC accessibility

Only PUBLIC methods YOU have defined will be accessible over RPC.

# Blocking operations

Please try to avoid blocking operations as they will block the main Reactor loop.

However, if you really need to perform such operations, you can update the relevant methods to expect a block and then pass the desired return value to that block instead of returning it the usual way.

This will result in the method’s payload to be deferred into a Thread of its own.

In addition, you can use the {#defer} and {#run_asap} methods is you need more control over what gets deferred and general scheduling.

# Asynchronous operations

Methods which perform async operations should expect a block and pass their results to that block instead of returning a value.

@author Tasos “Zapotek” Laskos <tasos.laskos@arachni-scanner.com>

Attributes

dispatcher[R]
options[R]

Public Class Methods

new( options, dispatcher ) click to toggle source
# File lib/arachni/rpc/server/dispatcher/service.rb, line 42
def initialize( options, dispatcher )
    @options    = options
    @dispatcher = dispatcher
end

Public Instance Methods

connect_to_dispatcher( url ) click to toggle source

Connects to a Dispatcher by ‘url`

@param [String] url

@return [Client::Dispatcher]

# File lib/arachni/rpc/server/dispatcher/service.rb, line 121
def connect_to_dispatcher( url )
    @dispatcher_connections ||= {}
    @dispatcher_connections[url] ||= Client::Dispatcher.new( options, url )
end
connect_to_instance( *args ) click to toggle source

Connects to an Instance by ‘url`.

@example

connect_to_instance( url, token )
connect_to_instance( url: url, token: token )
connect_to_instance( 'url' => url, 'token' => token )

@param [Vararg] args

@return [Client::Instance]

# File lib/arachni/rpc/server/dispatcher/service.rb, line 136
def connect_to_instance( *args )
    url = token = nil

    if args.size == 2
        url, token = *args
    elsif args.first.is_a? Hash
        connection_options = args.first
        url     = connection_options['url']   || connection_options[:url]
        token   = connection_options['token'] || connection_options[:token]
    end

    @instance_connections ||= {}
    @instance_connections[url] ||= Client::Instance.new( options, url, token )
end
defer( operation = nil, callback = nil, &block ) click to toggle source

Defers a blocking operation in order to avoid blocking the main Reactor loop.

The operation will be run in its own Thread - DO NOT block forever.

Accepts either 2 parameters (an ‘operation` and a `callback` or an operation as a block.

@param [Proc] operation

Operation to defer.

@param [Proc] callback

Block to call with the results of the operation.

@param [Block] block

Operation to defer.
# File lib/arachni/rpc/server/dispatcher/service.rb, line 91
def defer( operation = nil, callback = nil, &block )
    Thread.new( *[operation, callback].compact, &block )
end
each_instance( &block ) click to toggle source

Performs an asynchronous iteration over all running instances.

@param [Proc] block

Block to be passed {Client::Instance} and `Arachni::Reactor::Iterator`.
# File lib/arachni/rpc/server/dispatcher/service.rb, line 70
def each_instance( &block )
    wrap = proc do |instance, iterator|
        block.call( connect_to_instance( instance ), iterator )
    end
    iterator_for( instances ).each( &wrap )
end
instances() click to toggle source

@return [Array<Hash>]

Alive instances.
# File lib/arachni/rpc/server/dispatcher/service.rb, line 112
def instances
    dispatcher.running_jobs
end
iterator_for( list, max_concurrency = 10 ) click to toggle source

@param [Array] list

@return [Reactor::Iterator]

Iterator for the provided array.
# File lib/arachni/rpc/server/dispatcher/service.rb, line 106
def iterator_for( list, max_concurrency = 10 )
    Reactor.global.create_iterator( list, max_concurrency )
end
map_instances( each, after ) click to toggle source

Performs an asynchronous map operation over all running instances.

@param [Proc] each

Block to be passed {Client::Instance} and `Arachni::Reactor::Iterator`.

@param [Proc] after

Block to be passed the Array of results.
# File lib/arachni/rpc/server/dispatcher/service.rb, line 59
def map_instances( each, after )
    wrap_each = proc do |instance, iterator|
        each.call( connect_to_instance( instance ), iterator )
    end
    iterator_for( instances ).map( wrap_each, after )
end
node() click to toggle source

@return [Server::Dispatcher::Node]

Local node.
# File lib/arachni/rpc/server/dispatcher/service.rb, line 49
def node
    dispatcher.instance_eval { @node }
end
run_asap( &block ) click to toggle source

Runs a block as soon as possible in the Reactor loop.

@param [Block] block

# File lib/arachni/rpc/server/dispatcher/service.rb, line 98
def run_asap( &block )
    Reactor.global.next_tick( &block )
end