Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing LIFX headers returns wrong protocol number

Tags:

elixir

I am trying to parse the LIFX headers as per their documentation.

Here is the code I have:

data = <<36, 0, 0, 52, 33, 235, 176, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0>>
<< size :: little-integer-size(16),
   origin :: little-integer-size(2),
   tagged :: size(1),
   addressable :: size(1),
   protocol :: little-integer-size(12),
   rest :: bitstring >> = data
IO.puts protocol

This tells me that protocol is 1027, but LIFX's documentation says it should be 1024. I've confirmed by using LIFX's RubyGem that this field's value is 1024.

Why in Elixir am I seeing this value of 1027, rather than 1024?

like image 282
Ryan Bigg Avatar asked Oct 19 '22 08:10

Ryan Bigg


1 Answers

I'm no expert at this, but I have a theory that the endianess isn't working the way you would expect when you take 12 bits instead of 16. This solution is just me playing around with the numbers as I found it an interesting problem. There may be a better solution, I haven't looked too deeply in to the erlang implementation yet.

If we ignore all other data, then we have this:

data = <<0, 52>>

# data is equal to 0000 0000 0011 0100
#                  oota pppp pppp pppp

<< origin :: little-integer-size(2),
   tagged :: size(1),
   addressable :: size(1),
   protocol :: little-integer-size(12) >> = data

IO.puts protocol     # 1027
IO.puts origin       # 0
IO.puts tagged       # 0
IO.puts addressable  # 0

# doing little-endiain on 12 bits = 0100 0000 0011
#                                   pppp pppp pppp

Since this is little-endian, if we swap the two bytes round, we get:

data = <<52, 0>>

# data is equal to 0011 0100 0000 0000
#                  oota pppp pppp pppp

<< origin :: integer-size(2),
   tagged :: size(1),
   addressable :: size(1),
   protocol :: integer-size(12) >> = data

IO.puts protocol     # 1024
IO.puts origin       # 0
IO.puts tagged       # 1
IO.puts addressable  # 1

So one solution is:

data = <<0, 52>>
<< p1 :: integer-size(4),
   p2 :: integer-size(4),
   << origin :: size(2), tagged :: size(1), addressable :: size(1) >>,
   p3 :: integer-size(4) >> = data

IO.inspect p1        # 0
IO.inspect p2        # 0
IO.inspect p3        # 4
<< protocol :: size(12) >> = <<p3 :: size(4), p2 :: size(4), p1 :: size(4)>>
IO.puts protocol     # 1024
IO.puts origin       # 0
IO.puts tagged       # 1
IO.puts addressable  # 1
like image 153
Gazler Avatar answered Oct 21 '22 06:10

Gazler