Skip to content
Snippets Groups Projects
Commit 31321b40 authored by PUBERT Quentin's avatar PUBERT Quentin
Browse files

Merge branch 'handshake' into dev

parents a00b15e6 5c9d23ae
Branches
Tags
No related merge requests found
Pipeline #1346 failed
......@@ -6,16 +6,17 @@ defmodule Dunixir.Application do
use Application
def start(_type, _args) do
ws2p_port = String.to_integer(System.get_env("PORT") || "20900")
children = [
# Starts a worker by calling: Dunixir.Worker.start_link(arg)
# {Dunixir.Worker, arg}
BDD.Create,
Plug.Adapters.Cowboy.child_spec(
scheme: :http,
plug: ServerHttp.Router,
options: [port: 8085]
)
]
Plug.Adapters.Cowboy.child_spec(scheme: :http, plug: ServerHttp.Router, options: [port: 8085]),
{Registry, keys: :unique, name: WS2P.Connection.Registry},
{DynamicSupervisor, strategy: :one_for_one, name: WS2P.ConnectionSupervisor},
{Task, fn -> WS2P.Endpoint.accept_connections!(ws2p_port, "/") end}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
......
defmodule WS2P.Connection do
use GenServer, restart: :transient
require Logger
@keypair Ed25519.generate_key_pair()
@currency_name "g1-test"
def start_link({:connect, address_and_port, socket_options}) do
GenServer.start_link(__MODULE__, {:connect, address_and_port, socket_options},
name: {:via, Registry, {WS2P.Connection.Registry, address_and_port}}
)
end
def start_link({:accept, socket}) do
address_and_port = Socket.Web.remote!(socket)
GenServer.start_link(__MODULE__, {:accept, address_and_port, socket},
name: {:via, Registry, {WS2P.Connection.Registry, address_and_port}}
)
end
def init({:connect, address_and_port, socket_options}) do
socket = Socket.Web.connect!(address_and_port, socket_options)
Logger.info("Connected socket to #{inspect(address_and_port)}")
schedule_poll_remote_packets()
{:ok,
%{
socket: socket,
keypair: @keypair,
currency_name: @currency_name,
address_and_port: address_and_port
}, {:continue, :send_connect_object}}
end
def init({:accept, address_and_port, socket}) do
Logger.info("Accepted socket from #{inspect(address_and_port)}")
schedule_poll_remote_packets()
{:ok,
%{
socket: socket,
keypair: @keypair,
currency_name: @currency_name,
address_and_port: address_and_port
}, {:continue, :send_connect_object}}
end
def handle_continue(
:send_connect_object,
%{
address_and_port: address_and_port,
keypair: {sec, pub},
currency_name: currency_name
} = state
) do
local_challenge = UUID.uuid4() <> UUID.uuid4()
pub_as_base58 = pub |> Base58.encode()
raw_format = "WS2P:CONNECT:#{currency_name}:#{pub_as_base58}:#{local_challenge}"
signature = Ed25519.signature(raw_format, sec, pub)
connect_object = %{
"auth" => "CONNECT",
"pub" => pub_as_base58,
"challenge" => local_challenge,
"sig" => signature |> Base.encode64()
}
Logger.info("Sending CONNECT to node #{inspect(address_and_port)}\n#{raw_format}")
handle_local_object(connect_object, Map.put_new(state, :local_challenge, local_challenge))
end
defp schedule_poll_remote_packets do
Process.send_after(self(), :poll_remote_packets, 1000)
end
def handle_info(:poll_remote_packets, %{socket: socket} = state) do
poll_remote_packets(socket)
|> Enum.map(fn packet ->
GenServer.cast(self(), {:remote_packet, packet})
end)
schedule_poll_remote_packets()
{:noreply, state}
end
defp poll_remote_packets(socket, remote_packets \\ []) do
case Socket.Web.recv(socket, timeout: 0) do
{:ok, packet} ->
poll_remote_packets(socket, [packet | remote_packets])
{:error, :timeout} ->
remote_packets
{:error, code} ->
Logger.error(code)
raise Socket.Error, reason: code
end
end
defp handle_local_packet(packet, %{socket: socket} = state) do
Socket.Web.send!(socket, packet)
{:noreply, state}
end
defp handle_local_msg(msg, state) do
handle_local_packet({:text, msg}, state)
end
defp handle_local_object(object, state) do
msg = Poison.encode!(object, pretty: true)
handle_local_msg(msg, state)
end
def handle_cast({:local_msg, msg}, state) do
handle_local_msg(msg, state)
end
def handle_cast({:local_object, object}, state) do
handle_local_object(object, state)
end
def handle_cast({:remote_packet, packet}, state) do
handle_remote_packet(packet, state)
end
defp handle_remote_object(
%{
"auth" => "CONNECT",
"challenge" => challenge,
"pub" => _pub,
"sig" => _sig
},
%{
keypair: {my_sec, my_pub},
currency_name: currency_name,
address_and_port: address_and_port
} = state
) do
Logger.info("Received CONNECT from node #{inspect(address_and_port)}")
my_pub_as_base58 = my_pub |> Base58.encode()
raw_format = "WS2P:ACK:#{currency_name}:#{my_pub_as_base58}:#{challenge}"
signature = Ed25519.signature(raw_format, my_sec, my_pub)
ack_object = %{
"auth" => "ACK",
"pub" => my_pub_as_base58,
"sig" => signature |> Base.encode64()
}
Logger.info("Sending ACK to node #{inspect(address_and_port)}\n#{raw_format}")
handle_local_object(ack_object, state)
end
defp handle_remote_object(
%{
"auth" => "ACK",
"pub" => _pub,
"sig" => _sig
},
%{
keypair: {my_sec, my_pub},
currency_name: currency_name,
local_challenge: local_challenge,
address_and_port: address_and_port
} = state
) do
Logger.info("Received ACK from node #{inspect(address_and_port)}")
my_pub_as_base58 = my_pub |> Base58.encode()
raw_format = "WS2P:OK:#{currency_name}:#{my_pub_as_base58}:#{local_challenge}"
signature = Ed25519.signature(raw_format, my_sec, my_pub)
ok_object = %{
"auth" => "OK",
"sig" => signature |> Base.encode64()
}
Logger.info("Sent OK to node #{inspect(address_and_port)}\n#{raw_format}")
handle_local_object(ok_object, state)
end
defp handle_remote_object(
%{
"auth" => "OK",
"sig" => _sig
},
%{
address_and_port: address_and_port
} = state
) do
Logger.info("Received OK from node #{inspect(address_and_port)}")
{:noreply, state}
end
defp handle_remote_object(object, state) do
IO.puts("Received unhandled remote object:")
IO.inspect(object)
{:noreply, state}
end
defp handle_remote_packet({:text, msg}, state) do
case Poison.decode(msg) do
{:ok, object} ->
handle_remote_object(object, state)
{:error, error} ->
Logger.warn("Could not decode message:\n#{inspect(error, pretty_print: true)}")
{:noreply, state}
end
end
defp handle_remote_packet({type, msg}, %{socket: socket} = state) do
Logger.debug("Received message of type #{inspect(type)} from #{socket.origin}:\n#{msg}")
{:noreply, state}
end
defp handle_remote_packet(:close, %{socket: socket, address_and_port: address_and_port} = state) do
Logger.info("Remote #{inspect(address_and_port)} closed socket connection")
Socket.Web.close(socket)
{:stop, :shutdown, state}
end
defp handle_remote_packet(
{:close, code, reason},
%{socket: socket, address_and_port: address_and_port} = state
) do
Logger.debug(
"Remote #{inspect(address_and_port)} closed socket connection with code \"#{code}\""
)
Logger.debug("Reason: \"#{reason}\"")
Socket.Web.close(socket)
{:stop, :shutdown, state}
end
end
defmodule WS2P.Endpoint do
require Logger
defp start_connection!(args) do
{:ok, connection} =
DynamicSupervisor.start_child(
WS2P.ConnectionSupervisor,
{WS2P.Connection, args}
)
connection
end
def connect!(address_and_port, socket_options \\ []) do
start_connection!({:connect, address_and_port, socket_options})
end
def accept_connections!(port, path) do
websocket_listener = Socket.Web.listen!(port)
Logger.info("Listening for websocket connections on port #{port} at #{path}")
loop(websocket_listener, path)
end
defp loop(websocket_listener, path) do
client_socket = Socket.Web.accept!(websocket_listener)
if client_socket.path == path do
start_connection!({:accept, client_socket})
end
loop(websocket_listener, path)
end
end
......@@ -35,7 +35,9 @@ defmodule Dunixir.MixProject do
{:plug_cowboy, "~> 1.0"},
{:json, "~> 1.4"},
{:ymlr, "~> 1.0"},
{:ex2ms, "~> 1.0"}
{:ex2ms, "~> 1.0"},
{:elixir_uuid, "~> 1.2"},
{:socket, "~> 0.3.13"},
]
end
end
%{
"B58": {:hex, :b58, "1.0.1", "db9443361d2597ea60559ab5ef29a461f0da9698727e68d1ce2d5366644ebc1f", [:mix], [], "hexpm", "f0de289ba02513c8e966b3137b32c50826281e0ac2e11c22e2e7a0e810b4202d"},
"ed25519": {:hex, :ed25519, "1.3.2", "e3a2d4badf57f0799279cf09925bd761ec38df6df3696e266585626280b5c0ad", [:mix], [], "hexpm", "2290e46e0e23717adbe20632c6dd29aa71a46ca6e153ef7ba41fe1204f66f859"},
"elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
"enacl": {:hex, :enacl, "1.1.1", "f65dc64d9bff2d8a534cb77aef14da5e7a2fa148987d87856f79a4745c9c2627", [:rebar3], [], "hexpm", "60d329ac3976008f774e21aba254671104976d61a792287615bb26816f09ea0f"},
"scrypt_elixir": {:hex, :scrypt_elixir, "0.1.0", "c603bd2fc5816ac41e2dd3397719afde1adb687e4b79ced71959fbb92e6aa24e", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "b9536accc361e6ea6b284eb8b9795642e2660a63ec232d5ea6e83ca632961037"},
"ymlr": {:hex, :ymlr, "1.0.1", "1e0057b5fd157f3053e05af4e8a94e579c69969d919e219723bc35dc827ed9d4", [:mix], [], "hexpm", "b4d5f25b34dca432760ae5f96496b4398a31155df3c4de1ef4f2e60e3da7fd5f"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"cowboy": {:hex, :cowboy, "1.0.4", "a324a8df9f2316c833a470d918aaf73ae894278b8aa6226ce7a9bf699388f878", [:make, :rebar], [{:cowlib, "~> 1.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "6a0edee96885fae3a8dd0ac1f333538a42e807db638a9453064ccfdaa6b9fdac"},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm", "db622da03aa039e6366ab953e31186cc8190d32905e33788a1acb22744e6abd2"},
......@@ -12,6 +7,11 @@
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
"ecto": {:hex, :ecto, "3.5.5", "48219a991bb86daba6e38a1e64f8cea540cded58950ff38fbc8163e062281a07", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "98dd0e5e1de7f45beca6130d13116eae675db59adfa055fb79612406acf6f6f1"},
"ecto_sql": {:hex, :ecto_sql, "3.5.3", "1964df0305538364b97cc4661a2bd2b6c89d803e66e5655e4e55ff1571943efd", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.5.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d2f53592432ce17d3978feb8f43e8dc0705e288b0890caf06d449785f018061c"},
"ed25519": {:hex, :ed25519, "1.3.2", "e3a2d4badf57f0799279cf09925bd761ec38df6df3696e266585626280b5c0ad", [:mix], [], "hexpm", "2290e46e0e23717adbe20632c6dd29aa71a46ca6e153ef7ba41fe1204f66f859"},
"elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
"elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"},
"enacl": {:hex, :enacl, "1.1.1", "f65dc64d9bff2d8a534cb77aef14da5e7a2fa148987d87856f79a4745c9c2627", [:rebar3], [], "hexpm", "60d329ac3976008f774e21aba254671104976d61a792287615bb26816f09ea0f"},
"ex2ms": {:hex, :ex2ms, "1.6.0", "f39bbd9ff1b0f27b3f707bab2d167066dd8965e7df1149b962d94c74615d0e09", [:mix], [], "hexpm", "0d1ab5e08421af5cd69146efb408dbb1ff77f38a2f4df5f086f2512dc8cf65bf"},
"json": {:hex, :json, "1.4.1", "8648f04a9439765ad449bc56a3ff7d8b11dd44ff08ffcdefc4329f7c93843dfa", [:mix], [], "hexpm", "9abf218dbe4ea4fcb875e087d5f904ef263d012ee5ed21d46e9dbca63f053d16"},
"mime": {:hex, :mime, "1.5.0", "203ef35ef3389aae6d361918bf3f952fa17a09e8e43b5aa592b93eba05d0fb8d", [:mix], [], "hexpm", "55a94c0f552249fc1a3dd9cd2d3ab9de9d3c89b559c2bd01121f824834f24746"},
"plug": {:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"},
......@@ -20,6 +20,8 @@
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},
"postgrex": {:hex, :postgrex, "0.15.7", "724410acd48abac529d0faa6c2a379fb8ae2088e31247687b16cacc0e0883372", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "88310c010ff047cecd73d5ceca1d99205e4b1ab1b9abfdab7e00f5c9d20ef8f9"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
"scrypt_elixir": {:hex, :scrypt_elixir, "0.1.0", "c603bd2fc5816ac41e2dd3397719afde1adb687e4b79ced71959fbb92e6aa24e", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "b9536accc361e6ea6b284eb8b9795642e2660a63ec232d5ea6e83ca632961037"},
"socket": {:hex, :socket, "0.3.13", "98a2ab20ce17f95fb512c5cadddba32b57273e0d2dba2d2e5f976c5969d0c632", [:mix], [], "hexpm", "f82ea9833ef49dde272e6568ab8aac657a636acb4cf44a7de8a935acb8957c2e"},
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
"ex2ms": {:hex, :ex2ms, "1.6.0", "f39bbd9ff1b0f27b3f707bab2d167066dd8965e7df1149b962d94c74615d0e09", [:mix], [], "hexpm", "0d1ab5e08421af5cd69146efb408dbb1ff77f38a2f4df5f086f2512dc8cf65bf"},
"ymlr": {:hex, :ymlr, "1.0.1", "1e0057b5fd157f3053e05af4e8a94e579c69969d919e219723bc35dc827ed9d4", [:mix], [], "hexpm", "b4d5f25b34dca432760ae5f96496b4398a31155df3c4de1ef4f2e60e3da7fd5f"},
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment