Class: CoRE::CoAP::Transmission
- Inherits:
-
Object
- Object
- CoRE::CoAP::Transmission
- Defined in:
- lib/core/coap/transmission.rb
Overview
Socket abstraction.
Constant Summary collapse
- DEFAULT_RECV_TIMEOUT =
2
Instance Attribute Summary collapse
-
#address_family ⇒ Object
readonly
Returns the value of attribute address_family.
-
#max_retransmit ⇒ Object
Returns the value of attribute max_retransmit.
-
#recv_timeout ⇒ Object
Returns the value of attribute recv_timeout.
-
#socket ⇒ Object
readonly
Returns the value of attribute socket.
Class Method Summary collapse
-
.from_host(host, options = {}) ⇒ Object
Return Transmission instance with socket matching address family.
-
.request(*args) ⇒ Object
Instanciate matching Transmission and perform request.
-
.send(*args) ⇒ Object
Instanciate matching Transmission and send message.
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ Transmission
constructor
A new instance of Transmission.
- #ipv6? ⇒ Boolean
-
#receive(options = {}) ⇒ Object
Receive from socket and return parsed CoAP message.
-
#request(message, host, port = CoAP::PORT) ⇒ Object
Send
message(retransmit if necessary) and wait for answer. -
#send(message, host, port = CoAP::PORT) ⇒ Object
Send
message.
Constructor Details
#initialize(options = {}) ⇒ Transmission
Returns a new instance of Transmission.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/core/coap/transmission.rb', line 10 def initialize( = {}) @max_retransmit = [:max_retransmit] || 4 @recv_timeout = [:recv_timeout] || DEFAULT_RECV_TIMEOUT @socket = [:socket] @force_ipv6 = !![:force_ipv6] @retransmit = if [:retransmit].nil? true else !![:retransmit] end if @socket @socket_class = @socket.class @address_family = @socket.addr.first else @socket_class = [:socket_class] || Celluloid::IO::UDPSocket @address_family = [:address_family] || Socket::AF_INET6 @socket = @socket_class.new(@address_family) end # http://lists.apple.com/archives/darwin-kernel/2014/Mar/msg00012.html if OS.osx? && ipv6? ifname = Socket.if_up?('en1') ? 'en1' : 'en0' ifindex = Socket.if_nametoindex(ifname) s = @socket.to_io rescue @socket s.setsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_IF, [ifindex].pack('i_')) end @socket end |
Instance Attribute Details
#address_family ⇒ Object (readonly)
Returns the value of attribute address_family.
8 9 10 |
# File 'lib/core/coap/transmission.rb', line 8 def address_family @address_family end |
#max_retransmit ⇒ Object
Returns the value of attribute max_retransmit.
7 8 9 |
# File 'lib/core/coap/transmission.rb', line 7 def max_retransmit @max_retransmit end |
#recv_timeout ⇒ Object
Returns the value of attribute recv_timeout.
7 8 9 |
# File 'lib/core/coap/transmission.rb', line 7 def recv_timeout @recv_timeout end |
#socket ⇒ Object (readonly)
Returns the value of attribute socket.
8 9 10 |
# File 'lib/core/coap/transmission.rb', line 8 def socket @socket end |
Class Method Details
.from_host(host, options = {}) ⇒ Object
Return Transmission instance with socket matching address family.
124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/core/coap/transmission.rb', line 124 def from_host(host, = {}) if IPAddr.new(host).ipv6? new() else new(.merge(address_family: Socket::AF_INET)) end # MRI throws IPAddr::InvalidAddressError, JRuby an ArgumentError rescue ArgumentError host = Resolver.address(host, [:force_ipv6]) retry end |
.request(*args) ⇒ Object
Instanciate matching Transmission and perform request.
142 143 144 |
# File 'lib/core/coap/transmission.rb', line 142 def request(*args) invoke(:request, *args) end |
.send(*args) ⇒ Object
Instanciate matching Transmission and send message.
137 138 139 |
# File 'lib/core/coap/transmission.rb', line 137 def send(*args) invoke(:send, *args) end |
Instance Method Details
#ipv6? ⇒ Boolean
43 44 45 |
# File 'lib/core/coap/transmission.rb', line 43 def ipv6? @address_family == Socket::AF_INET6 end |
#receive(options = {}) ⇒ Object
Receive from socket and return parsed CoAP message. (ACK is sent on CON messages.)
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 |
# File 'lib/core/coap/transmission.rb', line 49 def receive( = {}) retry_count = [:retry_count] || 0 timeout = ([:timeout] || @recv_timeout) ** (retry_count + 1) mid = [:mid] flags = mid.nil? ? 0 : Socket::MSG_PEEK data = Timeout.timeout(timeout) do @socket.recvfrom(1152, flags) end answer = CoAP.parse(data[0].force_encoding('BINARY')) if mid == answer.mid Timeout.timeout(1) { @socket.recvfrom(1152) } end if answer.tt == :con = Message.new(:ack, 0, answer.mid, nil, {token: answer.[:token]}) send(, data[1][3]) end answer end |
#request(message, host, port = CoAP::PORT) ⇒ Object
Send message (retransmit if necessary) and wait for answer. Returns answer.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/core/coap/transmission.rb', line 78 def request(, host, port = CoAP::PORT) retry_count = 0 retransmit = @retransmit && .tt == :con begin send(, host, port) response = receive(retry_count: retry_count, mid: .mid) rescue Timeout::Error raise unless retransmit retry_count += 1 if retry_count > @max_retransmit raise "Maximum retransmission count of #{@max_retransmit} reached." end retry unless .tt == :non end if seperate?(response) response = receive(timeout: 10, mid: .mid) end response end |
#send(message, host, port = CoAP::PORT) ⇒ Object
Send message.
105 106 107 108 109 110 111 112 |
# File 'lib/core/coap/transmission.rb', line 105 def send(, host, port = CoAP::PORT) = .to_wire if .respond_to?(:to_wire) # In MRI and Rubinius, the Socket::MSG_DONTWAIT option is 64. # It is not defined by JRuby. # TODO Is it really necessary? @socket.send(, 64, host, port) end |