Browse Source

Switch to a Rust libsodium build

Caleb James DeLisle 3 years ago
parent
commit
caf9963793
58 changed files with 448 additions and 366 deletions
  1. 1 0
      .gitignore
  2. 126 0
      Cargo.lock
  3. 13 0
      Cargo.toml
  4. 2 2
      admin/Admin.c
  5. 1 1
      admin/angel/Core.c
  6. 1 1
      client/AdminClient.c
  7. 2 1
      client/cjdroute2.c
  8. 2 1
      contrib/c/makekeys.c
  9. 2 1
      contrib/c/mkpasswd.c
  10. 3 2
      contrib/c/privatetopublic.c
  11. 2 1
      contrib/c/publictoip6.c
  12. 3 2
      contrib/c/sybilsim.c
  13. 2 1
      crypto/AddressCalc.c
  14. 3 3
      crypto/CryptoAuth.c
  15. 1 1
      crypto/Key.c
  16. 2 2
      crypto/Sign.c
  17. 2 2
      crypto/random/Random.c
  18. 1 1
      crypto/random/randombytes.c
  19. 1 1
      crypto/random/seed/RandomSeed.c
  20. 1 1
      crypto/sign/crypto_int16.h
  21. 1 1
      crypto/sign/crypto_int32.h
  22. 1 1
      crypto/sign/crypto_int64.h
  23. 1 1
      crypto/sign/crypto_int8.h
  24. 1 1
      crypto/sign/crypto_uint16.h
  25. 1 1
      crypto/sign/crypto_uint32.h
  26. 1 1
      crypto/sign/crypto_uint64.h
  27. 1 1
      crypto/sign/crypto_uint8.h
  28. 1 1
      crypto/sign/fe_isnonzero.c
  29. 3 2
      crypto/sign/open.c
  30. 1 1
      crypto/test/Sign_test.c
  31. 17 1
      do
  32. 1 1
      node_build/CjdnsTest.js
  33. 0 7
      node_build/FindPython.js
  34. 0 223
      node_build/TestRunner.js
  35. 20 29
      node_build/builder.js
  36. 22 67
      node_build/make.js
  37. 16 0
      rust/cjdns_sys/Cargo.toml
  38. 71 0
      rust/cjdns_sys/build.rs
  39. 19 0
      rust/cjdns_sys/src/lib.rs
  40. 11 0
      rust/cjdroute/Cargo.toml
  41. 1 0
      rust/cjdroute/src/main.rs
  42. 11 0
      rust/makekeys/Cargo.toml
  43. 1 0
      rust/makekeys/src/main.rs
  44. 11 0
      rust/mkpasswd/Cargo.toml
  45. 1 0
      rust/mkpasswd/src/main.rs
  46. 11 0
      rust/privatetopublic/Cargo.toml
  47. 1 0
      rust/privatetopublic/src/main.rs
  48. 11 0
      rust/publictoip6/Cargo.toml
  49. 1 0
      rust/publictoip6/src/main.rs
  50. 11 0
      rust/randombytes/Cargo.toml
  51. 1 0
      rust/randombytes/src/main.rs
  52. 11 0
      rust/sybilsim/Cargo.toml
  53. 1 0
      rust/sybilsim/src/main.rs
  54. 11 0
      rust/testcjdroute/Cargo.toml
  55. 1 0
      rust/testcjdroute/src/main.rs
  56. 1 1
      subnode/ReachabilityAnnouncer.c
  57. 1 1
      test/CryptoAddress_test.c
  58. 1 1
      test/testcjdroute.c

+ 1 - 0
.gitignore

@@ -32,3 +32,4 @@
 /node_modules/.bin
 /contrib/docker/cjdns*/
 .vscode
+/target

+ 126 - 0
Cargo.lock

