diff --git a/.ci/functional_test.sh b/.ci/functional_test.sh index 9254055f3..a9d4516ff 100755 --- a/.ci/functional_test.sh +++ b/.ci/functional_test.sh @@ -3,7 +3,8 @@ set -e echo "Setting capabilities" chmod +x cloudfire -sudo setcap "cap_net_admin,cap_net_raw,cap_dac_read_search+eip" cloudfire +sudo setcap "cap_net_admin,cap_net_raw,cap_dac_read_search+i" `which ip` +sudo setcap "cap_net_admin,cap_net_raw,cap_dac_read_search+ep" cloudfire echo "Capabilities:" sudo getcap cloudfire diff --git a/.ci/install_runtimes.sh b/.ci/install_runtimes.sh index c299230fd..b23e72732 100755 --- a/.ci/install_runtimes.sh +++ b/.ci/install_runtimes.sh @@ -8,4 +8,4 @@ curl -O https://packages.erlang-solutions.com/erlang/debian/pool/elixir_1.12.0-1 gdebi --non-interactive *.deb curl -sL https://deb.nodesource.com/setup_14.x | bash - -apt-get install gcc g++ make nodejs +apt-get install -y -q gcc g++ make nodejs cargo diff --git a/.tool-versions b/.tool-versions index 3c8e6982c..7d8c873e8 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,4 @@ erlang 24.0.3 elixir 1.12.1-otp-24 nodejs lts +rust system diff --git a/apps/cf_common/lib/cli.ex b/apps/cf_common/lib/cli.ex index 7fa563971..6b23ed9fa 100644 --- a/apps/cf_common/lib/cli.ex +++ b/apps/cf_common/lib/cli.ex @@ -4,8 +4,7 @@ defmodule CfCommon.CLI do """ def bash(cmd) do - # System.cmd("bash", ["-c", cmd]) - System.shell(cmd) + System.cmd("bash", ["-c", cmd]) end def exec!(cmd) do diff --git a/apps/cf_vpn/.gitignore b/apps/cf_vpn/.gitignore index f94d3cae0..0e207ade5 100644 --- a/apps/cf_vpn/.gitignore +++ b/apps/cf_vpn/.gitignore @@ -21,3 +21,5 @@ erl_crash.dump # Ignore package tarball (built via "mix hex.build"). cf_vpn-*.tar + +/native/cf_vpn/target/ diff --git a/apps/cf_vpn/lib/cf_vpn.ex b/apps/cf_vpn/lib/cf_vpn.ex index d6eb3b0b0..904fe8d3f 100644 --- a/apps/cf_vpn/lib/cf_vpn.ex +++ b/apps/cf_vpn/lib/cf_vpn.ex @@ -2,4 +2,7 @@ defmodule CfVpn do @moduledoc """ Documentation for `CfVpn`. """ + use Rustler, otp_app: :cf_vpn + + def add(_arg1, _arg2), do: :erlang.nif_error(:nif_not_loaded) end diff --git a/apps/cf_vpn/mix.exs b/apps/cf_vpn/mix.exs index fa80e5ee4..631cfe34a 100644 --- a/apps/cf_vpn/mix.exs +++ b/apps/cf_vpn/mix.exs @@ -34,6 +34,7 @@ defmodule CfVpn.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:rustler, "~> 0.22.0"}, {:cf_common, in_umbrella: true}, {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, {:excoveralls, "~> 0.13", only: :test} diff --git a/apps/cf_vpn/native/cf_vpn/.cargo/config b/apps/cf_vpn/native/cf_vpn/.cargo/config new file mode 100644 index 000000000..d375c2d8a --- /dev/null +++ b/apps/cf_vpn/native/cf_vpn/.cargo/config @@ -0,0 +1,5 @@ +[target.aarch64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] diff --git a/apps/cf_vpn/native/cf_vpn/Cargo.lock b/apps/cf_vpn/native/cf_vpn/Cargo.lock new file mode 100644 index 000000000..6922d5a86 --- /dev/null +++ b/apps/cf_vpn/native/cf_vpn/Cargo.lock @@ -0,0 +1,115 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cf_vpn" +version = "0.1.0" +dependencies = [ + "lazy_static", + "rustler", + "rustler_codegen", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "proc-macro2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustler" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b787d3b2a80007f41cd4c0c310cdeb3936192768159585f65ecc7e96faf97fc3" +dependencies = [ + "lazy_static", + "rustler_codegen", + "rustler_sys", +] + +[[package]] +name = "rustler_codegen" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a1f867002b6f0130f47abf215cac4405646db6f5d7b009b21c890980490aa4" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rustler_sys" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cb382fde4f421c51555919e9920b058c0286f6bf59e53d02eb4d281eae6758b" +dependencies = [ + "unreachable", +] + +[[package]] +name = "syn" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-segmentation" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/apps/cf_vpn/native/cf_vpn/Cargo.toml b/apps/cf_vpn/native/cf_vpn/Cargo.toml new file mode 100644 index 000000000..6ed392bb8 --- /dev/null +++ b/apps/cf_vpn/native/cf_vpn/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "cf_vpn" +version = "0.1.0" +authors = [] + +[lib] +name = "cf_vpn" +path = "src/lib.rs" +crate-type = ["dylib"] + +[dependencies] +rustler = "0.22.0" +rustler_codegen = "0.22.0" +lazy_static = "1.0" diff --git a/apps/cf_vpn/native/cf_vpn/README.md b/apps/cf_vpn/native/cf_vpn/README.md new file mode 100644 index 000000000..52d9febd3 --- /dev/null +++ b/apps/cf_vpn/native/cf_vpn/README.md @@ -0,0 +1,22 @@ +# Nif for Elixir.Net + +## To build the NIF module: + +- Make sure your projects `mix.exs` has the `:rustler` compiler listed in the `project` function: `compilers: [:rustler] ++ Mix.compilers()` If there already is a `:compilers` list, you should append `:rustler` to it. +- Add your crate to the `rustler_crates` attribute in the `project function. [See here](https://hexdocs.pm/rustler/basics.html#crate-configuration). +- Your NIF will now build along with your project. + +## To load the NIF: + +```elixir +defmodule Net do + use Rustler, otp_app: , crate: "net" + + # When your NIF is loaded, it will override this function. + def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded) +end +``` + +## Examples + +[This](https://github.com/hansihe/NifIo) is a complete example of a NIF written in Rust. diff --git a/apps/cf_vpn/native/cf_vpn/src/lib.rs b/apps/cf_vpn/native/cf_vpn/src/lib.rs new file mode 100644 index 000000000..101980e85 --- /dev/null +++ b/apps/cf_vpn/native/cf_vpn/src/lib.rs @@ -0,0 +1,27 @@ +#[macro_use] extern crate rustler; +#[macro_use] extern crate rustler_codegen; +#[macro_use] extern crate lazy_static; + +use rustler::{Env, Term, NifResult, Encoder}; + +mod atoms { + rustler_atoms! { + atom ok; + //atom error; + //atom __true__ = "true"; + //atom __false__ = "false"; + } +} + +rustler_export_nifs! { + "Elixir.CfVpn", + [("add", 2, add)], + None +} + +fn add<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult> { + let num1: i64 = args[0].decode()?; + let num2: i64 = args[1].decode()?; + + Ok((atoms::ok(), num1 + num2).encode(env)) +} diff --git a/config/config.exs b/config/config.exs index 697abbfe5..fb3841ece 100644 --- a/config/config.exs +++ b/config/config.exs @@ -72,6 +72,8 @@ config :cf_http, CfHttp.Vault, config :cf_common, :config_file_module, File +config :cf_vpn, CfVpn, crate: :cf_vpn, mode: :debug + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/config/prod.exs b/config/prod.exs index ea1cede7f..c7dfd477a 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -13,6 +13,8 @@ config :cf_vpn, cli: CfVpn.CLI.Live, server_process_opts: [name: {:global, :cf_vpn_server}] +config :cf_vpn, CfVpn, crate: :cf_vpn, mode: :debug + config :cf_wall, cli: CfWall.CLI.Live, server_process_opts: [name: {:global, :cf_wall_server}] diff --git a/mix.lock b/mix.lock index f03972215..c41b609e3 100644 --- a/mix.lock +++ b/mix.lock @@ -47,9 +47,11 @@ "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, "postgrex": {:hex, :postgrex, "0.15.9", "46f8fe6f25711aeb861c4d0ae09780facfdf3adbd2fb5594ead61504dd489bda", [: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", "610719103e4cb2223d4ab78f9f0f3e720320eeca6011415ab4137ddef730adee"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, + "rustler": {:hex, :rustler, "0.22.0", "e2930f9d6933e910f87526bb0a7f904e32b62a7e838a3ca4a884ee7fdfb957ed", [:mix], [{:toml, "~> 0.5.2", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "01f5989dd511ebec09be481e07d3c59773d5373c5061e09d3ebc3ef61811b49d"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"}, "tesla": {:hex, :tesla, "1.3.3", "26ae98627af5c406584aa6755ab5fc96315d70d69a24dd7f8369cfcb75094a45", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "2648f1c276102f9250299e0b7b57f3071c67827349d9173f34c281756a1b124c"}, + "toml": {:hex, :toml, "0.5.2", "e471388a8726d1ce51a6b32f864b8228a1eb8edc907a0edf2bb50eab9321b526", [:mix], [], "hexpm", "f1e3dabef71fb510d015fad18c0e05e7c57281001141504c6b69d94e99750a07"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "wallaby": {:hex, :wallaby, "0.28.0", "2ff217c0f245cadb3e5d91748ebcf0102873ceb9ef8a3507717c8bdd73915668", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:httpoison, "~> 0.12 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]}, {:web_driver_client, "~> 0.1.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}], "hexpm", "e58112650d0b51e81714a626eab7d486d7a77342c9bbc2ba262b6653f9b22558"}, "web_driver_client": {:hex, :web_driver_client, "0.1.0", "19466a989c76b7ec803c796cec0fec4611a64f445fd5120ce50c9e3817e09c2c", [:mix], [{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.3.0", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "c9c031ca915e8fc75b5e24ac93503244f3cc406dd7f53047087a45aa62d60e9e"},