Compare commits

..

1 commit

Author SHA1 Message Date
8d8b42f9be
0.1.0 2024-12-29 20:08:07 -03:00

View file

@ -70,8 +70,17 @@ module NatPMP
def initialize(@gateway_ip : String, autoconnect : Bool = true)
# The specification is IPV4 only!
@socket = UDPSocket.new(Socket::Family::INET)
# A given host may have more than one independent
# NAT-PMP client running at the same time, and address announcements
# need to be available to all of them. Clients should therefore set
# the SO_REUSEPORT option or equivalent in order to allow other
# processes to also listen on port 5350.
@socket.reuse_port = true
@socket.reuse_address = true
# Additionally, implementers
# have encountered issues when one or more processes on the same device
# listen to port 5350 on *all* addresses. Clients should therefore
# bind specifically to 224.0.0.1:5350, not to 0.0.0.0:5350.
@socket.bind 5350
if autoconnect
connect()
@ -79,6 +88,7 @@ module NatPMP
end
def connect
# @socket.join_group(Socket::IPAddress.new("224.0.0.1", 5351))
@socket.connect(@gateway_ip, 5351)
end
@ -99,6 +109,11 @@ module NatPMP
@socket.receive(msg)
break
rescue IO::TimeoutError
# If no
# NAT-PMP response is received from the gateway after 250 ms, the
# client retransmits its request and waits 500 ms. The client SHOULD
# repeat this process with the interval between attempts doubling each
# time.
@socket.read_timeout = @socket.read_timeout.not_nil!*2
next
rescue
@ -112,6 +127,9 @@ module NatPMP
result_code = decode_msg(UInt16, msg[2..3])
epoch = decode_msg(UInt32, msg[4..7])
# If the result code is non-zero, the value of the External
# IPv4 Address field is undefined (MUST be set to zero on transmission,
# and MUST be ignored on reception).
if result_code != 0
ip_address = nil
else
@ -120,7 +138,6 @@ module NatPMP
return vers, op, result_code, epoch, ip_address
end
# https://datatracker.ietf.org/doc/html/rfc6886#section-3.3
def request_mapping(internal_port : UInt16, external_port : UInt16, operation : UInt8, lifetime : UInt32 = 7200)
request = MappingPacket.new(internal_port, external_port, lifetime, operation).to_slice
msg = Bytes.new(16)