aboutsummaryrefslogtreecommitdiff
path: root/lib/net/tcpconn.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/net/tcpconn.ex')
-rw-r--r--lib/net/tcpconn.ex106
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