class Arachni::Processes::Instances

Helper for managing {RPC::Server::Instance} processes.

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

Attributes

list[R]

@return [Array<String>] URLs and tokens of all running Instances.

Public Class Methods

method_missing( sym, *args, &block ) click to toggle source
Calls superclass method
# File lib/arachni/processes/instances.rb, line 219
def self.method_missing( sym, *args, &block )
    if instance.respond_to?( sym )
        instance.send( sym, *args, &block )
    else
        super( sym, *args, &block )
    end
end
new() click to toggle source
# File lib/arachni/processes/instances.rb, line 24
def initialize
    @list = {}
    @instance_connections = {}
end
respond_to?( m ) click to toggle source
Calls superclass method
# File lib/arachni/processes/instances.rb, line 227
def self.respond_to?( m )
    super( m ) || instance.respond_to?( m )
end

Public Instance Methods

connect( url, token = nil ) click to toggle source

Connects to a Instance by URL.

@param [String] url URL of the Dispatcher. @param [String] token

Authentication token -- only need be provided once.

@return [RPC::Client::Instance]

# File lib/arachni/processes/instances.rb, line 38
def connect( url, token = nil )
    Reactor.global.run_in_thread if !Reactor.global.running?

    token ||= @list[url]
    @list[url] ||= token

    @instance_connections[url] ||=
        RPC::Client::Instance.new( Options, url, token )
end
dispatcher_spawn() click to toggle source

Starts {RPC::Server::Dispatcher} and returns an Instance.

@return [RPC::Client::Instance]

# File lib/arachni/processes/instances.rb, line 172
def dispatcher_spawn
    info = Dispatchers.light_spawn.dispatch
    connect( info['url'], info['token'] )
end
each( &block ) click to toggle source

@param [Block] block Block to pass an RPC client for each Instance.

# File lib/arachni/processes/instances.rb, line 49
def each( &block )
    @list.keys.each do |url|
        block.call connect( url )
    end
end
grid_spawn( options = {} ) click to toggle source

Starts {RPC::Server::Dispatcher} grid and returns a high-performance Instance.

@param [Hash] options @option options [Integer] :grid_size (3) Amount of Dispatchers to spawn.

@return [RPC::Client::Instance]

# File lib/arachni/processes/instances.rb, line 122
def grid_spawn( options = {} )
    options[:grid_size] ||= 3

    last_member = nil
    options[:grid_size].times do |i|
        last_member = Dispatchers.spawn(
            neighbour: last_member ? last_member.url : last_member,
            pipe_id:   Utilities.available_port.to_s + Utilities.available_port.to_s
        )
    end

    info = last_member.dispatch

    instance = connect( info['url'], info['token'] )
    instance.framework.set_as_master
    instance.options.set( dispatcher: { grid_mode: :aggregate } )
    instance
end
kill( url ) click to toggle source
# File lib/arachni/processes/instances.rb, line 177
def kill( url )
    service = connect( url ).service
    service.consumed_pids do |pids|
        service.shutdown do
            # Make sure....
            Manager.kill_many pids
        end
    end

    @list.delete url
end
killall() click to toggle source

Kills all {Instances list}.

# File lib/arachni/processes/instances.rb, line 190
def killall
    pids = []
    each do |instance|
        begin
            Timeout.timeout 5 do
                pids |= instance.service.consumed_pids
            end
        rescue => e
            #ap e
            #ap e.backtrace
        end
    end

    each do |instance|
        begin
            Timeout.timeout 5 do
                instance.service.shutdown
            end
        rescue => e
            #ap e
            #ap e.backtrace
        end
    end

    @list.clear
    @instance_connections.clear
    Manager.kill_many pids
end
light_grid_spawn( options = {} ) click to toggle source

Starts {RPC::Server::Dispatcher} grid and returns a high-performance Instance.

@param [Hash] options @option options [Integer] :grid_size (3) Amount of Dispatchers to spawn.

@return [RPC::Client::Instance]

# File lib/arachni/processes/instances.rb, line 147
def light_grid_spawn( options = {} )
    options[:grid_size] ||= 3

    last_member = nil
    options[:grid_size].times do |i|
        last_member = Dispatchers.light_spawn(
            neighbour: last_member ? last_member.url : last_member,
            pipe_id:   Utilities.available_port.to_s + Utilities.available_port.to_s
        )
    end

    info = nil
    info = last_member.dispatch while !info && sleep( 0.1 )

    instance = connect( info['url'], info['token'] )
    instance.framework.set_as_master
    instance.options.set( dispatcher: { grid_mode: :aggregate } )
    instance
end
spawn( options = {}, &block ) click to toggle source

Spawns an {RPC::Server::Instance} process.

@param [Hash] options

To be passed to {Arachni::Options#set}. Allows `address` instead of
`rpc_server_address` and `port` instead of `rpc_port`.

@return [RPC::Client::Instance]

# File lib/arachni/processes/instances.rb, line 71
def spawn( options = {}, &block )
    token = options.delete(:token) || Utilities.generate_token
    fork  = options.delete(:fork)

    options = {
        spawns: options[:spawns],
        rpc:    {
            server_socket:  options[:socket],
            server_port:    options[:port]    || Utilities.available_port,
            server_address: options[:address] || '127.0.0.1'
        }
    }

    url = nil
    if options[:rpc][:server_socket]
        url = options[:rpc][:server_socket]

        options[:rpc].delete :server_address
        options[:rpc].delete :server_port
    else
        url = "#{options[:rpc][:server_address]}:#{options[:rpc][:server_port]}"
    end

    Manager.spawn( :instance, options: options, token: token, fork: fork )

    client = connect( url, token )

    if block_given?
        client.when_ready do
            block.call client
        end
    else
        while sleep( 0.1 )
            begin
                client.service.alive?
                break
            rescue => e
                # ap "#{e.class}: #{e}"
                # ap e.backtrace
            end
        end
        client
    end
end
token_for( client_or_url ) click to toggle source

@param [String, RPC::Client::Instance] client_or_url

@return [String] Cached authentication token for the given Instance.

# File lib/arachni/processes/instances.rb, line 60
def token_for( client_or_url )
    @list[client_or_url.is_a?( String ) ? client_or_url : client_or_url.url ]
end