defmodule P2pChat.TransportProto do defmodule Messages do defmodule Hello do defstruct [:netid] end defmodule InformNeighbor do defstruct [:netid, :addr, :port] end defmodule Goodbye do defstruct [] end end # # Public API # def encode_message(%Messages.Hello{} = msg) do [encode_version(), <<0x01::8>>, encode_string(msg.netid)] end def encode_message(%Messages.InformNeighbor{} = msg) do [encode_version(), <<0x02::8>>, encode_string(msg.netid), encode_ip_addr(msg.addr)] end def encode_message(%Messages.Goodbye{} = _msg) do [encode_version(), <<0x03::8>>] end def decode_message(<<0x01::8, 0x01::8, payload::binary>>) do <> = payload %Messages.Hello{netid: netid} end def decode_message(<<0x01::8, 0x02::8, payload::binary>>) do <> = payload %Messages.InformNeighbor{netid: netid, addr: addr} end def decode_message(<<0x01::8, 0x03::8>>) do %Messages.Goodbye{} end def decode_message(<<0x01::8, _::binary>>), do: :error def decode_message(<<_::binary>>), do: :error # # Private Utilities # defp encode_version() do <<0x01::8>> end defp encode_string(str) do [<>, str] end defp encode_ip_addr({a1, a2, a3, a4, a5, a6, a7, a8}) do <<6::8, a1::8, a2::8, a3::8, a4::8, a5::8, a6::8, a7::8, a8::8>> end defp encode_ip_addr({a1, a2, a3, a4}) do <<4::8, a1::8, a2::8, a3::8, a4::8>> end end