Module: Takagi::Network::Framing::Tcp
- Defined in:
- lib/takagi/network/framing/tcp.rb
Overview
RFC 8323 CoAP over TCP framing with variable-length encoding
Class Method Summary collapse
-
.decode(data) ⇒ Message::Inbound
Decode framed TCP message.
-
.encode(message) ⇒ String
Encode message with RFC 8323 framing.
-
.read_from_socket(socket, logger: nil) ⇒ String?
Read a complete message from socket.
Class Method Details
.decode(data) ⇒ Message::Inbound
Decode framed TCP message
22 23 24 |
# File 'lib/takagi/network/framing/tcp.rb', line 22 def decode(data) Message::Inbound.new(data, transport: :tcp) end |
.encode(message) ⇒ String
Encode message with RFC 8323 framing
12 13 14 15 16 17 |
# File 'lib/takagi/network/framing/tcp.rb', line 12 def encode() # Build base message packet = () # Add RFC 8323 framing frame(packet) end |
.read_from_socket(socket, logger: nil) ⇒ String?
Read a complete message from socket
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 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/takagi/network/framing/tcp.rb', line 30 def read_from_socket(socket, logger: nil) first_byte_data = socket.read(1) return nil if first_byte_data.nil? || first_byte_data.empty? first_byte = first_byte_data.unpack1('C') len_nibble = (first_byte >> 4) & 0x0F tkl = first_byte & 0x0F logger&.debug "read_from_socket: first_byte=0x#{first_byte.to_s(16)}, len_nibble=#{len_nibble}, tkl=#{tkl}" length = read_length(socket, len_nibble, logger: logger) return nil unless length logger&.debug "read_from_socket: message length=#{length} bytes" # Read: Code (1) + Token (tkl) + Options + Payload (length) bytes_to_read = 1 + tkl + length data = +''.b remaining = bytes_to_read while remaining.positive? begin chunk = socket.readpartial(remaining) rescue IO::WaitReadable IO.select([socket]) retry rescue EOFError logger&.error "read_from_socket: Incomplete message (expected #{bytes_to_read}, got #{data.bytesize})" return nil end data << chunk remaining -= chunk.bytesize end logger&.debug "read_from_socket: Successfully read #{bytes_to_read} bytes" first_byte_data + data rescue IOError, Errno::ECONNRESET => e logger&.debug "read_from_socket: Socket error (#{e.class}: #{e.})" nil end |