diff options
Diffstat (limited to 'lib/net/tcpconn.ex')
-rw-r--r-- | lib/net/tcpconn.ex | 106 |
1 files changed, 0 insertions, 106 deletions
diff --git a/lib/net/tcpconn.ex b/lib/net/tcpconn.ex deleted file mode 100644 index 44669bb..0000000 --- a/lib/net/tcpconn.ex +++ /dev/null @@ -1,106 +0,0 @@ -defmodule SNet.TCPConn do - use GenServer, restart: :temporary - require Salty.Box.Curve25519xchacha20poly1305, as: Box - require Salty.Sign.Ed25519, as: Sign - require Logger - - def start_link(state) do - GenServer.start_link(__MODULE__, state) - end - - def init(state) do - GenServer.cast(self(), :handshake) - {:ok, state} - end - - def handle_call(:get_host_str, _from, state) do - {:reply, "#{state.his_pkey|>Base.encode16|>String.downcase}@#{to_string(:inet_parse.ntoa(state.addr))}:#{state.port}", state} - end - - def handle_cast(:handshake, state) do - socket = state.socket - - {srv_pkey, srv_skey} = Shard.Identity.get_keypair - {:ok, sess_pkey, sess_skey} = Box.keypair - {:ok, challenge} = Salty.Random.buf 32 - - # Exchange public keys and challenge - hello = {srv_pkey, sess_pkey, challenge, state.my_port} - :gen_tcp.send(socket, :erlang.term_to_binary hello) - {:ok, pkt} = :gen_tcp.recv(socket, 0) - {cli_pkey, cli_sess_pkey, cli_challenge, his_port} = :erlang.binary_to_term(pkt, [:safe]) - - # Do challenge and check their challenge - {:ok, cli_challenge_sign} = Sign.sign_detached(cli_challenge, srv_skey) - pkt = encode_pkt(cli_challenge_sign, cli_sess_pkey, sess_skey) - :gen_tcp.send(socket, pkt) - - {:ok, pkt} = :gen_tcp.recv(socket, 0) - challenge_sign = decode_pkt(pkt, cli_sess_pkey, sess_skey) - :ok = Sign.verify_detached(challenge_sign, challenge, cli_pkey) - - expected_suffix = Application.get_env(:shard, :peer_id_suffix) - len = byte_size(expected_suffix) - ^len = :binary.longest_common_suffix([cli_pkey, expected_suffix]) - - # Connected - :inet.setopts(socket, [active: true]) - - {:ok, {addr, port}} = :inet.peername socket - state =%{ socket: socket, - my_pkey: srv_pkey, - my_skey: srv_skey, - his_pkey: cli_pkey, - conn_my_pkey: sess_pkey, - conn_my_skey: sess_skey, - conn_his_pkey: cli_sess_pkey, - addr: addr, - port: port, - his_port: his_port - } - GenServer.cast(Shard.Manager, {:peer_up, cli_pkey, self(), addr, his_port}) - Logger.info "New peer: #{print_id state} at #{inspect addr}:#{port}" - - {:noreply, state} - end - - def handle_cast({:send_msg, msg}, state) do - msgbin = :erlang.term_to_binary msg - enc = encode_pkt(msgbin, state.conn_his_pkey, state.conn_my_skey) - :gen_tcp.send(state.socket, enc) - {:noreply, state} - end - - defp encode_pkt(pkt, pk, sk) do - {:ok, n} = Salty.Random.buf Box.noncebytes - {:ok, msg} = Box.easy(pkt, n, pk, sk) - n <> msg - end - - defp decode_pkt(pkt, pk, sk) do - n = binary_part(pkt, 0, Box.noncebytes) - enc = binary_part(pkt, Box.noncebytes, (byte_size pkt) - Box.noncebytes) - {:ok, msg} = Box.open_easy(enc, n, pk, sk) - msg - end - - def handle_info({:tcp, _socket, raw_data}, state) do - msg = decode_pkt(raw_data, state.conn_his_pkey, state.conn_my_skey) - msg_data = :erlang.binary_to_term(msg, [:safe]) - Shard.Manager.dispatch(state.his_pkey, msg_data) - {:noreply, state} - end - - def handle_info({:tcp_closed, _socket}, state) do - Logger.info "Disconnected: #{print_id state} at #{inspect state.addr}:#{state.port}" - GenServer.cast(Shard.Manager, {:peer_down, state.his_pkey, state.addr, state.his_port}) - exit(:normal) - end - - defp print_id(state) do - state.his_pkey - |> binary_part(0, 8) - |> Base.encode16 - |> String.downcase - end -end |