p2pchat/lib/p2p_chat/transport_proto.ex

67 lines
1.6 KiB
Elixir

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
<<netid_len::16, netid::size(netid_len)-binary>> = payload
%Messages.Hello{netid: netid}
end
def decode_message(<<0x01::8, 0x02::8, payload::binary>>) do
<<netid_len::16, netid::size(netid_len)-binary, addr_len::16, addr::size(addr_len)-binary>> = 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
[<<byte_size(str)::16>>, 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