Class: Arachni::Processes::Dispatchers

Inherits:
Object
  • Object
show all
Includes:
Utilities, Singleton
Defined in:
lib/arachni/processes/dispatchers.rb

Overview

Helper for managing RPC::Server::Dispatcher processes.

Author:

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utilities

#available_port, available_port_mutex, #bytes_to_kilobytes, #bytes_to_megabytes, #caller_name, #caller_path, #cookie_decode, #cookie_encode, #cookies_from_file, #cookies_from_parser, #cookies_from_response, #exception_jail, #exclude_path?, #follow_protocol?, #form_decode, #form_encode, #forms_from_parser, #forms_from_response, #full_and_absolute_url?, #generate_token, #get_path, #hms_to_seconds, #html_decode, #html_encode, #include_path?, #links_from_parser, #links_from_response, #normalize_url, #page_from_response, #page_from_url, #parse_set_cookie, #path_in_domain?, #path_too_deep?, #port_available?, #rand_port, #random_seed, #redundant_path?, #regexp_array_match, #remove_constants, #request_parse_body, #seconds_to_hms, #skip_page?, #skip_path?, #skip_resource?, #skip_response?, #to_absolute, #uri_decode, #uri_encode, #uri_parse, #uri_parse_query, #uri_parser, #uri_rewrite

Constructor Details

#initializeDispatchers

Returns a new instance of Dispatchers.



24
25
26
27
# File 'lib/arachni/processes/dispatchers.rb', line 24

def initialize
    @list = []
    @dispatcher_connections = {}
end

Instance Attribute Details

#listArray<String> (readonly)

Returns URLs of all running Dispatchers.

Returns:



22
23
24
# File 'lib/arachni/processes/dispatchers.rb', line 22

def list
  @list
end

Class Method Details

.method_missing(sym, *args, &block) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/arachni/processes/dispatchers.rb', line 127

def self.method_missing( sym, *args, &block )
    if instance.respond_to?( sym )
        instance.send( sym, *args, &block )
    else
        super( sym, *args, &block )
    end
end

.respond_to?(m) ⇒ Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/arachni/processes/dispatchers.rb', line 135

def self.respond_to?( m )
    super( m ) || instance.respond_to?( m )
end

Instance Method Details

#connect(url, options = { }) ⇒ RPC::Client::Dispatcher

Connects to a Dispatcher by URL.

Parameters:

  • url (String)

    URL of the Dispatcher.

  • options (Hash) (defaults to: { })

    Options for the RPC client.

Returns:



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/arachni/processes/dispatchers.rb', line 35

def connect( url, options = { } )
    Reactor.global.run_in_thread if !Reactor.global.running?

    options[:client_max_retries] = options.delete(:max_retries)

    fresh = options.delete( :fresh )

    opts     = OpenStruct.new
    opts.rpc = OpenStruct.new( options )

    if fresh
        @dispatcher_connections[url] = RPC::Client::Dispatcher.new( opts, url )
    else
        @dispatcher_connections[url] ||= RPC::Client::Dispatcher.new( opts, url )
    end
end

#each(&block) ⇒ Object

Parameters:

  • block (Block)

    Block to pass an RPC client for each Dispatcher.



53
54
55
56
57
# File 'lib/arachni/processes/dispatchers.rb', line 53

def each( &block )
    @list.each do |url|
        block.call connect( url )
    end
end

#kill(url) ⇒ Object

Note:

Will also kill all Instances started by the Dispatcher.

Parameters:

  • url (String)

    URL of the Dispatcher to kill.



107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/arachni/processes/dispatchers.rb', line 107

def kill( url )
    dispatcher = connect( url )
    Manager.kill_many dispatcher.statistics['consumed_pids']
    Manager.kill dispatcher.pid
rescue => e
    #ap e
    #ap e.backtrace
    nil
ensure
    @list.delete( url )
    @dispatcher_connections.delete( url )
end

#killallObject

Kills all #list.



121
122
123
124
125
# File 'lib/arachni/processes/dispatchers.rb', line 121

def killall
    @list.dup.each do |url|
        kill url
    end
end

#light_spawn(options = {}, &block) ⇒ Object

Same as #spawn but sets the pool size to `1`.



100
101
102
# File 'lib/arachni/processes/dispatchers.rb', line 100

def light_spawn( options = {}, &block )
    spawn( options.merge( pool_size: 1 ), &block )
end

#spawn(options = {}) ⇒ RPC::Client::Dispatcher

Spawns a RPC::Server::Dispatcher process.

Parameters:

  • options (Hash) (defaults to: {})

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

Returns:



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/arachni/processes/dispatchers.rb', line 66

def spawn( options = {} )
    fork = options.delete(:fork)

    options = {
        dispatcher: {
            neighbour:        options[:neighbour],
            node_pipe_id:     options[:pipe_id],
            node_weight:      options[:weight],
            external_address: options[:external_address],
            pool_size:        options[:pool_size]
        },
        rpc:        {
            server_port:    options[:port]    || Utilities.available_port,
            server_address: options[:address] || '127.0.0.1'
        }
    }

    Manager.spawn( :dispatcher, options: options, fork: fork )

    url = "#{options[:rpc][:server_address]}:#{options[:rpc][:server_port]}"
    while sleep( 0.1 )
        begin
            connect( url, connection_pool_size: 1, max_retries: 1 ).alive?
            break
        rescue => e
            # ap e
        end
    end

    @list << url
    connect( url, fresh: true )
end