@@ -0,0 +1,126 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "anyhow"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
+
+[[package]]
+name = "cc"
+version = "1.0.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c"
+
+[[package]]
+name = "cjdns_sys"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "cc",
+ "sodiumoxide",
+]
+
+[[package]]
+name = "cjdroute"
+version = "0.1.0"
+dependencies = [
+ "cjdns_sys",
+ "sodiumoxide",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
+
+[[package]]
+name = "libsodium-sys"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a685b64f837b339074115f2e7f7b431ac73681d08d75b389db7498b8892b8a58"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
+name = "makekeys"
+version = "0.1.0"
+dependencies = [
+ "cjdns_sys",
+ "sodiumoxide",
+]
+
+[[package]]
+name = "mkpasswd"
+version = "0.1.0"
+dependencies = [
+ "cjdns_sys",
+ "sodiumoxide",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
+
+[[package]]
+name = "privatetopublic"
+version = "0.1.0"
+dependencies = [
+ "cjdns_sys",
+ "sodiumoxide",
+]
+
+[[package]]
+name = "publictoip6"
+version = "0.1.0"
+dependencies = [
+ "cjdns_sys",
+ "sodiumoxide",
+]
+
+[[package]]
+name = "randombytes"
+version = "0.1.0"
+dependencies = [
+ "cjdns_sys",
+ "sodiumoxide",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.116"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
+
+[[package]]
+name = "sodiumoxide"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7038b67c941e23501573cb7242ffb08709abe9b11eb74bceff875bbda024a6a8"
+dependencies = [
+ "libc",
+ "libsodium-sys",
+ "serde",
+]
+
+[[package]]
+name = "sybilsim"
+version = "0.1.0"
+dependencies = [
+ "cjdns_sys",
+ "sodiumoxide",
+]
+
+[[package]]
+name = "testcjdroute"
+version = "0.1.0"
+dependencies = [
+ "cjdns_sys",
+ "sodiumoxide",
+]

+ 13 - 0
Cargo.toml

@@ -0,0 +1,13 @@
+[workspace]
+
+members = [
+    "rust/cjdns_sys",
+    "rust/cjdroute",
+    "rust/publictoip6",
+    "rust/mkpasswd",
+    "rust/sybilsim",
+    "rust/testcjdroute",
+    "rust/randombytes",
+    "rust/privatetopublic",
+    "rust/makekeys",
+]

+ 2 - 2
admin/Admin.c

@@ -29,8 +29,8 @@
 #include "util/platform/Sockaddr.h"
 #include "util/Defined.h"
 
-#include <crypto_hash_sha256.h>
-#include <crypto_verify_32.h>
+#include <sodium/crypto_hash_sha256.h>
+#include <sodium/crypto_verify_32.h>
 
 #include <stdlib.h>
 #include <stdio.h>

+ 1 - 1
admin/angel/Core.c

@@ -75,7 +75,7 @@
 #include "wire/Headers.h"
 #include "net/NetCore.h"
 
-#include <crypto_scalarmult_curve25519.h>
+#include <sodium/crypto_scalarmult_curve25519.h>
 
 #include <stdlib.h>
 #include <unistd.h>

+ 1 - 1
client/AdminClient.c

@@ -24,7 +24,7 @@
 #include "util/Identity.h"
 #include "wire/Message.h"
 
-#include <crypto_hash_sha256.h>
+#include <sodium/crypto_hash_sha256.h>
 
 #include <stdio.h>
 #include <stdlib.h>

+ 2 - 1
client/cjdroute2.c

@@ -595,7 +595,8 @@ static String* getPipePath(Dict* config, struct Allocator* alloc)
     return out;
 }
 
-int main(int argc, char** argv)
+// This is invoked from cjdroute.rs
+int cjdroute2_main(int argc, char** argv)
 {
     #ifdef Log_KEYS
         fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n");

+ 2 - 1
contrib/c/makekeys.c

@@ -23,7 +23,8 @@
 #include <signal.h>
 #include <stdio.h>
 
-int main(int argc, char** argv)
+// This is invoked from makekeys.rs
+int makekeys_main(int argc, char** argv)
 {
     struct Allocator* alloc = MallocAllocator_new(1<<22);
     struct Random* rand = Random_new(alloc, NULL, NULL);

+ 2 - 1
contrib/c/mkpasswd.c

@@ -19,7 +19,8 @@
 #include <stdio.h>
 #include <unistd.h>
 
-int main()
+// This is invoked from mkpasswd.rs
+int mkpasswd_main(int argc, char** argv)
 {
     struct Allocator* alloc = MallocAllocator_new(1<<22);
     struct Random* rand = Random_new(alloc, NULL, NULL);

+ 3 - 2
contrib/c/privatetopublic.c

@@ -17,7 +17,7 @@
 #include "util/Base32.h"
 #include "util/Hex.h"
 
-#include "crypto_scalarmult_curve25519.h"
+#include <sodium/crypto_scalarmult_curve25519.h>
 
 #include <unistd.h>
 #include <stdio.h>
@@ -43,7 +43,8 @@ static int usage(char* appName)
     return 0;
 }
 
-int main(int argc, char** argv)
+// This is invoked from privatetopublic.rs
+int privatetopublic_main(int argc, char** argv)
 {
     struct Address address;
     uint8_t addressOut[40];

+ 2 - 1
contrib/c/publictoip6.c

@@ -27,7 +27,8 @@ static int usage(char* appName)
     return 0;
 }
 
-int main(int argc, char** argv)
+// This is invoked from publictoip6.rs
+int publictoip6_main(int argc, char** argv)
 {
     if (argc < 2) {
         return usage(argv[0]);

+ 3 - 2
contrib/c/sybilsim.c

@@ -39,7 +39,7 @@
 #include "util/events/FakeNetwork.h"
 #include "util/Hash.h"
 
-#include "crypto_scalarmult_curve25519.h"
+#include <sodium/crypto_scalarmult_curve25519.h>
 
 #include <unistd.h> // isatty()
 
@@ -435,7 +435,8 @@ static int usage(char* appName)
     return 0;
 }
 
-int main(int argc, char** argv)
+// This is invoked from sybilsim.rs
+int sybilsim_main(int argc, char** argv)
 {
     Assert_true(argc > 0);
     if (isatty(STDIN_FILENO)) {

+ 2 - 1
crypto/AddressCalc.c

@@ -12,11 +12,12 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
-#include "crypto_hash_sha512.h"
 #include "util/Bits.h"
 #include "util/Endian.h"
 #include "crypto/AddressCalc.h"
 
+#include <sodium/crypto_hash_sha512.h>
+
 #include <stdint.h>
 #include <stdbool.h>
 

+ 3 - 3
crypto/CryptoAuth.c

@@ -32,9 +32,9 @@
 #include "wire/Headers.h"
 #include "wire/Message.h"
 
-#include "crypto_box_curve25519xsalsa20poly1305.h"
-#include "crypto_hash_sha256.h"
-#include "crypto_scalarmult_curve25519.h"
+#include <sodium/crypto_box_curve25519xsalsa20poly1305.h>
+#include <sodium/crypto_hash_sha256.h>
+#include <sodium/crypto_scalarmult_curve25519.h>
 
 #include <stdint.h>
 #include <stdbool.h>

+ 1 - 1
crypto/Key.c

@@ -18,7 +18,7 @@
 #include "util/Base32.h"
 #include "crypto/AddressCalc.h"
 
-#include "crypto_scalarmult_curve25519.h"
+#include <sodium/crypto_scalarmult_curve25519.h>
 
 #include <stddef.h>
 

+ 2 - 2
crypto/Sign.c

@@ -15,8 +15,6 @@
 
 #include "crypto/Sign.h"
 
-#include "crypto_hash_sha512.h"
-
 #include "crypto/sign/crypto_sign_ed25519.h"
 #include "crypto/sign/ge.h"
 #include "crypto/sign/sc.h"
@@ -58,6 +56,8 @@ Linker_require("crypto/sign/sc_muladd.c")
 Linker_require("crypto/sign/sc_reduce.c")
 Linker_require("crypto/sign/open.c")
 
+#include <sodium/crypto_hash_sha512.h>
+
 // This is fairly streight forward, we're taking a curve25519 private key and
 // interpreting it as an ed25519 key. This works in conjunction with the public
 // key converter Sign_publicSigningKeyToCurve25519() which is able to re-derive

+ 2 - 2
crypto/random/Random.c

@@ -22,8 +22,8 @@
 #include "util/Identity.h"
 #include "util/Endian.h"
 
-#include <crypto_hash_sha256.h>
-#include <crypto_stream_salsa20.h>
+#include <sodium/crypto_hash_sha256.h>
+#include <sodium/crypto_stream_salsa20.h>
 
 /**
  * cjdns random generator:

+ 1 - 1
crypto/random/randombytes.c

@@ -18,7 +18,7 @@
 
 #include <unistd.h>
 
-int main()
+int randombytes_main()
 {
     struct Allocator* alloc = MallocAllocator_new(1<<20);
     struct Random* rand = Random_new(alloc, NULL, NULL);

+ 1 - 1
crypto/random/seed/RandomSeed.c

@@ -17,7 +17,7 @@
 #include "util/log/Log.h"
 #include "util/Bits.h"
 
-#include <crypto_hash_sha512.h>
+#include <sodium/crypto_hash_sha512.h>
 
 struct RandomSeed_pvt
 {

+ 1 - 1
crypto/sign/crypto_int16.h

@@ -1 +1 @@
-#include <crypto_types.h>
+#include "crypto_types.h"

+ 1 - 1
crypto/sign/crypto_int32.h

@@ -1 +1 @@
-#include <crypto_types.h>
+#include "crypto_types.h"

+ 1 - 1
crypto/sign/crypto_int64.h

@@ -1 +1 @@
-#include <crypto_types.h>
+#include "crypto_types.h"

+ 1 - 1
crypto/sign/crypto_int8.h

@@ -1 +1 @@
-#include <crypto_types.h>
+#include "crypto_types.h"

+ 1 - 1
crypto/sign/crypto_uint16.h

@@ -1 +1 @@
-#include <crypto_types.h>
+#include "crypto_types.h"

+ 1 - 1
crypto/sign/crypto_uint32.h

@@ -1 +1 @@
-#include <crypto_types.h>
+#include "crypto_types.h"

+ 1 - 1
crypto/sign/crypto_uint64.h

@@ -1 +1 @@
-#include <crypto_types.h>
+#include "crypto_types.h"

+ 1 - 1
crypto/sign/crypto_uint8.h

@@ -1 +1 @@
-#include <crypto_types.h>
+#include "crypto_types.h"

+ 1 - 1
crypto/sign/fe_isnonzero.c

@@ -1,5 +1,5 @@
 #include "fe.h"
-#include "crypto_verify_32.h"
+#include <sodium/crypto_verify_32.h>
 
 /*
 return 1 if f == 0

+ 3 - 2
crypto/sign/open.c

@@ -1,9 +1,10 @@
 #include "crypto_sign.h"
-#include "crypto_hash_sha512.h"
-#include "crypto_verify_32.h"
 #include "ge.h"
 #include "sc.h"
 
+#include <sodium/crypto_hash_sha512.h>
+#include <sodium/crypto_verify_32.h>
+
 int crypto_sign_open(
   unsigned char *m,unsigned long long *mlen,
   const unsigned char *sm,unsigned long long smlen,

+ 1 - 1
crypto/test/Sign_test.c

@@ -19,7 +19,7 @@
 #include "util/Bits.h"
 #include "util/log/FileWriterLog.h"
 
-#include "crypto_scalarmult_curve25519.h"
+#include <sodium/crypto_scalarmult_curve25519.h>
 
 int main()
 {

+ 17 - 1
do

@@ -1,2 +1,18 @@
 #!/bin/sh
-MAINJS=./node_build/make.js ./node_build/node.sh "$@"
+##MAINJS=./node_build/make.js ./node_build/node.sh "$@"
+set -e
+CARGO=$(command -v cargo)
+if test "x$CARGO" = "x"; then
+    printf "Rust is required in order to build cjdns, see https://rustup.rs/ for more info\n"
+    exit 1
+fi
+$CARGO build -vv --release
+./target/release/testcjdroute all >/dev/null
+mv ./target/release/cjdroute ./
+mv ./target/release/makekeys ./
+mv ./target/release/mkpasswd ./
+mv ./target/release/privatetopublic ./
+mv ./target/release/publictoip6 ./
+mv ./target/release/randombytes ./
+mv ./target/release/sybilsim ./
+printf "\x1b[1;32mBuild completed successfully, type ./cjdroute to begin setup.\x1b[0m\n"

+ 1 - 1
node_build/CjdnsTest.js

@@ -30,7 +30,7 @@ const Fs_stat = function (file, callback) {
 };
 
 const getTests = function (file, tests, isSubnode, callback) {
-    if (/\/(.git|build_.*|node_build|contrib)\//.test(file)) { callback(); return; }
+    if (/\/(.git|build_.*|node_build|contrib|target)\//.test(file)) { callback(); return; }
     if (isSubnode && /\/dht\//.test(file)) { callback(); return; }
     Fs_stat(file, function (err, stat) {
         if (err) { throw err; }

+ 0 - 7
node_build/FindPython.js

@@ -48,13 +48,6 @@ var find = module.exports.find = function (tempFile, callback) {
             py.stdout.on('data', function (dat) { console.log(dat.toString('utf8')); });
             py.on('close', function(ret) {
                 if (ret === 0) {
-                    Fs.exists(tempFile, waitFor(function (exists) {
-                        if (!exists) { return; }
-
-                        Fs.unlink(tempFile, waitFor(function (err) {
-                            if (err) { throw err; }
-                        }));
-                    }));
                     callback(undefined, python);
                     waitFor.abort();
                 } else {

+ 0 - 223
node_build/TestRunner.js

@@ -1,223 +0,0 @@
-/*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-'use strict';
-var Spawn = require('child_process').spawn;
-var Http = require("http");
-var Fs = require("fs");
-
-var TIMEOUT = 600000;
-if (process.env.TestRunner_TIMEOUT && !isNaN(Number(process.env.TestRunner_TIMEOUT))) {
-    TIMEOUT = Number(process.env.TestRunner_TIMEOUT);
-}
-console.log("timeout is " + TIMEOUT);
-
-var parseURL = function (url)
-{
-    url = url.replace(/[a-zA-Z]*:\/\//, '');
-    var path = url.split('/')[1] || '';
-    url = url.split('/')[0];
-    var port = url.split(':')[1];
-    url = url.split(':')[0];
-    port = Number(port) || 8083;
-    var host = url || undefined;
-    return {
-        host: host,
-        port: port,
-        path: '/' + path
-    };
-};
-
-var remote = module.exports.remote = function (url, argv) {
-    var params = parseURL(url);
-    if (!params.host) { throw new Error("For the client, the hostname is required"); }
-    params.headers = { args: [ JSON.stringify(argv) ] };
-    params.method = 'POST';
-
-    return function (fileName, callback) {
-        var out = [];
-        out.push('Testing Remotely');
-        var req = Http.request(params, function(res) {
-            if (res.statusCode !== 200) {
-                out.push('STATUS: ' + res.statusCode);
-                out.push('HEADERS: ' + JSON.stringify(res.headers));
-            }
-            res.setEncoding('utf8');
-            var body = '';
-            res.on('data', function (chunk) { body += String(chunk); });
-            res.on('end', function () {
-                var ret = JSON.parse(body);
-                if (ret.returnCode !== 0) {
-                    output.push(ret.stdout);
-                }
-                out.push(ret.stderr);
-                callback(out.join('\n'), (ret.returnCode !== 0));
-            });
-        });
-        Fs.createReadStream(fileName).pipe(req);
-        req.on('error', function(e) {
-            console.log('problem with request: ' + e.message);
-        });
-    };
-};
-
-var client = function (url, fileName, argv) {
-    var params = parseURL(url);
-
-    if (!params.host) { throw new Error("For the client, the hostname is required"); }
-
-    params.headers = { args: [ JSON.stringify(argv) ] };
-    params.method = 'POST';
-
-    var req = Http.request(params, function(res) {
-        if (res.statusCode !== 200) {
-            console.log('STATUS: ' + res.statusCode);
-            console.log('HEADERS: ' + JSON.stringify(res.headers));
-        }
-        res.setEncoding('utf8');
-        var body = '';
-        res.on('data', function (chunk) { body += String(chunk); });
-        res.on('end', function () {
-            var ret = JSON.parse(body);
-            process.stdout.write(ret.stdout);
-            process.stderr.write(ret.stderr);
-            process.exit(ret.returnCode);
-        });
-    });
-    Fs.createReadStream(fileName).pipe(req);
-    req.on('error', function(e) {
-        console.log('problem with request: ' + e.message);
-    });
-};
-
-
-/// Server
-
-var spawnProc = function(file, args, callback, timeoutMilliseconds) {
-    var child = Spawn(file, args);
-    var out = '', err = '';
-    var t0 = +new Date();
-    var to = setTimeout(function() {
-        child.kill('SIGKILL');
-        err += "test TIMEOUT in [" + ((+new Date()) - t0) +
-            "ms] try TestRunner_TIMEOUT=<number>\n";
-        callback(1000, out, err);
-    }, timeoutMilliseconds);
-    child.stdout.on('data', function (data) { out += String(data); });
-    child.stderr.on('data', function (data) { err += String(data); });
-    child.on('close', function (code) {
-        clearTimeout(to);
-        callback(code, out, err);
-    });
-    child.on('error', function(err) {
-        clearTimeout(to);
-        callback(1, '', err.stack);
-    });
-};
-
-var local = module.exports.local = function (argv) {
-    return function (fileName, callback) {
-        var output = [];
-        spawnProc(fileName, argv, function (code, out, err) {
-            if (code !== 0) {
-                output.push(out);
-            }
-            output.push(err);
-            callback(output.join('\n'), (code !== 0));
-        }, TIMEOUT);
-    };
-};
-
-var send = function (response, content) {
-    response.writeHeader(200, {"Content-Type": "text/plain"});
-    response.write(content);
-    response.end();
-};
-
-var runTest = function (fileName, args, response, timeoutMilliseconds) {
-    Fs.chmodSync(fileName, '755');
-setTimeout(function () {
-    spawnProc(fileName, args, function(code, out, err) {
-        send(response, JSON.stringify({ returnCode: code, stdout: out, stderr: err }));
-        //Fs.unlink(fileName);
-    }, timeoutMilliseconds);
-}, 100);
-};
-
-var server = function (url, tempDir) {
-    var params = parseURL(url);
-    tempDir = tempDir || '/tmp';
-
-    console.log("Serving http://" + (params.host || '<any>') + ':' + params.port + params.path);
-
-    Http.createServer(function(request, response) {
-        if (request.method === 'POST' && request.url === params.path) {
-            var args = JSON.parse(request.headers.args);
-            var fileName = tempDir + "/test-" + String(Math.random()).substring(2) + ".exe";
-            request.pipe(Fs.createWriteStream(fileName));
-            request.on("end", function() {
-                runTest(fileName, args, response, TIMEOUT);
-            });
-        } else {
-            response.end();
-        }
-    }).listen(params.port, params.host);
-};
-
-/// Main
-
-var usage = function ()
-{
-    console.log(
-        "Usage:\n" +
-        "  TestRunner server [http://][<hostname>][:<port>][/<password>] [tempDir]\n" +
-        "    bind to <port> (default port is 8083) and allow remote execution by anyone\n" +
-        "    providing <password>. <tempDir> will be used for temporary files (default is /tmp)\n" +
-        "    http:// is optional, you can put https:// or penispenispenis:// or whatever you\n" +
-        "    want but only http is supported.\n" +
-        "    To bind to all interfaces, you can omit the hostname, eg: :3333/supersecret\n" +
-        "    and to have the default port, you can provide only the password eg: /secret\n" +
-        "    or the hostname and password, eg:  mycomputer/secret\n" +
-        "    The server will print a line explaining exactly what hostname/port/pass it is\n" +
-        "    serving.\n" +
-        "\n" +
-        "  TestRunner client [http://][<hostname>][:<port>][/<password>] <executable> [argv1, " +
-            "[argv2, ...]]\n" +
-        "    connect to the specified URL and upload <exectable> to be run with\n" +
-        "    arguments <argv1> <argv2> ...\n" +
-        "    the URL has the same semantics as that for the server except the hostname must be\n" +
-        "    specified.");
-};
-
-var main = function (argv)
-{
-    var cli = argv.indexOf("client");
-    if (cli !== -1) {
-        argv.splice(0,cli+1);
-        var cliUrl = argv.shift();
-        var fileName = argv.shift();
-        return client(cliUrl, fileName, argv);
-    }
-    var serv = argv.indexOf("server");
-    if (serv !== -1) {
-        argv.splice(0,serv+1);
-        var servUrl = argv.shift();
-        var tempDir = argv.shift();
-        return server(servUrl, tempDir);
-    }
-    return usage();
-};
-
-if (!module.parent) {
-    main(process.argv);
-}

+ 20 - 29
node_build/builder.js

@@ -39,8 +39,6 @@ export type Builder_Compiler_t = {|
     version: string
 |};
 export type Builder_State_t = {|
-    rebuildIfChanges: string[],
-    rebuildIfChangesHash: string,
     compilerType: Builder_Compiler_t,
     cFiles: { [string]: Builder_File_t },
     hFiles: { [string]: Builder_Hfile_t },
@@ -49,6 +47,7 @@ export type Builder_Linter_t = (string, string, (string, bool)=>void)=>void;
 export type Builder_TestRunnerCb_t = (string, bool)=>void;
 export type Builder_t = {|
     cc: (string[], (number, string, string)=>void)=>void,
+    buildLibrary: (string)=>void,
     buildExecutable: (string, ?string)=>void,
     buildTest: (string)=>string,
     runTest: (string, (string, Builder_TestRunnerCb_t)=>void)=>void,
@@ -76,7 +75,11 @@ export type Builder_Config_t = {
 import type { Nthen_WaitFor_t } from 'nthen';
 import type { Saferphore_t } from 'saferphore';
 export type Builder_Stage_t = (Builder_t, Nthen_WaitFor_t)=>void;
-export type Builder_CompileJob_t = { cFile: string, outputFile: ?string };
+export type Builder_CompileJob_t = {
+    cFile: string,
+    outputFile: ?string,
+    type: 'exe'|'lib'
+};
 export type Builder_PreCtx_t = {
     buildStage: Builder_Stage_t,
     testStage: Builder_Stage_t,
@@ -195,9 +198,6 @@ const cc = function (
 
 const getStatePrototype = function () /*:Builder_State_t*/ {
     return {
-        rebuildIfChanges: [],
-        rebuildIfChangesHash: '',
-
         compilerType: {
             isLLVM: false,
             isClang: false,
@@ -226,13 +226,17 @@ const finalizeCtx = function (
             compiler(ctx, args, callback, '');
         },
 
+        buildLibrary: function (cFile) {
+            ctx.executables.push({ cFile, outputFile: null, type: 'lib' });
+        },
+
         buildExecutable: function (cFile, outputFile) {
-            ctx.executables.push({ cFile, outputFile });
+            ctx.executables.push({ cFile, outputFile, type: 'exe' });
         },
 
         buildTest: function (cFile) {
             const outputFile = getTempExe(ctx, cFile);
-            ctx.executables.push({ cFile, outputFile });
+            ctx.executables.push({ cFile, outputFile, type: 'exe' });
             return outputFile;
         },
 
@@ -839,6 +843,11 @@ module.exports.configure = function (
 
     }).nThen(function (waitFor) {
 
+        if (process.env['CJDNS_FULL_REBUILD']) {
+            debug("CJDNS_FULL_REBUILD set, non-incremental build");
+            return;
+        }
+
         // read out the state if it exists
         Fs.exists(buildDir + '/state.json', waitFor(function (exists) {
             if (!exists) { return; }
@@ -850,15 +859,6 @@ module.exports.configure = function (
             }));
         }));
 
-    }).nThen(function (waitFor) {
-
-        getRebuildIfChangesHash(state.rebuildIfChanges, waitFor(function (rich) {
-            if (rich !== state.rebuildIfChangesHash) {
-                debug("rebuildIfChanges changed, rebuilding everything");
-                state.cFiles = {};
-            }
-        }));
-
     }).nThen(function (waitFor) {
 
         debug("Initialize " + time() + "ms");
@@ -1006,17 +1006,6 @@ const postConfigure = (ctx /*:Builder_Ctx_t*/, time) => {
     const state = ctx.state;
     nThen((waitFor) => {
 
-        if (state.rebuildIfChanges.indexOf(module.parent.filename) === -1) {
-            // Always always rebuild if the makefile was changed.
-            state.rebuildIfChanges.push(module.parent.filename);
-        }
-
-        getRebuildIfChangesHash(state.rebuildIfChanges, waitFor(function (rich) {
-            state.rebuildIfChangesHash = rich;
-        }));
-
-    }).nThen(function (waitFor) {
-
         removeStaleFiles(ctx, waitFor());
 
     }).nThen(function (waitFor) {
@@ -1055,7 +1044,9 @@ const postConfigure = (ctx /*:Builder_Ctx_t*/, time) => {
     }).nThen(function (waitFor) {
         debug("Compile " + time() + "ms");
         for (const exe of ctx.executables) {
-            link(exe.cFile, waitFor(), ctx);
+            if (exe.type === 'exe') {
+                link(exe.cFile, waitFor(), ctx);
+            }
         }
     }).nThen((w) => {
         debug("Link " + time() + "ms");

+ 22 - 67
node_build/make.js

@@ -21,7 +21,6 @@ var Cp = require('./Cp');
 var Spawn = require('child_process').spawn;
 var FindPython = require('./FindPython');
 var Builder = require('./builder');
-var TestRunner = require('./TestRunner');
 const CjdnsTest = require('./CjdnsTest');
 const GetVersion = require('./GetVersion');
 
@@ -30,6 +29,7 @@ var LDFLAGS = process.env['LDFLAGS'];
 var NO_MARCH_FLAG = ['arm', 'ppc', 'ppc64'];
 
 Builder.configure({
+    buildDir:       process.env['OUT_DIR'], // set by cargo
     systemName:     process.env['SYSTEM'] || process.platform,
     gcc:            process.env['CC'],
 }, function (builder, waitFor) {
@@ -48,6 +48,8 @@ Builder.configure({
         '-D', builder.config.systemName + '=1',
         '-Wno-unused-parameter',
         '-fomit-frame-pointer',
+        '-ffunction-sections',
+        '-fdata-sections',
 
         '-D', 'Log_' + (process.env['Log_LEVEL'] || 'DEBUG'),
 
@@ -251,48 +253,17 @@ Builder.configure({
 
     }).nThen(function (waitFor) {
 
-        builder.config.libs.push(dependencyDir + '/cnacl/jsbuild/libnacl.a');
-        builder.config.includeDirs.push(dependencyDir + '/cnacl/jsbuild/include/');
-
-        // needed for Sign.c which pulls in crypto_int32.h
-        builder.config.includeDirs.push(dependencyDir + '/cnacl/jsbuild/include_internal/');
-
-        Fs.exists(dependencyDir + '/cnacl/jsbuild/libnacl.a', waitFor(function (exists) {
-            if (exists) { return; }
-
-            console.log("Build NaCl");
-            var cwd = process.cwd();
-            process.chdir(dependencyDir + '/cnacl/');
-
-            // $FlowFixMe non-static require
-            var NaCl = require(process.cwd() + '/node_build/make.js');
-            NaCl.build(function (args, callback) {
-                if (builder.config.systemName !== 'win32') {
-                    args.unshift('-fPIC');
-                }
-
-                args.unshift(optimizeLevel, '-fomit-frame-pointer');
-
-                if (!/^\-O0$/.test(optimizeLevel)) {
-                    args.unshift('-D_FORTIFY_SOURCE=2');
-                }
-
-                if (CFLAGS) {
-                    [].push.apply(args, CFLAGS.split(' '));
-                }
-
-                if (!builder.config.crossCompiling) {
-                    if (NO_MARCH_FLAG.indexOf(process.arch) == -1) {
-                        args.unshift('-march=native');
-                    }
-                }
-
-                builder.cc(args, callback);
-            },
-            builder.config,
-            waitFor(function () {
-                process.chdir(cwd);
-            }));
+        const profile = process.env.PROFILE || 'debug';
+        Fs.readdir(`./target/${profile}/build/`, waitFor((err, ret) => {
+            if (err) { throw err; }
+            for (const f of ret) {
+                if (!/^libsodium-sys-/.test(f)) { continue; }
+                builder.config.includeDirs.push(
+                    `./target/debug/${profile}/${f}/out/installed/include/`
+                );
+                return;
+            }
+            throw new Error("Unable to find a path to libsodium headers");
         }));
 
     }).nThen(function (waitFor) {
@@ -429,15 +400,15 @@ Builder.configure({
 
 }).build(function (builder, waitFor) {
 
-    builder.buildExecutable('client/cjdroute2.c', 'cjdroute');
+    builder.buildLibrary('client/cjdroute2.c');
 
-    builder.buildExecutable('contrib/c/publictoip6.c');
-    builder.buildExecutable('contrib/c/privatetopublic.c');
-    builder.buildExecutable('contrib/c/sybilsim.c');
-    builder.buildExecutable('contrib/c/makekeys.c');
-    builder.buildExecutable('contrib/c/mkpasswd.c');
+    builder.buildLibrary('contrib/c/publictoip6.c');
+    builder.buildLibrary('contrib/c/privatetopublic.c');
+    builder.buildLibrary('contrib/c/sybilsim.c');
+    builder.buildLibrary('contrib/c/makekeys.c');
+    builder.buildLibrary('contrib/c/mkpasswd.c');
 
-    builder.buildExecutable('crypto/random/randombytes.c');
+    builder.buildLibrary('crypto/random/randombytes.c');
 
     builder.lintFiles(function (fileName, file, callback) {
         if (/dependencies/.test(fileName) || /crypto\/sign/.test(fileName)) {
@@ -448,23 +419,7 @@ Builder.configure({
         Codestyle.lint(fileName, file, callback);
     });
 
-    var testcjdroute = builder.buildTest('test/testcjdroute.c');
-    if (builder.config.crossCompiling) {
-        console.log("Cross compiling. Building, but not running tests.");
-        return;
-    }
-
-    var testRunner = TestRunner.local(['all']);
-    if (process.env['REMOTE_TEST']) {
-        testRunner = TestRunner.remote(process.env['REMOTE_TEST'], ['all']);
-    }
-    if (!process.env['NO_TEST']) {
-        builder.runTest(testcjdroute, testRunner);
-    }
-
-}).success(function (builder, waitFor) {
-
-    console.log('\x1b[1;32mBuild completed successfully, type ./cjdroute to begin setup.\x1b[0m');
+    builder.buildLibrary('test/testcjdroute.c');
 
 }).failure(function (builder, waitFor) {
 

+ 16 - 0
rust/cjdns_sys/Cargo.toml

@@ -0,0 +1,16 @@
+[package]
+name = "cjdns_sys"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+build = "build.rs"
+
+[dependencies]
+sodiumoxide = "0.2"
+
+[build_dependencies]
+## This is also a build dependency in order to be sure it is present when the build script runs
+## because we need to have the headers in order to compile the C code
+sodiumoxide = "0.2"
+cc = "1.0"
+anyhow = "1.0"

+ 71 - 0
rust/cjdns_sys/build.rs

@@ -0,0 +1,71 @@
+use anyhow::{bail, Result};
+use std::env;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+fn cfiles<P: AsRef<Path>>(out: &mut Vec<PathBuf>, path: P) -> Result<()> {
+    for entry in std::fs::read_dir(path)? {
+        let entry = entry?;
+        let p = entry.path();
+        if !p.is_dir() {
+            out.push(p);
+            continue;
+        }
+        let file = p.file_name().unwrap();
+        if file == "target" || file == ".git" || file == "dependencies" {
+            continue;
+        }
+        cfiles(out, p)?;
+    }
+    Ok(())
+}
+
+fn main() -> Result<()> {
+    let ret = Command::new("/bin/sh")
+        .current_dir("../../")
+        .env("MAINJS", "./node_build/make.js")
+        .arg("./node_build/node.sh")
+        .status()?
+        .code()
+        .unwrap();
+    if ret != 0 {
+        bail!("Failed to build cjdns");
+    }
+
+    let mut cf: Vec<PathBuf> = Vec::new();
+    cfiles(&mut cf, "../../")?;
+    for f in cf {
+        println!("cargo:rerun-if-changed={}", f.to_str().unwrap());
+    }
+
+    let out_dir = env::var("OUT_DIR").unwrap();
+
+    //.//target/cjdns_build/dependencies/libuv/out/Release/libuv.a
+    // OR /libuv/out/Release/obj.target/libuv.a
+    let mut ok = false;
+    for x in ["", "/obj.target"].iter() {
+        let p = format!("{}/dependencies/libuv/out/Release{}/libuv.a", out_dir, x);
+        if Path::new(&p).exists() {
+            println!(
+                "cargo:rustc-link-search={}/dependencies/libuv/out/Release{}",
+                out_dir, x);
+            println!("cargo:rustc-link-lib=static=uv");
+            ok = true;
+            break;
+        }
+    }
+    if !ok {
+        panic!("Unable to find libuv");
+    }
+
+    let mut build = cc::Build::new();
+    for entry in std::fs::read_dir(out_dir)? {
+        let entry = entry?;
+        let path = entry.path();
+        if !path.is_dir() && path.extension().unwrap() == "o" {
+            build.object(path);
+        }
+    }
+    build.compile("cjdns-sys.a");
+    Ok(())
+}

+ 19 - 0
rust/cjdns_sys/src/lib.rs

@@ -0,0 +1,19 @@
+#[macro_export]
+macro_rules! c_main {
+    ($cmain:ident) => {
+        use std::ffi::CString;
+        use std::os::raw::c_char;
+        use std::os::raw::c_int;
+        extern "C" {
+            fn $cmain(argc: c_int, argv: *const *mut c_char);
+        }
+        fn main() {
+            sodiumoxide::init().unwrap();
+            let c_args = std::env::args()
+                .map(|arg| CString::new(arg).unwrap())
+                .map(|arg| arg.into_raw())
+                .collect::<Vec<*mut c_char>>();
+            unsafe { $cmain(c_args.len() as c_int, c_args.as_ptr()) }
+        }
+    };
+}

+ 11 - 0
rust/cjdroute/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "cjdroute"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cjdns_sys = { path = "../cjdns_sys" }
+sodiumoxide = "0.2"

+ 1 - 0
rust/cjdroute/src/main.rs

@@ -0,0 +1 @@
+cjdns_sys::c_main!(cjdroute2_main);

+ 11 - 0
rust/makekeys/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "makekeys"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cjdns_sys = { path = "../cjdns_sys" }
+sodiumoxide = "0.2"

+ 1 - 0
rust/makekeys/src/main.rs

@@ -0,0 +1 @@
+cjdns_sys::c_main!(makekeys_main);

+ 11 - 0
rust/mkpasswd/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "mkpasswd"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cjdns_sys = { path = "../cjdns_sys" }
+sodiumoxide = "0.2"

+ 1 - 0
rust/mkpasswd/src/main.rs

@@ -0,0 +1 @@
+cjdns_sys::c_main!(mkpasswd_main);

+ 11 - 0
rust/privatetopublic/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "privatetopublic"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cjdns_sys = { path = "../cjdns_sys" }
+sodiumoxide = "0.2"

+ 1 - 0
rust/privatetopublic/src/main.rs

@@ -0,0 +1 @@
+cjdns_sys::c_main!(privatetopublic_main);

+ 11 - 0
rust/publictoip6/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "publictoip6"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cjdns_sys = { path = "../cjdns_sys" }
+sodiumoxide = "0.2"

+ 1 - 0
rust/publictoip6/src/main.rs

@@ -0,0 +1 @@
+cjdns_sys::c_main!(publictoip6_main);

+ 11 - 0
rust/randombytes/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "randombytes"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cjdns_sys = { path = "../cjdns_sys" }
+sodiumoxide = "0.2"

+ 1 - 0
rust/randombytes/src/main.rs

@@ -0,0 +1 @@
+cjdns_sys::c_main!(randombytes_main);

+ 11 - 0
rust/sybilsim/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "sybilsim"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cjdns_sys = { path = "../cjdns_sys" }
+sodiumoxide = "0.2"

+ 1 - 0
rust/sybilsim/src/main.rs

@@ -0,0 +1 @@
+cjdns_sys::c_main!(sybilsim_main);

+ 11 - 0
rust/testcjdroute/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "testcjdroute"
+version = "0.1.0"
+authors = ["Caleb James DeLisle <cjd@cjdns.fr>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cjdns_sys = { path = "../cjdns_sys" }
+sodiumoxide = "0.2"

+ 1 - 0
rust/testcjdroute/src/main.rs

@@ -0,0 +1 @@
+cjdns_sys::c_main!(testcjdroute_main);

+ 1 - 1
subnode/ReachabilityAnnouncer.c

@@ -24,7 +24,7 @@
 #include "util/Hex.h"
 #include "util/Hash.h"
 
-#include "crypto_hash_sha512.h"
+#include <sodium/crypto_hash_sha512.h>
 
 // This is the time between the timestamp of the newest message and the point where
 // snode and subnode agree to drop messages from the snode state.

+ 1 - 1
test/CryptoAddress_test.c

@@ -20,7 +20,7 @@
 #include "util/Hex.h"
 #include "util/Assert.h"
 
-#include "crypto_scalarmult_curve25519.h"
+#include <sodium/crypto_scalarmult_curve25519.h>
 
 #include <stdio.h>
 

+ 1 - 1
test/testcjdroute.c

@@ -267,7 +267,7 @@ static int main2(int argc, char** argv, struct Allocator* alloc, struct Random*
     return 0;
 }
 
-int main(int argc, char** argv)
+int testcjdroute_main(int argc, char** argv)
 {
     struct Allocator* alloc = MallocAllocator_new(1<<24);
     struct RandomSeed* rs = DeterminentRandomSeed_new(alloc, RANDOM_SEED);