Class: Rex::Proto::Kademlia::BootstrapResponse

Inherits:
Message
  • Object
show all
Defined in:
lib/rex/proto/kademlia/bootstrap_response.rb

Overview

A Kademlia bootstrap response message

Constant Summary collapse

BOOTSTRAP_PEER_SIZE =

The minimum size of a peer in a KADEMLIA2_BOOTSTRAP_RES message: peer ID (16-bytes), IP (4 bytes), UDP port (2 bytes), TCP port (2 bytes) and version (1 byte)

25

Constants inherited from Message

Message::COMPRESSED_PACKET, Message::STANDARD_PACKET

Instance Attribute Summary collapse

Attributes inherited from Message

#body, #type

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Message

#==, #to_str

Constructor Details

#initialize(peer_id, tcp_port, version, peers) ⇒ BootstrapResponse

Constructs a new bootstrap response



29
30
31
32
33
34
# File 'lib/rex/proto/kademlia/bootstrap_response.rb', line 29

def initialize(peer_id, tcp_port, version, peers)
  @peer_id = peer_id
  @tcp_port = tcp_port
  @version = version
  @peers = peers
end

Instance Attribute Details

#peer_idString (readonly)



15
16
17
# File 'lib/rex/proto/kademlia/bootstrap_response.rb', line 15

def peer_id
  @peer_id
end

#peersArray<Hash<String, Object>> (readonly)



21
22
23
# File 'lib/rex/proto/kademlia/bootstrap_response.rb', line 21

def peers
  @peers
end

#tcp_portInteger (readonly)



17
18
19
# File 'lib/rex/proto/kademlia/bootstrap_response.rb', line 17

def tcp_port
  @tcp_port
end

#versionInteger (readonly)



19
20
21
# File 'lib/rex/proto/kademlia/bootstrap_response.rb', line 19

def version
  @version
end

Class Method Details

.from_data(data) ⇒ BootstrapResponse

Builds a bootstrap response from given data



45
46
47
48
49
50
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
# File 'lib/rex/proto/kademlia/bootstrap_response.rb', line 45

def self.from_data(data)
  message = Message.from_data(data)
  # abort if this isn't a valid response
  return unless message
  return unless message.type == BOOTSTRAP_RESPONSE
  return unless message.body.size >= 23
  bootstrap_peer_id = Rex::Proto::Kademlia.decode_peer_id(message.body.slice!(0, 16))
  bootstrap_tcp_port, bootstrap_version, num_peers = message.body.slice!(0, 5).unpack('vCv')
  # protocol says there are no peers and the body confirms this, so just return with no peers
  if num_peers == 0 && message.body.to_s.empty?
    peers = []
  else
    peers_data = message.body
    # peers data is too long/short, abort
    return if peers_data.size % BOOTSTRAP_PEER_SIZE != 0
    peers = []
    until peers_data.to_s.empty?
      peer_data = peers_data.slice!(0, BOOTSTRAP_PEER_SIZE)
      peer_id = Rex::Proto::Kademlia.decode_peer_id(peer_data.slice!(0, 16))
      ip, udp_port, tcp_port, version = peer_data.unpack('VvvC')
      peers << {
        id: peer_id,
        ip: Rex::Socket.addr_itoa(ip),
        tcp_port: tcp_port,
        udp_port: udp_port,
        version: version
      }
    end
  end
  BootstrapResponse.new(bootstrap_peer_id, bootstrap_tcp_port, bootstrap_version, peers)
end