Class: Arachni::RPC::Server::Dispatcher::Node

Inherits:
Object
  • Object
show all
Includes:
UI::Output
Defined in:
lib/arachni/rpc/server/node.rb

Overview

Dispatcher node class, helps maintain a list of all available Dispatchers in the grid and announce itself to neighbouring Dispatchers.

As soon as a new Node is fired up it checks-in with its neighbour and grabs a list of all available peers.

As soon as it receives the peer list it then announces itself to them.

Upon convergence there will be a grid of Dispatchers each one with its own copy of all available Dispatcher URLs.

@author: Tasos “Zapotek” Laskos

<[email protected]>
<[email protected]>

@version: 0.1

Instance Method Summary collapse

Methods included from UI::Output

#buffer, #debug!, #debug?, #flush_buffer, #mute!, #muted?, #only_positives!, #only_positives?, #print_bad, #print_debug, #print_debug_backtrace, #print_debug_pp, #print_error, #print_error_backtrace, #print_info, #print_line, #print_ok, #print_status, #print_verbose, #reroute_to_file, #reroute_to_file?, #uncap_buffer!, #unmute!, #verbose!, #verbose?

Constructor Details

#initialize(opts, logfile) ⇒ Node

Initializes the node by:

  • Adding the neighbour (if the user has supplied one) to the peer list

  • Getting the neighbour’s peer list and appending them to its own

  • Announces itself to the neighbour and instructs it to propagate our URL to the others

Parameters:



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
# File 'lib/arachni/rpc/server/node.rb', line 51

def initialize( opts, logfile )
    @opts = opts

    reroute_to_file( logfile )

    print_status( 'Initing grid node...' )

    @dead_nodes = []
    @neighbours = Set.new
    @nodes_info_cache = []

    if neighbour = @opts.neighbour
        add_neighbour( neighbour )

        peer = connect_to_peer( neighbour )
        peer.node.neighbours {
            |urls|
            urls.each {
                |url|
                @neighbours << url if url != @opts.datastore[:dispatcher_url]
            }
        }

        peer.node.add_neighbour( @opts.datastore[:dispatcher_url], true ){
            |res|

            if res.rpc_exception?
                print_info( 'Neighbour seems dead: ' + neighbour )
                remove_neighbour( neighbour )
            end
        }
    end

    print_status( 'Node ready.' )

    log_updated_neighbours

    ::EM.add_periodic_timer( 60 ) {
        ::EM.defer {
            ping
            check_for_comebacks
        }
    }
end

Instance Method Details

#add_neighbour(node_url, propagate = false) ⇒ Object

Adds a neighbour to the peer list

Parameters:

  • node_url (String)

    URL of a neighbouring node

  • propagate (Boolean) (defaults to: false)

    wether or not to announce the new node to the ones in the peer list



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/arachni/rpc/server/node.rb', line 103

def add_neighbour( node_url, propagate = false )
    # we don't want ourselves in the Set
    return false if node_url == @opts.datastore[:dispatcher_url]

    print_status 'Adding neighbour: ' + node_url

    @neighbours << node_url
    log_updated_neighbours
    announce( node_url ) if propagate

    return true
end

#infoHash

Returns node specific info:

  • Bandwidth Pipe ID

  • Weight

  • Nickname

  • Cost

Returns:

  • (Hash)


174
175
176
177
178
179
180
181
182
# File 'lib/arachni/rpc/server/node.rb', line 174

def info
    return {
        'url'        => @opts.datastore[:dispatcher_url],
        'pipe_id'    => @opts.pipe_id,
        'weight'     => @opts.weight,
        'nickname'   => @opts.nickname,
        'cost'       => @opts.cost
    }
end

#neighboursArray

Returns all neighbour/node/peer URLs

Returns:



122
123
124
# File 'lib/arachni/rpc/server/node.rb', line 122

def neighbours
    @neighbours.to_a
end

#neighbours_with_info(&block) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/arachni/rpc/server/node.rb', line 131

def neighbours_with_info( &block )
    raise( "This method requires a block!" ) if !block_given?

    @neighbours_cmp = ''
    if @nodes_info_cache.empty? || @neighbours_cmp != neighbours.to_s

        @neighbours_cmp = neighbours.to_s

        ::EM::Iterator.new( neighbours ).map( proc {
            |neighbour, iter|

            connect_to_peer( neighbour ).node.info {
                |info|

                if info.rpc_exception?
                    print_info( 'Neighbour seems dead: ' + neighbour )
                    remove_neighbour( neighbour )
                    log_updated_neighbours

                    iter.return( nil )
                else
                    iter.return( info )
                end
            }
        }, proc {
            |nodes|
            @nodes_info_cache = nodes.compact
            block.call( @nodes_info_cache )
        })
    else
        block.call( @nodes_info_cache )
    end
end

#remove_neighbour(node_url) ⇒ Object



126
127
128
129
# File 'lib/arachni/rpc/server/node.rb', line 126

def remove_neighbour( node_url )
    @neighbours -= [node_url]
    @dead_nodes << node_url
end