Class: StunClient::GenericClient
- Inherits:
-
Object
- Object
- StunClient::GenericClient
- Defined in:
- lib/stun-client/generic/client.rb
Overview
Generic STUN client. This contains functions which are used by all STUN clients independent of the RFC.
Direct Known Subclasses
Instance Method Summary collapse
-
#initialize(parameters) ⇒ GenericClient
constructor
Creates a new generic client.
-
#parse_mapped_address(value, prefix = nil) ⇒ Hash
Parses an IP port pair and returns a hash with the information.
-
#receive_message ⇒ Object
Attempts to receive a response from the server.
-
#send_binary(parameters, request, new_interval, attempts_default, interval_default) ⇒ Array
Sends a request in binary form to a server.
-
#try_sending(request, attempts, interval, new_interval) ⇒ Object
Attempts to send a message ‘request` `attempts` times to the server.
-
#validate_and_get_change(parameters) ⇒ Array
The function validates the Change IP and Change Port parameters and returns those.
Constructor Details
#initialize(parameters) ⇒ GenericClient
Creates a new generic client.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/stun-client/generic/client.rb', line 14 def initialize parameters raise ArgumentError, 'Missing socket' if ! parameters.has_key? :socket raise ArgumentError, 'Socket must be a UDPSocket' if ! parameters[:socket].is_a? UDPSocket if parameters.has_key?(:host) && parameters[:host] raise ArgumentError, 'Host must be a string' if ! parameters[:host].is_a? String else parameters[:host] = 'stun.1und1.de' end if parameters.has_key?(:port) && parameters[:port] raise ArgumentError, 'Port must be a integer' if ! parameters[:port].is_a? Integer else parameters[:port] = 3478 end @socket = parameters[:socket] @host = parameters[:host] @port = parameters[:port] end |
Instance Method Details
#parse_mapped_address(value, prefix = nil) ⇒ Hash
Parses an IP port pair and returns a hash with the information.
It throws the exception ‘UnableToInterpretResponse` if the IP version is unknown. Known are IPv4 and IPv6.
The ‘UnableToInterpretResponse` is thrown if the IP address is not encoded correctly.
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 |
# File 'lib/stun-client/generic/client.rb', line 46 def parse_mapped_address value, prefix = nil res = {} family_sym = "#{prefix}family".to_sym host_sym = "#{prefix}host".to_sym port_sym = "#{prefix}port".to_sym case value[:family] when 1 res[family_sym] = :IPv4 when 2 res[family_sym] = :IPv6 else raise UnableToInterpretResponse, "Unknown IP family. Family is #{value[family_sym].inspect}" end begin res[host_sym] = IPAddr.ntop value[:address] rescue IPAddr::AddressFamilyError raise UnableToInterpretResponse, 'Failed to parse ip address' end res[port_sym] = value[:port] return res end |
#receive_message ⇒ Object
Attempts to receive a response from the server. If there is no response, ‘false` is returned.
177 178 179 180 181 182 183 |
# File 'lib/stun-client/generic/client.rb', line 177 def begin @socket.recvfrom_nonblock(1024) rescue IO::WaitReadable return false end end |
#send_binary(parameters, request, new_interval, attempts_default, interval_default) ⇒ Array
Sends a request in binary form to a server.
‘ArgumentError` is thrown if one of the arguments is not valid. `TimeoutError` is thrown if the server does not respond.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/stun-client/generic/client.rb', line 126 def send_binary parameters, request, new_interval, attempts_default, interval_default attempts = attempts_default if parameters.has_key?(:attempts) && parameters[:attempts] attempts = parameters[:attempts] raise ArgumentError, 'Attepts must be a integer' if ! attempts.is_a? Integer end interval = interval_default if parameters.has_key?(:interval) && parameters[:interval] interval = parameters[:interval] raise ArgumentError, 'Interval must be a integer' if ! (interval.is_a?(Integer) || interval.is_a?(Float)) end interval = interval.to_f response = try_sending request, attempts, interval, new_interval raise TimeoutError, 'Server failed to answer' if ! response return response end |
#try_sending(request, attempts, interval, new_interval) ⇒ Object
Attempts to send a message ‘request` `attempts` times to the server. The meaning of the intervals can be taken from the `send_binary` function.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/stun-client/generic/client.rb', line 156 def try_sending request, attempts, interval, new_interval attempts.times do |index| @socket.send(request, 0, @host, @port) # Waiting for answer. No remote server should be able # to respond **immediately**. sleep interval resp = return resp if resp if index != (attempts - 1) interval = new_interval.call(interval).round(3) end end return false end |
#validate_and_get_change(parameters) ⇒ Array
The function validates the Change IP and Change Port parameters and returns those. If no parameters are specified, the default value false is used.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/stun-client/generic/client.rb', line 82 def validate_and_get_change parameters change_port = 0 change_ip = 0 if parameters.has_key?(:change_port) && parameters[:change_port] if ! (parameters[:change_port].is_a?(TrueClass) || parameters[:change_port].is_a?(FalseClass)) raise ArgumentError, 'Change port must be a boolean' end change_port = ( parameters[:change_port] ? 1 : 0 ) end if parameters.has_key?(:change_ip) && parameters[:change_ip] if ! (parameters[:change_ip].is_a?(TrueClass) || parameters[:change_ip].is_a?(FalseClass)) raise ArgumentError, 'Change IP must be a boolean' end change_ip = ( parameters[:change_ip] ? 1 : 0 ) end return change_port, change_ip end |