Implement protocol encryption #2
@ -107,7 +107,11 @@ defmodule Amethyst.ConnectionHandler do
|
||||
send_packet(socket, connstate, packet, version, state)
|
||||
loop(socket, connstate, version, state)
|
||||
after 0 ->
|
||||
# Received stuff from the connection receiver is lower priority
|
||||
receive do
|
||||
{:get_encryption, from} ->
|
||||
send(from, Map.get(state, :decryption_state))
|
||||
loop(socket, connstate, version, state)
|
||||
{:packet, id, data} ->
|
||||
state = handle_packet(id, data, connstate, version, state)
|
||||
loop(socket, connstate, version, state)
|
||||
@ -216,13 +220,7 @@ defmodule Amethyst.ConnectionHandler do
|
||||
|
||||
defp handle_packet(id, data, connstate, version, state) do
|
||||
try do
|
||||
packet = case Map.get(state, :decryption_state) do
|
||||
nil ->
|
||||
connstate.deserialize(id, version, data)
|
||||
dstate ->
|
||||
data = :crypto.crypto_update(dstate, data)
|
||||
connstate.deserialize(id, version, data)
|
||||
end
|
||||
packet = connstate.deserialize(id, version, data)
|
||||
case connstate.handle(packet, version, state) do
|
||||
:ok -> state
|
||||
{:error, reason} ->
|
||||
|
@ -35,7 +35,7 @@ defmodule Amethyst.ConnectionReceiver do
|
||||
{:ok, spawn(fn ->
|
||||
Process.set_label("ConnectionReceiver for #{inspect(socket)}")
|
||||
{:ok, pid} = Amethyst.ConnectionHandler.start_link(socket, Amethyst.ConnectionState.Handshake, 0)
|
||||
receive(socket, pid)
|
||||
receive(socket, pid, nil)
|
||||
end)}
|
||||
end
|
||||
|
||||
@ -44,29 +44,46 @@ defmodule Amethyst.ConnectionReceiver do
|
||||
{:ok, spawn_link(fn ->
|
||||
Process.set_label("ConnectionReceiver for #{inspect(socket)}")
|
||||
{:ok, pid} = Amethyst.ConnectionHandler.start_link(socket, Amethyst.ConnectionState.Handshake, 0)
|
||||
receive(socket, pid)
|
||||
receive(socket, pid, nil)
|
||||
end)}
|
||||
end
|
||||
|
||||
@spec receive(:gen_tcp.socket(), pid()) :: no_return()
|
||||
def receive(socket, sender) do
|
||||
case get_packet(socket) do
|
||||
@spec receive(:gen_tcp.socket(), pid(), nil | :crypto.crypto_state()) :: no_return()
|
||||
def receive(socket, sender, cstate) do
|
||||
case get_packet(socket, cstate) do
|
||||
:closed -> send(sender, :closed)
|
||||
Process.exit(self(), :normal)
|
||||
{:error, error} -> Logger.error("Error reading packet: #{error}")
|
||||
{id, data} -> send(sender, {:packet, id, data})
|
||||
end
|
||||
receive(socket, sender)
|
||||
if cstate == nil do
|
||||
# Ask the handler if the encryption state has changed
|
||||
send(sender, {:get_encryption, self()})
|
||||
Logger.debug("Asking for news on encryption...")
|
||||
receive do
|
||||
nil -> receive(socket, sender, cstate)
|
||||
some ->
|
||||
Logger.debug("Enabling decryption!")
|
||||
receive(socket, sender, some)
|
||||
end
|
||||
else
|
||||
receive(socket, sender, cstate)
|
||||
end
|
||||
end
|
||||
|
||||
def get_packet(client) do
|
||||
case get_varint(client, "") do
|
||||
def get_packet(client, cstate) do
|
||||
case get_varint(client, "", cstate) do
|
||||
:closed -> :closed
|
||||
{:error, error} -> {:error, error}
|
||||
{[length], ""} ->
|
||||
recv = :gen_tcp.recv(client, length)
|
||||
case recv do
|
||||
{:ok, full_packet} -> ({[id], data} = Read.start(full_packet) |> Read.varint() |> Read.stop()
|
||||
{:ok, full_packet} ->
|
||||
full_packet = case cstate do
|
||||
nil -> full_packet
|
||||
ds -> :crypto.crypto_update(ds, full_packet)
|
||||
end
|
||||
({[id], data} = Read.start(full_packet) |> Read.varint() |> Read.stop()
|
||||
{id, data})
|
||||
{:error, :closed} -> :closed
|
||||
{:error, error} -> {:error, error}
|
||||
@ -74,11 +91,16 @@ defmodule Amethyst.ConnectionReceiver do
|
||||
end
|
||||
end
|
||||
|
||||
defp get_varint(client, acc) do
|
||||
defp get_varint(client, acc, cstate) do
|
||||
case :gen_tcp.recv(client, 1) do
|
||||
{:ok, byte} -> case byte do
|
||||
{:ok, byte} ->
|
||||
byte = case cstate do
|
||||
nil -> byte
|
||||
ds -> :crypto.crypto_update(ds, byte)
|
||||
end
|
||||
case byte do
|
||||
<<0::1, _::7>> -> Read.start(acc <> byte) |> Read.varint() |> Read.stop()
|
||||
<<1::1, _::7>> -> get_varint(client, acc <> byte)
|
||||
<<1::1, _::7>> -> get_varint(client, acc <> byte, cstate)
|
||||
end
|
||||
{:error, :closed} -> :closed
|
||||
{:error, error} -> {:error, error}
|
||||
|
Loading…
Reference in New Issue
Block a user