Class: Net::NATPMP::Request
- Inherits:
-
Object
- Object
- Net::NATPMP::Request
- Includes:
- Constants
- Defined in:
- lib/net/natpmp/requests.rb
Overview
Main request class
Direct Known Subclasses
Constant Summary
Constants included from Constants
Constants::BASE_DELAY, Constants::DEFAULT_INSIDE_PORT, Constants::DEFAULT_LIFETIME, Constants::DEFAULT_OUTSIDE_PORT, Constants::DEFAULT_PROTO, Constants::MAX_WAIT, Constants::OP_CODES, Constants::PROTO_CODES, Constants::RESULT_CODES, Constants::RESULT_CODES_DESC, Constants::VERSION
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#socket ⇒ Object
readonly
Returns the value of attribute socket.
Class Method Summary collapse
Instance Method Summary collapse
- #check_reply(reply, sent_op) ⇒ Object
-
#initialize(config) ⇒ Request
constructor
A new instance of Request.
-
#send(msg, expected_response_size = 16) ⇒ Object
Send a message to the NAT-PMP server.
Constructor Details
#initialize(config) ⇒ Request
Returns a new instance of Request.
14 15 16 17 18 19 20 |
# File 'lib/net/natpmp/requests.rb', line 14 def initialize(config) @config = config @socket = UDPSocket.new @socket.bind(config.bind_address.to_s, config.bind_port) @socket.connect(config.gw.to_s, config.port) end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
12 13 14 |
# File 'lib/net/natpmp/requests.rb', line 12 def config @config end |
#socket ⇒ Object (readonly)
Returns the value of attribute socket.
12 13 14 |
# File 'lib/net/natpmp/requests.rb', line 12 def socket @socket end |
Class Method Details
.req(config, _opts = {}) ⇒ Object
22 23 24 |
# File 'lib/net/natpmp/requests.rb', line 22 def self.req(config, _opts = {}) new(config) end |
Instance Method Details
#check_reply(reply, sent_op) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/net/natpmp/requests.rb', line 60 def check_reply(reply, sent_op) # Check the first 4 bytes only (the rest are variable) version, opcode, result = reply.unpack('CCn') # Check the version in the reply raise InvalidVersion, "Invalid version #{version}" unless version == VERSION # Check the operation code in the reply. Always (128 + sent opcode) expected_opcode = 128 + sent_op if opcode != expected_opcode raise InvalidReply, "Invalid reply opcode. Was expecting #{expected_opcode}, got: #{opcode}" end # Check the result code in the reply raise RequestFailed, result_code: result unless result == RESULT_CODES[:success] end |
#send(msg, expected_response_size = 16) ⇒ Object
Send a message to the NAT-PMP server. Takes a message and an optional response size
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/net/natpmp/requests.rb', line 27 def send(msg, expected_response_size = 16) sent_op = msg.unpack1('xC') # To verify the response size_sent = @socket.send(msg, 0) raise RequestFailed unless size_sent == msg.size delay = Constants::BASE_DELAY attempts = 1 begin sleep delay reply, = @socket.recvfrom_nonblock(expected_response_size) check_reply(reply, sent_op) reply rescue IO::WaitReadable if delay < MAX_WAIT delay *= 2 puts "Timeout, retrying after #{delay} seconds" attempts += 1 retry end raise TimeoutException, "Timeout after #{attempts} attempts" rescue Errno::ECONNREFUSED raise ConnectionRefused, 'Connection refused' end ensure sleep 0.25 # Sleep for a bit to make sure the socket is not closed too soon @socket.close # Close the socket because we don't need it anymore end |