Skip to content

Commit

Permalink
Merge pull request #1 from D4-project/master
Browse files Browse the repository at this point in the history
add: [lib] initla commit
  • Loading branch information
gallypette authored Mar 6, 2023
2 parents d1f4703 + 29569f0 commit f6df960
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
exd4-*.tar

# Temporary files, for example, from tests.
/tmp/
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Ex_d4

Ex_d4 allows for communicating with d4-servers in elixir.

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `ex_d4` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:exd4, "~> 0.1.0"}
]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/ex_d4>.
98 changes: 98 additions & 0 deletions lib/ex_d4.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
defmodule Exd4 do
alias Ecto.UUID

@moduledoc """
Module that holds D4 connection struct, and provides encapsulation method.
"""
@moduledoc since: "0.1.0"

# D4 protocol parameters
# bits
@version_size 8
# bits
@type_size 8
# bytes
@uuid_size 16
# bits
@timestamp_size 64
# bytes
@hmac_size 32
# bits
@size_size 32

# TODO metaheader implementation
# @metaheader_max_size 100_000

@enforce_keys [:destination, :uuid]

defstruct destination: nil,
uuid: nil,
snaplen: 4096,
port: 4443,
key: "private key to change",
type: 3,
version: 1

@typedoc "A d4 connection struct"
@type t() :: %__MODULE__{
destination: :inet.ip_address(),
uuid: String.t(),
snaplen: non_neg_integer(),
port: non_neg_integer(),
key: String.t(),
type: non_neg_integer(),
version: non_neg_integer()
}

@doc """
Encapsultate data to ship to a given D4 server.
Return a tuple {:ok, [IO data]}
"""
def encapsulate!(d4_connection, data) do
# initialize header
uuid_bytes =
case UUID.dump(d4_connection.uuid) do
{:ok, uuid_bytes} ->
uuid_bytes

:error ->
raise("Cannot convert UUID #{d4_connection.uuid}")
end

timestamp = :os.system_time(:second)
hmac_init = :binary.copy(<<0>>, @hmac_size)

# build header
header = <<
d4_connection.version::@version_size,
d4_connection.type::@type_size,
uuid_bytes::@uuid_size-binary,
timestamp::unsigned-integer-size(@timestamp_size)-little,
hmac_init::binary,
byte_size(data)::unsigned-integer-size(@size_size)-little
>>

# compute HMAC on header + data
hmac =
:crypto.macN(
:hmac,
:sha256,
:unicode.characters_to_binary(d4_connection.key),
header <> data,
32
)

# update the HMAC in the header
header = <<
d4_connection.version::@version_size,
d4_connection.type::@type_size,
uuid_bytes::@uuid_size-binary,
timestamp::integer-size(@timestamp_size)-little,
hmac::binary,
byte_size(data)::unsigned-integer-size(@size_size)-little
>>

{:ok, [header, data]}
end
end
Binary file added media/text12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
defmodule Exd4.MixProject do
use Mix.Project

def project do
[
app: :ex_d4,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps(),

# Docs
name: "D4 elixir client",
organization: "d4project",
source_url: "https://github.com/d4-project/ex_d4",
homepage_url: "http://d4-project.org",
licence: "MIT",
docs: [
main: "D4 client",
logo: "media/text12.png",
extras: ["README.md"]
]
]
end

# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger, :crypto]
]
end

# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:ecto, "~> 3.9.4"},
{:ex_doc, "~> 0.27", only: :dev, runtime: false}
]
end
end
11 changes: 11 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
%{
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
"earmark_parser": {:hex, :earmark_parser, "1.4.31", "a93921cdc6b9b869f519213d5bc79d9e218ba768d7270d46fdcf1c01bacff9e2", [:mix], [], "hexpm", "317d367ee0335ef037a87e46c91a2269fef6306413f731e8ec11fc45a7efd059"},
"ecto": {:hex, :ecto, "3.9.4", "3ee68e25dbe0c36f980f1ba5dd41ee0d3eb0873bccae8aeaf1a2647242bffa35", [: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 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "de5f988c142a3aa4ec18b85a4ec34a2390b65b24f02385c1144252ff6ff8ee75"},
"ex_doc": {:hex, :ex_doc, "0.29.2", "dfa97532ba66910b2a3016a4bbd796f41a86fc71dd5227e96f4c8581fdf0fdf0", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "6b5d7139eda18a753e3250e27e4a929f8d2c880dd0d460cb9986305dea3e03af"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
}
38 changes: 38 additions & 0 deletions test/ex_d4_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
defmodule Exd4Test do
use ExUnit.Case, async: true

require Logger

test "Encapsulating and shiping data to a d4 server" do
options = [
:binary,
active: false,
verify: :verify_none
]

d4_connection = %Exd4{
destination: {10, 106, 129, 254},
uuid: "b5062e1f-674e-45a0-9c30-2557d6e70ef5"
}

:ok = :ssl.start()

case :ssl.connect(d4_connection.destination, d4_connection.port, options, 5_000) do
{:ok, socket} ->
case Exd4.encapsulate!(d4_connection, "123456789\n") do
{:ok, packet} ->
assert :ssl.send(socket, packet) == :ok
end

case Exd4.encapsulate!(d4_connection, "Is my D4 client broken??\n") do
{:ok, packet} ->
assert :ssl.send(socket, packet) == :ok
end

:ok = :ssl.close(socket)

{:error, reason} ->
Logger.error("Failed to connect to test server #{inspect({:error, reason})}")
end
end
end
1 change: 1 addition & 0 deletions test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ExUnit.start()

0 comments on commit f6df960

Please sign in to comment.