diff --git a/LICENSE.sig b/LICENSE.sig new file mode 100644 index 000000000..b4ebd7e9c --- /dev/null +++ b/LICENSE.sig @@ -0,0 +1,93 @@ +-----BEGIN PGP MESSAGE----- +Version: Keybase OpenPGP v2.0.82 +Comment: https://keybase.io/crypto + +yM9+Anic3Vo9jCRHFV7zY4mTkEDGCQnlkZB3Td+cfdgGnyWk3e2ePXCePXZ2OR+W +QTXd1TPF9XS1q7p3dogMGRkSKRESErYcIhICEEIOwBGJRWRZIkJGZCA5AN579dsz +s3eHyFhZcDPT9erV+/ne91717z/98Z1Lj/z0c4++98RffvHeQ3/8985Olnc73/3R +E6fsfn/7Dc/ngt2UuaiNuHSPJ78ltJGqZleHT2bs67zuuF6xq08++fSFi+Zt21y7 +cmW5XA45bTNUenalsluZK5dw4cnh8csTtj8+YNePxgejk9HReMJuHB2z08lhxo4P +bx0fHZxex68zeupgNDk5Hr1wit+QgKeG7ECUspYtKGeGl5w2A3eiATNzXlVsIXjN +WjhpK/TCMF4XLFd1YVexUmnWGZExLRqtii7HrzMnCp8tpGm1nHb4PeOGFbilKNh0 +xSYit0KeAvladbM5e46pEj5IeE7l3ULU7bpeSm8olqtmpeVs3jK1rIVmoBIslO2K +8a6dKy2/T/s5OdtWtHPeMth0pjksrGf0kLNDooCY8YodkugNJboaD0jaC8ZzkuK1 +ADPAs06MggecglIYuzUYtNWqyhjXwn+oSOkMT4PfdnUBy3K1WKjaSXIPsqVs51aO +3XDIbihNejSdbhRETLRqcLj30cBJGdBRDNuVe3apWgqdgfs0eAmVkLX9d8ZaxXIO +TsfnnBT7E1lAswWv+Uyg83Bf0+Vzp1jGlnNBxwfv076cZKeWWUqMJpCyK0ETco+Z +ywYllbIEazZC5yh695knv7hH2ykwjzW8F9S1pgWrow/ATVoYLxFETkUNRsgluLIn +PdEzuvyO6gZsF9biv/RgL/U6/Ic2OZNFh7I0S+PDCRDnoK00qAjovZDGUMBTnNkk +ILdshNoEdsshBSG9FuuR1mhRCq1hOf1aksXv4hYLVUg4Gqes8g6WdV51ZApIQlar +llVyIXF38KNRZbvE8DK0ITilAOv73CNBTox9IPP5X8pZp+l3cEslEvg4mn4PQmFT +dV6v7Hfgjq6i/Ci1WsCP+ZzXoLVPEIiK2uCT3AcUfVO5jyXjzJqHxGX9AzoZa8eE +tGkkJpQi5dwxZxAJcAb4unfgFL3gpGcWvQ3Ksbm7EIXkrF016bFvK313AxSW8CVp +TDiEkRZTQNb+GCEBrOncsRa8ACA547Li08rnf4JLGaIpBmDOXSjxgAse3cAM8HCA +N2speFiSWXnbYm0hC3ltnYhdOIA454sGdoaFAO0Q5nYhPrnfNAJ2PodkqtRyL1rh +QGh5BlY8EwwNYgbrEYB7bLeBO72TZG3gFZ9yg86rKRUL3AOjH6LHYhVuRe7CXFjO +ZT5PwACc1UINgMzU4kySKzGKwTQuT5gACyvtP4EI5+Y0m5wwrHLCQKSQ9TlspipK +ClgmZ7KGXTZ9vonHHqfKXvpnbN18znoYzc53JN5VDS0WXIb8FA3XFCloFzrGQmhR +rSAP6rtkuClEC8ZJzRdizztdAhDpkudUJLKkRgajbiiF1hGqjF6/jlDuavxWj6/n +QEjZZL9gQJdwvpYGPVBYzycUw4VjIl6SsrahVfD7RcpnSVK0iPoKtq48bJtuCtjh +wMPzDoou0pzUc6lAGxGOb9AK72Uqd/esFilRQVSm7THepwKMWYIpLiYvD1bt2SCc +aeBk2XofYBkWiQoSUCsA4wy9MOUVxdFS47qayEdXO+szzILU6CIaCu3UmpgsZH+T +3bMUBexK94D/ok6AiLLCxRVQSpCWlKxAhczKtGJhUgiHmtsJLCE51Uj3hHU/Vj7L +VgLXSo2eJTDSi4LE2mg34Lh5Z6jK044LwktHI28T4sXSJM69Efpn9fEIRzGNzDvV +GUjeBdd3Efp0ZEeecgkjZzVhP4Qi+ogMuzUSEawGY7A3Z2muDgebKbzGr8OxfQbe +l/KkBkR8XKxtyuagzFRAPAFlFITkoHS6T0xCI17vIH4q3DZXYG9brpHwJulngejq +kL2ItAq3vR6O75kVm3S2uLpY3drMJGmWorKAKskSAzGEENCZWBzxAiCHcEpgeI1o +wTI+/AD6qmIpkWvUqr5MnjdwYvx4GViPnmHjpFa8aleXSy3gkwRid6ZyBPKNau76 +P9zQd1uwAnKswTjeQLoI5003hbVgRQjUpuIQ6OEb0NmWWkPfOGKR9m0pzQ9YTGR5 +Y8ct5ZywxTroy4mDbnEE3f8D7+zCMtG0mGDQcrSeIoGCxjZEe6yxZ028B3QdhM35 +mSCW5xWiPlqVJfI8KAKiAvi1/wuIonRrHRNwwBFlxwoJZvzJ0ATWR35X3jQVtpuq +BqeTlRG7nGp5xSXY2z6bHA6sSEJS6wbcrCF7jeFaUnaWGtDHdzRC+tqXJv6u2YM2 +WNXCVUSAP2AkgdXTsvUF/kC2w3XVFtS3JK+vnNtiia7wtW7IRiX6P/RCBpAKYzo4 +pZUzqwKfcfyZQM417ruxYAVurZUxl8lgeIxcdcif7GfwPGcVX5pOtnjUSsxsEQCL +eeUjJ1hDxXsBHNUEq7hxrXaUk0fnrPyxvD8WxFRBjKVi/Uj0lMk3oy5TfKMRc8yV +PM+qbHXAFEXv+VjhxhO2Ar70wResC9KwTywsFDw9ZMcinQwNaesFX0VkW0chwEHp +uU0Pj+7B8sglSBthsw5AjuIIGQ38vwoVud822xJ+AZJlsRUig8TQWghhvVyqCnoi +W989dl3zdXaX79mTdhBpM9QX1bP9BrhVwhERtFLqG7pD/Ns4KKf6sN5JPE9l1O85 +Tfa0g5tIpbGPwv7dDnU0hhC0D7LGOLHdo0m2R4gLIY0ysXWfkTGEldPfOU921qKF +BMs8b05aeOoOQKP1wyUbhw1jQGSYYbE6Zi66M4TFQiBvyhIyQSHaxnRzZ7MjiC36 +rEMq/kXmZtHTyyDlCkWEFqoMHhPNaTNOt7Fw2ZNsluq+0Yo9BK3gf9f4oasH46OT +0fXDASTfeUv2xrRzeyDlTvZJsyuBgC2ZsmFZ8lciyreeHHzIC+oxY9CJrWZFUOI4 +503EOFAjZLAHoSNkD2LXRMx2C2+1KwUbyKgEN9hOpVN6tyRmKxAj2PSaV5N7HaOt +o4V6UWXuqcPzKZj3gizN6/4Aisky4gyWzFmsgJvylc42rcw910umXK432GKlci1T +iEBAB2idBQJ1cRkPuQq+qXE+Bw0zEgvBoQk9mdsuDPFr08yJv4k82FY6DPmgh4jN +KzKUvjoutwixVr3ZfCgbvCjw3xr7nTQiEyledWehB8mEzFrfgCPSM1E/heONohB1 +0S08be1FjAcW2/95d65jGhnYDzHADFuTiaZV0DNZHqC79fizhrno3mKriWJXQbSV +hvWWAKwNvhJXoBB3jlRlHMlJZK09lruFwcfR3pYrIysmuStS5RZtspg2JTWLqwta +kXQ6F1KJ5OHWyTQvKrBxW9WrwoF14yyZqDTGUW8sEzqVtU6g55BnqNlxNwG2V40s +0AzZaQ1V1JDTxDlslEtsf0lickES5hurdRaZDLOSMdaFo6vI9HHH9UGOpXrTdPr8 +37RmjmaRmknAWBGWuhb+9tGuH6sWF4XbG6ovU2WbMkzbGbV3WEZINdNBOTCiEPYi +CNMgcYnbyLILOyAFK4aWaAY9HQX+ymUIdWTiXOQJxBPwBoNoMePa3iut9x7uLuBZ +gEJPQAzCYsKjC0XI2VrKndwIoeHdhZqlL/4agy9wbhYYDU69hD7Dmb77CDq5GLYP ++6D1GvtIiW2qFq930t0eYUE34BMs6eRSKPxqgdfTqA1YGXhHDgd0rghNB05qN+az +Ppu831w12FICrKW+MmQH0lDrhJe2JbsN/BPssgpJEFSdrmwDS503tlgRBsiL1LzE +KVgWHeZy30RVd1FXHBqst6jp0zi+7Dl3D+daAPmD/QkbTQbshf3JaOKNe3t08tLR +6Qm7vX98vD8+GR1O2NFxei1/dIPtj++wb4zGB0B3pL0BPsfpqIknkYQrRTImjRlE +c1LucWoFTS6ZihoivQmxYMyT0cnNwwysPr48Gt84Ho1fPHz5cHySsZcPj6+/BFru +vzC6OTq5QyF0Y3QyPpzY1wf2nYxb+8fgsNOb+8fs1unxraPJoa229rawwpsF0L+B +TSXdOtDNjO0K++ECntOq0RLpOR24hOjCRyj+IuIm81I7bTQGOBEe18O1NITsRuUy +tMkW1N09K01j04vWzWbWxt5Xh/DZmxQX3ZR8Kiu6PB9h5WVAf+qW9LAy4KuKhp2g +I3TayajF32RBALXpyKAWs0oC+8rFXhZuu7PeKDdMfu4b77uWKOBMv5JTInSk3Azn +EeHewm/Z4hsIhm7Ht+eHRc9e+cChjHdZJWljNxEg1/IFn/Vn+LjavxIQXw4wjcC7 +9eT2GRIKiK29SkACY2e6eCHnhHqExpkb6I3jam3vzLGKh1qNt8brjS5ZswsY09lv +ZO2cmeBqOjHYveeduNcKj10pG7AzpYqlrNLZ4V0oyqppOE4JkRN0qHjJZdVpW414 +VXZ1JDdUBLe8CYK3ABi8qT3sxsJA4GAcIkFfH8Q5GWGYzoszSZekpXt9AzLAGcG/ +3ODE2wx4bsj2c6wJaAWPvLjzfizUSVLcniN176fr+mXhPa/bPAvN50rZKShNOnuX +7TRzBd5WCsITgDrSkNe5sIdo7BjUod+K4k4sany1JA7ErFkrrztT08pNoYi3XEHY +QeZrr1rgPJgvrr+SHkFDg/GSWmInZFvJYDCyZyI4no/eaKmr5DYkcG53LUJDXPc1 +AmmEUdKXmE68RYmIHidFSRi4mTD2TLK0+IwJb/OdbFMG2xSihHbFrgBmXGwZnXO9 +ICTy5DpYMaZzp3W8LXOTY8Bk6MqxWbVD1GxzbjxdObIRD7RCC0SbBjK/TKIxoY1B +FxvAh+MDrKvbXoOj3/dv3YJHRq9cQxfStAAQdeVeX0hf3cPfSJVluEuCv5MHXJC5 +1yj60wRPqxVkjYY2vPVTjSx28qUUVWEYFAhIdgv6U7ylFBCZg1dfGwTgo8mEq3Yr +H0yEqq7rSzrpIds9UPXj4X2BJEe98Mf2GHXr1KYaoBcQCUDxgx6uO0jKdnI3i7li +VoDn5+EilJp6qwDgBCysDF5Q2afdnNSjOD1r4waiDBmrbbuIZja+GPur1amIr6zQ +DanXxODCAShHg2vE4AHWiv7Np3v5BdWEwJPhPt5Zzt+7hvFMHHJwnc/xxtoGQ7xM +fHUFf6+xV0lv0HPtlvU1etwFSZH0TP3wydIXQtkuPhDeudx7HkX4fgSBwJYvNz73 +NF7Wrg0laAwRFSgOi12/mtK0jPdGdj6QeevD/X6vnN4E7j6eHF4GlWnJgzD0i7iH +e+cMxSQjtc03nPDSIH3gIgb+P9JvT7zJbBMheir4ICdaAzEDR6tnHQQcUAIoC/X6 +m31uWhL5utk81/DS777ziZ1HLu08/MmP4avGO5c+9Rn/DvIP3n1o551ff/DPX5U/ +fuPDxx9+p/nC57/00dt/evTNvff/cfuts1fe/tubf9/512Pv/fxn+VPffOOHj/7k +rY+e/e1vvnbnz1+9+uG7337/zod//ewHv/zDfwC38yMP +=Utyb +-----END PGP MESSAGE----- diff --git a/media/dependencies.png b/media/dependencies.png index 3c7dc287d..a1f5acd90 100644 Binary files a/media/dependencies.png and b/media/dependencies.png differ diff --git a/nix/generated/node-packages.nix b/nix/generated/node-packages.nix index 5ea5f30ab..7d59a7e8a 100644 --- a/nix/generated/node-packages.nix +++ b/nix/generated/node-packages.nix @@ -499,6 +499,15 @@ let sha512 = "4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="; }; }; + "@multiformats/base-x-4.0.1" = { + name = "_at_multiformats_slash_base-x"; + packageName = "@multiformats/base-x"; + version = "4.0.1"; + src = fetchurl { + url = "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz"; + sha512 = "eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw=="; + }; + }; "@nodelib/fs.scandir-2.1.3" = { name = "_at_nodelib_slash_fs.scandir"; packageName = "@nodelib/fs.scandir"; @@ -1363,6 +1372,24 @@ let sha512 = "2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA=="; }; }; + "@xstate/graph-1.2.0" = { + name = "_at_xstate_slash_graph"; + packageName = "@xstate/graph"; + version = "1.2.0"; + src = fetchurl { + url = "https://registry.npmjs.org/@xstate/graph/-/graph-1.2.0.tgz"; + sha512 = "6h8ZRmnHsg1BW2NmkM2gb1l6bJwi6SaSLi7ErFzzseLKmcQL2oWBSjHJdsdYMuD2DXFsnHbVi3WqsQE++R7nmA=="; + }; + }; + "@xstate/test-0.4.1" = { + name = "_at_xstate_slash_test"; + packageName = "@xstate/test"; + version = "0.4.1"; + src = fetchurl { + url = "https://registry.npmjs.org/@xstate/test/-/test-0.4.1.tgz"; + sha512 = "N8xEWcnWPVVpRkVgGGhpHGTJKLnm2UyGqkvk7eNaMqWdcg8fT6SyRSLtzJuqtJe8wZviScTr7P71Yp1cLawDWg=="; + }; + }; "@xtuc/ieee754-1.2.0" = { name = "_at_xtuc_slash_ieee754"; packageName = "@xtuc/ieee754"; @@ -2812,6 +2839,15 @@ let sha1 = "7bde5ced145b6d551a90db87f83c558b4eb48a8f"; }; }; + "base-x-3.0.8" = { + name = "base-x"; + packageName = "base-x"; + version = "3.0.8"; + src = fetchurl { + url = "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz"; + sha512 = "Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA=="; + }; + }; "base64-js-1.3.0" = { name = "base64-js"; packageName = "base64-js"; @@ -2875,6 +2911,15 @@ let sha1 = "37ee70b2ff04208912bf124248d47e89d71eeb28"; }; }; + "blakejs-1.1.0" = { + name = "blakejs"; + packageName = "blakejs"; + version = "1.1.0"; + src = fetchurl { + url = "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz"; + sha1 = "69df92ef953aa88ca51a32df6ab1c54a155fc7a5"; + }; + }; "bluebird-3.7.2" = { name = "bluebird"; packageName = "bluebird"; @@ -3424,6 +3469,15 @@ let sha512 = "5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="; }; }; + "cids-1.0.1" = { + name = "cids"; + packageName = "cids"; + version = "1.0.1"; + src = fetchurl { + url = "https://registry.npmjs.org/cids/-/cids-1.0.1.tgz"; + sha512 = "A5DvnNMr7ABdP3IWFPEdbpued8Sw2cHu6n4+Hke9MpzEqhQH74Pm6Zk2TB59aNHIuue1Oh/jZi/t0wgISWgOow=="; + }; + }; "cipher-base-1.0.4" = { name = "cipher-base"; packageName = "cipher-base"; @@ -3433,6 +3487,15 @@ let sha1 = "8760e4ecc272f4c363532f926d874aae2c1397de"; }; }; + "class-is-1.1.0" = { + name = "class-is"; + packageName = "class-is"; + version = "1.1.0"; + src = fetchurl { + url = "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz"; + sha512 = "rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw=="; + }; + }; "class-utils-0.3.6" = { name = "class-utils"; packageName = "class-utils"; @@ -4279,6 +4342,15 @@ let sha512 = "TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA=="; }; }; + "detect-node-2.0.4" = { + name = "detect-node"; + packageName = "detect-node"; + version = "2.0.4"; + src = fetchurl { + url = "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz"; + sha512 = "ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw=="; + }; + }; "detective-4.7.1" = { name = "detective"; packageName = "detective"; @@ -7195,6 +7267,15 @@ let sha512 = "YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ=="; }; }; + "js-sha3-0.8.0" = { + name = "js-sha3"; + packageName = "js-sha3"; + version = "0.8.0"; + src = fetchurl { + url = "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz"; + sha512 = "gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="; + }; + }; "js-tokens-3.0.2" = { name = "js-tokens"; packageName = "js-tokens"; @@ -7483,6 +7564,15 @@ let sha512 = "KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="; }; }; + "k-bucket-5.0.0" = { + name = "k-bucket"; + packageName = "k-bucket"; + version = "5.0.0"; + src = fetchurl { + url = "https://registry.npmjs.org/k-bucket/-/k-bucket-5.0.0.tgz"; + sha512 = "r/q+wV/Kde62/tk+rqyttEJn6h0jR7x+incdMVSYTqK73zVxVrzJa70kJL49cIKen8XjIgUZKSvk8ktnrQbK4w=="; + }; + }; "kbpgp-2.0.82" = { name = "kbpgp"; packageName = "kbpgp"; @@ -8617,6 +8707,60 @@ let sha512 = "xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg=="; }; }; + "multibase-0.7.0" = { + name = "multibase"; + packageName = "multibase"; + version = "0.7.0"; + src = fetchurl { + url = "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz"; + sha512 = "TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg=="; + }; + }; + "multibase-3.0.1" = { + name = "multibase"; + packageName = "multibase"; + version = "3.0.1"; + src = fetchurl { + url = "https://registry.npmjs.org/multibase/-/multibase-3.0.1.tgz"; + sha512 = "MRU5WpnSg81/vYO977MweoeUAxBdXl7+F5Af2Es+X6Vcgfk/g/EjIqXTgm3kb+xO3m1Kzr+aIV14oRX7nv5Z9w=="; + }; + }; + "multicodec-2.0.1" = { + name = "multicodec"; + packageName = "multicodec"; + version = "2.0.1"; + src = fetchurl { + url = "https://registry.npmjs.org/multicodec/-/multicodec-2.0.1.tgz"; + sha512 = "YDYeWn9iGa76hOHAyyZa0kbt3tr5FLg1ZXUHrZUJltjnxxdbTIbHnxWLd2zTcMOjdT3QyO+Xs4bQgJUcC2RWUA=="; + }; + }; + "multihashes-0.4.21" = { + name = "multihashes"; + packageName = "multihashes"; + version = "0.4.21"; + src = fetchurl { + url = "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz"; + sha512 = "uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw=="; + }; + }; + "multihashes-3.0.1" = { + name = "multihashes"; + packageName = "multihashes"; + version = "3.0.1"; + src = fetchurl { + url = "https://registry.npmjs.org/multihashes/-/multihashes-3.0.1.tgz"; + sha512 = "fFY67WOtb0359IjDZxaCU3gJILlkwkFbxbwrK9Bej5+NqNaYztzLOj8/NgMNMg/InxmhK+Uu8S/U4EcqsHzB7Q=="; + }; + }; + "multihashing-0.3.3" = { + name = "multihashing"; + packageName = "multihashing"; + version = "0.3.3"; + src = fetchurl { + url = "https://registry.npmjs.org/multihashing/-/multihashing-0.3.3.tgz"; + sha512 = "jXVWf5uqnZUhc1mLFPWOssuOpkj/A/vVLKrtEscD1PzSLobXYocBy9Gqa/Aw4229/heGnl0RBHU3cD53MbHUig=="; + }; + }; "multimatch-4.0.0" = { name = "multimatch"; packageName = "multimatch"; @@ -12433,6 +12577,24 @@ let sha1 = "1f7154202f2a1b8af353871dda651bf34ce93e95"; }; }; + "uint8arrays-1.0.0" = { + name = "uint8arrays"; + packageName = "uint8arrays"; + version = "1.0.0"; + src = fetchurl { + url = "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.0.0.tgz"; + sha512 = "14tqEVujDREW7YwonSZZwLvo7aFDfX7b6ubvM/U7XvZol+CC/LbhaX/550VlWmhddAL9Wou1sxp0Of3tGqXigg=="; + }; + }; + "uint8arrays-1.1.0" = { + name = "uint8arrays"; + packageName = "uint8arrays"; + version = "1.1.0"; + src = fetchurl { + url = "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz"; + sha512 = "cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA=="; + }; + }; "unc-path-regex-0.1.2" = { name = "unc-path-regex"; packageName = "unc-path-regex"; @@ -12757,6 +12919,15 @@ let sha1 = "1c243a50b595c1be54a754bfece8563b9ff8d813"; }; }; + "varint-5.0.2" = { + name = "varint"; + packageName = "varint"; + version = "5.0.2"; + src = fetchurl { + url = "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz"; + sha512 = "lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow=="; + }; + }; "vary-1.1.2" = { name = "vary"; packageName = "vary"; @@ -12928,6 +13099,24 @@ let sha512 = "+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA=="; }; }; + "web-encoding-1.0.4" = { + name = "web-encoding"; + packageName = "web-encoding"; + version = "1.0.4"; + src = fetchurl { + url = "https://registry.npmjs.org/web-encoding/-/web-encoding-1.0.4.tgz"; + sha512 = "DcXs2lbVPzuJmn2kuDEwul2oZg7p4YMa5J2f0YzsOBHaAnBYGPNUB/rJ74DTjTKpw7F0+lSsVM8sFHE2UyBixg=="; + }; + }; + "webcrypto-0.1.1" = { + name = "webcrypto"; + packageName = "webcrypto"; + version = "0.1.1"; + src = fetchurl { + url = "https://registry.npmjs.org/webcrypto/-/webcrypto-0.1.1.tgz"; + sha512 = "BAvoatS38TbHdyt42ECLroi27NmDh5iea5l5rHC6nZTZjlbJlndrT0FoIiEq7fmPHpmNtP0lMFKVMEKZQFIrGA=="; + }; + }; "webidl-conversions-4.0.2" = { name = "webidl-conversions"; packageName = "webidl-conversions"; @@ -13198,6 +13387,15 @@ let sha512 = "JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="; }; }; + "xstate-4.13.0" = { + name = "xstate"; + packageName = "xstate"; + version = "4.13.0"; + src = fetchurl { + url = "https://registry.npmjs.org/xstate/-/xstate-4.13.0.tgz"; + sha512 = "UnUJJzP2KTPqnmxIoD/ymXtpy/hehZnUlO6EXqWC/72XkPb15p9Oz/X4WhS3QE+by7NP+6b5bCi/GTGFzm5D+A=="; + }; + }; "xtend-4.0.1" = { name = "xtend"; packageName = "xtend"; @@ -13578,6 +13776,7 @@ let ]; }) sources."@jsdevtools/ono-7.1.3" + sources."@multiformats/base-x-4.0.1" sources."@nodelib/fs.scandir-2.1.3" sources."@nodelib/fs.stat-2.0.3" sources."@nodelib/fs.walk-1.2.4" @@ -13722,6 +13921,15 @@ let sources."@webassemblyjs/wasm-parser-1.9.0" sources."@webassemblyjs/wast-parser-1.9.0" sources."@webassemblyjs/wast-printer-1.9.0" + sources."@xstate/graph-1.2.0" + (sources."@xstate/test-0.4.1" // { + dependencies = [ + sources."ansi-styles-3.2.1" + sources."chalk-2.4.2" + sources."has-flag-3.0.0" + sources."supports-color-5.5.0" + ]; + }) sources."@xtuc/ieee754-1.2.0" sources."@xtuc/long-4.2.2" sources."JSONStream-1.3.4" @@ -13802,12 +14010,6 @@ let sources."arrify-2.0.1" sources."asn1-0.2.4" sources."asn1.js-4.10.1" - (sources."assert-1.5.0" // { - dependencies = [ - sources."inherits-2.0.1" - sources."util-0.10.3" - ]; - }) sources."assert-plus-1.0.0" sources."assign-symbols-1.0.0" sources."astral-regex-1.0.0" @@ -13967,6 +14169,7 @@ let sources."kind-of-6.0.2" ]; }) + sources."base-x-3.0.8" sources."base64-js-1.3.0" (sources."bcrypt-pbkdf-1.0.2" // { dependencies = [ @@ -13978,6 +14181,7 @@ let sources."binary-extensions-1.11.0" sources."bindings-1.5.0" sources."bitset-5.0.3" + sources."blakejs-1.1.0" sources."bluebird-3.7.2" sources."bn-1.0.1" sources."bn.js-4.11.8" @@ -14056,7 +14260,9 @@ let sources."character-reference-invalid-1.1.2" sources."chownr-1.1.4" sources."chrome-trace-event-1.0.2" + sources."cids-1.0.1" sources."cipher-base-1.0.4" + sources."class-is-1.1.0" (sources."class-utils-0.3.6" // { dependencies = [ sources."define-property-0.2.5" @@ -14204,6 +14410,7 @@ let sources."detect-file-1.0.0" sources."detect-indent-4.0.0" sources."detect-newline-3.1.0" + sources."detect-node-2.0.4" sources."detective-4.7.1" sources."diagnostics-1.1.1" (sources."dicer-0.2.5" // { @@ -15212,6 +15419,7 @@ let }) sources."jmespath-0.15.0" sources."joycon-2.2.5" + sources."js-sha3-0.8.0" sources."js-tokens-3.0.2" sources."js-yaml-3.14.0" sources."jsbn-0.1.1" @@ -15247,6 +15455,7 @@ let sources."jsprim-1.4.1" sources."jwa-2.0.0" sources."jws-4.0.0" + sources."k-bucket-5.0.0" (sources."kbpgp-2.0.82" // { dependencies = [ sources."deep-equal-1.0.1" @@ -15424,6 +15633,19 @@ let sources."mri-1.1.4" sources."ms-2.0.0" sources."multer-1.4.2" + sources."multibase-3.0.1" + (sources."multicodec-2.0.1" // { + dependencies = [ + sources."uint8arrays-1.0.0" + ]; + }) + sources."multihashes-3.0.1" + (sources."multihashing-0.3.3" // { + dependencies = [ + sources."multibase-0.7.0" + sources."multihashes-0.4.21" + ]; + }) sources."multimatch-4.0.0" (sources."mv-2.1.1" // { dependencies = [ @@ -15449,6 +15671,12 @@ let sources."node-int64-0.4.0" (sources."node-libs-browser-2.2.1" // { dependencies = [ + (sources."assert-1.5.0" // { + dependencies = [ + sources."inherits-2.0.1" + sources."util-0.10.3" + ]; + }) sources."buffer-4.9.2" sources."process-0.11.10" sources."punycode-1.4.1" @@ -16152,6 +16380,7 @@ let sources."uid-safe-2.1.5" sources."uid2-0.0.3" sources."uint64be-1.0.1" + sources."uint8arrays-1.1.0" sources."unc-path-regex-0.1.2" sources."unherit-1.1.1" sources."unified-6.2.0" @@ -16207,6 +16436,7 @@ let }) sources."validate-npm-package-license-3.0.4" sources."value-or-function-3.0.0" + sources."varint-5.0.2" sources."vary-1.1.2" sources."verror-1.10.0" sources."vfile-2.3.0" @@ -16313,6 +16543,8 @@ let sources."upath-1.2.0" ]; }) + sources."web-encoding-1.0.4" + sources."webcrypto-0.1.1" sources."webidl-conversions-4.0.2" (sources."webpack-4.43.0" // { dependencies = [ @@ -16463,6 +16695,7 @@ let sources."xdg-basedir-4.0.0" sources."xml-name-validator-3.0.0" sources."xmlchars-2.2.0" + sources."xstate-4.13.0" sources."xtend-4.0.1" sources."y18n-3.2.1" sources."yallist-2.1.2" diff --git a/openapi.yaml b/openapi.yaml index 1964ba34e..f855f02bf 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -46,7 +46,7 @@ paths: "200": description: Certificate Chain content: - application/json: + text/plain: schema: type: array items: @@ -97,7 +97,7 @@ paths: "200": description: Vault List content: - application/json: + text/plain: schema: type: array items: @@ -129,7 +129,7 @@ paths: "200": description: Secret List content: - application/json: + text/plain: schema: type: array items: @@ -206,6 +206,10 @@ paths: text/plain: schema: type: string + application/octet-stream: + schema: + type: string + format: binary "401": description: Not authenticated "403": @@ -222,11 +226,15 @@ paths: - bearerAuth: [admin, write_secrets] - OAuth2-Client: [admin, write_secrets] requestBody: - description: Object describing the secret + description: Secret content content: text/plain: schema: type: string + application/octet-stream: + schema: + type: string + format: binary responses: "200": description: Secret was created successfully diff --git a/package-lock.json b/package-lock.json index d7259af7b..6f9b7a0f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1549,6 +1549,11 @@ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" }, + "@multiformats/base-x": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz", + "integrity": "sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==" + }, "@nodelib/fs.scandir": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", @@ -2508,6 +2513,59 @@ "@xtuc/long": "4.2.2" } }, + "@xstate/graph": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xstate/graph/-/graph-1.2.0.tgz", + "integrity": "sha512-6h8ZRmnHsg1BW2NmkM2gb1l6bJwi6SaSLi7ErFzzseLKmcQL2oWBSjHJdsdYMuD2DXFsnHbVi3WqsQE++R7nmA==", + "dev": true + }, + "@xstate/test": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@xstate/test/-/test-0.4.1.tgz", + "integrity": "sha512-N8xEWcnWPVVpRkVgGGhpHGTJKLnm2UyGqkvk7eNaMqWdcg8fT6SyRSLtzJuqtJe8wZviScTr7P71Yp1cLawDWg==", + "dev": true, + "requires": { + "@xstate/graph": "^1.1.0", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -3035,40 +3093,12 @@ "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -4396,6 +4426,14 @@ } } }, + "base-x": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", @@ -4450,6 +4488,11 @@ "resolved": "https://registry.npmjs.org/bitset/-/bitset-5.0.3.tgz", "integrity": "sha1-N+5wsv8EIIkSvxJCSNR+idce6yg=" }, + "blakejs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -4464,8 +4507,7 @@ "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", - "dev": true + "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=" }, "body": { "version": "5.1.0", @@ -4491,8 +4533,7 @@ "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, "browser-process-hrtime": { "version": "1.0.0", @@ -4521,7 +4562,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, "requires": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -4535,7 +4575,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, "requires": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", @@ -4546,7 +4585,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, "requires": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", @@ -4557,8 +4595,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -4566,7 +4603,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, "requires": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" @@ -4576,7 +4612,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, "requires": { "bn.js": "^4.1.1", "browserify-rsa": "^4.0.0", @@ -4658,8 +4693,7 @@ "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, "builtin-modules": { "version": "1.1.1", @@ -4941,16 +4975,32 @@ "tslib": "^1.9.0" } }, + "cids": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cids/-/cids-1.0.1.tgz", + "integrity": "sha512-A5DvnNMr7ABdP3IWFPEdbpued8Sw2cHu6n4+Hke9MpzEqhQH74Pm6Zk2TB59aNHIuue1Oh/jZi/t0wgISWgOow==", + "requires": { + "class-is": "^1.1.0", + "multibase": "^3.0.1", + "multicodec": "^2.0.1", + "multihashes": "^3.0.1", + "uint8arrays": "^1.1.0" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, + "class-is": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -5588,7 +5638,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, "requires": { "bn.js": "^4.1.0", "elliptic": "^6.0.0" @@ -5598,7 +5647,6 @@ "version": "1.2.0", "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, "requires": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -5611,7 +5659,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -5620,14 +5667,12 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "sha.js": { "version": "2.4.11", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -5639,7 +5684,6 @@ "version": "1.1.7", "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, "requires": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -5653,7 +5697,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -5662,14 +5705,12 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "sha.js": { "version": "2.4.11", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -5692,7 +5733,6 @@ "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, "requires": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", @@ -5894,7 +5934,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, "requires": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" @@ -5935,6 +5974,11 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==" + }, "detective": { "version": "4.7.1", "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", @@ -6009,7 +6053,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, "requires": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", @@ -6767,7 +6810,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -7471,7 +7513,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, "requires": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -9088,7 +9129,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -9097,8 +9137,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, @@ -9106,7 +9145,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "dev": true, "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -9168,7 +9206,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, "requires": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -12744,6 +12781,11 @@ "integrity": "sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ==", "dev": true }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -12973,6 +13015,14 @@ "safe-buffer": "^5.0.1" } }, + "k-bucket": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/k-bucket/-/k-bucket-5.0.0.tgz", + "integrity": "sha512-r/q+wV/Kde62/tk+rqyttEJn6h0jR7x+incdMVSYTqK73zVxVrzJa70kJL49cIKen8XjIgUZKSvk8ktnrQbK4w==", + "requires": { + "randombytes": "^2.0.3" + } + }, "kbpgp": { "version": "2.0.82", "resolved": "https://registry.npmjs.org/kbpgp/-/kbpgp-2.0.82.tgz", @@ -13429,7 +13479,6 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -13439,14 +13488,12 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -13601,7 +13648,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, "requires": { "bn.js": "^4.0.0", "brorand": "^1.0.1" @@ -13647,14 +13693,12 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=", - "dev": true + "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=" }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { "version": "3.0.4", @@ -13995,6 +14039,77 @@ "xtend": "^4.0.0" } }, + "multibase": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.0.1.tgz", + "integrity": "sha512-MRU5WpnSg81/vYO977MweoeUAxBdXl7+F5Af2Es+X6Vcgfk/g/EjIqXTgm3kb+xO3m1Kzr+aIV14oRX7nv5Z9w==", + "requires": { + "@multiformats/base-x": "^4.0.1", + "web-encoding": "^1.0.2" + } + }, + "multicodec": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-2.0.1.tgz", + "integrity": "sha512-YDYeWn9iGa76hOHAyyZa0kbt3tr5FLg1ZXUHrZUJltjnxxdbTIbHnxWLd2zTcMOjdT3QyO+Xs4bQgJUcC2RWUA==", + "requires": { + "uint8arrays": "1.0.0", + "varint": "^5.0.0" + }, + "dependencies": { + "uint8arrays": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.0.0.tgz", + "integrity": "sha512-14tqEVujDREW7YwonSZZwLvo7aFDfX7b6ubvM/U7XvZol+CC/LbhaX/550VlWmhddAL9Wou1sxp0Of3tGqXigg==", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + } + } + }, + "multihashes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-3.0.1.tgz", + "integrity": "sha512-fFY67WOtb0359IjDZxaCU3gJILlkwkFbxbwrK9Bej5+NqNaYztzLOj8/NgMNMg/InxmhK+Uu8S/U4EcqsHzB7Q==", + "requires": { + "multibase": "^3.0.0", + "uint8arrays": "^1.0.0", + "varint": "^5.0.0" + } + }, + "multihashing": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/multihashing/-/multihashing-0.3.3.tgz", + "integrity": "sha512-jXVWf5uqnZUhc1mLFPWOssuOpkj/A/vVLKrtEscD1PzSLobXYocBy9Gqa/Aw4229/heGnl0RBHU3cD53MbHUig==", + "requires": { + "blakejs": "^1.1.0", + "js-sha3": "~0.8.0", + "multihashes": "~0.4.14", + "webcrypto": "~0.1.1" + }, + "dependencies": { + "multibase": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", + "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", + "requires": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "multihashes": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", + "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", + "requires": { + "buffer": "^5.5.0", + "multibase": "^0.7.0", + "varint": "^5.0.0" + } + } + } + }, "multimatch": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", @@ -14163,6 +14278,33 @@ "vm-browserify": "^1.0.1" }, "dependencies": { + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, "buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", @@ -14739,7 +14881,6 @@ "version": "5.1.5", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", - "dev": true, "requires": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", @@ -14942,7 +15083,6 @@ "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "dev": true, "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -14954,14 +15094,12 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "sha.js": { "version": "2.4.11", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -15363,7 +15501,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, "requires": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", @@ -15376,8 +15513,7 @@ "safe-buffer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" } } }, @@ -15445,7 +15581,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -15454,7 +15589,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, "requires": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" @@ -16027,7 +16161,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -16036,8 +16169,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, @@ -18517,6 +18649,15 @@ "resolved": "https://registry.npmjs.org/uint64be/-/uint64be-1.0.1.tgz", "integrity": "sha1-H3FUIC8qG4rzU4cd2mUb80zpPpU=" }, + "uint8arrays": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz", + "integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==", + "requires": { + "multibase": "^3.0.0", + "web-encoding": "^1.0.2" + } + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -18846,6 +18987,11 @@ "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, + "varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -19529,6 +19675,20 @@ } } }, + "web-encoding": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.0.4.tgz", + "integrity": "sha512-DcXs2lbVPzuJmn2kuDEwul2oZg7p4YMa5J2f0YzsOBHaAnBYGPNUB/rJ74DTjTKpw7F0+lSsVM8sFHE2UyBixg==" + }, + "webcrypto": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/webcrypto/-/webcrypto-0.1.1.tgz", + "integrity": "sha512-BAvoatS38TbHdyt42ECLroi27NmDh5iea5l5rHC6nZTZjlbJlndrT0FoIiEq7fmPHpmNtP0lMFKVMEKZQFIrGA==", + "requires": { + "crypto-browserify": "^3.10.0", + "detect-node": "^2.0.3" + } + }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -20540,6 +20700,12 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "xstate": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/xstate/-/xstate-4.13.0.tgz", + "integrity": "sha512-UnUJJzP2KTPqnmxIoD/ymXtpy/hehZnUlO6EXqWC/72XkPb15p9Oz/X4WhS3QE+by7NP+6b5bCi/GTGFzm5D+A==", + "dev": true + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index 96e99b6cb..528b244f2 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "async-mutex": "^0.2.4", "bunyan": "^1.8.14", "chalk": "^4.0.0", + "cids": "^1.0.1", "commander": "^5.1.0", "configstore": "^5.0.1", "encryptedfs": "^1.0.2", @@ -65,7 +66,9 @@ "isomorphic-git": "^1.7.4", "js-yaml": "^3.3.0", "jsonwebtoken": "^8.5.1", + "k-bucket": "^5.0.0", "kbpgp": "^2.0.82", + "multihashing": "^0.3.3", "node-forge": "^0.9.1", "oauth2orize": "^1.11.0", "pako": "^1.0.11", @@ -98,6 +101,7 @@ "@types/swagger-ui-express": "^4.1.2", "@types/uuid": "^8.3.0", "@types/webpack": "^4.41.21", + "@xstate/test": "^0.4.1", "arkit": "^1.6.4", "copy-webpack-plugin": "^6.0.2", "documentation": "^8.1.2", @@ -119,7 +123,8 @@ "typescript": "^3.8.3", "webpack": "^4.42.1", "webpack-cli": "^3.3.11", - "webpack-node-externals": "^1.7.2" + "webpack-node-externals": "^1.7.2", + "xstate": "^4.13.0" }, "bugs": { "url": "https://github.com/MatrixAI/js-polykey/issues" diff --git a/proto/Agent.proto b/proto/Agent.proto index f800e39cb..3e481d98b 100644 --- a/proto/Agent.proto +++ b/proto/Agent.proto @@ -29,6 +29,7 @@ service Agent { rpc ListPeers (EmptyMessage) returns (StringListMessage) {}; rpc ListSecrets (StringMessage) returns (StringListMessage) {}; rpc ListVaults (EmptyMessage) returns (StringListMessage) {}; + rpc LockNode (EmptyMessage) returns (EmptyMessage) {}; rpc NewClientCertificate (NewClientCertificateMessage) returns (NewClientCertificateMessage) {}; rpc NewNode (NewNodeMessage) returns (BooleanMessage) {}; rpc NewSecret (SecretContentMessage) returns (BooleanMessage) {}; @@ -36,14 +37,12 @@ service Agent { rpc NewVault (StringMessage) returns (BooleanMessage) {}; rpc PingPeer (ContactPeerMessage) returns (BooleanMessage) {}; rpc PullVault (VaultPathMessage) returns (BooleanMessage) {}; - rpc RegisterNode (StringMessage) returns (BooleanMessage) {}; rpc RevokeOAuthToken (StringMessage) returns (BooleanMessage) {}; - rpc RequestHolePunch (StringMessage) returns (BooleanMessage) {}; - rpc RequestRelay (StringMessage) returns (BooleanMessage) {}; rpc ScanVaultNames (StringMessage) returns (StringListMessage) {}; rpc SignFile (SignFileMessage) returns (StringMessage) {}; rpc StopAgent (EmptyMessage) returns (BooleanMessage) {}; rpc ToggleStealthMode (BooleanMessage) returns (BooleanMessage) {}; + rpc UnlockNode (UnlockNodeMessage) returns (BooleanMessage) {}; rpc UpdateLocalPeerInfo (PeerInfoMessage) returns (BooleanMessage) {}; rpc UpdatePeerInfo (PeerInfoMessage) returns (BooleanMessage) {}; rpc UpdateSecret (SecretContentMessage) returns (BooleanMessage) {}; @@ -63,7 +62,7 @@ message StringListMessage { // === PeerInfo === // message PeerInfoMessage { string public_key = 1; - string relay_public_key = 2; + string root_certificate = 2; string peer_address = 3; string api_address = 4; } @@ -82,14 +81,12 @@ message AgentStatusMessage { message NewNodeMessage { string userId = 1; string passphrase = 2; - int32 nbits = 3; } // ==== DeriveKey ==== // message DeriveKeyMessage { - string vault_name = 1; - string key_name = 2; - string passphrase = 3; + string key_name = 1; + string passphrase = 2; } // ==== SignFile ==== // @@ -149,6 +146,12 @@ message ContactPeerMessage { int32 timeout = 2; } +// === UnlockNode === // +message UnlockNodeMessage { + string passphrase = 1; + int32 timeout = 2; +} + // === ContactPeer === // message NewClientCertificateMessage { string domain = 1; diff --git a/proto/Peer.proto b/proto/Peer.proto index 691dfc55f..ef506ac34 100644 --- a/proto/Peer.proto +++ b/proto/Peer.proto @@ -18,6 +18,7 @@ enum SubServiceType { GIT = 1; NAT_TRAVERSAL = 2; CERTIFICATE_AUTHORITY = 3; + PEER_DHT = 4; } /////////////// @@ -30,7 +31,7 @@ message PingPeerMessage { } message PeerInfoMessage { string public_key = 1; - string relay_public_key = 2; + string root_certificate = 2; string peer_address = 3; string api_address = 4; } @@ -49,11 +50,10 @@ message ErrorMessage { // NAT Traversal // /////////////////// enum NatMessageType { - ERROR = 0; - RELAY_CONNECTION = 1; - PEER_CONNECTION = 2; - UDP_ADDRESS = 3; - PEER_UDP_ADDRESS = 4; + UDP_ADDRESS = 0; + DIRECT_CONNECTION = 1; + HOLE_PUNCH_CONNECTION = 2; + RELAY_CONNECTION = 3; } message NatMessage { NatMessageType type = 1; @@ -61,51 +61,37 @@ message NatMessage { bytes sub_message = 3; } -////////////////////// -// Relay Connection // -////////////////////// -message RelayConnectionRequest { - string public_key = 1; -} -message RelayConnectionResponse { - string server_address = 1; -} - -///////////////////// -// Peer Connection // -///////////////////// -message PeerConnectionRequest { - string public_key = 1; -} -message PeerConnectionResponse { - string peer_address = 1; -} - ///////////////// // UDP Address // ///////////////// -message UDPAddressResponse { +message UDPAddressMessage { string address = 1; + string token = 2; } -///////////////////////// -// Hole Punch Register // -///////////////////////// -message HolePunchRegisterRequest { - string public_key = 1; +/////////////////////// +// Direct Connection // +/////////////////////// +message DirectConnectionMessage { + string peer_id = 1; } -message HolePunchRegisterResponse { - string connected_address = 1; + +/////////////////////////// +// Hole Punch Connection // +/////////////////////////// +message HolePunchConnectionMessage { + string target_peer_id = 1; + string origin_peer_id = 2; + string udp_address = 3; } ////////////////////// -// Peer UDP Address // +// Relay Connection // ////////////////////// -message PeerUdpAddressRequest { - string public_key = 1; -} -message PeerUdpAddressResponse { - string address = 1; +message RelayConnectionMessage { + string target_peer_id = 1; + string origin_peer_id = 2; + string relay_address = 3; } ////////////////////// @@ -120,3 +106,41 @@ message CAMessage { bool is_response = 2; bytes sub_message = 3; } + +/////////////////////// +// DHT Functionality // +/////////////////////// +enum PeerDHTMessageType { + PING = 0; + FIND_NODE = 1; +} +message PeerDHTMessage { + PeerDHTMessageType type = 1; + bool is_response = 2; + bytes sub_message = 3; +} +message PeerDHTPingNodeMessage { + string peer_id = 1; + string random_challenge = 2; +} +message PeerDHTFindNodeMessage { + string peer_id = 1; + repeated PeerInfoMessage closest_peers = 2; +} + +////////////////////////////// +// Micro Transport Protocol // +////////////////////////////// +message MTPPacket { + int32 id = 1; + string peerId = 2; + int32 connection = 3; + int32 timestamp = 4; + int32 timediff = 5; + int32 window = 6; + int32 seq = 7; + int32 ack = 8; + bytes data = 9; + int32 sent = 10; +} + diff --git a/proto/compiled/Agent_grpc_pb.d.ts b/proto/compiled/Agent_grpc_pb.d.ts index 6df6f982f..b0e9a594f 100644 --- a/proto/compiled/Agent_grpc_pb.d.ts +++ b/proto/compiled/Agent_grpc_pb.d.ts @@ -31,6 +31,7 @@ interface IAgentService extends grpc.ServiceDefinition; responseDeserialize: grpc.deserialize; } +interface IAgentService_ILockNode extends grpc.MethodDefinition { + path: string; // "/agentInterface.Agent/LockNode" + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} interface IAgentService_INewClientCertificate extends grpc.MethodDefinition { path: string; // "/agentInterface.Agent/NewClientCertificate" requestStream: false; @@ -322,15 +330,6 @@ interface IAgentService_IPullVault extends grpc.MethodDefinition; responseDeserialize: grpc.deserialize; } -interface IAgentService_IRegisterNode extends grpc.MethodDefinition { - path: string; // "/agentInterface.Agent/RegisterNode" - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; -} interface IAgentService_IRevokeOAuthToken extends grpc.MethodDefinition { path: string; // "/agentInterface.Agent/RevokeOAuthToken" requestStream: false; @@ -340,24 +339,6 @@ interface IAgentService_IRevokeOAuthToken extends grpc.MethodDefinition; responseDeserialize: grpc.deserialize; } -interface IAgentService_IRequestHolePunch extends grpc.MethodDefinition { - path: string; // "/agentInterface.Agent/RequestHolePunch" - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; -} -interface IAgentService_IRequestRelay extends grpc.MethodDefinition { - path: string; // "/agentInterface.Agent/RequestRelay" - requestStream: false; - responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; -} interface IAgentService_IScanVaultNames extends grpc.MethodDefinition { path: string; // "/agentInterface.Agent/ScanVaultNames" requestStream: false; @@ -394,6 +375,15 @@ interface IAgentService_IToggleStealthMode extends grpc.MethodDefinition; responseDeserialize: grpc.deserialize; } +interface IAgentService_IUnlockNode extends grpc.MethodDefinition { + path: string; // "/agentInterface.Agent/UnlockNode" + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} interface IAgentService_IUpdateLocalPeerInfo extends grpc.MethodDefinition { path: string; // "/agentInterface.Agent/UpdateLocalPeerInfo" requestStream: false; @@ -457,6 +447,7 @@ export interface IAgentServer { listPeers: grpc.handleUnaryCall; listSecrets: grpc.handleUnaryCall; listVaults: grpc.handleUnaryCall; + lockNode: grpc.handleUnaryCall; newClientCertificate: grpc.handleUnaryCall; newNode: grpc.handleUnaryCall; newSecret: grpc.handleUnaryCall; @@ -464,14 +455,12 @@ export interface IAgentServer { newVault: grpc.handleUnaryCall; pingPeer: grpc.handleUnaryCall; pullVault: grpc.handleUnaryCall; - registerNode: grpc.handleUnaryCall; revokeOAuthToken: grpc.handleUnaryCall; - requestHolePunch: grpc.handleUnaryCall; - requestRelay: grpc.handleUnaryCall; scanVaultNames: grpc.handleUnaryCall; signFile: grpc.handleUnaryCall; stopAgent: grpc.handleUnaryCall; toggleStealthMode: grpc.handleUnaryCall; + unlockNode: grpc.handleUnaryCall; updateLocalPeerInfo: grpc.handleUnaryCall; updatePeerInfo: grpc.handleUnaryCall; updateSecret: grpc.handleUnaryCall; @@ -548,6 +537,9 @@ export interface IAgentClient { listVaults(request: Agent_pb.EmptyMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; listVaults(request: Agent_pb.EmptyMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; listVaults(request: Agent_pb.EmptyMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; + lockNode(request: Agent_pb.EmptyMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.EmptyMessage) => void): grpc.ClientUnaryCall; + lockNode(request: Agent_pb.EmptyMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.EmptyMessage) => void): grpc.ClientUnaryCall; + lockNode(request: Agent_pb.EmptyMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.EmptyMessage) => void): grpc.ClientUnaryCall; newClientCertificate(request: Agent_pb.NewClientCertificateMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.NewClientCertificateMessage) => void): grpc.ClientUnaryCall; newClientCertificate(request: Agent_pb.NewClientCertificateMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.NewClientCertificateMessage) => void): grpc.ClientUnaryCall; newClientCertificate(request: Agent_pb.NewClientCertificateMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.NewClientCertificateMessage) => void): grpc.ClientUnaryCall; @@ -569,18 +561,9 @@ export interface IAgentClient { pullVault(request: Agent_pb.VaultPathMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; pullVault(request: Agent_pb.VaultPathMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; pullVault(request: Agent_pb.VaultPathMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - registerNode(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - registerNode(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - registerNode(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; revokeOAuthToken(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; revokeOAuthToken(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; revokeOAuthToken(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - requestHolePunch(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - requestHolePunch(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - requestHolePunch(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - requestRelay(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - requestRelay(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - requestRelay(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; scanVaultNames(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; scanVaultNames(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; scanVaultNames(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; @@ -593,6 +576,9 @@ export interface IAgentClient { toggleStealthMode(request: Agent_pb.BooleanMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; toggleStealthMode(request: Agent_pb.BooleanMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; toggleStealthMode(request: Agent_pb.BooleanMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; + unlockNode(request: Agent_pb.UnlockNodeMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; + unlockNode(request: Agent_pb.UnlockNodeMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; + unlockNode(request: Agent_pb.UnlockNodeMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; updateLocalPeerInfo(request: Agent_pb.PeerInfoMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; updateLocalPeerInfo(request: Agent_pb.PeerInfoMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; updateLocalPeerInfo(request: Agent_pb.PeerInfoMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; @@ -678,6 +664,9 @@ export class AgentClient extends grpc.Client implements IAgentClient { public listVaults(request: Agent_pb.EmptyMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; public listVaults(request: Agent_pb.EmptyMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; public listVaults(request: Agent_pb.EmptyMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; + public lockNode(request: Agent_pb.EmptyMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.EmptyMessage) => void): grpc.ClientUnaryCall; + public lockNode(request: Agent_pb.EmptyMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.EmptyMessage) => void): grpc.ClientUnaryCall; + public lockNode(request: Agent_pb.EmptyMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.EmptyMessage) => void): grpc.ClientUnaryCall; public newClientCertificate(request: Agent_pb.NewClientCertificateMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.NewClientCertificateMessage) => void): grpc.ClientUnaryCall; public newClientCertificate(request: Agent_pb.NewClientCertificateMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.NewClientCertificateMessage) => void): grpc.ClientUnaryCall; public newClientCertificate(request: Agent_pb.NewClientCertificateMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.NewClientCertificateMessage) => void): grpc.ClientUnaryCall; @@ -699,18 +688,9 @@ export class AgentClient extends grpc.Client implements IAgentClient { public pullVault(request: Agent_pb.VaultPathMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public pullVault(request: Agent_pb.VaultPathMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public pullVault(request: Agent_pb.VaultPathMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public registerNode(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public registerNode(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public registerNode(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public revokeOAuthToken(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public revokeOAuthToken(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public revokeOAuthToken(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public requestHolePunch(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public requestHolePunch(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public requestHolePunch(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public requestRelay(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public requestRelay(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; - public requestRelay(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public scanVaultNames(request: Agent_pb.StringMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; public scanVaultNames(request: Agent_pb.StringMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; public scanVaultNames(request: Agent_pb.StringMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.StringListMessage) => void): grpc.ClientUnaryCall; @@ -723,6 +703,9 @@ export class AgentClient extends grpc.Client implements IAgentClient { public toggleStealthMode(request: Agent_pb.BooleanMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public toggleStealthMode(request: Agent_pb.BooleanMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public toggleStealthMode(request: Agent_pb.BooleanMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; + public unlockNode(request: Agent_pb.UnlockNodeMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; + public unlockNode(request: Agent_pb.UnlockNodeMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; + public unlockNode(request: Agent_pb.UnlockNodeMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public updateLocalPeerInfo(request: Agent_pb.PeerInfoMessage, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public updateLocalPeerInfo(request: Agent_pb.PeerInfoMessage, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; public updateLocalPeerInfo(request: Agent_pb.PeerInfoMessage, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: Agent_pb.BooleanMessage) => void): grpc.ClientUnaryCall; diff --git a/proto/compiled/Agent_grpc_pb.js b/proto/compiled/Agent_grpc_pb.js index fca8076f6..7c5778e88 100644 --- a/proto/compiled/Agent_grpc_pb.js +++ b/proto/compiled/Agent_grpc_pb.js @@ -202,6 +202,17 @@ function deserialize_agentInterface_StringMessage(buffer_arg) { return Agent_pb.StringMessage.deserializeBinary(new Uint8Array(buffer_arg)); } +function serialize_agentInterface_UnlockNodeMessage(arg) { + if (!(arg instanceof Agent_pb.UnlockNodeMessage)) { + throw new Error('Expected argument of type agentInterface.UnlockNodeMessage'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_agentInterface_UnlockNodeMessage(buffer_arg) { + return Agent_pb.UnlockNodeMessage.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_agentInterface_VaultPathMessage(arg) { if (!(arg instanceof Agent_pb.VaultPathMessage)) { throw new Error('Expected argument of type agentInterface.VaultPathMessage'); @@ -482,6 +493,17 @@ var AgentService = exports.AgentService = { responseSerialize: serialize_agentInterface_StringListMessage, responseDeserialize: deserialize_agentInterface_StringListMessage, }, + lockNode: { + path: '/agentInterface.Agent/LockNode', + requestStream: false, + responseStream: false, + requestType: Agent_pb.EmptyMessage, + responseType: Agent_pb.EmptyMessage, + requestSerialize: serialize_agentInterface_EmptyMessage, + requestDeserialize: deserialize_agentInterface_EmptyMessage, + responseSerialize: serialize_agentInterface_EmptyMessage, + responseDeserialize: deserialize_agentInterface_EmptyMessage, + }, newClientCertificate: { path: '/agentInterface.Agent/NewClientCertificate', requestStream: false, @@ -559,17 +581,6 @@ var AgentService = exports.AgentService = { responseSerialize: serialize_agentInterface_BooleanMessage, responseDeserialize: deserialize_agentInterface_BooleanMessage, }, - registerNode: { - path: '/agentInterface.Agent/RegisterNode', - requestStream: false, - responseStream: false, - requestType: Agent_pb.StringMessage, - responseType: Agent_pb.BooleanMessage, - requestSerialize: serialize_agentInterface_StringMessage, - requestDeserialize: deserialize_agentInterface_StringMessage, - responseSerialize: serialize_agentInterface_BooleanMessage, - responseDeserialize: deserialize_agentInterface_BooleanMessage, - }, revokeOAuthToken: { path: '/agentInterface.Agent/RevokeOAuthToken', requestStream: false, @@ -581,28 +592,6 @@ var AgentService = exports.AgentService = { responseSerialize: serialize_agentInterface_BooleanMessage, responseDeserialize: deserialize_agentInterface_BooleanMessage, }, - requestHolePunch: { - path: '/agentInterface.Agent/RequestHolePunch', - requestStream: false, - responseStream: false, - requestType: Agent_pb.StringMessage, - responseType: Agent_pb.BooleanMessage, - requestSerialize: serialize_agentInterface_StringMessage, - requestDeserialize: deserialize_agentInterface_StringMessage, - responseSerialize: serialize_agentInterface_BooleanMessage, - responseDeserialize: deserialize_agentInterface_BooleanMessage, - }, - requestRelay: { - path: '/agentInterface.Agent/RequestRelay', - requestStream: false, - responseStream: false, - requestType: Agent_pb.StringMessage, - responseType: Agent_pb.BooleanMessage, - requestSerialize: serialize_agentInterface_StringMessage, - requestDeserialize: deserialize_agentInterface_StringMessage, - responseSerialize: serialize_agentInterface_BooleanMessage, - responseDeserialize: deserialize_agentInterface_BooleanMessage, - }, scanVaultNames: { path: '/agentInterface.Agent/ScanVaultNames', requestStream: false, @@ -647,6 +636,17 @@ var AgentService = exports.AgentService = { responseSerialize: serialize_agentInterface_BooleanMessage, responseDeserialize: deserialize_agentInterface_BooleanMessage, }, + unlockNode: { + path: '/agentInterface.Agent/UnlockNode', + requestStream: false, + responseStream: false, + requestType: Agent_pb.UnlockNodeMessage, + responseType: Agent_pb.BooleanMessage, + requestSerialize: serialize_agentInterface_UnlockNodeMessage, + requestDeserialize: deserialize_agentInterface_UnlockNodeMessage, + responseSerialize: serialize_agentInterface_BooleanMessage, + responseDeserialize: deserialize_agentInterface_BooleanMessage, + }, updateLocalPeerInfo: { path: '/agentInterface.Agent/UpdateLocalPeerInfo', requestStream: false, diff --git a/proto/compiled/Agent_pb.d.ts b/proto/compiled/Agent_pb.d.ts index 300997b61..298a5445e 100644 --- a/proto/compiled/Agent_pb.d.ts +++ b/proto/compiled/Agent_pb.d.ts @@ -92,8 +92,8 @@ export class PeerInfoMessage extends jspb.Message { getPublicKey(): string; setPublicKey(value: string): PeerInfoMessage; - getRelayPublicKey(): string; - setRelayPublicKey(value: string): PeerInfoMessage; + getRootCertificate(): string; + setRootCertificate(value: string): PeerInfoMessage; getPeerAddress(): string; setPeerAddress(value: string): PeerInfoMessage; @@ -115,7 +115,7 @@ export class PeerInfoMessage extends jspb.Message { export namespace PeerInfoMessage { export type AsObject = { publicKey: string, - relayPublicKey: string, + rootCertificate: string, peerAddress: string, apiAddress: string, } @@ -149,9 +149,6 @@ export class NewNodeMessage extends jspb.Message { getPassphrase(): string; setPassphrase(value: string): NewNodeMessage; - getNbits(): number; - setNbits(value: number): NewNodeMessage; - serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): NewNodeMessage.AsObject; @@ -167,7 +164,6 @@ export namespace NewNodeMessage { export type AsObject = { userid: string, passphrase: string, - nbits: number, } } @@ -440,6 +436,31 @@ export namespace ContactPeerMessage { } } +export class UnlockNodeMessage extends jspb.Message { + getPassphrase(): string; + setPassphrase(value: string): UnlockNodeMessage; + + getTimeout(): number; + setTimeout(value: number): UnlockNodeMessage; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): UnlockNodeMessage.AsObject; + static toObject(includeInstance: boolean, msg: UnlockNodeMessage): UnlockNodeMessage.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: UnlockNodeMessage, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): UnlockNodeMessage; + static deserializeBinaryFromReader(message: UnlockNodeMessage, reader: jspb.BinaryReader): UnlockNodeMessage; +} + +export namespace UnlockNodeMessage { + export type AsObject = { + passphrase: string, + timeout: number, + } +} + export class NewClientCertificateMessage extends jspb.Message { getDomain(): string; setDomain(value: string): NewClientCertificateMessage; diff --git a/proto/compiled/Agent_pb.js b/proto/compiled/Agent_pb.js index 8a9b61281..59755cdc2 100644 --- a/proto/compiled/Agent_pb.js +++ b/proto/compiled/Agent_pb.js @@ -31,6 +31,7 @@ goog.exportSymbol('proto.agentInterface.SecretPathMessage', null, global); goog.exportSymbol('proto.agentInterface.SignFileMessage', null, global); goog.exportSymbol('proto.agentInterface.StringListMessage', null, global); goog.exportSymbol('proto.agentInterface.StringMessage', null, global); +goog.exportSymbol('proto.agentInterface.UnlockNodeMessage', null, global); goog.exportSymbol('proto.agentInterface.VaultPathMessage', null, global); goog.exportSymbol('proto.agentInterface.VerifyFileMessage', null, global); /** @@ -390,6 +391,27 @@ if (goog.DEBUG && !COMPILED) { */ proto.agentInterface.ContactPeerMessage.displayName = 'proto.agentInterface.ContactPeerMessage'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.agentInterface.UnlockNodeMessage = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.agentInterface.UnlockNodeMessage, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.agentInterface.UnlockNodeMessage.displayName = 'proto.agentInterface.UnlockNodeMessage'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -1003,7 +1025,7 @@ proto.agentInterface.PeerInfoMessage.prototype.toObject = function(opt_includeIn proto.agentInterface.PeerInfoMessage.toObject = function(includeInstance, msg) { var f, obj = { publicKey: jspb.Message.getFieldWithDefault(msg, 1, ""), - relayPublicKey: jspb.Message.getFieldWithDefault(msg, 2, ""), + rootCertificate: jspb.Message.getFieldWithDefault(msg, 2, ""), peerAddress: jspb.Message.getFieldWithDefault(msg, 3, ""), apiAddress: jspb.Message.getFieldWithDefault(msg, 4, "") }; @@ -1048,7 +1070,7 @@ proto.agentInterface.PeerInfoMessage.deserializeBinaryFromReader = function(msg, break; case 2: var value = /** @type {string} */ (reader.readString()); - msg.setRelayPublicKey(value); + msg.setRootCertificate(value); break; case 3: var value = /** @type {string} */ (reader.readString()); @@ -1094,7 +1116,7 @@ proto.agentInterface.PeerInfoMessage.serializeBinaryToWriter = function(message, f ); } - f = message.getRelayPublicKey(); + f = message.getRootCertificate(); if (f.length > 0) { writer.writeString( 2, @@ -1137,10 +1159,10 @@ proto.agentInterface.PeerInfoMessage.prototype.setPublicKey = function(value) { /** - * optional string relay_public_key = 2; + * optional string root_certificate = 2; * @return {string} */ -proto.agentInterface.PeerInfoMessage.prototype.getRelayPublicKey = function() { +proto.agentInterface.PeerInfoMessage.prototype.getRootCertificate = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; @@ -1149,7 +1171,7 @@ proto.agentInterface.PeerInfoMessage.prototype.getRelayPublicKey = function() { * @param {string} value * @return {!proto.agentInterface.PeerInfoMessage} returns this */ -proto.agentInterface.PeerInfoMessage.prototype.setRelayPublicKey = function(value) { +proto.agentInterface.PeerInfoMessage.prototype.setRootCertificate = function(value) { return jspb.Message.setProto3StringField(this, 2, value); }; @@ -1353,8 +1375,7 @@ proto.agentInterface.NewNodeMessage.prototype.toObject = function(opt_includeIns proto.agentInterface.NewNodeMessage.toObject = function(includeInstance, msg) { var f, obj = { userid: jspb.Message.getFieldWithDefault(msg, 1, ""), - passphrase: jspb.Message.getFieldWithDefault(msg, 2, ""), - nbits: jspb.Message.getFieldWithDefault(msg, 3, 0) + passphrase: jspb.Message.getFieldWithDefault(msg, 2, "") }; if (includeInstance) { @@ -1399,10 +1420,6 @@ proto.agentInterface.NewNodeMessage.deserializeBinaryFromReader = function(msg, var value = /** @type {string} */ (reader.readString()); msg.setPassphrase(value); break; - case 3: - var value = /** @type {number} */ (reader.readInt32()); - msg.setNbits(value); - break; default: reader.skipField(); break; @@ -1446,13 +1463,6 @@ proto.agentInterface.NewNodeMessage.serializeBinaryToWriter = function(message, f ); } - f = message.getNbits(); - if (f !== 0) { - writer.writeInt32( - 3, - f - ); - } }; @@ -1492,24 +1502,6 @@ proto.agentInterface.NewNodeMessage.prototype.setPassphrase = function(value) { }; -/** - * optional int32 nbits = 3; - * @return {number} - */ -proto.agentInterface.NewNodeMessage.prototype.getNbits = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0)); -}; - - -/** - * @param {number} value - * @return {!proto.agentInterface.NewNodeMessage} returns this - */ -proto.agentInterface.NewNodeMessage.prototype.setNbits = function(value) { - return jspb.Message.setProto3IntField(this, 3, value); -}; - - @@ -3254,6 +3246,166 @@ proto.agentInterface.ContactPeerMessage.prototype.setTimeout = function(value) { +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.agentInterface.UnlockNodeMessage.prototype.toObject = function(opt_includeInstance) { + return proto.agentInterface.UnlockNodeMessage.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.agentInterface.UnlockNodeMessage} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.agentInterface.UnlockNodeMessage.toObject = function(includeInstance, msg) { + var f, obj = { + passphrase: jspb.Message.getFieldWithDefault(msg, 1, ""), + timeout: jspb.Message.getFieldWithDefault(msg, 2, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.agentInterface.UnlockNodeMessage} + */ +proto.agentInterface.UnlockNodeMessage.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.agentInterface.UnlockNodeMessage; + return proto.agentInterface.UnlockNodeMessage.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.agentInterface.UnlockNodeMessage} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.agentInterface.UnlockNodeMessage} + */ +proto.agentInterface.UnlockNodeMessage.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setPassphrase(value); + break; + case 2: + var value = /** @type {number} */ (reader.readInt32()); + msg.setTimeout(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.agentInterface.UnlockNodeMessage.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.agentInterface.UnlockNodeMessage.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.agentInterface.UnlockNodeMessage} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.agentInterface.UnlockNodeMessage.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getPassphrase(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getTimeout(); + if (f !== 0) { + writer.writeInt32( + 2, + f + ); + } +}; + + +/** + * optional string passphrase = 1; + * @return {string} + */ +proto.agentInterface.UnlockNodeMessage.prototype.getPassphrase = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.agentInterface.UnlockNodeMessage} returns this + */ +proto.agentInterface.UnlockNodeMessage.prototype.setPassphrase = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional int32 timeout = 2; + * @return {number} + */ +proto.agentInterface.UnlockNodeMessage.prototype.getTimeout = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.agentInterface.UnlockNodeMessage} returns this + */ +proto.agentInterface.UnlockNodeMessage.prototype.setTimeout = function(value) { + return jspb.Message.setProto3IntField(this, 2, value); +}; + + + + + if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto. diff --git a/proto/compiled/Peer_pb.d.ts b/proto/compiled/Peer_pb.d.ts index 81f7664b0..e91832bca 100644 --- a/proto/compiled/Peer_pb.d.ts +++ b/proto/compiled/Peer_pb.d.ts @@ -71,8 +71,8 @@ export class PeerInfoMessage extends jspb.Message { getPublicKey(): string; setPublicKey(value: string): PeerInfoMessage; - getRelayPublicKey(): string; - setRelayPublicKey(value: string): PeerInfoMessage; + getRootCertificate(): string; + setRootCertificate(value: string): PeerInfoMessage; getPeerAddress(): string; setPeerAddress(value: string): PeerInfoMessage; @@ -94,7 +94,7 @@ export class PeerInfoMessage extends jspb.Message { export namespace PeerInfoMessage { export type AsObject = { publicKey: string, - relayPublicKey: string, + rootCertificate: string, peerAddress: string, apiAddress: string, } @@ -148,9 +148,6 @@ export class NatMessage extends jspb.Message { getType(): NatMessageType; setType(value: NatMessageType): NatMessage; - getIsResponse(): boolean; - setIsResponse(value: boolean): NatMessage; - getSubMessage(): Uint8Array | string; getSubMessage_asU8(): Uint8Array; getSubMessage_asB64(): string; @@ -170,11 +167,35 @@ export class NatMessage extends jspb.Message { export namespace NatMessage { export type AsObject = { type: NatMessageType, - isResponse: boolean, subMessage: Uint8Array | string, } } +export class UDPAddressMessage extends jspb.Message { + getAddress(): string; + setAddress(value: string): UDPAddressMessage; + + getToken(): string; + setToken(value: string): UDPAddressMessage; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): UDPAddressMessage.AsObject; + static toObject(includeInstance: boolean, msg: UDPAddressMessage): UDPAddressMessage.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: UDPAddressMessage, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): UDPAddressMessage; + static deserializeBinaryFromReader(message: UDPAddressMessage, reader: jspb.BinaryReader): UDPAddressMessage; +} + +export namespace UDPAddressMessage { + export type AsObject = { + address: string, + token: string, + } +} + export class RelayConnectionRequest extends jspb.Message { getPublicKey(): string; setPublicKey(value: string): RelayConnectionRequest; @@ -259,27 +280,6 @@ export namespace PeerConnectionResponse { } } -export class UDPAddressResponse extends jspb.Message { - getAddress(): string; - setAddress(value: string): UDPAddressResponse; - - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): UDPAddressResponse.AsObject; - static toObject(includeInstance: boolean, msg: UDPAddressResponse): UDPAddressResponse.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: UDPAddressResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): UDPAddressResponse; - static deserializeBinaryFromReader(message: UDPAddressResponse, reader: jspb.BinaryReader): UDPAddressResponse; -} - -export namespace UDPAddressResponse { - export type AsObject = { - address: string, - } -} - export class HolePunchRegisterRequest extends jspb.Message { getPublicKey(): string; setPublicKey(value: string): HolePunchRegisterRequest; @@ -395,22 +395,110 @@ export namespace CAMessage { } } +export class PeerDHTMessage extends jspb.Message { + getType(): PeerDHTMessageType; + setType(value: PeerDHTMessageType): PeerDHTMessage; + + getIsResponse(): boolean; + setIsResponse(value: boolean): PeerDHTMessage; + + getSubMessage(): Uint8Array | string; + getSubMessage_asU8(): Uint8Array; + getSubMessage_asB64(): string; + setSubMessage(value: Uint8Array | string): PeerDHTMessage; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): PeerDHTMessage.AsObject; + static toObject(includeInstance: boolean, msg: PeerDHTMessage): PeerDHTMessage.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: PeerDHTMessage, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): PeerDHTMessage; + static deserializeBinaryFromReader(message: PeerDHTMessage, reader: jspb.BinaryReader): PeerDHTMessage; +} + +export namespace PeerDHTMessage { + export type AsObject = { + type: PeerDHTMessageType, + isResponse: boolean, + subMessage: Uint8Array | string, + } +} + +export class PeerDHTPingNodeMessage extends jspb.Message { + getPublicKey(): string; + setPublicKey(value: string): PeerDHTPingNodeMessage; + + getRandomChallenge(): string; + setRandomChallenge(value: string): PeerDHTPingNodeMessage; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): PeerDHTPingNodeMessage.AsObject; + static toObject(includeInstance: boolean, msg: PeerDHTPingNodeMessage): PeerDHTPingNodeMessage.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: PeerDHTPingNodeMessage, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): PeerDHTPingNodeMessage; + static deserializeBinaryFromReader(message: PeerDHTPingNodeMessage, reader: jspb.BinaryReader): PeerDHTPingNodeMessage; +} + +export namespace PeerDHTPingNodeMessage { + export type AsObject = { + publicKey: string, + randomChallenge: string, + } +} + +export class PeerDHTFindNodeMessage extends jspb.Message { + getPublicKey(): string; + setPublicKey(value: string): PeerDHTFindNodeMessage; + + clearClosestPeersList(): void; + getClosestPeersList(): Array; + setClosestPeersList(value: Array): PeerDHTFindNodeMessage; + addClosestPeers(value?: PeerInfoMessage, index?: number): PeerInfoMessage; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): PeerDHTFindNodeMessage.AsObject; + static toObject(includeInstance: boolean, msg: PeerDHTFindNodeMessage): PeerDHTFindNodeMessage.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: PeerDHTFindNodeMessage, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): PeerDHTFindNodeMessage; + static deserializeBinaryFromReader(message: PeerDHTFindNodeMessage, reader: jspb.BinaryReader): PeerDHTFindNodeMessage; +} + +export namespace PeerDHTFindNodeMessage { + export type AsObject = { + publicKey: string, + closestPeersList: Array, + } +} + export enum SubServiceType { PING_PEER = 0, GIT = 1, NAT_TRAVERSAL = 2, CERTIFICATE_AUTHORITY = 3, + PEER_DHT = 4, } export enum NatMessageType { - ERROR = 0, + UDP_ADDRESS = 0, RELAY_CONNECTION = 1, PEER_CONNECTION = 2, - UDP_ADDRESS = 3, - PEER_UDP_ADDRESS = 4, + PEER_UDP_ADDRESS = 3, } export enum CAMessageType { ROOT_CERT = 0, REQUEST_CERT = 1, } + +export enum PeerDHTMessageType { + PING = 0, + FIND_NODE = 1, +} diff --git a/proto/compiled/Peer_pb.js b/proto/compiled/Peer_pb.js index 556225eec..b92edbfec 100644 --- a/proto/compiled/Peer_pb.js +++ b/proto/compiled/Peer_pb.js @@ -21,6 +21,10 @@ goog.exportSymbol('proto.peerInterface.NatMessage', null, global); goog.exportSymbol('proto.peerInterface.NatMessageType', null, global); goog.exportSymbol('proto.peerInterface.PeerConnectionRequest', null, global); goog.exportSymbol('proto.peerInterface.PeerConnectionResponse', null, global); +goog.exportSymbol('proto.peerInterface.PeerDHTFindNodeMessage', null, global); +goog.exportSymbol('proto.peerInterface.PeerDHTMessage', null, global); +goog.exportSymbol('proto.peerInterface.PeerDHTMessageType', null, global); +goog.exportSymbol('proto.peerInterface.PeerDHTPingNodeMessage', null, global); goog.exportSymbol('proto.peerInterface.PeerInfoListMessage', null, global); goog.exportSymbol('proto.peerInterface.PeerInfoMessage', null, global); goog.exportSymbol('proto.peerInterface.PeerMessage', null, global); @@ -30,7 +34,7 @@ goog.exportSymbol('proto.peerInterface.PingPeerMessage', null, global); goog.exportSymbol('proto.peerInterface.RelayConnectionRequest', null, global); goog.exportSymbol('proto.peerInterface.RelayConnectionResponse', null, global); goog.exportSymbol('proto.peerInterface.SubServiceType', null, global); -goog.exportSymbol('proto.peerInterface.UDPAddressResponse', null, global); +goog.exportSymbol('proto.peerInterface.UDPAddressMessage', null, global); /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -167,16 +171,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.peerInterface.RelayConnectionRequest = function(opt_data) { +proto.peerInterface.UDPAddressMessage = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.peerInterface.RelayConnectionRequest, jspb.Message); +goog.inherits(proto.peerInterface.UDPAddressMessage, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.peerInterface.RelayConnectionRequest.displayName = 'proto.peerInterface.RelayConnectionRequest'; + proto.peerInterface.UDPAddressMessage.displayName = 'proto.peerInterface.UDPAddressMessage'; } /** * Generated by JsPbCodeGenerator. @@ -188,16 +192,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.peerInterface.RelayConnectionResponse = function(opt_data) { +proto.peerInterface.RelayConnectionRequest = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.peerInterface.RelayConnectionResponse, jspb.Message); +goog.inherits(proto.peerInterface.RelayConnectionRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.peerInterface.RelayConnectionResponse.displayName = 'proto.peerInterface.RelayConnectionResponse'; + proto.peerInterface.RelayConnectionRequest.displayName = 'proto.peerInterface.RelayConnectionRequest'; } /** * Generated by JsPbCodeGenerator. @@ -209,16 +213,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.peerInterface.PeerConnectionRequest = function(opt_data) { +proto.peerInterface.RelayConnectionResponse = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.peerInterface.PeerConnectionRequest, jspb.Message); +goog.inherits(proto.peerInterface.RelayConnectionResponse, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.peerInterface.PeerConnectionRequest.displayName = 'proto.peerInterface.PeerConnectionRequest'; + proto.peerInterface.RelayConnectionResponse.displayName = 'proto.peerInterface.RelayConnectionResponse'; } /** * Generated by JsPbCodeGenerator. @@ -230,16 +234,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.peerInterface.PeerConnectionResponse = function(opt_data) { +proto.peerInterface.PeerConnectionRequest = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.peerInterface.PeerConnectionResponse, jspb.Message); +goog.inherits(proto.peerInterface.PeerConnectionRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.peerInterface.PeerConnectionResponse.displayName = 'proto.peerInterface.PeerConnectionResponse'; + proto.peerInterface.PeerConnectionRequest.displayName = 'proto.peerInterface.PeerConnectionRequest'; } /** * Generated by JsPbCodeGenerator. @@ -251,16 +255,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.peerInterface.UDPAddressResponse = function(opt_data) { +proto.peerInterface.PeerConnectionResponse = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.peerInterface.UDPAddressResponse, jspb.Message); +goog.inherits(proto.peerInterface.PeerConnectionResponse, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.peerInterface.UDPAddressResponse.displayName = 'proto.peerInterface.UDPAddressResponse'; + proto.peerInterface.PeerConnectionResponse.displayName = 'proto.peerInterface.PeerConnectionResponse'; } /** * Generated by JsPbCodeGenerator. @@ -367,6 +371,69 @@ if (goog.DEBUG && !COMPILED) { */ proto.peerInterface.CAMessage.displayName = 'proto.peerInterface.CAMessage'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.peerInterface.PeerDHTMessage = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.peerInterface.PeerDHTMessage, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.peerInterface.PeerDHTMessage.displayName = 'proto.peerInterface.PeerDHTMessage'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.peerInterface.PeerDHTPingNodeMessage = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.peerInterface.PeerDHTPingNodeMessage, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.peerInterface.PeerDHTPingNodeMessage.displayName = 'proto.peerInterface.PeerDHTPingNodeMessage'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.peerInterface.PeerDHTFindNodeMessage = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.peerInterface.PeerDHTFindNodeMessage.repeatedFields_, null); +}; +goog.inherits(proto.peerInterface.PeerDHTFindNodeMessage, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.peerInterface.PeerDHTFindNodeMessage.displayName = 'proto.peerInterface.PeerDHTFindNodeMessage'; +} @@ -801,7 +868,7 @@ proto.peerInterface.PeerInfoMessage.prototype.toObject = function(opt_includeIns proto.peerInterface.PeerInfoMessage.toObject = function(includeInstance, msg) { var f, obj = { publicKey: jspb.Message.getFieldWithDefault(msg, 1, ""), - relayPublicKey: jspb.Message.getFieldWithDefault(msg, 2, ""), + rootCertificate: jspb.Message.getFieldWithDefault(msg, 2, ""), peerAddress: jspb.Message.getFieldWithDefault(msg, 3, ""), apiAddress: jspb.Message.getFieldWithDefault(msg, 4, "") }; @@ -846,7 +913,7 @@ proto.peerInterface.PeerInfoMessage.deserializeBinaryFromReader = function(msg, break; case 2: var value = /** @type {string} */ (reader.readString()); - msg.setRelayPublicKey(value); + msg.setRootCertificate(value); break; case 3: var value = /** @type {string} */ (reader.readString()); @@ -892,7 +959,7 @@ proto.peerInterface.PeerInfoMessage.serializeBinaryToWriter = function(message, f ); } - f = message.getRelayPublicKey(); + f = message.getRootCertificate(); if (f.length > 0) { writer.writeString( 2, @@ -935,10 +1002,10 @@ proto.peerInterface.PeerInfoMessage.prototype.setPublicKey = function(value) { /** - * optional string relay_public_key = 2; + * optional string root_certificate = 2; * @return {string} */ -proto.peerInterface.PeerInfoMessage.prototype.getRelayPublicKey = function() { +proto.peerInterface.PeerInfoMessage.prototype.getRootCertificate = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; @@ -947,7 +1014,7 @@ proto.peerInterface.PeerInfoMessage.prototype.getRelayPublicKey = function() { * @param {string} value * @return {!proto.peerInterface.PeerInfoMessage} returns this */ -proto.peerInterface.PeerInfoMessage.prototype.setRelayPublicKey = function(value) { +proto.peerInterface.PeerInfoMessage.prototype.setRootCertificate = function(value) { return jspb.Message.setProto3StringField(this, 2, value); }; @@ -1311,7 +1378,6 @@ proto.peerInterface.NatMessage.prototype.toObject = function(opt_includeInstance proto.peerInterface.NatMessage.toObject = function(includeInstance, msg) { var f, obj = { type: jspb.Message.getFieldWithDefault(msg, 1, 0), - isResponse: jspb.Message.getBooleanFieldWithDefault(msg, 2, false), subMessage: msg.getSubMessage_asB64() }; @@ -1354,10 +1420,6 @@ proto.peerInterface.NatMessage.deserializeBinaryFromReader = function(msg, reade msg.setType(value); break; case 2: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setIsResponse(value); - break; - case 3: var value = /** @type {!Uint8Array} */ (reader.readBytes()); msg.setSubMessage(value); break; @@ -1397,17 +1459,10 @@ proto.peerInterface.NatMessage.serializeBinaryToWriter = function(message, write f ); } - f = message.getIsResponse(); - if (f) { - writer.writeBool( - 2, - f - ); - } f = message.getSubMessage_asU8(); if (f.length > 0) { writer.writeBytes( - 3, + 2, f ); } @@ -1433,34 +1488,16 @@ proto.peerInterface.NatMessage.prototype.setType = function(value) { /** - * optional bool is_response = 2; - * @return {boolean} - */ -proto.peerInterface.NatMessage.prototype.getIsResponse = function() { - return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false)); -}; - - -/** - * @param {boolean} value - * @return {!proto.peerInterface.NatMessage} returns this - */ -proto.peerInterface.NatMessage.prototype.setIsResponse = function(value) { - return jspb.Message.setProto3BooleanField(this, 2, value); -}; - - -/** - * optional bytes sub_message = 3; + * optional bytes sub_message = 2; * @return {!(string|Uint8Array)} */ proto.peerInterface.NatMessage.prototype.getSubMessage = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 3, "")); + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** - * optional bytes sub_message = 3; + * optional bytes sub_message = 2; * This is a type-conversion wrapper around `getSubMessage()` * @return {string} */ @@ -1471,7 +1508,7 @@ proto.peerInterface.NatMessage.prototype.getSubMessage_asB64 = function() { /** - * optional bytes sub_message = 3; + * optional bytes sub_message = 2; * Note that Uint8Array is not supported on all browsers. * @see http://caniuse.com/Uint8Array * This is a type-conversion wrapper around `getSubMessage()` @@ -1488,7 +1525,167 @@ proto.peerInterface.NatMessage.prototype.getSubMessage_asU8 = function() { * @return {!proto.peerInterface.NatMessage} returns this */ proto.peerInterface.NatMessage.prototype.setSubMessage = function(value) { - return jspb.Message.setProto3BytesField(this, 3, value); + return jspb.Message.setProto3BytesField(this, 2, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.peerInterface.UDPAddressMessage.prototype.toObject = function(opt_includeInstance) { + return proto.peerInterface.UDPAddressMessage.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.peerInterface.UDPAddressMessage} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.peerInterface.UDPAddressMessage.toObject = function(includeInstance, msg) { + var f, obj = { + address: jspb.Message.getFieldWithDefault(msg, 1, ""), + token: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.peerInterface.UDPAddressMessage} + */ +proto.peerInterface.UDPAddressMessage.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.peerInterface.UDPAddressMessage; + return proto.peerInterface.UDPAddressMessage.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.peerInterface.UDPAddressMessage} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.peerInterface.UDPAddressMessage} + */ +proto.peerInterface.UDPAddressMessage.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setAddress(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setToken(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.peerInterface.UDPAddressMessage.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.peerInterface.UDPAddressMessage.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.peerInterface.UDPAddressMessage} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.peerInterface.UDPAddressMessage.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getAddress(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getToken(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string address = 1; + * @return {string} + */ +proto.peerInterface.UDPAddressMessage.prototype.getAddress = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.peerInterface.UDPAddressMessage} returns this + */ +proto.peerInterface.UDPAddressMessage.prototype.setAddress = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string token = 2; + * @return {string} + */ +proto.peerInterface.UDPAddressMessage.prototype.getToken = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.peerInterface.UDPAddressMessage} returns this + */ +proto.peerInterface.UDPAddressMessage.prototype.setToken = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); }; @@ -2028,8 +2225,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.peerInterface.UDPAddressResponse.prototype.toObject = function(opt_includeInstance) { - return proto.peerInterface.UDPAddressResponse.toObject(opt_includeInstance, this); +proto.peerInterface.HolePunchRegisterRequest.prototype.toObject = function(opt_includeInstance) { + return proto.peerInterface.HolePunchRegisterRequest.toObject(opt_includeInstance, this); }; @@ -2038,13 +2235,13 @@ proto.peerInterface.UDPAddressResponse.prototype.toObject = function(opt_include * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.peerInterface.UDPAddressResponse} msg The msg instance to transform. + * @param {!proto.peerInterface.HolePunchRegisterRequest} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.peerInterface.UDPAddressResponse.toObject = function(includeInstance, msg) { +proto.peerInterface.HolePunchRegisterRequest.toObject = function(includeInstance, msg) { var f, obj = { - address: jspb.Message.getFieldWithDefault(msg, 1, "") + publicKey: jspb.Message.getFieldWithDefault(msg, 1, "") }; if (includeInstance) { @@ -2058,142 +2255,12 @@ proto.peerInterface.UDPAddressResponse.toObject = function(includeInstance, msg) /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.peerInterface.UDPAddressResponse} + * @return {!proto.peerInterface.HolePunchRegisterRequest} */ -proto.peerInterface.UDPAddressResponse.deserializeBinary = function(bytes) { +proto.peerInterface.HolePunchRegisterRequest.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.peerInterface.UDPAddressResponse; - return proto.peerInterface.UDPAddressResponse.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.peerInterface.UDPAddressResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.peerInterface.UDPAddressResponse} - */ -proto.peerInterface.UDPAddressResponse.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setAddress(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.peerInterface.UDPAddressResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.peerInterface.UDPAddressResponse.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.peerInterface.UDPAddressResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.peerInterface.UDPAddressResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getAddress(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } -}; - - -/** - * optional string address = 1; - * @return {string} - */ -proto.peerInterface.UDPAddressResponse.prototype.getAddress = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.peerInterface.UDPAddressResponse} returns this - */ -proto.peerInterface.UDPAddressResponse.prototype.setAddress = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.peerInterface.HolePunchRegisterRequest.prototype.toObject = function(opt_includeInstance) { - return proto.peerInterface.HolePunchRegisterRequest.toObject(opt_includeInstance, this); -}; - - -/** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.peerInterface.HolePunchRegisterRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.peerInterface.HolePunchRegisterRequest.toObject = function(includeInstance, msg) { - var f, obj = { - publicKey: jspb.Message.getFieldWithDefault(msg, 1, "") - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.peerInterface.HolePunchRegisterRequest} - */ -proto.peerInterface.HolePunchRegisterRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.peerInterface.HolePunchRegisterRequest; - return proto.peerInterface.HolePunchRegisterRequest.deserializeBinaryFromReader(msg, reader); + var msg = new proto.peerInterface.HolePunchRegisterRequest; + return proto.peerInterface.HolePunchRegisterRequest.deserializeBinaryFromReader(msg, reader); }; @@ -2876,33 +2943,605 @@ proto.peerInterface.CAMessage.prototype.setSubMessage = function(value) { }; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { /** - * @enum {number} + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} */ -proto.peerInterface.SubServiceType = { - PING_PEER: 0, - GIT: 1, - NAT_TRAVERSAL: 2, - CERTIFICATE_AUTHORITY: 3 +proto.peerInterface.PeerDHTMessage.prototype.toObject = function(opt_includeInstance) { + return proto.peerInterface.PeerDHTMessage.toObject(opt_includeInstance, this); }; + /** - * @enum {number} + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.peerInterface.PeerDHTMessage} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.peerInterface.NatMessageType = { - ERROR: 0, - RELAY_CONNECTION: 1, - PEER_CONNECTION: 2, - UDP_ADDRESS: 3, - PEER_UDP_ADDRESS: 4 +proto.peerInterface.PeerDHTMessage.toObject = function(includeInstance, msg) { + var f, obj = { + type: jspb.Message.getFieldWithDefault(msg, 1, 0), + isResponse: jspb.Message.getBooleanFieldWithDefault(msg, 2, false), + subMessage: msg.getSubMessage_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; }; +} + /** - * @enum {number} + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.peerInterface.PeerDHTMessage} */ -proto.peerInterface.CAMessageType = { - ROOT_CERT: 0, - REQUEST_CERT: 1 +proto.peerInterface.PeerDHTMessage.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.peerInterface.PeerDHTMessage; + return proto.peerInterface.PeerDHTMessage.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.peerInterface.PeerDHTMessage} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.peerInterface.PeerDHTMessage} + */ +proto.peerInterface.PeerDHTMessage.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!proto.peerInterface.PeerDHTMessageType} */ (reader.readEnum()); + msg.setType(value); + break; + case 2: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setIsResponse(value); + break; + case 3: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setSubMessage(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.peerInterface.PeerDHTMessage.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.peerInterface.PeerDHTMessage.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.peerInterface.PeerDHTMessage} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.peerInterface.PeerDHTMessage.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getType(); + if (f !== 0.0) { + writer.writeEnum( + 1, + f + ); + } + f = message.getIsResponse(); + if (f) { + writer.writeBool( + 2, + f + ); + } + f = message.getSubMessage_asU8(); + if (f.length > 0) { + writer.writeBytes( + 3, + f + ); + } +}; + + +/** + * optional PeerDHTMessageType type = 1; + * @return {!proto.peerInterface.PeerDHTMessageType} + */ +proto.peerInterface.PeerDHTMessage.prototype.getType = function() { + return /** @type {!proto.peerInterface.PeerDHTMessageType} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {!proto.peerInterface.PeerDHTMessageType} value + * @return {!proto.peerInterface.PeerDHTMessage} returns this + */ +proto.peerInterface.PeerDHTMessage.prototype.setType = function(value) { + return jspb.Message.setProto3EnumField(this, 1, value); +}; + + +/** + * optional bool is_response = 2; + * @return {boolean} + */ +proto.peerInterface.PeerDHTMessage.prototype.getIsResponse = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.peerInterface.PeerDHTMessage} returns this + */ +proto.peerInterface.PeerDHTMessage.prototype.setIsResponse = function(value) { + return jspb.Message.setProto3BooleanField(this, 2, value); +}; + + +/** + * optional bytes sub_message = 3; + * @return {!(string|Uint8Array)} + */ +proto.peerInterface.PeerDHTMessage.prototype.getSubMessage = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * optional bytes sub_message = 3; + * This is a type-conversion wrapper around `getSubMessage()` + * @return {string} + */ +proto.peerInterface.PeerDHTMessage.prototype.getSubMessage_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getSubMessage())); +}; + + +/** + * optional bytes sub_message = 3; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getSubMessage()` + * @return {!Uint8Array} + */ +proto.peerInterface.PeerDHTMessage.prototype.getSubMessage_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getSubMessage())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.peerInterface.PeerDHTMessage} returns this + */ +proto.peerInterface.PeerDHTMessage.prototype.setSubMessage = function(value) { + return jspb.Message.setProto3BytesField(this, 3, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.peerInterface.PeerDHTPingNodeMessage.prototype.toObject = function(opt_includeInstance) { + return proto.peerInterface.PeerDHTPingNodeMessage.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.peerInterface.PeerDHTPingNodeMessage} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.peerInterface.PeerDHTPingNodeMessage.toObject = function(includeInstance, msg) { + var f, obj = { + publicKey: jspb.Message.getFieldWithDefault(msg, 1, ""), + randomChallenge: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.peerInterface.PeerDHTPingNodeMessage} + */ +proto.peerInterface.PeerDHTPingNodeMessage.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.peerInterface.PeerDHTPingNodeMessage; + return proto.peerInterface.PeerDHTPingNodeMessage.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.peerInterface.PeerDHTPingNodeMessage} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.peerInterface.PeerDHTPingNodeMessage} + */ +proto.peerInterface.PeerDHTPingNodeMessage.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setPublicKey(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setRandomChallenge(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.peerInterface.PeerDHTPingNodeMessage.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.peerInterface.PeerDHTPingNodeMessage.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.peerInterface.PeerDHTPingNodeMessage} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.peerInterface.PeerDHTPingNodeMessage.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getPublicKey(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getRandomChallenge(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string public_key = 1; + * @return {string} + */ +proto.peerInterface.PeerDHTPingNodeMessage.prototype.getPublicKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.peerInterface.PeerDHTPingNodeMessage} returns this + */ +proto.peerInterface.PeerDHTPingNodeMessage.prototype.setPublicKey = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string random_challenge = 2; + * @return {string} + */ +proto.peerInterface.PeerDHTPingNodeMessage.prototype.getRandomChallenge = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.peerInterface.PeerDHTPingNodeMessage} returns this + */ +proto.peerInterface.PeerDHTPingNodeMessage.prototype.setRandomChallenge = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.peerInterface.PeerDHTFindNodeMessage.repeatedFields_ = [2]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.peerInterface.PeerDHTFindNodeMessage.prototype.toObject = function(opt_includeInstance) { + return proto.peerInterface.PeerDHTFindNodeMessage.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.peerInterface.PeerDHTFindNodeMessage} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.peerInterface.PeerDHTFindNodeMessage.toObject = function(includeInstance, msg) { + var f, obj = { + publicKey: jspb.Message.getFieldWithDefault(msg, 1, ""), + closestPeersList: jspb.Message.toObjectList(msg.getClosestPeersList(), + proto.peerInterface.PeerInfoMessage.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.peerInterface.PeerDHTFindNodeMessage} + */ +proto.peerInterface.PeerDHTFindNodeMessage.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.peerInterface.PeerDHTFindNodeMessage; + return proto.peerInterface.PeerDHTFindNodeMessage.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.peerInterface.PeerDHTFindNodeMessage} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.peerInterface.PeerDHTFindNodeMessage} + */ +proto.peerInterface.PeerDHTFindNodeMessage.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setPublicKey(value); + break; + case 2: + var value = new proto.peerInterface.PeerInfoMessage; + reader.readMessage(value,proto.peerInterface.PeerInfoMessage.deserializeBinaryFromReader); + msg.addClosestPeers(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.peerInterface.PeerDHTFindNodeMessage.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.peerInterface.PeerDHTFindNodeMessage.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.peerInterface.PeerDHTFindNodeMessage} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.peerInterface.PeerDHTFindNodeMessage.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getPublicKey(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getClosestPeersList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 2, + f, + proto.peerInterface.PeerInfoMessage.serializeBinaryToWriter + ); + } +}; + + +/** + * optional string public_key = 1; + * @return {string} + */ +proto.peerInterface.PeerDHTFindNodeMessage.prototype.getPublicKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.peerInterface.PeerDHTFindNodeMessage} returns this + */ +proto.peerInterface.PeerDHTFindNodeMessage.prototype.setPublicKey = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * repeated PeerInfoMessage closest_peers = 2; + * @return {!Array} + */ +proto.peerInterface.PeerDHTFindNodeMessage.prototype.getClosestPeersList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.peerInterface.PeerInfoMessage, 2)); +}; + + +/** + * @param {!Array} value + * @return {!proto.peerInterface.PeerDHTFindNodeMessage} returns this +*/ +proto.peerInterface.PeerDHTFindNodeMessage.prototype.setClosestPeersList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 2, value); +}; + + +/** + * @param {!proto.peerInterface.PeerInfoMessage=} opt_value + * @param {number=} opt_index + * @return {!proto.peerInterface.PeerInfoMessage} + */ +proto.peerInterface.PeerDHTFindNodeMessage.prototype.addClosestPeers = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.peerInterface.PeerInfoMessage, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.peerInterface.PeerDHTFindNodeMessage} returns this + */ +proto.peerInterface.PeerDHTFindNodeMessage.prototype.clearClosestPeersList = function() { + return this.setClosestPeersList([]); +}; + + +/** + * @enum {number} + */ +proto.peerInterface.SubServiceType = { + PING_PEER: 0, + GIT: 1, + NAT_TRAVERSAL: 2, + CERTIFICATE_AUTHORITY: 3, + PEER_DHT: 4 +}; + +/** + * @enum {number} + */ +proto.peerInterface.NatMessageType = { + UDP_ADDRESS: 0, + RELAY_CONNECTION: 1, + PEER_CONNECTION: 2, + PEER_UDP_ADDRESS: 3 +}; + +/** + * @enum {number} + */ +proto.peerInterface.CAMessageType = { + ROOT_CERT: 0, + REQUEST_CERT: 1 +}; + +/** + * @enum {number} + */ +proto.peerInterface.PeerDHTMessageType = { + PING: 0, + FIND_NODE: 1 }; goog.object.extend(exports, proto.peerInterface); diff --git a/proto/js/Agent.d.ts b/proto/js/Agent.d.ts new file mode 100644 index 000000000..526de9736 --- /dev/null +++ b/proto/js/Agent.d.ts @@ -0,0 +1,2336 @@ +import * as $protobuf from "protobufjs"; +export = Agent; + +declare namespace Agent { + + + /** Namespace agentInterface. */ + namespace agentInterface { + + /** Represents an Agent */ + class Agent extends $protobuf.rpc.Service { + + /** + * Constructs a new Agent service. + * @param rpcImpl RPC implementation + * @param [requestDelimited=false] Whether requests are length-delimited + * @param [responseDelimited=false] Whether responses are length-delimited + */ + constructor(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean); + + /** + * Creates new Agent service using the specified rpc implementation. + * @param rpcImpl RPC implementation + * @param [requestDelimited=false] Whether requests are length-delimited + * @param [responseDelimited=false] Whether responses are length-delimited + * @returns RPC service. Useful where requests and/or responses are streamed. + */ + public static create(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean): Agent; + + /** + * Calls AddPeer. + * @param request PeerInfoMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public addPeer(request: agentInterface.IPeerInfoMessage, callback: agentInterface.Agent.AddPeerCallback): void; + + /** + * Calls AddPeer. + * @param request PeerInfoMessage message or plain object + * @returns Promise + */ + public addPeer(request: agentInterface.IPeerInfoMessage): Promise; + + /** + * Calls DecryptFile. + * @param request DecryptFileMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringMessage + */ + public decryptFile(request: agentInterface.IDecryptFileMessage, callback: agentInterface.Agent.DecryptFileCallback): void; + + /** + * Calls DecryptFile. + * @param request DecryptFileMessage message or plain object + * @returns Promise + */ + public decryptFile(request: agentInterface.IDecryptFileMessage): Promise; + + /** + * Calls DeleteKey. + * @param request StringMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public deleteKey(request: agentInterface.IStringMessage, callback: agentInterface.Agent.DeleteKeyCallback): void; + + /** + * Calls DeleteKey. + * @param request StringMessage message or plain object + * @returns Promise + */ + public deleteKey(request: agentInterface.IStringMessage): Promise; + + /** + * Calls DeleteSecret. + * @param request SecretPathMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public deleteSecret(request: agentInterface.ISecretPathMessage, callback: agentInterface.Agent.DeleteSecretCallback): void; + + /** + * Calls DeleteSecret. + * @param request SecretPathMessage message or plain object + * @returns Promise + */ + public deleteSecret(request: agentInterface.ISecretPathMessage): Promise; + + /** + * Calls DeleteVault. + * @param request StringMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public deleteVault(request: agentInterface.IStringMessage, callback: agentInterface.Agent.DeleteVaultCallback): void; + + /** + * Calls DeleteVault. + * @param request StringMessage message or plain object + * @returns Promise + */ + public deleteVault(request: agentInterface.IStringMessage): Promise; + + /** + * Calls DeriveKey. + * @param request DeriveKeyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public deriveKey(request: agentInterface.IDeriveKeyMessage, callback: agentInterface.Agent.DeriveKeyCallback): void; + + /** + * Calls DeriveKey. + * @param request DeriveKeyMessage message or plain object + * @returns Promise + */ + public deriveKey(request: agentInterface.IDeriveKeyMessage): Promise; + + /** + * Calls EncryptFile. + * @param request EncryptFileMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringMessage + */ + public encryptFile(request: agentInterface.IEncryptFileMessage, callback: agentInterface.Agent.EncryptFileCallback): void; + + /** + * Calls EncryptFile. + * @param request EncryptFileMessage message or plain object + * @returns Promise + */ + public encryptFile(request: agentInterface.IEncryptFileMessage): Promise; + + /** + * Calls FindPeer. + * @param request ContactPeerMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public findPeer(request: agentInterface.IContactPeerMessage, callback: agentInterface.Agent.FindPeerCallback): void; + + /** + * Calls FindPeer. + * @param request ContactPeerMessage message or plain object + * @returns Promise + */ + public findPeer(request: agentInterface.IContactPeerMessage): Promise; + + /** + * Calls FindSocialPeer. + * @param request ContactPeerMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public findSocialPeer(request: agentInterface.IContactPeerMessage, callback: agentInterface.Agent.FindSocialPeerCallback): void; + + /** + * Calls FindSocialPeer. + * @param request ContactPeerMessage message or plain object + * @returns Promise + */ + public findSocialPeer(request: agentInterface.IContactPeerMessage): Promise; + + /** + * Calls GetOAuthClient. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and OAuthClientMessage + */ + public getOAuthClient(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.GetOAuthClientCallback): void; + + /** + * Calls GetOAuthClient. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public getOAuthClient(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls GetKey. + * @param request StringMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringMessage + */ + public getKey(request: agentInterface.IStringMessage, callback: agentInterface.Agent.GetKeyCallback): void; + + /** + * Calls GetKey. + * @param request StringMessage message or plain object + * @returns Promise + */ + public getKey(request: agentInterface.IStringMessage): Promise; + + /** + * Calls GetLocalPeerInfo. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and PeerInfoMessage + */ + public getLocalPeerInfo(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.GetLocalPeerInfoCallback): void; + + /** + * Calls GetLocalPeerInfo. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public getLocalPeerInfo(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls GetPeerInfo. + * @param request StringMessage message or plain object + * @param callback Node-style callback called with the error, if any, and PeerInfoMessage + */ + public getPeerInfo(request: agentInterface.IStringMessage, callback: agentInterface.Agent.GetPeerInfoCallback): void; + + /** + * Calls GetPeerInfo. + * @param request StringMessage message or plain object + * @returns Promise + */ + public getPeerInfo(request: agentInterface.IStringMessage): Promise; + + /** + * Calls GetPrimaryKeyPair. + * @param request BooleanMessage message or plain object + * @param callback Node-style callback called with the error, if any, and KeyPairMessage + */ + public getPrimaryKeyPair(request: agentInterface.IBooleanMessage, callback: agentInterface.Agent.GetPrimaryKeyPairCallback): void; + + /** + * Calls GetPrimaryKeyPair. + * @param request BooleanMessage message or plain object + * @returns Promise + */ + public getPrimaryKeyPair(request: agentInterface.IBooleanMessage): Promise; + + /** + * Calls GetRootCertificate. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringMessage + */ + public getRootCertificate(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.GetRootCertificateCallback): void; + + /** + * Calls GetRootCertificate. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public getRootCertificate(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls GetSecret. + * @param request SecretPathMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringMessage + */ + public getSecret(request: agentInterface.ISecretPathMessage, callback: agentInterface.Agent.GetSecretCallback): void; + + /** + * Calls GetSecret. + * @param request SecretPathMessage message or plain object + * @returns Promise + */ + public getSecret(request: agentInterface.ISecretPathMessage): Promise; + + /** + * Calls GetStatus. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and AgentStatusMessage + */ + public getStatus(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.GetStatusCallback): void; + + /** + * Calls GetStatus. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public getStatus(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls ListOAuthTokens. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringListMessage + */ + public listOAuthTokens(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.ListOAuthTokensCallback): void; + + /** + * Calls ListOAuthTokens. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public listOAuthTokens(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls ListKeys. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringListMessage + */ + public listKeys(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.ListKeysCallback): void; + + /** + * Calls ListKeys. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public listKeys(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls ListNodes. + * @param request BooleanMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringListMessage + */ + public listNodes(request: agentInterface.IBooleanMessage, callback: agentInterface.Agent.ListNodesCallback): void; + + /** + * Calls ListNodes. + * @param request BooleanMessage message or plain object + * @returns Promise + */ + public listNodes(request: agentInterface.IBooleanMessage): Promise; + + /** + * Calls ListPeers. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringListMessage + */ + public listPeers(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.ListPeersCallback): void; + + /** + * Calls ListPeers. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public listPeers(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls ListSecrets. + * @param request StringMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringListMessage + */ + public listSecrets(request: agentInterface.IStringMessage, callback: agentInterface.Agent.ListSecretsCallback): void; + + /** + * Calls ListSecrets. + * @param request StringMessage message or plain object + * @returns Promise + */ + public listSecrets(request: agentInterface.IStringMessage): Promise; + + /** + * Calls ListVaults. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringListMessage + */ + public listVaults(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.ListVaultsCallback): void; + + /** + * Calls ListVaults. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public listVaults(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls LockNode. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and EmptyMessage + */ + public lockNode(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.LockNodeCallback): void; + + /** + * Calls LockNode. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public lockNode(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls NewClientCertificate. + * @param request NewClientCertificateMessage message or plain object + * @param callback Node-style callback called with the error, if any, and NewClientCertificateMessage + */ + public newClientCertificate(request: agentInterface.INewClientCertificateMessage, callback: agentInterface.Agent.NewClientCertificateCallback): void; + + /** + * Calls NewClientCertificate. + * @param request NewClientCertificateMessage message or plain object + * @returns Promise + */ + public newClientCertificate(request: agentInterface.INewClientCertificateMessage): Promise; + + /** + * Calls NewNode. + * @param request NewNodeMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public newNode(request: agentInterface.INewNodeMessage, callback: agentInterface.Agent.NewNodeCallback): void; + + /** + * Calls NewNode. + * @param request NewNodeMessage message or plain object + * @returns Promise + */ + public newNode(request: agentInterface.INewNodeMessage): Promise; + + /** + * Calls NewSecret. + * @param request SecretContentMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public newSecret(request: agentInterface.ISecretContentMessage, callback: agentInterface.Agent.NewSecretCallback): void; + + /** + * Calls NewSecret. + * @param request SecretContentMessage message or plain object + * @returns Promise + */ + public newSecret(request: agentInterface.ISecretContentMessage): Promise; + + /** + * Calls NewOAuthToken. + * @param request NewOAuthTokenMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringMessage + */ + public newOAuthToken(request: agentInterface.INewOAuthTokenMessage, callback: agentInterface.Agent.NewOAuthTokenCallback): void; + + /** + * Calls NewOAuthToken. + * @param request NewOAuthTokenMessage message or plain object + * @returns Promise + */ + public newOAuthToken(request: agentInterface.INewOAuthTokenMessage): Promise; + + /** + * Calls NewVault. + * @param request StringMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public newVault(request: agentInterface.IStringMessage, callback: agentInterface.Agent.NewVaultCallback): void; + + /** + * Calls NewVault. + * @param request StringMessage message or plain object + * @returns Promise + */ + public newVault(request: agentInterface.IStringMessage): Promise; + + /** + * Calls PingPeer. + * @param request ContactPeerMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public pingPeer(request: agentInterface.IContactPeerMessage, callback: agentInterface.Agent.PingPeerCallback): void; + + /** + * Calls PingPeer. + * @param request ContactPeerMessage message or plain object + * @returns Promise + */ + public pingPeer(request: agentInterface.IContactPeerMessage): Promise; + + /** + * Calls PullVault. + * @param request VaultPathMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public pullVault(request: agentInterface.IVaultPathMessage, callback: agentInterface.Agent.PullVaultCallback): void; + + /** + * Calls PullVault. + * @param request VaultPathMessage message or plain object + * @returns Promise + */ + public pullVault(request: agentInterface.IVaultPathMessage): Promise; + + /** + * Calls RevokeOAuthToken. + * @param request StringMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public revokeOAuthToken(request: agentInterface.IStringMessage, callback: agentInterface.Agent.RevokeOAuthTokenCallback): void; + + /** + * Calls RevokeOAuthToken. + * @param request StringMessage message or plain object + * @returns Promise + */ + public revokeOAuthToken(request: agentInterface.IStringMessage): Promise; + + /** + * Calls ScanVaultNames. + * @param request StringMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringListMessage + */ + public scanVaultNames(request: agentInterface.IStringMessage, callback: agentInterface.Agent.ScanVaultNamesCallback): void; + + /** + * Calls ScanVaultNames. + * @param request StringMessage message or plain object + * @returns Promise + */ + public scanVaultNames(request: agentInterface.IStringMessage): Promise; + + /** + * Calls SignFile. + * @param request SignFileMessage message or plain object + * @param callback Node-style callback called with the error, if any, and StringMessage + */ + public signFile(request: agentInterface.ISignFileMessage, callback: agentInterface.Agent.SignFileCallback): void; + + /** + * Calls SignFile. + * @param request SignFileMessage message or plain object + * @returns Promise + */ + public signFile(request: agentInterface.ISignFileMessage): Promise; + + /** + * Calls StopAgent. + * @param request EmptyMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public stopAgent(request: agentInterface.IEmptyMessage, callback: agentInterface.Agent.StopAgentCallback): void; + + /** + * Calls StopAgent. + * @param request EmptyMessage message or plain object + * @returns Promise + */ + public stopAgent(request: agentInterface.IEmptyMessage): Promise; + + /** + * Calls ToggleStealthMode. + * @param request BooleanMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public toggleStealthMode(request: agentInterface.IBooleanMessage, callback: agentInterface.Agent.ToggleStealthModeCallback): void; + + /** + * Calls ToggleStealthMode. + * @param request BooleanMessage message or plain object + * @returns Promise + */ + public toggleStealthMode(request: agentInterface.IBooleanMessage): Promise; + + /** + * Calls UnlockNode. + * @param request UnlockNodeMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public unlockNode(request: agentInterface.IUnlockNodeMessage, callback: agentInterface.Agent.UnlockNodeCallback): void; + + /** + * Calls UnlockNode. + * @param request UnlockNodeMessage message or plain object + * @returns Promise + */ + public unlockNode(request: agentInterface.IUnlockNodeMessage): Promise; + + /** + * Calls UpdateLocalPeerInfo. + * @param request PeerInfoMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public updateLocalPeerInfo(request: agentInterface.IPeerInfoMessage, callback: agentInterface.Agent.UpdateLocalPeerInfoCallback): void; + + /** + * Calls UpdateLocalPeerInfo. + * @param request PeerInfoMessage message or plain object + * @returns Promise + */ + public updateLocalPeerInfo(request: agentInterface.IPeerInfoMessage): Promise; + + /** + * Calls UpdatePeerInfo. + * @param request PeerInfoMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public updatePeerInfo(request: agentInterface.IPeerInfoMessage, callback: agentInterface.Agent.UpdatePeerInfoCallback): void; + + /** + * Calls UpdatePeerInfo. + * @param request PeerInfoMessage message or plain object + * @returns Promise + */ + public updatePeerInfo(request: agentInterface.IPeerInfoMessage): Promise; + + /** + * Calls UpdateSecret. + * @param request SecretContentMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public updateSecret(request: agentInterface.ISecretContentMessage, callback: agentInterface.Agent.UpdateSecretCallback): void; + + /** + * Calls UpdateSecret. + * @param request SecretContentMessage message or plain object + * @returns Promise + */ + public updateSecret(request: agentInterface.ISecretContentMessage): Promise; + + /** + * Calls VerifyFile. + * @param request VerifyFileMessage message or plain object + * @param callback Node-style callback called with the error, if any, and BooleanMessage + */ + public verifyFile(request: agentInterface.IVerifyFileMessage, callback: agentInterface.Agent.VerifyFileCallback): void; + + /** + * Calls VerifyFile. + * @param request VerifyFileMessage message or plain object + * @returns Promise + */ + public verifyFile(request: agentInterface.IVerifyFileMessage): Promise; + } + + namespace Agent { + + /** + * Callback as used by {@link agentInterface.Agent#addPeer}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type AddPeerCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#decryptFile}. + * @param error Error, if any + * @param [response] StringMessage + */ + type DecryptFileCallback = (error: (Error|null), response?: agentInterface.StringMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#deleteKey}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type DeleteKeyCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#deleteSecret}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type DeleteSecretCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#deleteVault}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type DeleteVaultCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#deriveKey}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type DeriveKeyCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#encryptFile}. + * @param error Error, if any + * @param [response] StringMessage + */ + type EncryptFileCallback = (error: (Error|null), response?: agentInterface.StringMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#findPeer}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type FindPeerCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#findSocialPeer}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type FindSocialPeerCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#getOAuthClient}. + * @param error Error, if any + * @param [response] OAuthClientMessage + */ + type GetOAuthClientCallback = (error: (Error|null), response?: agentInterface.OAuthClientMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#getKey}. + * @param error Error, if any + * @param [response] StringMessage + */ + type GetKeyCallback = (error: (Error|null), response?: agentInterface.StringMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#getLocalPeerInfo}. + * @param error Error, if any + * @param [response] PeerInfoMessage + */ + type GetLocalPeerInfoCallback = (error: (Error|null), response?: agentInterface.PeerInfoMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#getPeerInfo}. + * @param error Error, if any + * @param [response] PeerInfoMessage + */ + type GetPeerInfoCallback = (error: (Error|null), response?: agentInterface.PeerInfoMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#getPrimaryKeyPair}. + * @param error Error, if any + * @param [response] KeyPairMessage + */ + type GetPrimaryKeyPairCallback = (error: (Error|null), response?: agentInterface.KeyPairMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#getRootCertificate}. + * @param error Error, if any + * @param [response] StringMessage + */ + type GetRootCertificateCallback = (error: (Error|null), response?: agentInterface.StringMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#getSecret}. + * @param error Error, if any + * @param [response] StringMessage + */ + type GetSecretCallback = (error: (Error|null), response?: agentInterface.StringMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#getStatus}. + * @param error Error, if any + * @param [response] AgentStatusMessage + */ + type GetStatusCallback = (error: (Error|null), response?: agentInterface.AgentStatusMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#listOAuthTokens}. + * @param error Error, if any + * @param [response] StringListMessage + */ + type ListOAuthTokensCallback = (error: (Error|null), response?: agentInterface.StringListMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#listKeys}. + * @param error Error, if any + * @param [response] StringListMessage + */ + type ListKeysCallback = (error: (Error|null), response?: agentInterface.StringListMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#listNodes}. + * @param error Error, if any + * @param [response] StringListMessage + */ + type ListNodesCallback = (error: (Error|null), response?: agentInterface.StringListMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#listPeers}. + * @param error Error, if any + * @param [response] StringListMessage + */ + type ListPeersCallback = (error: (Error|null), response?: agentInterface.StringListMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#listSecrets}. + * @param error Error, if any + * @param [response] StringListMessage + */ + type ListSecretsCallback = (error: (Error|null), response?: agentInterface.StringListMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#listVaults}. + * @param error Error, if any + * @param [response] StringListMessage + */ + type ListVaultsCallback = (error: (Error|null), response?: agentInterface.StringListMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#lockNode}. + * @param error Error, if any + * @param [response] EmptyMessage + */ + type LockNodeCallback = (error: (Error|null), response?: agentInterface.EmptyMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#newClientCertificate}. + * @param error Error, if any + * @param [response] NewClientCertificateMessage + */ + type NewClientCertificateCallback = (error: (Error|null), response?: agentInterface.NewClientCertificateMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#newNode}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type NewNodeCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#newSecret}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type NewSecretCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#newOAuthToken}. + * @param error Error, if any + * @param [response] StringMessage + */ + type NewOAuthTokenCallback = (error: (Error|null), response?: agentInterface.StringMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#newVault}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type NewVaultCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#pingPeer}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type PingPeerCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#pullVault}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type PullVaultCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#revokeOAuthToken}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type RevokeOAuthTokenCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#scanVaultNames}. + * @param error Error, if any + * @param [response] StringListMessage + */ + type ScanVaultNamesCallback = (error: (Error|null), response?: agentInterface.StringListMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#signFile}. + * @param error Error, if any + * @param [response] StringMessage + */ + type SignFileCallback = (error: (Error|null), response?: agentInterface.StringMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#stopAgent}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type StopAgentCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#toggleStealthMode}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type ToggleStealthModeCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#unlockNode}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type UnlockNodeCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#updateLocalPeerInfo}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type UpdateLocalPeerInfoCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#updatePeerInfo}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type UpdatePeerInfoCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#updateSecret}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type UpdateSecretCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + + /** + * Callback as used by {@link agentInterface.Agent#verifyFile}. + * @param error Error, if any + * @param [response] BooleanMessage + */ + type VerifyFileCallback = (error: (Error|null), response?: agentInterface.BooleanMessage) => void; + } + + /** Properties of an EmptyMessage. */ + interface IEmptyMessage { + } + + /** Represents an EmptyMessage. */ + class EmptyMessage implements IEmptyMessage { + + /** + * Constructs a new EmptyMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IEmptyMessage); + + /** + * Creates a new EmptyMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns EmptyMessage instance + */ + public static create(properties?: agentInterface.IEmptyMessage): agentInterface.EmptyMessage; + + /** + * Encodes the specified EmptyMessage message. Does not implicitly {@link agentInterface.EmptyMessage.verify|verify} messages. + * @param m EmptyMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IEmptyMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified EmptyMessage message, length delimited. Does not implicitly {@link agentInterface.EmptyMessage.verify|verify} messages. + * @param message EmptyMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IEmptyMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes an EmptyMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns EmptyMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.EmptyMessage; + + /** + * Decodes an EmptyMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns EmptyMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.EmptyMessage; + } + + /** Properties of a StringMessage. */ + interface IStringMessage { + + /** StringMessage s */ + s?: (string|null); + } + + /** Represents a StringMessage. */ + class StringMessage implements IStringMessage { + + /** + * Constructs a new StringMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IStringMessage); + + /** StringMessage s. */ + public s: string; + + /** + * Creates a new StringMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns StringMessage instance + */ + public static create(properties?: agentInterface.IStringMessage): agentInterface.StringMessage; + + /** + * Encodes the specified StringMessage message. Does not implicitly {@link agentInterface.StringMessage.verify|verify} messages. + * @param m StringMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IStringMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified StringMessage message, length delimited. Does not implicitly {@link agentInterface.StringMessage.verify|verify} messages. + * @param message StringMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IStringMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a StringMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns StringMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.StringMessage; + + /** + * Decodes a StringMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns StringMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.StringMessage; + } + + /** Properties of a BooleanMessage. */ + interface IBooleanMessage { + + /** BooleanMessage b */ + b?: (boolean|null); + } + + /** Represents a BooleanMessage. */ + class BooleanMessage implements IBooleanMessage { + + /** + * Constructs a new BooleanMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IBooleanMessage); + + /** BooleanMessage b. */ + public b: boolean; + + /** + * Creates a new BooleanMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns BooleanMessage instance + */ + public static create(properties?: agentInterface.IBooleanMessage): agentInterface.BooleanMessage; + + /** + * Encodes the specified BooleanMessage message. Does not implicitly {@link agentInterface.BooleanMessage.verify|verify} messages. + * @param m BooleanMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IBooleanMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified BooleanMessage message, length delimited. Does not implicitly {@link agentInterface.BooleanMessage.verify|verify} messages. + * @param message BooleanMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IBooleanMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a BooleanMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns BooleanMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.BooleanMessage; + + /** + * Decodes a BooleanMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns BooleanMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.BooleanMessage; + } + + /** Properties of a StringListMessage. */ + interface IStringListMessage { + + /** StringListMessage s */ + s?: (string[]|null); + } + + /** Represents a StringListMessage. */ + class StringListMessage implements IStringListMessage { + + /** + * Constructs a new StringListMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IStringListMessage); + + /** StringListMessage s. */ + public s: string[]; + + /** + * Creates a new StringListMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns StringListMessage instance + */ + public static create(properties?: agentInterface.IStringListMessage): agentInterface.StringListMessage; + + /** + * Encodes the specified StringListMessage message. Does not implicitly {@link agentInterface.StringListMessage.verify|verify} messages. + * @param m StringListMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IStringListMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified StringListMessage message, length delimited. Does not implicitly {@link agentInterface.StringListMessage.verify|verify} messages. + * @param message StringListMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IStringListMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a StringListMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns StringListMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.StringListMessage; + + /** + * Decodes a StringListMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns StringListMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.StringListMessage; + } + + /** Properties of a PeerInfoMessage. */ + interface IPeerInfoMessage { + + /** PeerInfoMessage publicKey */ + publicKey?: (string|null); + + /** PeerInfoMessage rootCertificate */ + rootCertificate?: (string|null); + + /** PeerInfoMessage peerAddress */ + peerAddress?: (string|null); + + /** PeerInfoMessage apiAddress */ + apiAddress?: (string|null); + } + + /** Represents a PeerInfoMessage. */ + class PeerInfoMessage implements IPeerInfoMessage { + + /** + * Constructs a new PeerInfoMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IPeerInfoMessage); + + /** PeerInfoMessage publicKey. */ + public publicKey: string; + + /** PeerInfoMessage rootCertificate. */ + public rootCertificate: string; + + /** PeerInfoMessage peerAddress. */ + public peerAddress: string; + + /** PeerInfoMessage apiAddress. */ + public apiAddress: string; + + /** + * Creates a new PeerInfoMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns PeerInfoMessage instance + */ + public static create(properties?: agentInterface.IPeerInfoMessage): agentInterface.PeerInfoMessage; + + /** + * Encodes the specified PeerInfoMessage message. Does not implicitly {@link agentInterface.PeerInfoMessage.verify|verify} messages. + * @param m PeerInfoMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IPeerInfoMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified PeerInfoMessage message, length delimited. Does not implicitly {@link agentInterface.PeerInfoMessage.verify|verify} messages. + * @param message PeerInfoMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IPeerInfoMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a PeerInfoMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns PeerInfoMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.PeerInfoMessage; + + /** + * Decodes a PeerInfoMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns PeerInfoMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.PeerInfoMessage; + } + + /** AgentStatusType enum. */ + enum AgentStatusType { + ONLINE = 0, + OFFLINE = 1, + ERRORED = 2 + } + + /** Properties of an AgentStatusMessage. */ + interface IAgentStatusMessage { + + /** AgentStatusMessage status */ + status?: (agentInterface.AgentStatusType|null); + } + + /** Represents an AgentStatusMessage. */ + class AgentStatusMessage implements IAgentStatusMessage { + + /** + * Constructs a new AgentStatusMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IAgentStatusMessage); + + /** AgentStatusMessage status. */ + public status: agentInterface.AgentStatusType; + + /** + * Creates a new AgentStatusMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns AgentStatusMessage instance + */ + public static create(properties?: agentInterface.IAgentStatusMessage): agentInterface.AgentStatusMessage; + + /** + * Encodes the specified AgentStatusMessage message. Does not implicitly {@link agentInterface.AgentStatusMessage.verify|verify} messages. + * @param m AgentStatusMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IAgentStatusMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified AgentStatusMessage message, length delimited. Does not implicitly {@link agentInterface.AgentStatusMessage.verify|verify} messages. + * @param message AgentStatusMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IAgentStatusMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes an AgentStatusMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns AgentStatusMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.AgentStatusMessage; + + /** + * Decodes an AgentStatusMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns AgentStatusMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.AgentStatusMessage; + } + + /** Properties of a NewNodeMessage. */ + interface INewNodeMessage { + + /** NewNodeMessage userId */ + userId?: (string|null); + + /** NewNodeMessage passphrase */ + passphrase?: (string|null); + } + + /** Represents a NewNodeMessage. */ + class NewNodeMessage implements INewNodeMessage { + + /** + * Constructs a new NewNodeMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.INewNodeMessage); + + /** NewNodeMessage userId. */ + public userId: string; + + /** NewNodeMessage passphrase. */ + public passphrase: string; + + /** + * Creates a new NewNodeMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns NewNodeMessage instance + */ + public static create(properties?: agentInterface.INewNodeMessage): agentInterface.NewNodeMessage; + + /** + * Encodes the specified NewNodeMessage message. Does not implicitly {@link agentInterface.NewNodeMessage.verify|verify} messages. + * @param m NewNodeMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.INewNodeMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified NewNodeMessage message, length delimited. Does not implicitly {@link agentInterface.NewNodeMessage.verify|verify} messages. + * @param message NewNodeMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.INewNodeMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a NewNodeMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns NewNodeMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.NewNodeMessage; + + /** + * Decodes a NewNodeMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns NewNodeMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.NewNodeMessage; + } + + /** Properties of a DeriveKeyMessage. */ + interface IDeriveKeyMessage { + + /** DeriveKeyMessage vaultName */ + vaultName?: (string|null); + + /** DeriveKeyMessage keyName */ + keyName?: (string|null); + + /** DeriveKeyMessage passphrase */ + passphrase?: (string|null); + } + + /** Represents a DeriveKeyMessage. */ + class DeriveKeyMessage implements IDeriveKeyMessage { + + /** + * Constructs a new DeriveKeyMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IDeriveKeyMessage); + + /** DeriveKeyMessage vaultName. */ + public vaultName: string; + + /** DeriveKeyMessage keyName. */ + public keyName: string; + + /** DeriveKeyMessage passphrase. */ + public passphrase: string; + + /** + * Creates a new DeriveKeyMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns DeriveKeyMessage instance + */ + public static create(properties?: agentInterface.IDeriveKeyMessage): agentInterface.DeriveKeyMessage; + + /** + * Encodes the specified DeriveKeyMessage message. Does not implicitly {@link agentInterface.DeriveKeyMessage.verify|verify} messages. + * @param m DeriveKeyMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IDeriveKeyMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified DeriveKeyMessage message, length delimited. Does not implicitly {@link agentInterface.DeriveKeyMessage.verify|verify} messages. + * @param message DeriveKeyMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IDeriveKeyMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a DeriveKeyMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns DeriveKeyMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.DeriveKeyMessage; + + /** + * Decodes a DeriveKeyMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns DeriveKeyMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.DeriveKeyMessage; + } + + /** Properties of a SignFileMessage. */ + interface ISignFileMessage { + + /** SignFileMessage filePath */ + filePath?: (string|null); + + /** SignFileMessage privateKeyPath */ + privateKeyPath?: (string|null); + + /** SignFileMessage passphrase */ + passphrase?: (string|null); + } + + /** Represents a SignFileMessage. */ + class SignFileMessage implements ISignFileMessage { + + /** + * Constructs a new SignFileMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.ISignFileMessage); + + /** SignFileMessage filePath. */ + public filePath: string; + + /** SignFileMessage privateKeyPath. */ + public privateKeyPath: string; + + /** SignFileMessage passphrase. */ + public passphrase: string; + + /** + * Creates a new SignFileMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns SignFileMessage instance + */ + public static create(properties?: agentInterface.ISignFileMessage): agentInterface.SignFileMessage; + + /** + * Encodes the specified SignFileMessage message. Does not implicitly {@link agentInterface.SignFileMessage.verify|verify} messages. + * @param m SignFileMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.ISignFileMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified SignFileMessage message, length delimited. Does not implicitly {@link agentInterface.SignFileMessage.verify|verify} messages. + * @param message SignFileMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.ISignFileMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a SignFileMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns SignFileMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.SignFileMessage; + + /** + * Decodes a SignFileMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns SignFileMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.SignFileMessage; + } + + /** Properties of a VerifyFileMessage. */ + interface IVerifyFileMessage { + + /** VerifyFileMessage filePath */ + filePath?: (string|null); + + /** VerifyFileMessage publicKeyPath */ + publicKeyPath?: (string|null); + } + + /** Represents a VerifyFileMessage. */ + class VerifyFileMessage implements IVerifyFileMessage { + + /** + * Constructs a new VerifyFileMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IVerifyFileMessage); + + /** VerifyFileMessage filePath. */ + public filePath: string; + + /** VerifyFileMessage publicKeyPath. */ + public publicKeyPath: string; + + /** + * Creates a new VerifyFileMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns VerifyFileMessage instance + */ + public static create(properties?: agentInterface.IVerifyFileMessage): agentInterface.VerifyFileMessage; + + /** + * Encodes the specified VerifyFileMessage message. Does not implicitly {@link agentInterface.VerifyFileMessage.verify|verify} messages. + * @param m VerifyFileMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IVerifyFileMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified VerifyFileMessage message, length delimited. Does not implicitly {@link agentInterface.VerifyFileMessage.verify|verify} messages. + * @param message VerifyFileMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IVerifyFileMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a VerifyFileMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns VerifyFileMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.VerifyFileMessage; + + /** + * Decodes a VerifyFileMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns VerifyFileMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.VerifyFileMessage; + } + + /** Properties of a SecretPathMessage. */ + interface ISecretPathMessage { + + /** SecretPathMessage vaultName */ + vaultName?: (string|null); + + /** SecretPathMessage secretName */ + secretName?: (string|null); + } + + /** Represents a SecretPathMessage. */ + class SecretPathMessage implements ISecretPathMessage { + + /** + * Constructs a new SecretPathMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.ISecretPathMessage); + + /** SecretPathMessage vaultName. */ + public vaultName: string; + + /** SecretPathMessage secretName. */ + public secretName: string; + + /** + * Creates a new SecretPathMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns SecretPathMessage instance + */ + public static create(properties?: agentInterface.ISecretPathMessage): agentInterface.SecretPathMessage; + + /** + * Encodes the specified SecretPathMessage message. Does not implicitly {@link agentInterface.SecretPathMessage.verify|verify} messages. + * @param m SecretPathMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.ISecretPathMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified SecretPathMessage message, length delimited. Does not implicitly {@link agentInterface.SecretPathMessage.verify|verify} messages. + * @param message SecretPathMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.ISecretPathMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a SecretPathMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns SecretPathMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.SecretPathMessage; + + /** + * Decodes a SecretPathMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns SecretPathMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.SecretPathMessage; + } + + /** Properties of a SecretContentMessage. */ + interface ISecretContentMessage { + + /** SecretContentMessage secretPath */ + secretPath?: (agentInterface.ISecretPathMessage|null); + + /** SecretContentMessage secretFilePath */ + secretFilePath?: (string|null); + + /** SecretContentMessage secretContent */ + secretContent?: (string|null); + } + + /** Represents a SecretContentMessage. */ + class SecretContentMessage implements ISecretContentMessage { + + /** + * Constructs a new SecretContentMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.ISecretContentMessage); + + /** SecretContentMessage secretPath. */ + public secretPath?: (agentInterface.ISecretPathMessage|null); + + /** SecretContentMessage secretFilePath. */ + public secretFilePath: string; + + /** SecretContentMessage secretContent. */ + public secretContent: string; + + /** + * Creates a new SecretContentMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns SecretContentMessage instance + */ + public static create(properties?: agentInterface.ISecretContentMessage): agentInterface.SecretContentMessage; + + /** + * Encodes the specified SecretContentMessage message. Does not implicitly {@link agentInterface.SecretContentMessage.verify|verify} messages. + * @param m SecretContentMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.ISecretContentMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified SecretContentMessage message, length delimited. Does not implicitly {@link agentInterface.SecretContentMessage.verify|verify} messages. + * @param message SecretContentMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.ISecretContentMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a SecretContentMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns SecretContentMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.SecretContentMessage; + + /** + * Decodes a SecretContentMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns SecretContentMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.SecretContentMessage; + } + + /** Properties of an EncryptFileMessage. */ + interface IEncryptFileMessage { + + /** EncryptFileMessage filePath */ + filePath?: (string|null); + + /** EncryptFileMessage publicKeyPath */ + publicKeyPath?: (string|null); + } + + /** Represents an EncryptFileMessage. */ + class EncryptFileMessage implements IEncryptFileMessage { + + /** + * Constructs a new EncryptFileMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IEncryptFileMessage); + + /** EncryptFileMessage filePath. */ + public filePath: string; + + /** EncryptFileMessage publicKeyPath. */ + public publicKeyPath: string; + + /** + * Creates a new EncryptFileMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns EncryptFileMessage instance + */ + public static create(properties?: agentInterface.IEncryptFileMessage): agentInterface.EncryptFileMessage; + + /** + * Encodes the specified EncryptFileMessage message. Does not implicitly {@link agentInterface.EncryptFileMessage.verify|verify} messages. + * @param m EncryptFileMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IEncryptFileMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified EncryptFileMessage message, length delimited. Does not implicitly {@link agentInterface.EncryptFileMessage.verify|verify} messages. + * @param message EncryptFileMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IEncryptFileMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes an EncryptFileMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns EncryptFileMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.EncryptFileMessage; + + /** + * Decodes an EncryptFileMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns EncryptFileMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.EncryptFileMessage; + } + + /** Properties of a DecryptFileMessage. */ + interface IDecryptFileMessage { + + /** DecryptFileMessage filePath */ + filePath?: (string|null); + + /** DecryptFileMessage privateKeyPath */ + privateKeyPath?: (string|null); + + /** DecryptFileMessage passphrase */ + passphrase?: (string|null); + } + + /** Represents a DecryptFileMessage. */ + class DecryptFileMessage implements IDecryptFileMessage { + + /** + * Constructs a new DecryptFileMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IDecryptFileMessage); + + /** DecryptFileMessage filePath. */ + public filePath: string; + + /** DecryptFileMessage privateKeyPath. */ + public privateKeyPath: string; + + /** DecryptFileMessage passphrase. */ + public passphrase: string; + + /** + * Creates a new DecryptFileMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns DecryptFileMessage instance + */ + public static create(properties?: agentInterface.IDecryptFileMessage): agentInterface.DecryptFileMessage; + + /** + * Encodes the specified DecryptFileMessage message. Does not implicitly {@link agentInterface.DecryptFileMessage.verify|verify} messages. + * @param m DecryptFileMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IDecryptFileMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified DecryptFileMessage message, length delimited. Does not implicitly {@link agentInterface.DecryptFileMessage.verify|verify} messages. + * @param message DecryptFileMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IDecryptFileMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a DecryptFileMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns DecryptFileMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.DecryptFileMessage; + + /** + * Decodes a DecryptFileMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns DecryptFileMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.DecryptFileMessage; + } + + /** Properties of a KeyPairMessage. */ + interface IKeyPairMessage { + + /** KeyPairMessage publicKey */ + publicKey?: (string|null); + + /** KeyPairMessage privateKey */ + privateKey?: (string|null); + } + + /** Represents a KeyPairMessage. */ + class KeyPairMessage implements IKeyPairMessage { + + /** + * Constructs a new KeyPairMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IKeyPairMessage); + + /** KeyPairMessage publicKey. */ + public publicKey: string; + + /** KeyPairMessage privateKey. */ + public privateKey: string; + + /** + * Creates a new KeyPairMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns KeyPairMessage instance + */ + public static create(properties?: agentInterface.IKeyPairMessage): agentInterface.KeyPairMessage; + + /** + * Encodes the specified KeyPairMessage message. Does not implicitly {@link agentInterface.KeyPairMessage.verify|verify} messages. + * @param m KeyPairMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IKeyPairMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified KeyPairMessage message, length delimited. Does not implicitly {@link agentInterface.KeyPairMessage.verify|verify} messages. + * @param message KeyPairMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IKeyPairMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a KeyPairMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns KeyPairMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.KeyPairMessage; + + /** + * Decodes a KeyPairMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns KeyPairMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.KeyPairMessage; + } + + /** Properties of a VaultPathMessage. */ + interface IVaultPathMessage { + + /** VaultPathMessage vaultName */ + vaultName?: (string|null); + + /** VaultPathMessage publicKey */ + publicKey?: (string|null); + } + + /** Represents a VaultPathMessage. */ + class VaultPathMessage implements IVaultPathMessage { + + /** + * Constructs a new VaultPathMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IVaultPathMessage); + + /** VaultPathMessage vaultName. */ + public vaultName: string; + + /** VaultPathMessage publicKey. */ + public publicKey: string; + + /** + * Creates a new VaultPathMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns VaultPathMessage instance + */ + public static create(properties?: agentInterface.IVaultPathMessage): agentInterface.VaultPathMessage; + + /** + * Encodes the specified VaultPathMessage message. Does not implicitly {@link agentInterface.VaultPathMessage.verify|verify} messages. + * @param m VaultPathMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IVaultPathMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified VaultPathMessage message, length delimited. Does not implicitly {@link agentInterface.VaultPathMessage.verify|verify} messages. + * @param message VaultPathMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IVaultPathMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a VaultPathMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns VaultPathMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.VaultPathMessage; + + /** + * Decodes a VaultPathMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns VaultPathMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.VaultPathMessage; + } + + /** Properties of a ContactPeerMessage. */ + interface IContactPeerMessage { + + /** ContactPeerMessage publicKeyOrHandle */ + publicKeyOrHandle?: (string|null); + + /** ContactPeerMessage timeout */ + timeout?: (number|null); + } + + /** Represents a ContactPeerMessage. */ + class ContactPeerMessage implements IContactPeerMessage { + + /** + * Constructs a new ContactPeerMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IContactPeerMessage); + + /** ContactPeerMessage publicKeyOrHandle. */ + public publicKeyOrHandle: string; + + /** ContactPeerMessage timeout. */ + public timeout: number; + + /** + * Creates a new ContactPeerMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns ContactPeerMessage instance + */ + public static create(properties?: agentInterface.IContactPeerMessage): agentInterface.ContactPeerMessage; + + /** + * Encodes the specified ContactPeerMessage message. Does not implicitly {@link agentInterface.ContactPeerMessage.verify|verify} messages. + * @param m ContactPeerMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IContactPeerMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified ContactPeerMessage message, length delimited. Does not implicitly {@link agentInterface.ContactPeerMessage.verify|verify} messages. + * @param message ContactPeerMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IContactPeerMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a ContactPeerMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns ContactPeerMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.ContactPeerMessage; + + /** + * Decodes a ContactPeerMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns ContactPeerMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.ContactPeerMessage; + } + + /** Properties of an UnlockNodeMessage. */ + interface IUnlockNodeMessage { + + /** UnlockNodeMessage passphrase */ + passphrase?: (string|null); + + /** UnlockNodeMessage timeout */ + timeout?: (number|null); + } + + /** Represents an UnlockNodeMessage. */ + class UnlockNodeMessage implements IUnlockNodeMessage { + + /** + * Constructs a new UnlockNodeMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IUnlockNodeMessage); + + /** UnlockNodeMessage passphrase. */ + public passphrase: string; + + /** UnlockNodeMessage timeout. */ + public timeout: number; + + /** + * Creates a new UnlockNodeMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns UnlockNodeMessage instance + */ + public static create(properties?: agentInterface.IUnlockNodeMessage): agentInterface.UnlockNodeMessage; + + /** + * Encodes the specified UnlockNodeMessage message. Does not implicitly {@link agentInterface.UnlockNodeMessage.verify|verify} messages. + * @param m UnlockNodeMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IUnlockNodeMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified UnlockNodeMessage message, length delimited. Does not implicitly {@link agentInterface.UnlockNodeMessage.verify|verify} messages. + * @param message UnlockNodeMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IUnlockNodeMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes an UnlockNodeMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns UnlockNodeMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.UnlockNodeMessage; + + /** + * Decodes an UnlockNodeMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns UnlockNodeMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.UnlockNodeMessage; + } + + /** Properties of a NewClientCertificateMessage. */ + interface INewClientCertificateMessage { + + /** NewClientCertificateMessage domain */ + domain?: (string|null); + + /** NewClientCertificateMessage certFile */ + certFile?: (string|null); + + /** NewClientCertificateMessage keyFile */ + keyFile?: (string|null); + } + + /** Represents a NewClientCertificateMessage. */ + class NewClientCertificateMessage implements INewClientCertificateMessage { + + /** + * Constructs a new NewClientCertificateMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.INewClientCertificateMessage); + + /** NewClientCertificateMessage domain. */ + public domain: string; + + /** NewClientCertificateMessage certFile. */ + public certFile: string; + + /** NewClientCertificateMessage keyFile. */ + public keyFile: string; + + /** + * Creates a new NewClientCertificateMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns NewClientCertificateMessage instance + */ + public static create(properties?: agentInterface.INewClientCertificateMessage): agentInterface.NewClientCertificateMessage; + + /** + * Encodes the specified NewClientCertificateMessage message. Does not implicitly {@link agentInterface.NewClientCertificateMessage.verify|verify} messages. + * @param m NewClientCertificateMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.INewClientCertificateMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified NewClientCertificateMessage message, length delimited. Does not implicitly {@link agentInterface.NewClientCertificateMessage.verify|verify} messages. + * @param message NewClientCertificateMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.INewClientCertificateMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a NewClientCertificateMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns NewClientCertificateMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.NewClientCertificateMessage; + + /** + * Decodes a NewClientCertificateMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns NewClientCertificateMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.NewClientCertificateMessage; + } + + /** Properties of a NewOAuthTokenMessage. */ + interface INewOAuthTokenMessage { + + /** NewOAuthTokenMessage scopes */ + scopes?: (string[]|null); + + /** NewOAuthTokenMessage expiry */ + expiry?: (number|null); + } + + /** Represents a NewOAuthTokenMessage. */ + class NewOAuthTokenMessage implements INewOAuthTokenMessage { + + /** + * Constructs a new NewOAuthTokenMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.INewOAuthTokenMessage); + + /** NewOAuthTokenMessage scopes. */ + public scopes: string[]; + + /** NewOAuthTokenMessage expiry. */ + public expiry: number; + + /** + * Creates a new NewOAuthTokenMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns NewOAuthTokenMessage instance + */ + public static create(properties?: agentInterface.INewOAuthTokenMessage): agentInterface.NewOAuthTokenMessage; + + /** + * Encodes the specified NewOAuthTokenMessage message. Does not implicitly {@link agentInterface.NewOAuthTokenMessage.verify|verify} messages. + * @param m NewOAuthTokenMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.INewOAuthTokenMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified NewOAuthTokenMessage message, length delimited. Does not implicitly {@link agentInterface.NewOAuthTokenMessage.verify|verify} messages. + * @param message NewOAuthTokenMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.INewOAuthTokenMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a NewOAuthTokenMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns NewOAuthTokenMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.NewOAuthTokenMessage; + + /** + * Decodes a NewOAuthTokenMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns NewOAuthTokenMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.NewOAuthTokenMessage; + } + + /** Properties of a OAuthClientMessage. */ + interface IOAuthClientMessage { + + /** OAuthClientMessage id */ + id?: (string|null); + + /** OAuthClientMessage secret */ + secret?: (string|null); + } + + /** Represents a OAuthClientMessage. */ + class OAuthClientMessage implements IOAuthClientMessage { + + /** + * Constructs a new OAuthClientMessage. + * @param [p] Properties to set + */ + constructor(p?: agentInterface.IOAuthClientMessage); + + /** OAuthClientMessage id. */ + public id: string; + + /** OAuthClientMessage secret. */ + public secret: string; + + /** + * Creates a new OAuthClientMessage instance using the specified properties. + * @param [properties] Properties to set + * @returns OAuthClientMessage instance + */ + public static create(properties?: agentInterface.IOAuthClientMessage): agentInterface.OAuthClientMessage; + + /** + * Encodes the specified OAuthClientMessage message. Does not implicitly {@link agentInterface.OAuthClientMessage.verify|verify} messages. + * @param m OAuthClientMessage message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: agentInterface.IOAuthClientMessage, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified OAuthClientMessage message, length delimited. Does not implicitly {@link agentInterface.OAuthClientMessage.verify|verify} messages. + * @param message OAuthClientMessage message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: agentInterface.IOAuthClientMessage, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a OAuthClientMessage message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns OAuthClientMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): agentInterface.OAuthClientMessage; + + /** + * Decodes a OAuthClientMessage message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns OAuthClientMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): agentInterface.OAuthClientMessage; + } + } +} diff --git a/proto/js/Agent.js b/proto/js/Agent.js index 6d9e0818f..98482af9f 100644 --- a/proto/js/Agent.js +++ b/proto/js/Agent.js @@ -347,6 +347,39 @@ $root.agentInterface = (function() { * @variation 2 */ + /** + * Callback as used by {@link agentInterface.Agent#getOAuthClient}. + * @memberof agentInterface.Agent + * @typedef GetOAuthClientCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {agentInterface.OAuthClientMessage} [response] OAuthClientMessage + */ + + /** + * Calls GetOAuthClient. + * @function getOAuthClient + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IEmptyMessage} request EmptyMessage message or plain object + * @param {agentInterface.Agent.GetOAuthClientCallback} callback Node-style callback called with the error, if any, and OAuthClientMessage + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Agent.prototype.getOAuthClient = function getOAuthClient(request, callback) { + return this.rpcCall(getOAuthClient, $root.agentInterface.EmptyMessage, $root.agentInterface.OAuthClientMessage, request, callback); + }, "name", { value: "GetOAuthClient" }); + + /** + * Calls GetOAuthClient. + * @function getOAuthClient + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IEmptyMessage} request EmptyMessage message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link agentInterface.Agent#getKey}. * @memberof agentInterface.Agent @@ -479,6 +512,39 @@ $root.agentInterface = (function() { * @variation 2 */ + /** + * Callback as used by {@link agentInterface.Agent#getRootCertificate}. + * @memberof agentInterface.Agent + * @typedef GetRootCertificateCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {agentInterface.StringMessage} [response] StringMessage + */ + + /** + * Calls GetRootCertificate. + * @function getRootCertificate + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IEmptyMessage} request EmptyMessage message or plain object + * @param {agentInterface.Agent.GetRootCertificateCallback} callback Node-style callback called with the error, if any, and StringMessage + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Agent.prototype.getRootCertificate = function getRootCertificate(request, callback) { + return this.rpcCall(getRootCertificate, $root.agentInterface.EmptyMessage, $root.agentInterface.StringMessage, request, callback); + }, "name", { value: "GetRootCertificate" }); + + /** + * Calls GetRootCertificate. + * @function getRootCertificate + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IEmptyMessage} request EmptyMessage message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link agentInterface.Agent#getSecret}. * @memberof agentInterface.Agent @@ -545,6 +611,39 @@ $root.agentInterface = (function() { * @variation 2 */ + /** + * Callback as used by {@link agentInterface.Agent#listOAuthTokens}. + * @memberof agentInterface.Agent + * @typedef ListOAuthTokensCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {agentInterface.StringListMessage} [response] StringListMessage + */ + + /** + * Calls ListOAuthTokens. + * @function listOAuthTokens + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IEmptyMessage} request EmptyMessage message or plain object + * @param {agentInterface.Agent.ListOAuthTokensCallback} callback Node-style callback called with the error, if any, and StringListMessage + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Agent.prototype.listOAuthTokens = function listOAuthTokens(request, callback) { + return this.rpcCall(listOAuthTokens, $root.agentInterface.EmptyMessage, $root.agentInterface.StringListMessage, request, callback); + }, "name", { value: "ListOAuthTokens" }); + + /** + * Calls ListOAuthTokens. + * @function listOAuthTokens + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IEmptyMessage} request EmptyMessage message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link agentInterface.Agent#listKeys}. * @memberof agentInterface.Agent @@ -710,6 +809,72 @@ $root.agentInterface = (function() { * @variation 2 */ + /** + * Callback as used by {@link agentInterface.Agent#lockNode}. + * @memberof agentInterface.Agent + * @typedef LockNodeCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {agentInterface.EmptyMessage} [response] EmptyMessage + */ + + /** + * Calls LockNode. + * @function lockNode + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IEmptyMessage} request EmptyMessage message or plain object + * @param {agentInterface.Agent.LockNodeCallback} callback Node-style callback called with the error, if any, and EmptyMessage + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Agent.prototype.lockNode = function lockNode(request, callback) { + return this.rpcCall(lockNode, $root.agentInterface.EmptyMessage, $root.agentInterface.EmptyMessage, request, callback); + }, "name", { value: "LockNode" }); + + /** + * Calls LockNode. + * @function lockNode + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IEmptyMessage} request EmptyMessage message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + + /** + * Callback as used by {@link agentInterface.Agent#newClientCertificate}. + * @memberof agentInterface.Agent + * @typedef NewClientCertificateCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {agentInterface.NewClientCertificateMessage} [response] NewClientCertificateMessage + */ + + /** + * Calls NewClientCertificate. + * @function newClientCertificate + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.INewClientCertificateMessage} request NewClientCertificateMessage message or plain object + * @param {agentInterface.Agent.NewClientCertificateCallback} callback Node-style callback called with the error, if any, and NewClientCertificateMessage + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Agent.prototype.newClientCertificate = function newClientCertificate(request, callback) { + return this.rpcCall(newClientCertificate, $root.agentInterface.NewClientCertificateMessage, $root.agentInterface.NewClientCertificateMessage, request, callback); + }, "name", { value: "NewClientCertificate" }); + + /** + * Calls NewClientCertificate. + * @function newClientCertificate + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.INewClientCertificateMessage} request NewClientCertificateMessage message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link agentInterface.Agent#newNode}. * @memberof agentInterface.Agent @@ -776,6 +941,39 @@ $root.agentInterface = (function() { * @variation 2 */ + /** + * Callback as used by {@link agentInterface.Agent#newOAuthToken}. + * @memberof agentInterface.Agent + * @typedef NewOAuthTokenCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {agentInterface.StringMessage} [response] StringMessage + */ + + /** + * Calls NewOAuthToken. + * @function newOAuthToken + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.INewOAuthTokenMessage} request NewOAuthTokenMessage message or plain object + * @param {agentInterface.Agent.NewOAuthTokenCallback} callback Node-style callback called with the error, if any, and StringMessage + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Agent.prototype.newOAuthToken = function newOAuthToken(request, callback) { + return this.rpcCall(newOAuthToken, $root.agentInterface.NewOAuthTokenMessage, $root.agentInterface.StringMessage, request, callback); + }, "name", { value: "NewOAuthToken" }); + + /** + * Calls NewOAuthToken. + * @function newOAuthToken + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.INewOAuthTokenMessage} request NewOAuthTokenMessage message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link agentInterface.Agent#newVault}. * @memberof agentInterface.Agent @@ -876,97 +1074,31 @@ $root.agentInterface = (function() { */ /** - * Callback as used by {@link agentInterface.Agent#registerNode}. + * Callback as used by {@link agentInterface.Agent#revokeOAuthToken}. * @memberof agentInterface.Agent - * @typedef RegisterNodeCallback + * @typedef RevokeOAuthTokenCallback * @type {function} * @param {Error|null} error Error, if any * @param {agentInterface.BooleanMessage} [response] BooleanMessage */ /** - * Calls RegisterNode. - * @function registerNode + * Calls RevokeOAuthToken. + * @function revokeOAuthToken * @memberof agentInterface.Agent * @instance * @param {agentInterface.IStringMessage} request StringMessage message or plain object - * @param {agentInterface.Agent.RegisterNodeCallback} callback Node-style callback called with the error, if any, and BooleanMessage + * @param {agentInterface.Agent.RevokeOAuthTokenCallback} callback Node-style callback called with the error, if any, and BooleanMessage * @returns {undefined} * @variation 1 */ - Object.defineProperty(Agent.prototype.registerNode = function registerNode(request, callback) { - return this.rpcCall(registerNode, $root.agentInterface.StringMessage, $root.agentInterface.BooleanMessage, request, callback); - }, "name", { value: "RegisterNode" }); + Object.defineProperty(Agent.prototype.revokeOAuthToken = function revokeOAuthToken(request, callback) { + return this.rpcCall(revokeOAuthToken, $root.agentInterface.StringMessage, $root.agentInterface.BooleanMessage, request, callback); + }, "name", { value: "RevokeOAuthToken" }); /** - * Calls RegisterNode. - * @function registerNode - * @memberof agentInterface.Agent - * @instance - * @param {agentInterface.IStringMessage} request StringMessage message or plain object - * @returns {Promise} Promise - * @variation 2 - */ - - /** - * Callback as used by {@link agentInterface.Agent#requestHolePunch}. - * @memberof agentInterface.Agent - * @typedef RequestHolePunchCallback - * @type {function} - * @param {Error|null} error Error, if any - * @param {agentInterface.BooleanMessage} [response] BooleanMessage - */ - - /** - * Calls RequestHolePunch. - * @function requestHolePunch - * @memberof agentInterface.Agent - * @instance - * @param {agentInterface.IStringMessage} request StringMessage message or plain object - * @param {agentInterface.Agent.RequestHolePunchCallback} callback Node-style callback called with the error, if any, and BooleanMessage - * @returns {undefined} - * @variation 1 - */ - Object.defineProperty(Agent.prototype.requestHolePunch = function requestHolePunch(request, callback) { - return this.rpcCall(requestHolePunch, $root.agentInterface.StringMessage, $root.agentInterface.BooleanMessage, request, callback); - }, "name", { value: "RequestHolePunch" }); - - /** - * Calls RequestHolePunch. - * @function requestHolePunch - * @memberof agentInterface.Agent - * @instance - * @param {agentInterface.IStringMessage} request StringMessage message or plain object - * @returns {Promise} Promise - * @variation 2 - */ - - /** - * Callback as used by {@link agentInterface.Agent#requestRelay}. - * @memberof agentInterface.Agent - * @typedef RequestRelayCallback - * @type {function} - * @param {Error|null} error Error, if any - * @param {agentInterface.BooleanMessage} [response] BooleanMessage - */ - - /** - * Calls RequestRelay. - * @function requestRelay - * @memberof agentInterface.Agent - * @instance - * @param {agentInterface.IStringMessage} request StringMessage message or plain object - * @param {agentInterface.Agent.RequestRelayCallback} callback Node-style callback called with the error, if any, and BooleanMessage - * @returns {undefined} - * @variation 1 - */ - Object.defineProperty(Agent.prototype.requestRelay = function requestRelay(request, callback) { - return this.rpcCall(requestRelay, $root.agentInterface.StringMessage, $root.agentInterface.BooleanMessage, request, callback); - }, "name", { value: "RequestRelay" }); - - /** - * Calls RequestRelay. - * @function requestRelay + * Calls RevokeOAuthToken. + * @function revokeOAuthToken * @memberof agentInterface.Agent * @instance * @param {agentInterface.IStringMessage} request StringMessage message or plain object @@ -1106,6 +1238,39 @@ $root.agentInterface = (function() { * @variation 2 */ + /** + * Callback as used by {@link agentInterface.Agent#unlockNode}. + * @memberof agentInterface.Agent + * @typedef UnlockNodeCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {agentInterface.BooleanMessage} [response] BooleanMessage + */ + + /** + * Calls UnlockNode. + * @function unlockNode + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IUnlockNodeMessage} request UnlockNodeMessage message or plain object + * @param {agentInterface.Agent.UnlockNodeCallback} callback Node-style callback called with the error, if any, and BooleanMessage + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Agent.prototype.unlockNode = function unlockNode(request, callback) { + return this.rpcCall(unlockNode, $root.agentInterface.UnlockNodeMessage, $root.agentInterface.BooleanMessage, request, callback); + }, "name", { value: "UnlockNode" }); + + /** + * Calls UnlockNode. + * @function unlockNode + * @memberof agentInterface.Agent + * @instance + * @param {agentInterface.IUnlockNodeMessage} request UnlockNodeMessage message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link agentInterface.Agent#updateLocalPeerInfo}. * @memberof agentInterface.Agent @@ -1727,7 +1892,7 @@ $root.agentInterface = (function() { * @memberof agentInterface * @interface IPeerInfoMessage * @property {string|null} [publicKey] PeerInfoMessage publicKey - * @property {string|null} [relayPublicKey] PeerInfoMessage relayPublicKey + * @property {string|null} [rootCertificate] PeerInfoMessage rootCertificate * @property {string|null} [peerAddress] PeerInfoMessage peerAddress * @property {string|null} [apiAddress] PeerInfoMessage apiAddress */ @@ -1756,12 +1921,12 @@ $root.agentInterface = (function() { PeerInfoMessage.prototype.publicKey = ""; /** - * PeerInfoMessage relayPublicKey. - * @member {string} relayPublicKey + * PeerInfoMessage rootCertificate. + * @member {string} rootCertificate * @memberof agentInterface.PeerInfoMessage * @instance */ - PeerInfoMessage.prototype.relayPublicKey = ""; + PeerInfoMessage.prototype.rootCertificate = ""; /** * PeerInfoMessage peerAddress. @@ -1805,8 +1970,8 @@ $root.agentInterface = (function() { w = $Writer.create(); if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey")) w.uint32(10).string(m.publicKey); - if (m.relayPublicKey != null && Object.hasOwnProperty.call(m, "relayPublicKey")) - w.uint32(18).string(m.relayPublicKey); + if (m.rootCertificate != null && Object.hasOwnProperty.call(m, "rootCertificate")) + w.uint32(18).string(m.rootCertificate); if (m.peerAddress != null && Object.hasOwnProperty.call(m, "peerAddress")) w.uint32(26).string(m.peerAddress); if (m.apiAddress != null && Object.hasOwnProperty.call(m, "apiAddress")) @@ -1849,7 +2014,7 @@ $root.agentInterface = (function() { m.publicKey = r.string(); break; case 2: - m.relayPublicKey = r.string(); + m.rootCertificate = r.string(); break; case 3: m.peerAddress = r.string(); @@ -2030,7 +2195,6 @@ $root.agentInterface = (function() { * @interface INewNodeMessage * @property {string|null} [userId] NewNodeMessage userId * @property {string|null} [passphrase] NewNodeMessage passphrase - * @property {number|null} [nbits] NewNodeMessage nbits */ /** @@ -2064,14 +2228,6 @@ $root.agentInterface = (function() { */ NewNodeMessage.prototype.passphrase = ""; - /** - * NewNodeMessage nbits. - * @member {number} nbits - * @memberof agentInterface.NewNodeMessage - * @instance - */ - NewNodeMessage.prototype.nbits = 0; - /** * Creates a new NewNodeMessage instance using the specified properties. * @function create @@ -2100,8 +2256,6 @@ $root.agentInterface = (function() { w.uint32(10).string(m.userId); if (m.passphrase != null && Object.hasOwnProperty.call(m, "passphrase")) w.uint32(18).string(m.passphrase); - if (m.nbits != null && Object.hasOwnProperty.call(m, "nbits")) - w.uint32(24).int32(m.nbits); return w; }; @@ -2142,9 +2296,6 @@ $root.agentInterface = (function() { case 2: m.passphrase = r.string(); break; - case 3: - m.nbits = r.int32(); - break; default: r.skipType(t & 7); break; @@ -3588,6 +3739,569 @@ $root.agentInterface = (function() { return ContactPeerMessage; })(); + agentInterface.UnlockNodeMessage = (function() { + + /** + * Properties of an UnlockNodeMessage. + * @memberof agentInterface + * @interface IUnlockNodeMessage + * @property {string|null} [passphrase] UnlockNodeMessage passphrase + * @property {number|null} [timeout] UnlockNodeMessage timeout + */ + + /** + * Constructs a new UnlockNodeMessage. + * @memberof agentInterface + * @classdesc Represents an UnlockNodeMessage. + * @implements IUnlockNodeMessage + * @constructor + * @param {agentInterface.IUnlockNodeMessage=} [p] Properties to set + */ + function UnlockNodeMessage(p) { + if (p) + for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) + if (p[ks[i]] != null) + this[ks[i]] = p[ks[i]]; + } + + /** + * UnlockNodeMessage passphrase. + * @member {string} passphrase + * @memberof agentInterface.UnlockNodeMessage + * @instance + */ + UnlockNodeMessage.prototype.passphrase = ""; + + /** + * UnlockNodeMessage timeout. + * @member {number} timeout + * @memberof agentInterface.UnlockNodeMessage + * @instance + */ + UnlockNodeMessage.prototype.timeout = 0; + + /** + * Creates a new UnlockNodeMessage instance using the specified properties. + * @function create + * @memberof agentInterface.UnlockNodeMessage + * @static + * @param {agentInterface.IUnlockNodeMessage=} [properties] Properties to set + * @returns {agentInterface.UnlockNodeMessage} UnlockNodeMessage instance + */ + UnlockNodeMessage.create = function create(properties) { + return new UnlockNodeMessage(properties); + }; + + /** + * Encodes the specified UnlockNodeMessage message. Does not implicitly {@link agentInterface.UnlockNodeMessage.verify|verify} messages. + * @function encode + * @memberof agentInterface.UnlockNodeMessage + * @static + * @param {agentInterface.IUnlockNodeMessage} m UnlockNodeMessage message or plain object to encode + * @param {$protobuf.Writer} [w] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UnlockNodeMessage.encode = function encode(m, w) { + if (!w) + w = $Writer.create(); + if (m.passphrase != null && Object.hasOwnProperty.call(m, "passphrase")) + w.uint32(10).string(m.passphrase); + if (m.timeout != null && Object.hasOwnProperty.call(m, "timeout")) + w.uint32(16).int32(m.timeout); + return w; + }; + + /** + * Encodes the specified UnlockNodeMessage message, length delimited. Does not implicitly {@link agentInterface.UnlockNodeMessage.verify|verify} messages. + * @function encodeDelimited + * @memberof agentInterface.UnlockNodeMessage + * @static + * @param {agentInterface.IUnlockNodeMessage} message UnlockNodeMessage message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UnlockNodeMessage.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an UnlockNodeMessage message from the specified reader or buffer. + * @function decode + * @memberof agentInterface.UnlockNodeMessage + * @static + * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from + * @param {number} [l] Message length if known beforehand + * @returns {agentInterface.UnlockNodeMessage} UnlockNodeMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UnlockNodeMessage.decode = function decode(r, l) { + if (!(r instanceof $Reader)) + r = $Reader.create(r); + var c = l === undefined ? r.len : r.pos + l, m = new $root.agentInterface.UnlockNodeMessage(); + while (r.pos < c) { + var t = r.uint32(); + switch (t >>> 3) { + case 1: + m.passphrase = r.string(); + break; + case 2: + m.timeout = r.int32(); + break; + default: + r.skipType(t & 7); + break; + } + } + return m; + }; + + /** + * Decodes an UnlockNodeMessage message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof agentInterface.UnlockNodeMessage + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {agentInterface.UnlockNodeMessage} UnlockNodeMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UnlockNodeMessage.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + return UnlockNodeMessage; + })(); + + agentInterface.NewClientCertificateMessage = (function() { + + /** + * Properties of a NewClientCertificateMessage. + * @memberof agentInterface + * @interface INewClientCertificateMessage + * @property {string|null} [domain] NewClientCertificateMessage domain + * @property {string|null} [certFile] NewClientCertificateMessage certFile + * @property {string|null} [keyFile] NewClientCertificateMessage keyFile + */ + + /** + * Constructs a new NewClientCertificateMessage. + * @memberof agentInterface + * @classdesc Represents a NewClientCertificateMessage. + * @implements INewClientCertificateMessage + * @constructor + * @param {agentInterface.INewClientCertificateMessage=} [p] Properties to set + */ + function NewClientCertificateMessage(p) { + if (p) + for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) + if (p[ks[i]] != null) + this[ks[i]] = p[ks[i]]; + } + + /** + * NewClientCertificateMessage domain. + * @member {string} domain + * @memberof agentInterface.NewClientCertificateMessage + * @instance + */ + NewClientCertificateMessage.prototype.domain = ""; + + /** + * NewClientCertificateMessage certFile. + * @member {string} certFile + * @memberof agentInterface.NewClientCertificateMessage + * @instance + */ + NewClientCertificateMessage.prototype.certFile = ""; + + /** + * NewClientCertificateMessage keyFile. + * @member {string} keyFile + * @memberof agentInterface.NewClientCertificateMessage + * @instance + */ + NewClientCertificateMessage.prototype.keyFile = ""; + + /** + * Creates a new NewClientCertificateMessage instance using the specified properties. + * @function create + * @memberof agentInterface.NewClientCertificateMessage + * @static + * @param {agentInterface.INewClientCertificateMessage=} [properties] Properties to set + * @returns {agentInterface.NewClientCertificateMessage} NewClientCertificateMessage instance + */ + NewClientCertificateMessage.create = function create(properties) { + return new NewClientCertificateMessage(properties); + }; + + /** + * Encodes the specified NewClientCertificateMessage message. Does not implicitly {@link agentInterface.NewClientCertificateMessage.verify|verify} messages. + * @function encode + * @memberof agentInterface.NewClientCertificateMessage + * @static + * @param {agentInterface.INewClientCertificateMessage} m NewClientCertificateMessage message or plain object to encode + * @param {$protobuf.Writer} [w] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NewClientCertificateMessage.encode = function encode(m, w) { + if (!w) + w = $Writer.create(); + if (m.domain != null && Object.hasOwnProperty.call(m, "domain")) + w.uint32(10).string(m.domain); + if (m.certFile != null && Object.hasOwnProperty.call(m, "certFile")) + w.uint32(18).string(m.certFile); + if (m.keyFile != null && Object.hasOwnProperty.call(m, "keyFile")) + w.uint32(26).string(m.keyFile); + return w; + }; + + /** + * Encodes the specified NewClientCertificateMessage message, length delimited. Does not implicitly {@link agentInterface.NewClientCertificateMessage.verify|verify} messages. + * @function encodeDelimited + * @memberof agentInterface.NewClientCertificateMessage + * @static + * @param {agentInterface.INewClientCertificateMessage} message NewClientCertificateMessage message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NewClientCertificateMessage.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a NewClientCertificateMessage message from the specified reader or buffer. + * @function decode + * @memberof agentInterface.NewClientCertificateMessage + * @static + * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from + * @param {number} [l] Message length if known beforehand + * @returns {agentInterface.NewClientCertificateMessage} NewClientCertificateMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NewClientCertificateMessage.decode = function decode(r, l) { + if (!(r instanceof $Reader)) + r = $Reader.create(r); + var c = l === undefined ? r.len : r.pos + l, m = new $root.agentInterface.NewClientCertificateMessage(); + while (r.pos < c) { + var t = r.uint32(); + switch (t >>> 3) { + case 1: + m.domain = r.string(); + break; + case 2: + m.certFile = r.string(); + break; + case 3: + m.keyFile = r.string(); + break; + default: + r.skipType(t & 7); + break; + } + } + return m; + }; + + /** + * Decodes a NewClientCertificateMessage message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof agentInterface.NewClientCertificateMessage + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {agentInterface.NewClientCertificateMessage} NewClientCertificateMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NewClientCertificateMessage.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + return NewClientCertificateMessage; + })(); + + agentInterface.NewOAuthTokenMessage = (function() { + + /** + * Properties of a NewOAuthTokenMessage. + * @memberof agentInterface + * @interface INewOAuthTokenMessage + * @property {Array.|null} [scopes] NewOAuthTokenMessage scopes + * @property {number|null} [expiry] NewOAuthTokenMessage expiry + */ + + /** + * Constructs a new NewOAuthTokenMessage. + * @memberof agentInterface + * @classdesc Represents a NewOAuthTokenMessage. + * @implements INewOAuthTokenMessage + * @constructor + * @param {agentInterface.INewOAuthTokenMessage=} [p] Properties to set + */ + function NewOAuthTokenMessage(p) { + this.scopes = []; + if (p) + for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) + if (p[ks[i]] != null) + this[ks[i]] = p[ks[i]]; + } + + /** + * NewOAuthTokenMessage scopes. + * @member {Array.} scopes + * @memberof agentInterface.NewOAuthTokenMessage + * @instance + */ + NewOAuthTokenMessage.prototype.scopes = $util.emptyArray; + + /** + * NewOAuthTokenMessage expiry. + * @member {number} expiry + * @memberof agentInterface.NewOAuthTokenMessage + * @instance + */ + NewOAuthTokenMessage.prototype.expiry = 0; + + /** + * Creates a new NewOAuthTokenMessage instance using the specified properties. + * @function create + * @memberof agentInterface.NewOAuthTokenMessage + * @static + * @param {agentInterface.INewOAuthTokenMessage=} [properties] Properties to set + * @returns {agentInterface.NewOAuthTokenMessage} NewOAuthTokenMessage instance + */ + NewOAuthTokenMessage.create = function create(properties) { + return new NewOAuthTokenMessage(properties); + }; + + /** + * Encodes the specified NewOAuthTokenMessage message. Does not implicitly {@link agentInterface.NewOAuthTokenMessage.verify|verify} messages. + * @function encode + * @memberof agentInterface.NewOAuthTokenMessage + * @static + * @param {agentInterface.INewOAuthTokenMessage} m NewOAuthTokenMessage message or plain object to encode + * @param {$protobuf.Writer} [w] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NewOAuthTokenMessage.encode = function encode(m, w) { + if (!w) + w = $Writer.create(); + if (m.scopes != null && m.scopes.length) { + for (var i = 0; i < m.scopes.length; ++i) + w.uint32(10).string(m.scopes[i]); + } + if (m.expiry != null && Object.hasOwnProperty.call(m, "expiry")) + w.uint32(16).int32(m.expiry); + return w; + }; + + /** + * Encodes the specified NewOAuthTokenMessage message, length delimited. Does not implicitly {@link agentInterface.NewOAuthTokenMessage.verify|verify} messages. + * @function encodeDelimited + * @memberof agentInterface.NewOAuthTokenMessage + * @static + * @param {agentInterface.INewOAuthTokenMessage} message NewOAuthTokenMessage message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + NewOAuthTokenMessage.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a NewOAuthTokenMessage message from the specified reader or buffer. + * @function decode + * @memberof agentInterface.NewOAuthTokenMessage + * @static + * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from + * @param {number} [l] Message length if known beforehand + * @returns {agentInterface.NewOAuthTokenMessage} NewOAuthTokenMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NewOAuthTokenMessage.decode = function decode(r, l) { + if (!(r instanceof $Reader)) + r = $Reader.create(r); + var c = l === undefined ? r.len : r.pos + l, m = new $root.agentInterface.NewOAuthTokenMessage(); + while (r.pos < c) { + var t = r.uint32(); + switch (t >>> 3) { + case 1: + if (!(m.scopes && m.scopes.length)) + m.scopes = []; + m.scopes.push(r.string()); + break; + case 2: + m.expiry = r.int32(); + break; + default: + r.skipType(t & 7); + break; + } + } + return m; + }; + + /** + * Decodes a NewOAuthTokenMessage message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof agentInterface.NewOAuthTokenMessage + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {agentInterface.NewOAuthTokenMessage} NewOAuthTokenMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + NewOAuthTokenMessage.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + return NewOAuthTokenMessage; + })(); + + agentInterface.OAuthClientMessage = (function() { + + /** + * Properties of a OAuthClientMessage. + * @memberof agentInterface + * @interface IOAuthClientMessage + * @property {string|null} [id] OAuthClientMessage id + * @property {string|null} [secret] OAuthClientMessage secret + */ + + /** + * Constructs a new OAuthClientMessage. + * @memberof agentInterface + * @classdesc Represents a OAuthClientMessage. + * @implements IOAuthClientMessage + * @constructor + * @param {agentInterface.IOAuthClientMessage=} [p] Properties to set + */ + function OAuthClientMessage(p) { + if (p) + for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) + if (p[ks[i]] != null) + this[ks[i]] = p[ks[i]]; + } + + /** + * OAuthClientMessage id. + * @member {string} id + * @memberof agentInterface.OAuthClientMessage + * @instance + */ + OAuthClientMessage.prototype.id = ""; + + /** + * OAuthClientMessage secret. + * @member {string} secret + * @memberof agentInterface.OAuthClientMessage + * @instance + */ + OAuthClientMessage.prototype.secret = ""; + + /** + * Creates a new OAuthClientMessage instance using the specified properties. + * @function create + * @memberof agentInterface.OAuthClientMessage + * @static + * @param {agentInterface.IOAuthClientMessage=} [properties] Properties to set + * @returns {agentInterface.OAuthClientMessage} OAuthClientMessage instance + */ + OAuthClientMessage.create = function create(properties) { + return new OAuthClientMessage(properties); + }; + + /** + * Encodes the specified OAuthClientMessage message. Does not implicitly {@link agentInterface.OAuthClientMessage.verify|verify} messages. + * @function encode + * @memberof agentInterface.OAuthClientMessage + * @static + * @param {agentInterface.IOAuthClientMessage} m OAuthClientMessage message or plain object to encode + * @param {$protobuf.Writer} [w] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + OAuthClientMessage.encode = function encode(m, w) { + if (!w) + w = $Writer.create(); + if (m.id != null && Object.hasOwnProperty.call(m, "id")) + w.uint32(10).string(m.id); + if (m.secret != null && Object.hasOwnProperty.call(m, "secret")) + w.uint32(18).string(m.secret); + return w; + }; + + /** + * Encodes the specified OAuthClientMessage message, length delimited. Does not implicitly {@link agentInterface.OAuthClientMessage.verify|verify} messages. + * @function encodeDelimited + * @memberof agentInterface.OAuthClientMessage + * @static + * @param {agentInterface.IOAuthClientMessage} message OAuthClientMessage message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + OAuthClientMessage.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a OAuthClientMessage message from the specified reader or buffer. + * @function decode + * @memberof agentInterface.OAuthClientMessage + * @static + * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from + * @param {number} [l] Message length if known beforehand + * @returns {agentInterface.OAuthClientMessage} OAuthClientMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + OAuthClientMessage.decode = function decode(r, l) { + if (!(r instanceof $Reader)) + r = $Reader.create(r); + var c = l === undefined ? r.len : r.pos + l, m = new $root.agentInterface.OAuthClientMessage(); + while (r.pos < c) { + var t = r.uint32(); + switch (t >>> 3) { + case 1: + m.id = r.string(); + break; + case 2: + m.secret = r.string(); + break; + default: + r.skipType(t & 7); + break; + } + } + return m; + }; + + /** + * Decodes a OAuthClientMessage message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof agentInterface.OAuthClientMessage + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {agentInterface.OAuthClientMessage} OAuthClientMessage + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + OAuthClientMessage.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + return OAuthClientMessage; + })(); + return agentInterface; })(); diff --git a/proto/js/Peer.d.ts b/proto/js/Peer.d.ts index 52c8e5adc..cd309956f 100644 --- a/proto/js/Peer.d.ts +++ b/proto/js/Peer.d.ts @@ -131,7 +131,8 @@ declare namespace Peer { PING_PEER = 0, GIT = 1, NAT_TRAVERSAL = 2, - CERTIFICATE_AUTHORITY = 3 + CERTIFICATE_AUTHORITY = 3, + PEER_DHT = 4 } /** Properties of a PingPeerMessage. */ @@ -214,8 +215,8 @@ declare namespace Peer { /** PeerInfoMessage publicKey */ publicKey?: (string|null); - /** PeerInfoMessage relayPublicKey */ - relayPublicKey?: (string|null); + /** PeerInfoMessage rootCertificate */ + rootCertificate?: (string|null); /** PeerInfoMessage peerAddress */ peerAddress?: (string|null); @@ -236,8 +237,8 @@ declare namespace Peer { /** PeerInfoMessage publicKey. */ public publicKey: string; - /** PeerInfoMessage relayPublicKey. */ - public relayPublicKey: string; + /** PeerInfoMessage rootCertificate. */ + public rootCertificate: string; /** PeerInfoMessage peerAddress. */ public peerAddress: string; @@ -414,11 +415,10 @@ declare namespace Peer { /** NatMessageType enum. */ enum NatMessageType { - ERROR = 0, - RELAY_CONNECTION = 1, - PEER_CONNECTION = 2, - UDP_ADDRESS = 3, - PEER_UDP_ADDRESS = 4 + UDP_ADDRESS = 0, + DIRECT_CONNECTION = 1, + HOLE_PUNCH_CONNECTION = 2, + RELAY_CONNECTION = 3 } /** Properties of a NatMessage. */ @@ -495,643 +495,694 @@ declare namespace Peer { public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.NatMessage; } - /** Properties of a RelayConnectionRequest. */ - interface IRelayConnectionRequest { + /** Properties of a UDPAddressMessage. */ + interface IUDPAddressMessage { - /** RelayConnectionRequest publicKey */ - publicKey?: (string|null); + /** UDPAddressMessage address */ + address?: (string|null); + + /** UDPAddressMessage token */ + token?: (string|null); } - /** Represents a RelayConnectionRequest. */ - class RelayConnectionRequest implements IRelayConnectionRequest { + /** Represents a UDPAddressMessage. */ + class UDPAddressMessage implements IUDPAddressMessage { /** - * Constructs a new RelayConnectionRequest. + * Constructs a new UDPAddressMessage. * @param [p] Properties to set */ - constructor(p?: peerInterface.IRelayConnectionRequest); + constructor(p?: peerInterface.IUDPAddressMessage); - /** RelayConnectionRequest publicKey. */ - public publicKey: string; + /** UDPAddressMessage address. */ + public address: string; + + /** UDPAddressMessage token. */ + public token: string; /** - * Creates a new RelayConnectionRequest instance using the specified properties. + * Creates a new UDPAddressMessage instance using the specified properties. * @param [properties] Properties to set - * @returns RelayConnectionRequest instance + * @returns UDPAddressMessage instance */ - public static create(properties?: peerInterface.IRelayConnectionRequest): peerInterface.RelayConnectionRequest; + public static create(properties?: peerInterface.IUDPAddressMessage): peerInterface.UDPAddressMessage; /** - * Encodes the specified RelayConnectionRequest message. Does not implicitly {@link peerInterface.RelayConnectionRequest.verify|verify} messages. - * @param m RelayConnectionRequest message or plain object to encode + * Encodes the specified UDPAddressMessage message. Does not implicitly {@link peerInterface.UDPAddressMessage.verify|verify} messages. + * @param m UDPAddressMessage message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.IRelayConnectionRequest, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.IUDPAddressMessage, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified RelayConnectionRequest message, length delimited. Does not implicitly {@link peerInterface.RelayConnectionRequest.verify|verify} messages. - * @param message RelayConnectionRequest message or plain object to encode + * Encodes the specified UDPAddressMessage message, length delimited. Does not implicitly {@link peerInterface.UDPAddressMessage.verify|verify} messages. + * @param message UDPAddressMessage message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.IRelayConnectionRequest, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.IUDPAddressMessage, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a RelayConnectionRequest message from the specified reader or buffer. + * Decodes a UDPAddressMessage message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns RelayConnectionRequest + * @returns UDPAddressMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.RelayConnectionRequest; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.UDPAddressMessage; /** - * Decodes a RelayConnectionRequest message from the specified reader or buffer, length delimited. + * Decodes a UDPAddressMessage message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns RelayConnectionRequest + * @returns UDPAddressMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.RelayConnectionRequest; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.UDPAddressMessage; } - /** Properties of a RelayConnectionResponse. */ - interface IRelayConnectionResponse { + /** Properties of a DirectConnectionMessage. */ + interface IDirectConnectionMessage { - /** RelayConnectionResponse serverAddress */ - serverAddress?: (string|null); + /** DirectConnectionMessage peerId */ + peerId?: (string|null); } - /** Represents a RelayConnectionResponse. */ - class RelayConnectionResponse implements IRelayConnectionResponse { + /** Represents a DirectConnectionMessage. */ + class DirectConnectionMessage implements IDirectConnectionMessage { /** - * Constructs a new RelayConnectionResponse. + * Constructs a new DirectConnectionMessage. * @param [p] Properties to set */ - constructor(p?: peerInterface.IRelayConnectionResponse); + constructor(p?: peerInterface.IDirectConnectionMessage); - /** RelayConnectionResponse serverAddress. */ - public serverAddress: string; + /** DirectConnectionMessage peerId. */ + public peerId: string; /** - * Creates a new RelayConnectionResponse instance using the specified properties. + * Creates a new DirectConnectionMessage instance using the specified properties. * @param [properties] Properties to set - * @returns RelayConnectionResponse instance + * @returns DirectConnectionMessage instance */ - public static create(properties?: peerInterface.IRelayConnectionResponse): peerInterface.RelayConnectionResponse; + public static create(properties?: peerInterface.IDirectConnectionMessage): peerInterface.DirectConnectionMessage; /** - * Encodes the specified RelayConnectionResponse message. Does not implicitly {@link peerInterface.RelayConnectionResponse.verify|verify} messages. - * @param m RelayConnectionResponse message or plain object to encode + * Encodes the specified DirectConnectionMessage message. Does not implicitly {@link peerInterface.DirectConnectionMessage.verify|verify} messages. + * @param m DirectConnectionMessage message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.IRelayConnectionResponse, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.IDirectConnectionMessage, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified RelayConnectionResponse message, length delimited. Does not implicitly {@link peerInterface.RelayConnectionResponse.verify|verify} messages. - * @param message RelayConnectionResponse message or plain object to encode + * Encodes the specified DirectConnectionMessage message, length delimited. Does not implicitly {@link peerInterface.DirectConnectionMessage.verify|verify} messages. + * @param message DirectConnectionMessage message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.IRelayConnectionResponse, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.IDirectConnectionMessage, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a RelayConnectionResponse message from the specified reader or buffer. + * Decodes a DirectConnectionMessage message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns RelayConnectionResponse + * @returns DirectConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.RelayConnectionResponse; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.DirectConnectionMessage; /** - * Decodes a RelayConnectionResponse message from the specified reader or buffer, length delimited. + * Decodes a DirectConnectionMessage message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns RelayConnectionResponse + * @returns DirectConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.RelayConnectionResponse; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.DirectConnectionMessage; } - /** Properties of a PeerConnectionRequest. */ - interface IPeerConnectionRequest { + /** Properties of a HolePunchConnectionMessage. */ + interface IHolePunchConnectionMessage { - /** PeerConnectionRequest publicKey */ - publicKey?: (string|null); + /** HolePunchConnectionMessage targetPeerId */ + targetPeerId?: (string|null); + + /** HolePunchConnectionMessage originPeerId */ + originPeerId?: (string|null); + + /** HolePunchConnectionMessage udpAddress */ + udpAddress?: (string|null); } - /** Represents a PeerConnectionRequest. */ - class PeerConnectionRequest implements IPeerConnectionRequest { + /** Represents a HolePunchConnectionMessage. */ + class HolePunchConnectionMessage implements IHolePunchConnectionMessage { /** - * Constructs a new PeerConnectionRequest. + * Constructs a new HolePunchConnectionMessage. * @param [p] Properties to set */ - constructor(p?: peerInterface.IPeerConnectionRequest); + constructor(p?: peerInterface.IHolePunchConnectionMessage); - /** PeerConnectionRequest publicKey. */ - public publicKey: string; + /** HolePunchConnectionMessage targetPeerId. */ + public targetPeerId: string; + + /** HolePunchConnectionMessage originPeerId. */ + public originPeerId: string; + + /** HolePunchConnectionMessage udpAddress. */ + public udpAddress: string; /** - * Creates a new PeerConnectionRequest instance using the specified properties. + * Creates a new HolePunchConnectionMessage instance using the specified properties. * @param [properties] Properties to set - * @returns PeerConnectionRequest instance + * @returns HolePunchConnectionMessage instance */ - public static create(properties?: peerInterface.IPeerConnectionRequest): peerInterface.PeerConnectionRequest; + public static create(properties?: peerInterface.IHolePunchConnectionMessage): peerInterface.HolePunchConnectionMessage; /** - * Encodes the specified PeerConnectionRequest message. Does not implicitly {@link peerInterface.PeerConnectionRequest.verify|verify} messages. - * @param m PeerConnectionRequest message or plain object to encode + * Encodes the specified HolePunchConnectionMessage message. Does not implicitly {@link peerInterface.HolePunchConnectionMessage.verify|verify} messages. + * @param m HolePunchConnectionMessage message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.IPeerConnectionRequest, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.IHolePunchConnectionMessage, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified PeerConnectionRequest message, length delimited. Does not implicitly {@link peerInterface.PeerConnectionRequest.verify|verify} messages. - * @param message PeerConnectionRequest message or plain object to encode + * Encodes the specified HolePunchConnectionMessage message, length delimited. Does not implicitly {@link peerInterface.HolePunchConnectionMessage.verify|verify} messages. + * @param message HolePunchConnectionMessage message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.IPeerConnectionRequest, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.IHolePunchConnectionMessage, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a PeerConnectionRequest message from the specified reader or buffer. + * Decodes a HolePunchConnectionMessage message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns PeerConnectionRequest + * @returns HolePunchConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.PeerConnectionRequest; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.HolePunchConnectionMessage; /** - * Decodes a PeerConnectionRequest message from the specified reader or buffer, length delimited. + * Decodes a HolePunchConnectionMessage message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns PeerConnectionRequest + * @returns HolePunchConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.PeerConnectionRequest; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.HolePunchConnectionMessage; } - /** Properties of a PeerConnectionResponse. */ - interface IPeerConnectionResponse { + /** Properties of a RelayConnectionMessage. */ + interface IRelayConnectionMessage { - /** PeerConnectionResponse peerAddress */ - peerAddress?: (string|null); + /** RelayConnectionMessage targetPeerId */ + targetPeerId?: (string|null); + + /** RelayConnectionMessage originPeerId */ + originPeerId?: (string|null); + + /** RelayConnectionMessage relayAddress */ + relayAddress?: (string|null); } - /** Represents a PeerConnectionResponse. */ - class PeerConnectionResponse implements IPeerConnectionResponse { + /** Represents a RelayConnectionMessage. */ + class RelayConnectionMessage implements IRelayConnectionMessage { /** - * Constructs a new PeerConnectionResponse. + * Constructs a new RelayConnectionMessage. * @param [p] Properties to set */ - constructor(p?: peerInterface.IPeerConnectionResponse); + constructor(p?: peerInterface.IRelayConnectionMessage); - /** PeerConnectionResponse peerAddress. */ - public peerAddress: string; + /** RelayConnectionMessage targetPeerId. */ + public targetPeerId: string; + + /** RelayConnectionMessage originPeerId. */ + public originPeerId: string; + + /** RelayConnectionMessage relayAddress. */ + public relayAddress: string; /** - * Creates a new PeerConnectionResponse instance using the specified properties. + * Creates a new RelayConnectionMessage instance using the specified properties. * @param [properties] Properties to set - * @returns PeerConnectionResponse instance + * @returns RelayConnectionMessage instance */ - public static create(properties?: peerInterface.IPeerConnectionResponse): peerInterface.PeerConnectionResponse; + public static create(properties?: peerInterface.IRelayConnectionMessage): peerInterface.RelayConnectionMessage; /** - * Encodes the specified PeerConnectionResponse message. Does not implicitly {@link peerInterface.PeerConnectionResponse.verify|verify} messages. - * @param m PeerConnectionResponse message or plain object to encode + * Encodes the specified RelayConnectionMessage message. Does not implicitly {@link peerInterface.RelayConnectionMessage.verify|verify} messages. + * @param m RelayConnectionMessage message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.IPeerConnectionResponse, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.IRelayConnectionMessage, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified PeerConnectionResponse message, length delimited. Does not implicitly {@link peerInterface.PeerConnectionResponse.verify|verify} messages. - * @param message PeerConnectionResponse message or plain object to encode + * Encodes the specified RelayConnectionMessage message, length delimited. Does not implicitly {@link peerInterface.RelayConnectionMessage.verify|verify} messages. + * @param message RelayConnectionMessage message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.IPeerConnectionResponse, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.IRelayConnectionMessage, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a PeerConnectionResponse message from the specified reader or buffer. + * Decodes a RelayConnectionMessage message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns PeerConnectionResponse + * @returns RelayConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.PeerConnectionResponse; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.RelayConnectionMessage; /** - * Decodes a PeerConnectionResponse message from the specified reader or buffer, length delimited. + * Decodes a RelayConnectionMessage message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns PeerConnectionResponse + * @returns RelayConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.PeerConnectionResponse; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.RelayConnectionMessage; + } + + /** CAMessageType enum. */ + enum CAMessageType { + ROOT_CERT = 0, + REQUEST_CERT = 1 } - /** Properties of a UDPAddressResponse. */ - interface IUDPAddressResponse { + /** Properties of a CAMessage. */ + interface ICAMessage { + + /** CAMessage type */ + type?: (peerInterface.CAMessageType|null); - /** UDPAddressResponse address */ - address?: (string|null); + /** CAMessage isResponse */ + isResponse?: (boolean|null); + + /** CAMessage subMessage */ + subMessage?: (Uint8Array|null); } - /** Represents a UDPAddressResponse. */ - class UDPAddressResponse implements IUDPAddressResponse { + /** Represents a CAMessage. */ + class CAMessage implements ICAMessage { /** - * Constructs a new UDPAddressResponse. + * Constructs a new CAMessage. * @param [p] Properties to set */ - constructor(p?: peerInterface.IUDPAddressResponse); + constructor(p?: peerInterface.ICAMessage); - /** UDPAddressResponse address. */ - public address: string; + /** CAMessage type. */ + public type: peerInterface.CAMessageType; + + /** CAMessage isResponse. */ + public isResponse: boolean; + + /** CAMessage subMessage. */ + public subMessage: Uint8Array; /** - * Creates a new UDPAddressResponse instance using the specified properties. + * Creates a new CAMessage instance using the specified properties. * @param [properties] Properties to set - * @returns UDPAddressResponse instance + * @returns CAMessage instance */ - public static create(properties?: peerInterface.IUDPAddressResponse): peerInterface.UDPAddressResponse; + public static create(properties?: peerInterface.ICAMessage): peerInterface.CAMessage; /** - * Encodes the specified UDPAddressResponse message. Does not implicitly {@link peerInterface.UDPAddressResponse.verify|verify} messages. - * @param m UDPAddressResponse message or plain object to encode + * Encodes the specified CAMessage message. Does not implicitly {@link peerInterface.CAMessage.verify|verify} messages. + * @param m CAMessage message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.IUDPAddressResponse, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.ICAMessage, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified UDPAddressResponse message, length delimited. Does not implicitly {@link peerInterface.UDPAddressResponse.verify|verify} messages. - * @param message UDPAddressResponse message or plain object to encode + * Encodes the specified CAMessage message, length delimited. Does not implicitly {@link peerInterface.CAMessage.verify|verify} messages. + * @param message CAMessage message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.IUDPAddressResponse, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.ICAMessage, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a UDPAddressResponse message from the specified reader or buffer. + * Decodes a CAMessage message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns UDPAddressResponse + * @returns CAMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.UDPAddressResponse; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.CAMessage; /** - * Decodes a UDPAddressResponse message from the specified reader or buffer, length delimited. + * Decodes a CAMessage message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns UDPAddressResponse + * @returns CAMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.UDPAddressResponse; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.CAMessage; + } + + /** PeerDHTMessageType enum. */ + enum PeerDHTMessageType { + PING = 0, + FIND_NODE = 1 } - /** Properties of a HolePunchRegisterRequest. */ - interface IHolePunchRegisterRequest { + /** Properties of a PeerDHTMessage. */ + interface IPeerDHTMessage { - /** HolePunchRegisterRequest publicKey */ - publicKey?: (string|null); + /** PeerDHTMessage type */ + type?: (peerInterface.PeerDHTMessageType|null); + + /** PeerDHTMessage isResponse */ + isResponse?: (boolean|null); + + /** PeerDHTMessage subMessage */ + subMessage?: (Uint8Array|null); } - /** Represents a HolePunchRegisterRequest. */ - class HolePunchRegisterRequest implements IHolePunchRegisterRequest { + /** Represents a PeerDHTMessage. */ + class PeerDHTMessage implements IPeerDHTMessage { /** - * Constructs a new HolePunchRegisterRequest. + * Constructs a new PeerDHTMessage. * @param [p] Properties to set */ - constructor(p?: peerInterface.IHolePunchRegisterRequest); + constructor(p?: peerInterface.IPeerDHTMessage); - /** HolePunchRegisterRequest publicKey. */ - public publicKey: string; + /** PeerDHTMessage type. */ + public type: peerInterface.PeerDHTMessageType; + + /** PeerDHTMessage isResponse. */ + public isResponse: boolean; + + /** PeerDHTMessage subMessage. */ + public subMessage: Uint8Array; /** - * Creates a new HolePunchRegisterRequest instance using the specified properties. + * Creates a new PeerDHTMessage instance using the specified properties. * @param [properties] Properties to set - * @returns HolePunchRegisterRequest instance + * @returns PeerDHTMessage instance */ - public static create(properties?: peerInterface.IHolePunchRegisterRequest): peerInterface.HolePunchRegisterRequest; + public static create(properties?: peerInterface.IPeerDHTMessage): peerInterface.PeerDHTMessage; /** - * Encodes the specified HolePunchRegisterRequest message. Does not implicitly {@link peerInterface.HolePunchRegisterRequest.verify|verify} messages. - * @param m HolePunchRegisterRequest message or plain object to encode + * Encodes the specified PeerDHTMessage message. Does not implicitly {@link peerInterface.PeerDHTMessage.verify|verify} messages. + * @param m PeerDHTMessage message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.IHolePunchRegisterRequest, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.IPeerDHTMessage, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified HolePunchRegisterRequest message, length delimited. Does not implicitly {@link peerInterface.HolePunchRegisterRequest.verify|verify} messages. - * @param message HolePunchRegisterRequest message or plain object to encode + * Encodes the specified PeerDHTMessage message, length delimited. Does not implicitly {@link peerInterface.PeerDHTMessage.verify|verify} messages. + * @param message PeerDHTMessage message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.IHolePunchRegisterRequest, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.IPeerDHTMessage, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a HolePunchRegisterRequest message from the specified reader or buffer. + * Decodes a PeerDHTMessage message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns HolePunchRegisterRequest + * @returns PeerDHTMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.HolePunchRegisterRequest; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.PeerDHTMessage; /** - * Decodes a HolePunchRegisterRequest message from the specified reader or buffer, length delimited. + * Decodes a PeerDHTMessage message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns HolePunchRegisterRequest + * @returns PeerDHTMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.HolePunchRegisterRequest; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.PeerDHTMessage; } - /** Properties of a HolePunchRegisterResponse. */ - interface IHolePunchRegisterResponse { + /** Properties of a PeerDHTPingNodeMessage. */ + interface IPeerDHTPingNodeMessage { + + /** PeerDHTPingNodeMessage peerId */ + peerId?: (string|null); - /** HolePunchRegisterResponse connectedAddress */ - connectedAddress?: (string|null); + /** PeerDHTPingNodeMessage randomChallenge */ + randomChallenge?: (string|null); } - /** Represents a HolePunchRegisterResponse. */ - class HolePunchRegisterResponse implements IHolePunchRegisterResponse { + /** Represents a PeerDHTPingNodeMessage. */ + class PeerDHTPingNodeMessage implements IPeerDHTPingNodeMessage { /** - * Constructs a new HolePunchRegisterResponse. + * Constructs a new PeerDHTPingNodeMessage. * @param [p] Properties to set */ - constructor(p?: peerInterface.IHolePunchRegisterResponse); + constructor(p?: peerInterface.IPeerDHTPingNodeMessage); - /** HolePunchRegisterResponse connectedAddress. */ - public connectedAddress: string; + /** PeerDHTPingNodeMessage peerId. */ + public peerId: string; + + /** PeerDHTPingNodeMessage randomChallenge. */ + public randomChallenge: string; /** - * Creates a new HolePunchRegisterResponse instance using the specified properties. + * Creates a new PeerDHTPingNodeMessage instance using the specified properties. * @param [properties] Properties to set - * @returns HolePunchRegisterResponse instance + * @returns PeerDHTPingNodeMessage instance */ - public static create(properties?: peerInterface.IHolePunchRegisterResponse): peerInterface.HolePunchRegisterResponse; + public static create(properties?: peerInterface.IPeerDHTPingNodeMessage): peerInterface.PeerDHTPingNodeMessage; /** - * Encodes the specified HolePunchRegisterResponse message. Does not implicitly {@link peerInterface.HolePunchRegisterResponse.verify|verify} messages. - * @param m HolePunchRegisterResponse message or plain object to encode + * Encodes the specified PeerDHTPingNodeMessage message. Does not implicitly {@link peerInterface.PeerDHTPingNodeMessage.verify|verify} messages. + * @param m PeerDHTPingNodeMessage message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.IHolePunchRegisterResponse, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.IPeerDHTPingNodeMessage, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified HolePunchRegisterResponse message, length delimited. Does not implicitly {@link peerInterface.HolePunchRegisterResponse.verify|verify} messages. - * @param message HolePunchRegisterResponse message or plain object to encode + * Encodes the specified PeerDHTPingNodeMessage message, length delimited. Does not implicitly {@link peerInterface.PeerDHTPingNodeMessage.verify|verify} messages. + * @param message PeerDHTPingNodeMessage message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.IHolePunchRegisterResponse, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.IPeerDHTPingNodeMessage, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a HolePunchRegisterResponse message from the specified reader or buffer. + * Decodes a PeerDHTPingNodeMessage message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns HolePunchRegisterResponse + * @returns PeerDHTPingNodeMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.HolePunchRegisterResponse; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.PeerDHTPingNodeMessage; /** - * Decodes a HolePunchRegisterResponse message from the specified reader or buffer, length delimited. + * Decodes a PeerDHTPingNodeMessage message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns HolePunchRegisterResponse + * @returns PeerDHTPingNodeMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.HolePunchRegisterResponse; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.PeerDHTPingNodeMessage; } - /** Properties of a PeerUdpAddressRequest. */ - interface IPeerUdpAddressRequest { + /** Properties of a PeerDHTFindNodeMessage. */ + interface IPeerDHTFindNodeMessage { - /** PeerUdpAddressRequest publicKey */ - publicKey?: (string|null); + /** PeerDHTFindNodeMessage peerId */ + peerId?: (string|null); + + /** PeerDHTFindNodeMessage closestPeers */ + closestPeers?: (peerInterface.IPeerInfoMessage[]|null); } - /** Represents a PeerUdpAddressRequest. */ - class PeerUdpAddressRequest implements IPeerUdpAddressRequest { + /** Represents a PeerDHTFindNodeMessage. */ + class PeerDHTFindNodeMessage implements IPeerDHTFindNodeMessage { /** - * Constructs a new PeerUdpAddressRequest. + * Constructs a new PeerDHTFindNodeMessage. * @param [p] Properties to set */ - constructor(p?: peerInterface.IPeerUdpAddressRequest); + constructor(p?: peerInterface.IPeerDHTFindNodeMessage); - /** PeerUdpAddressRequest publicKey. */ - public publicKey: string; + /** PeerDHTFindNodeMessage peerId. */ + public peerId: string; + + /** PeerDHTFindNodeMessage closestPeers. */ + public closestPeers: peerInterface.IPeerInfoMessage[]; /** - * Creates a new PeerUdpAddressRequest instance using the specified properties. + * Creates a new PeerDHTFindNodeMessage instance using the specified properties. * @param [properties] Properties to set - * @returns PeerUdpAddressRequest instance + * @returns PeerDHTFindNodeMessage instance */ - public static create(properties?: peerInterface.IPeerUdpAddressRequest): peerInterface.PeerUdpAddressRequest; + public static create(properties?: peerInterface.IPeerDHTFindNodeMessage): peerInterface.PeerDHTFindNodeMessage; /** - * Encodes the specified PeerUdpAddressRequest message. Does not implicitly {@link peerInterface.PeerUdpAddressRequest.verify|verify} messages. - * @param m PeerUdpAddressRequest message or plain object to encode + * Encodes the specified PeerDHTFindNodeMessage message. Does not implicitly {@link peerInterface.PeerDHTFindNodeMessage.verify|verify} messages. + * @param m PeerDHTFindNodeMessage message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.IPeerUdpAddressRequest, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.IPeerDHTFindNodeMessage, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified PeerUdpAddressRequest message, length delimited. Does not implicitly {@link peerInterface.PeerUdpAddressRequest.verify|verify} messages. - * @param message PeerUdpAddressRequest message or plain object to encode + * Encodes the specified PeerDHTFindNodeMessage message, length delimited. Does not implicitly {@link peerInterface.PeerDHTFindNodeMessage.verify|verify} messages. + * @param message PeerDHTFindNodeMessage message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.IPeerUdpAddressRequest, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.IPeerDHTFindNodeMessage, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a PeerUdpAddressRequest message from the specified reader or buffer. + * Decodes a PeerDHTFindNodeMessage message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns PeerUdpAddressRequest + * @returns PeerDHTFindNodeMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.PeerUdpAddressRequest; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.PeerDHTFindNodeMessage; /** - * Decodes a PeerUdpAddressRequest message from the specified reader or buffer, length delimited. + * Decodes a PeerDHTFindNodeMessage message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns PeerUdpAddressRequest + * @returns PeerDHTFindNodeMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.PeerUdpAddressRequest; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.PeerDHTFindNodeMessage; } - /** Properties of a PeerUdpAddressResponse. */ - interface IPeerUdpAddressResponse { + /** Properties of a MTPPacket. */ + interface IMTPPacket { - /** PeerUdpAddressResponse address */ - address?: (string|null); - } + /** MTPPacket id */ + id?: (number|null); - /** Represents a PeerUdpAddressResponse. */ - class PeerUdpAddressResponse implements IPeerUdpAddressResponse { + /** MTPPacket peerId */ + peerId?: (string|null); - /** - * Constructs a new PeerUdpAddressResponse. - * @param [p] Properties to set - */ - constructor(p?: peerInterface.IPeerUdpAddressResponse); + /** MTPPacket connection */ + connection?: (number|null); - /** PeerUdpAddressResponse address. */ - public address: string; + /** MTPPacket timestamp */ + timestamp?: (number|null); - /** - * Creates a new PeerUdpAddressResponse instance using the specified properties. - * @param [properties] Properties to set - * @returns PeerUdpAddressResponse instance - */ - public static create(properties?: peerInterface.IPeerUdpAddressResponse): peerInterface.PeerUdpAddressResponse; + /** MTPPacket timediff */ + timediff?: (number|null); - /** - * Encodes the specified PeerUdpAddressResponse message. Does not implicitly {@link peerInterface.PeerUdpAddressResponse.verify|verify} messages. - * @param m PeerUdpAddressResponse message or plain object to encode - * @param [w] Writer to encode to - * @returns Writer - */ - public static encode(m: peerInterface.IPeerUdpAddressResponse, w?: $protobuf.Writer): $protobuf.Writer; + /** MTPPacket window */ + window?: (number|null); - /** - * Encodes the specified PeerUdpAddressResponse message, length delimited. Does not implicitly {@link peerInterface.PeerUdpAddressResponse.verify|verify} messages. - * @param message PeerUdpAddressResponse message or plain object to encode - * @param [writer] Writer to encode to - * @returns Writer - */ - public static encodeDelimited(message: peerInterface.IPeerUdpAddressResponse, writer?: $protobuf.Writer): $protobuf.Writer; + /** MTPPacket seq */ + seq?: (number|null); - /** - * Decodes a PeerUdpAddressResponse message from the specified reader or buffer. - * @param r Reader or buffer to decode from - * @param [l] Message length if known beforehand - * @returns PeerUdpAddressResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.PeerUdpAddressResponse; + /** MTPPacket ack */ + ack?: (number|null); + + /** MTPPacket data */ + data?: (Uint8Array|null); + + /** MTPPacket sent */ + sent?: (number|null); + } + + /** Represents a MTPPacket. */ + class MTPPacket implements IMTPPacket { /** - * Decodes a PeerUdpAddressResponse message from the specified reader or buffer, length delimited. - * @param reader Reader or buffer to decode from - * @returns PeerUdpAddressResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing + * Constructs a new MTPPacket. + * @param [p] Properties to set */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.PeerUdpAddressResponse; - } + constructor(p?: peerInterface.IMTPPacket); - /** CAMessageType enum. */ - enum CAMessageType { - ERROR = 0, - ROOT_CERT = 1, - REQUEST_CERT = 2 - } + /** MTPPacket id. */ + public id: number; - /** Properties of a CAMessage. */ - interface ICAMessage { + /** MTPPacket peerId. */ + public peerId: string; - /** CAMessage type */ - type?: (peerInterface.CAMessageType|null); + /** MTPPacket connection. */ + public connection: number; - /** CAMessage isResponse */ - isResponse?: (boolean|null); + /** MTPPacket timestamp. */ + public timestamp: number; - /** CAMessage subMessage */ - subMessage?: (Uint8Array|null); - } + /** MTPPacket timediff. */ + public timediff: number; - /** Represents a CAMessage. */ - class CAMessage implements ICAMessage { + /** MTPPacket window. */ + public window: number; - /** - * Constructs a new CAMessage. - * @param [p] Properties to set - */ - constructor(p?: peerInterface.ICAMessage); + /** MTPPacket seq. */ + public seq: number; - /** CAMessage type. */ - public type: peerInterface.CAMessageType; + /** MTPPacket ack. */ + public ack: number; - /** CAMessage isResponse. */ - public isResponse: boolean; + /** MTPPacket data. */ + public data: Uint8Array; - /** CAMessage subMessage. */ - public subMessage: Uint8Array; + /** MTPPacket sent. */ + public sent: number; /** - * Creates a new CAMessage instance using the specified properties. + * Creates a new MTPPacket instance using the specified properties. * @param [properties] Properties to set - * @returns CAMessage instance + * @returns MTPPacket instance */ - public static create(properties?: peerInterface.ICAMessage): peerInterface.CAMessage; + public static create(properties?: peerInterface.IMTPPacket): peerInterface.MTPPacket; /** - * Encodes the specified CAMessage message. Does not implicitly {@link peerInterface.CAMessage.verify|verify} messages. - * @param m CAMessage message or plain object to encode + * Encodes the specified MTPPacket message. Does not implicitly {@link peerInterface.MTPPacket.verify|verify} messages. + * @param m MTPPacket message or plain object to encode * @param [w] Writer to encode to * @returns Writer */ - public static encode(m: peerInterface.ICAMessage, w?: $protobuf.Writer): $protobuf.Writer; + public static encode(m: peerInterface.IMTPPacket, w?: $protobuf.Writer): $protobuf.Writer; /** - * Encodes the specified CAMessage message, length delimited. Does not implicitly {@link peerInterface.CAMessage.verify|verify} messages. - * @param message CAMessage message or plain object to encode + * Encodes the specified MTPPacket message, length delimited. Does not implicitly {@link peerInterface.MTPPacket.verify|verify} messages. + * @param message MTPPacket message or plain object to encode * @param [writer] Writer to encode to * @returns Writer */ - public static encodeDelimited(message: peerInterface.ICAMessage, writer?: $protobuf.Writer): $protobuf.Writer; + public static encodeDelimited(message: peerInterface.IMTPPacket, writer?: $protobuf.Writer): $protobuf.Writer; /** - * Decodes a CAMessage message from the specified reader or buffer. + * Decodes a MTPPacket message from the specified reader or buffer. * @param r Reader or buffer to decode from * @param [l] Message length if known beforehand - * @returns CAMessage + * @returns MTPPacket * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.CAMessage; + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): peerInterface.MTPPacket; /** - * Decodes a CAMessage message from the specified reader or buffer, length delimited. + * Decodes a MTPPacket message from the specified reader or buffer, length delimited. * @param reader Reader or buffer to decode from - * @returns CAMessage + * @returns MTPPacket * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.CAMessage; + public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): peerInterface.MTPPacket; } } } diff --git a/proto/js/Peer.js b/proto/js/Peer.js index 09b8ac873..b2b39b55c 100644 --- a/proto/js/Peer.js +++ b/proto/js/Peer.js @@ -244,6 +244,7 @@ $root.peerInterface = (function() { * @property {number} GIT=1 GIT value * @property {number} NAT_TRAVERSAL=2 NAT_TRAVERSAL value * @property {number} CERTIFICATE_AUTHORITY=3 CERTIFICATE_AUTHORITY value + * @property {number} PEER_DHT=4 PEER_DHT value */ peerInterface.SubServiceType = (function() { var valuesById = {}, values = Object.create(valuesById); @@ -251,6 +252,7 @@ $root.peerInterface = (function() { values[valuesById[1] = "GIT"] = 1; values[valuesById[2] = "NAT_TRAVERSAL"] = 2; values[valuesById[3] = "CERTIFICATE_AUTHORITY"] = 3; + values[valuesById[4] = "PEER_DHT"] = 4; return values; })(); @@ -411,7 +413,7 @@ $root.peerInterface = (function() { * @memberof peerInterface * @interface IPeerInfoMessage * @property {string|null} [publicKey] PeerInfoMessage publicKey - * @property {string|null} [relayPublicKey] PeerInfoMessage relayPublicKey + * @property {string|null} [rootCertificate] PeerInfoMessage rootCertificate * @property {string|null} [peerAddress] PeerInfoMessage peerAddress * @property {string|null} [apiAddress] PeerInfoMessage apiAddress */ @@ -440,12 +442,12 @@ $root.peerInterface = (function() { PeerInfoMessage.prototype.publicKey = ""; /** - * PeerInfoMessage relayPublicKey. - * @member {string} relayPublicKey + * PeerInfoMessage rootCertificate. + * @member {string} rootCertificate * @memberof peerInterface.PeerInfoMessage * @instance */ - PeerInfoMessage.prototype.relayPublicKey = ""; + PeerInfoMessage.prototype.rootCertificate = ""; /** * PeerInfoMessage peerAddress. @@ -489,8 +491,8 @@ $root.peerInterface = (function() { w = $Writer.create(); if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey")) w.uint32(10).string(m.publicKey); - if (m.relayPublicKey != null && Object.hasOwnProperty.call(m, "relayPublicKey")) - w.uint32(18).string(m.relayPublicKey); + if (m.rootCertificate != null && Object.hasOwnProperty.call(m, "rootCertificate")) + w.uint32(18).string(m.rootCertificate); if (m.peerAddress != null && Object.hasOwnProperty.call(m, "peerAddress")) w.uint32(26).string(m.peerAddress); if (m.apiAddress != null && Object.hasOwnProperty.call(m, "apiAddress")) @@ -533,7 +535,7 @@ $root.peerInterface = (function() { m.publicKey = r.string(); break; case 2: - m.relayPublicKey = r.string(); + m.rootCertificate = r.string(); break; case 3: m.peerAddress = r.string(); @@ -821,19 +823,17 @@ $root.peerInterface = (function() { * NatMessageType enum. * @name peerInterface.NatMessageType * @enum {number} - * @property {number} ERROR=0 ERROR value - * @property {number} RELAY_CONNECTION=1 RELAY_CONNECTION value - * @property {number} PEER_CONNECTION=2 PEER_CONNECTION value - * @property {number} UDP_ADDRESS=3 UDP_ADDRESS value - * @property {number} PEER_UDP_ADDRESS=4 PEER_UDP_ADDRESS value + * @property {number} UDP_ADDRESS=0 UDP_ADDRESS value + * @property {number} DIRECT_CONNECTION=1 DIRECT_CONNECTION value + * @property {number} HOLE_PUNCH_CONNECTION=2 HOLE_PUNCH_CONNECTION value + * @property {number} RELAY_CONNECTION=3 RELAY_CONNECTION value */ peerInterface.NatMessageType = (function() { var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "ERROR"] = 0; - values[valuesById[1] = "RELAY_CONNECTION"] = 1; - values[valuesById[2] = "PEER_CONNECTION"] = 2; - values[valuesById[3] = "UDP_ADDRESS"] = 3; - values[valuesById[4] = "PEER_UDP_ADDRESS"] = 4; + values[valuesById[0] = "UDP_ADDRESS"] = 0; + values[valuesById[1] = "DIRECT_CONNECTION"] = 1; + values[valuesById[2] = "HOLE_PUNCH_CONNECTION"] = 2; + values[valuesById[3] = "RELAY_CONNECTION"] = 3; return values; })(); @@ -987,24 +987,25 @@ $root.peerInterface = (function() { return NatMessage; })(); - peerInterface.RelayConnectionRequest = (function() { + peerInterface.UDPAddressMessage = (function() { /** - * Properties of a RelayConnectionRequest. + * Properties of a UDPAddressMessage. * @memberof peerInterface - * @interface IRelayConnectionRequest - * @property {string|null} [publicKey] RelayConnectionRequest publicKey + * @interface IUDPAddressMessage + * @property {string|null} [address] UDPAddressMessage address + * @property {string|null} [token] UDPAddressMessage token */ /** - * Constructs a new RelayConnectionRequest. + * Constructs a new UDPAddressMessage. * @memberof peerInterface - * @classdesc Represents a RelayConnectionRequest. - * @implements IRelayConnectionRequest + * @classdesc Represents a UDPAddressMessage. + * @implements IUDPAddressMessage * @constructor - * @param {peerInterface.IRelayConnectionRequest=} [p] Properties to set + * @param {peerInterface.IUDPAddressMessage=} [p] Properties to set */ - function RelayConnectionRequest(p) { + function UDPAddressMessage(p) { if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1012,75 +1013,88 @@ $root.peerInterface = (function() { } /** - * RelayConnectionRequest publicKey. - * @member {string} publicKey - * @memberof peerInterface.RelayConnectionRequest + * UDPAddressMessage address. + * @member {string} address + * @memberof peerInterface.UDPAddressMessage + * @instance + */ + UDPAddressMessage.prototype.address = ""; + + /** + * UDPAddressMessage token. + * @member {string} token + * @memberof peerInterface.UDPAddressMessage * @instance */ - RelayConnectionRequest.prototype.publicKey = ""; + UDPAddressMessage.prototype.token = ""; /** - * Creates a new RelayConnectionRequest instance using the specified properties. + * Creates a new UDPAddressMessage instance using the specified properties. * @function create - * @memberof peerInterface.RelayConnectionRequest + * @memberof peerInterface.UDPAddressMessage * @static - * @param {peerInterface.IRelayConnectionRequest=} [properties] Properties to set - * @returns {peerInterface.RelayConnectionRequest} RelayConnectionRequest instance + * @param {peerInterface.IUDPAddressMessage=} [properties] Properties to set + * @returns {peerInterface.UDPAddressMessage} UDPAddressMessage instance */ - RelayConnectionRequest.create = function create(properties) { - return new RelayConnectionRequest(properties); + UDPAddressMessage.create = function create(properties) { + return new UDPAddressMessage(properties); }; /** - * Encodes the specified RelayConnectionRequest message. Does not implicitly {@link peerInterface.RelayConnectionRequest.verify|verify} messages. + * Encodes the specified UDPAddressMessage message. Does not implicitly {@link peerInterface.UDPAddressMessage.verify|verify} messages. * @function encode - * @memberof peerInterface.RelayConnectionRequest + * @memberof peerInterface.UDPAddressMessage * @static - * @param {peerInterface.IRelayConnectionRequest} m RelayConnectionRequest message or plain object to encode + * @param {peerInterface.IUDPAddressMessage} m UDPAddressMessage message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - RelayConnectionRequest.encode = function encode(m, w) { + UDPAddressMessage.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey")) - w.uint32(10).string(m.publicKey); + if (m.address != null && Object.hasOwnProperty.call(m, "address")) + w.uint32(10).string(m.address); + if (m.token != null && Object.hasOwnProperty.call(m, "token")) + w.uint32(18).string(m.token); return w; }; /** - * Encodes the specified RelayConnectionRequest message, length delimited. Does not implicitly {@link peerInterface.RelayConnectionRequest.verify|verify} messages. + * Encodes the specified UDPAddressMessage message, length delimited. Does not implicitly {@link peerInterface.UDPAddressMessage.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.RelayConnectionRequest + * @memberof peerInterface.UDPAddressMessage * @static - * @param {peerInterface.IRelayConnectionRequest} message RelayConnectionRequest message or plain object to encode + * @param {peerInterface.IUDPAddressMessage} message UDPAddressMessage message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - RelayConnectionRequest.encodeDelimited = function encodeDelimited(message, writer) { + UDPAddressMessage.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a RelayConnectionRequest message from the specified reader or buffer. + * Decodes a UDPAddressMessage message from the specified reader or buffer. * @function decode - * @memberof peerInterface.RelayConnectionRequest + * @memberof peerInterface.UDPAddressMessage * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.RelayConnectionRequest} RelayConnectionRequest + * @returns {peerInterface.UDPAddressMessage} UDPAddressMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - RelayConnectionRequest.decode = function decode(r, l) { + UDPAddressMessage.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.RelayConnectionRequest(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.UDPAddressMessage(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.publicKey = r.string(); + m.address = r.string(); + break; + case 2: + m.token = r.string(); break; default: r.skipType(t & 7); @@ -1091,42 +1105,42 @@ $root.peerInterface = (function() { }; /** - * Decodes a RelayConnectionRequest message from the specified reader or buffer, length delimited. + * Decodes a UDPAddressMessage message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.RelayConnectionRequest + * @memberof peerInterface.UDPAddressMessage * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.RelayConnectionRequest} RelayConnectionRequest + * @returns {peerInterface.UDPAddressMessage} UDPAddressMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - RelayConnectionRequest.decodeDelimited = function decodeDelimited(reader) { + UDPAddressMessage.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return RelayConnectionRequest; + return UDPAddressMessage; })(); - peerInterface.RelayConnectionResponse = (function() { + peerInterface.DirectConnectionMessage = (function() { /** - * Properties of a RelayConnectionResponse. + * Properties of a DirectConnectionMessage. * @memberof peerInterface - * @interface IRelayConnectionResponse - * @property {string|null} [serverAddress] RelayConnectionResponse serverAddress + * @interface IDirectConnectionMessage + * @property {string|null} [peerId] DirectConnectionMessage peerId */ /** - * Constructs a new RelayConnectionResponse. + * Constructs a new DirectConnectionMessage. * @memberof peerInterface - * @classdesc Represents a RelayConnectionResponse. - * @implements IRelayConnectionResponse + * @classdesc Represents a DirectConnectionMessage. + * @implements IDirectConnectionMessage * @constructor - * @param {peerInterface.IRelayConnectionResponse=} [p] Properties to set + * @param {peerInterface.IDirectConnectionMessage=} [p] Properties to set */ - function RelayConnectionResponse(p) { + function DirectConnectionMessage(p) { if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1134,75 +1148,75 @@ $root.peerInterface = (function() { } /** - * RelayConnectionResponse serverAddress. - * @member {string} serverAddress - * @memberof peerInterface.RelayConnectionResponse + * DirectConnectionMessage peerId. + * @member {string} peerId + * @memberof peerInterface.DirectConnectionMessage * @instance */ - RelayConnectionResponse.prototype.serverAddress = ""; + DirectConnectionMessage.prototype.peerId = ""; /** - * Creates a new RelayConnectionResponse instance using the specified properties. + * Creates a new DirectConnectionMessage instance using the specified properties. * @function create - * @memberof peerInterface.RelayConnectionResponse + * @memberof peerInterface.DirectConnectionMessage * @static - * @param {peerInterface.IRelayConnectionResponse=} [properties] Properties to set - * @returns {peerInterface.RelayConnectionResponse} RelayConnectionResponse instance + * @param {peerInterface.IDirectConnectionMessage=} [properties] Properties to set + * @returns {peerInterface.DirectConnectionMessage} DirectConnectionMessage instance */ - RelayConnectionResponse.create = function create(properties) { - return new RelayConnectionResponse(properties); + DirectConnectionMessage.create = function create(properties) { + return new DirectConnectionMessage(properties); }; /** - * Encodes the specified RelayConnectionResponse message. Does not implicitly {@link peerInterface.RelayConnectionResponse.verify|verify} messages. + * Encodes the specified DirectConnectionMessage message. Does not implicitly {@link peerInterface.DirectConnectionMessage.verify|verify} messages. * @function encode - * @memberof peerInterface.RelayConnectionResponse + * @memberof peerInterface.DirectConnectionMessage * @static - * @param {peerInterface.IRelayConnectionResponse} m RelayConnectionResponse message or plain object to encode + * @param {peerInterface.IDirectConnectionMessage} m DirectConnectionMessage message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - RelayConnectionResponse.encode = function encode(m, w) { + DirectConnectionMessage.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.serverAddress != null && Object.hasOwnProperty.call(m, "serverAddress")) - w.uint32(10).string(m.serverAddress); + if (m.peerId != null && Object.hasOwnProperty.call(m, "peerId")) + w.uint32(10).string(m.peerId); return w; }; /** - * Encodes the specified RelayConnectionResponse message, length delimited. Does not implicitly {@link peerInterface.RelayConnectionResponse.verify|verify} messages. + * Encodes the specified DirectConnectionMessage message, length delimited. Does not implicitly {@link peerInterface.DirectConnectionMessage.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.RelayConnectionResponse + * @memberof peerInterface.DirectConnectionMessage * @static - * @param {peerInterface.IRelayConnectionResponse} message RelayConnectionResponse message or plain object to encode + * @param {peerInterface.IDirectConnectionMessage} message DirectConnectionMessage message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - RelayConnectionResponse.encodeDelimited = function encodeDelimited(message, writer) { + DirectConnectionMessage.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a RelayConnectionResponse message from the specified reader or buffer. + * Decodes a DirectConnectionMessage message from the specified reader or buffer. * @function decode - * @memberof peerInterface.RelayConnectionResponse + * @memberof peerInterface.DirectConnectionMessage * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.RelayConnectionResponse} RelayConnectionResponse + * @returns {peerInterface.DirectConnectionMessage} DirectConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - RelayConnectionResponse.decode = function decode(r, l) { + DirectConnectionMessage.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.RelayConnectionResponse(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.DirectConnectionMessage(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.serverAddress = r.string(); + m.peerId = r.string(); break; default: r.skipType(t & 7); @@ -1213,42 +1227,44 @@ $root.peerInterface = (function() { }; /** - * Decodes a RelayConnectionResponse message from the specified reader or buffer, length delimited. + * Decodes a DirectConnectionMessage message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.RelayConnectionResponse + * @memberof peerInterface.DirectConnectionMessage * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.RelayConnectionResponse} RelayConnectionResponse + * @returns {peerInterface.DirectConnectionMessage} DirectConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - RelayConnectionResponse.decodeDelimited = function decodeDelimited(reader) { + DirectConnectionMessage.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return RelayConnectionResponse; + return DirectConnectionMessage; })(); - peerInterface.PeerConnectionRequest = (function() { + peerInterface.HolePunchConnectionMessage = (function() { /** - * Properties of a PeerConnectionRequest. + * Properties of a HolePunchConnectionMessage. * @memberof peerInterface - * @interface IPeerConnectionRequest - * @property {string|null} [publicKey] PeerConnectionRequest publicKey + * @interface IHolePunchConnectionMessage + * @property {string|null} [targetPeerId] HolePunchConnectionMessage targetPeerId + * @property {string|null} [originPeerId] HolePunchConnectionMessage originPeerId + * @property {string|null} [udpAddress] HolePunchConnectionMessage udpAddress */ /** - * Constructs a new PeerConnectionRequest. + * Constructs a new HolePunchConnectionMessage. * @memberof peerInterface - * @classdesc Represents a PeerConnectionRequest. - * @implements IPeerConnectionRequest + * @classdesc Represents a HolePunchConnectionMessage. + * @implements IHolePunchConnectionMessage * @constructor - * @param {peerInterface.IPeerConnectionRequest=} [p] Properties to set + * @param {peerInterface.IHolePunchConnectionMessage=} [p] Properties to set */ - function PeerConnectionRequest(p) { + function HolePunchConnectionMessage(p) { if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1256,75 +1272,101 @@ $root.peerInterface = (function() { } /** - * PeerConnectionRequest publicKey. - * @member {string} publicKey - * @memberof peerInterface.PeerConnectionRequest + * HolePunchConnectionMessage targetPeerId. + * @member {string} targetPeerId + * @memberof peerInterface.HolePunchConnectionMessage + * @instance + */ + HolePunchConnectionMessage.prototype.targetPeerId = ""; + + /** + * HolePunchConnectionMessage originPeerId. + * @member {string} originPeerId + * @memberof peerInterface.HolePunchConnectionMessage * @instance */ - PeerConnectionRequest.prototype.publicKey = ""; + HolePunchConnectionMessage.prototype.originPeerId = ""; /** - * Creates a new PeerConnectionRequest instance using the specified properties. + * HolePunchConnectionMessage udpAddress. + * @member {string} udpAddress + * @memberof peerInterface.HolePunchConnectionMessage + * @instance + */ + HolePunchConnectionMessage.prototype.udpAddress = ""; + + /** + * Creates a new HolePunchConnectionMessage instance using the specified properties. * @function create - * @memberof peerInterface.PeerConnectionRequest + * @memberof peerInterface.HolePunchConnectionMessage * @static - * @param {peerInterface.IPeerConnectionRequest=} [properties] Properties to set - * @returns {peerInterface.PeerConnectionRequest} PeerConnectionRequest instance + * @param {peerInterface.IHolePunchConnectionMessage=} [properties] Properties to set + * @returns {peerInterface.HolePunchConnectionMessage} HolePunchConnectionMessage instance */ - PeerConnectionRequest.create = function create(properties) { - return new PeerConnectionRequest(properties); + HolePunchConnectionMessage.create = function create(properties) { + return new HolePunchConnectionMessage(properties); }; /** - * Encodes the specified PeerConnectionRequest message. Does not implicitly {@link peerInterface.PeerConnectionRequest.verify|verify} messages. + * Encodes the specified HolePunchConnectionMessage message. Does not implicitly {@link peerInterface.HolePunchConnectionMessage.verify|verify} messages. * @function encode - * @memberof peerInterface.PeerConnectionRequest + * @memberof peerInterface.HolePunchConnectionMessage * @static - * @param {peerInterface.IPeerConnectionRequest} m PeerConnectionRequest message or plain object to encode + * @param {peerInterface.IHolePunchConnectionMessage} m HolePunchConnectionMessage message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - PeerConnectionRequest.encode = function encode(m, w) { + HolePunchConnectionMessage.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey")) - w.uint32(10).string(m.publicKey); + if (m.targetPeerId != null && Object.hasOwnProperty.call(m, "targetPeerId")) + w.uint32(10).string(m.targetPeerId); + if (m.originPeerId != null && Object.hasOwnProperty.call(m, "originPeerId")) + w.uint32(18).string(m.originPeerId); + if (m.udpAddress != null && Object.hasOwnProperty.call(m, "udpAddress")) + w.uint32(26).string(m.udpAddress); return w; }; /** - * Encodes the specified PeerConnectionRequest message, length delimited. Does not implicitly {@link peerInterface.PeerConnectionRequest.verify|verify} messages. + * Encodes the specified HolePunchConnectionMessage message, length delimited. Does not implicitly {@link peerInterface.HolePunchConnectionMessage.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.PeerConnectionRequest + * @memberof peerInterface.HolePunchConnectionMessage * @static - * @param {peerInterface.IPeerConnectionRequest} message PeerConnectionRequest message or plain object to encode + * @param {peerInterface.IHolePunchConnectionMessage} message HolePunchConnectionMessage message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - PeerConnectionRequest.encodeDelimited = function encodeDelimited(message, writer) { + HolePunchConnectionMessage.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a PeerConnectionRequest message from the specified reader or buffer. + * Decodes a HolePunchConnectionMessage message from the specified reader or buffer. * @function decode - * @memberof peerInterface.PeerConnectionRequest + * @memberof peerInterface.HolePunchConnectionMessage * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.PeerConnectionRequest} PeerConnectionRequest + * @returns {peerInterface.HolePunchConnectionMessage} HolePunchConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - PeerConnectionRequest.decode = function decode(r, l) { + HolePunchConnectionMessage.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.PeerConnectionRequest(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.HolePunchConnectionMessage(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.publicKey = r.string(); + m.targetPeerId = r.string(); + break; + case 2: + m.originPeerId = r.string(); + break; + case 3: + m.udpAddress = r.string(); break; default: r.skipType(t & 7); @@ -1335,42 +1377,44 @@ $root.peerInterface = (function() { }; /** - * Decodes a PeerConnectionRequest message from the specified reader or buffer, length delimited. + * Decodes a HolePunchConnectionMessage message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.PeerConnectionRequest + * @memberof peerInterface.HolePunchConnectionMessage * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.PeerConnectionRequest} PeerConnectionRequest + * @returns {peerInterface.HolePunchConnectionMessage} HolePunchConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - PeerConnectionRequest.decodeDelimited = function decodeDelimited(reader) { + HolePunchConnectionMessage.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return PeerConnectionRequest; + return HolePunchConnectionMessage; })(); - peerInterface.PeerConnectionResponse = (function() { + peerInterface.RelayConnectionMessage = (function() { /** - * Properties of a PeerConnectionResponse. + * Properties of a RelayConnectionMessage. * @memberof peerInterface - * @interface IPeerConnectionResponse - * @property {string|null} [peerAddress] PeerConnectionResponse peerAddress + * @interface IRelayConnectionMessage + * @property {string|null} [targetPeerId] RelayConnectionMessage targetPeerId + * @property {string|null} [originPeerId] RelayConnectionMessage originPeerId + * @property {string|null} [relayAddress] RelayConnectionMessage relayAddress */ /** - * Constructs a new PeerConnectionResponse. + * Constructs a new RelayConnectionMessage. * @memberof peerInterface - * @classdesc Represents a PeerConnectionResponse. - * @implements IPeerConnectionResponse + * @classdesc Represents a RelayConnectionMessage. + * @implements IRelayConnectionMessage * @constructor - * @param {peerInterface.IPeerConnectionResponse=} [p] Properties to set + * @param {peerInterface.IRelayConnectionMessage=} [p] Properties to set */ - function PeerConnectionResponse(p) { + function RelayConnectionMessage(p) { if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1378,75 +1422,101 @@ $root.peerInterface = (function() { } /** - * PeerConnectionResponse peerAddress. - * @member {string} peerAddress - * @memberof peerInterface.PeerConnectionResponse + * RelayConnectionMessage targetPeerId. + * @member {string} targetPeerId + * @memberof peerInterface.RelayConnectionMessage * @instance */ - PeerConnectionResponse.prototype.peerAddress = ""; + RelayConnectionMessage.prototype.targetPeerId = ""; /** - * Creates a new PeerConnectionResponse instance using the specified properties. + * RelayConnectionMessage originPeerId. + * @member {string} originPeerId + * @memberof peerInterface.RelayConnectionMessage + * @instance + */ + RelayConnectionMessage.prototype.originPeerId = ""; + + /** + * RelayConnectionMessage relayAddress. + * @member {string} relayAddress + * @memberof peerInterface.RelayConnectionMessage + * @instance + */ + RelayConnectionMessage.prototype.relayAddress = ""; + + /** + * Creates a new RelayConnectionMessage instance using the specified properties. * @function create - * @memberof peerInterface.PeerConnectionResponse + * @memberof peerInterface.RelayConnectionMessage * @static - * @param {peerInterface.IPeerConnectionResponse=} [properties] Properties to set - * @returns {peerInterface.PeerConnectionResponse} PeerConnectionResponse instance + * @param {peerInterface.IRelayConnectionMessage=} [properties] Properties to set + * @returns {peerInterface.RelayConnectionMessage} RelayConnectionMessage instance */ - PeerConnectionResponse.create = function create(properties) { - return new PeerConnectionResponse(properties); + RelayConnectionMessage.create = function create(properties) { + return new RelayConnectionMessage(properties); }; /** - * Encodes the specified PeerConnectionResponse message. Does not implicitly {@link peerInterface.PeerConnectionResponse.verify|verify} messages. + * Encodes the specified RelayConnectionMessage message. Does not implicitly {@link peerInterface.RelayConnectionMessage.verify|verify} messages. * @function encode - * @memberof peerInterface.PeerConnectionResponse + * @memberof peerInterface.RelayConnectionMessage * @static - * @param {peerInterface.IPeerConnectionResponse} m PeerConnectionResponse message or plain object to encode + * @param {peerInterface.IRelayConnectionMessage} m RelayConnectionMessage message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - PeerConnectionResponse.encode = function encode(m, w) { + RelayConnectionMessage.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.peerAddress != null && Object.hasOwnProperty.call(m, "peerAddress")) - w.uint32(10).string(m.peerAddress); + if (m.targetPeerId != null && Object.hasOwnProperty.call(m, "targetPeerId")) + w.uint32(10).string(m.targetPeerId); + if (m.originPeerId != null && Object.hasOwnProperty.call(m, "originPeerId")) + w.uint32(18).string(m.originPeerId); + if (m.relayAddress != null && Object.hasOwnProperty.call(m, "relayAddress")) + w.uint32(26).string(m.relayAddress); return w; }; /** - * Encodes the specified PeerConnectionResponse message, length delimited. Does not implicitly {@link peerInterface.PeerConnectionResponse.verify|verify} messages. + * Encodes the specified RelayConnectionMessage message, length delimited. Does not implicitly {@link peerInterface.RelayConnectionMessage.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.PeerConnectionResponse + * @memberof peerInterface.RelayConnectionMessage * @static - * @param {peerInterface.IPeerConnectionResponse} message PeerConnectionResponse message or plain object to encode + * @param {peerInterface.IRelayConnectionMessage} message RelayConnectionMessage message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - PeerConnectionResponse.encodeDelimited = function encodeDelimited(message, writer) { + RelayConnectionMessage.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a PeerConnectionResponse message from the specified reader or buffer. + * Decodes a RelayConnectionMessage message from the specified reader or buffer. * @function decode - * @memberof peerInterface.PeerConnectionResponse + * @memberof peerInterface.RelayConnectionMessage * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.PeerConnectionResponse} PeerConnectionResponse + * @returns {peerInterface.RelayConnectionMessage} RelayConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - PeerConnectionResponse.decode = function decode(r, l) { + RelayConnectionMessage.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.PeerConnectionResponse(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.RelayConnectionMessage(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.peerAddress = r.string(); + m.targetPeerId = r.string(); + break; + case 2: + m.originPeerId = r.string(); + break; + case 3: + m.relayAddress = r.string(); break; default: r.skipType(t & 7); @@ -1457,42 +1527,58 @@ $root.peerInterface = (function() { }; /** - * Decodes a PeerConnectionResponse message from the specified reader or buffer, length delimited. + * Decodes a RelayConnectionMessage message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.PeerConnectionResponse + * @memberof peerInterface.RelayConnectionMessage * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.PeerConnectionResponse} PeerConnectionResponse + * @returns {peerInterface.RelayConnectionMessage} RelayConnectionMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - PeerConnectionResponse.decodeDelimited = function decodeDelimited(reader) { + RelayConnectionMessage.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return PeerConnectionResponse; + return RelayConnectionMessage; + })(); + + /** + * CAMessageType enum. + * @name peerInterface.CAMessageType + * @enum {number} + * @property {number} ROOT_CERT=0 ROOT_CERT value + * @property {number} REQUEST_CERT=1 REQUEST_CERT value + */ + peerInterface.CAMessageType = (function() { + var valuesById = {}, values = Object.create(valuesById); + values[valuesById[0] = "ROOT_CERT"] = 0; + values[valuesById[1] = "REQUEST_CERT"] = 1; + return values; })(); - peerInterface.UDPAddressResponse = (function() { + peerInterface.CAMessage = (function() { /** - * Properties of a UDPAddressResponse. + * Properties of a CAMessage. * @memberof peerInterface - * @interface IUDPAddressResponse - * @property {string|null} [address] UDPAddressResponse address + * @interface ICAMessage + * @property {peerInterface.CAMessageType|null} [type] CAMessage type + * @property {boolean|null} [isResponse] CAMessage isResponse + * @property {Uint8Array|null} [subMessage] CAMessage subMessage */ /** - * Constructs a new UDPAddressResponse. + * Constructs a new CAMessage. * @memberof peerInterface - * @classdesc Represents a UDPAddressResponse. - * @implements IUDPAddressResponse + * @classdesc Represents a CAMessage. + * @implements ICAMessage * @constructor - * @param {peerInterface.IUDPAddressResponse=} [p] Properties to set + * @param {peerInterface.ICAMessage=} [p] Properties to set */ - function UDPAddressResponse(p) { + function CAMessage(p) { if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1500,75 +1586,101 @@ $root.peerInterface = (function() { } /** - * UDPAddressResponse address. - * @member {string} address - * @memberof peerInterface.UDPAddressResponse + * CAMessage type. + * @member {peerInterface.CAMessageType} type + * @memberof peerInterface.CAMessage + * @instance + */ + CAMessage.prototype.type = 0; + + /** + * CAMessage isResponse. + * @member {boolean} isResponse + * @memberof peerInterface.CAMessage * @instance */ - UDPAddressResponse.prototype.address = ""; + CAMessage.prototype.isResponse = false; /** - * Creates a new UDPAddressResponse instance using the specified properties. + * CAMessage subMessage. + * @member {Uint8Array} subMessage + * @memberof peerInterface.CAMessage + * @instance + */ + CAMessage.prototype.subMessage = $util.newBuffer([]); + + /** + * Creates a new CAMessage instance using the specified properties. * @function create - * @memberof peerInterface.UDPAddressResponse + * @memberof peerInterface.CAMessage * @static - * @param {peerInterface.IUDPAddressResponse=} [properties] Properties to set - * @returns {peerInterface.UDPAddressResponse} UDPAddressResponse instance + * @param {peerInterface.ICAMessage=} [properties] Properties to set + * @returns {peerInterface.CAMessage} CAMessage instance */ - UDPAddressResponse.create = function create(properties) { - return new UDPAddressResponse(properties); + CAMessage.create = function create(properties) { + return new CAMessage(properties); }; /** - * Encodes the specified UDPAddressResponse message. Does not implicitly {@link peerInterface.UDPAddressResponse.verify|verify} messages. + * Encodes the specified CAMessage message. Does not implicitly {@link peerInterface.CAMessage.verify|verify} messages. * @function encode - * @memberof peerInterface.UDPAddressResponse + * @memberof peerInterface.CAMessage * @static - * @param {peerInterface.IUDPAddressResponse} m UDPAddressResponse message or plain object to encode + * @param {peerInterface.ICAMessage} m CAMessage message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - UDPAddressResponse.encode = function encode(m, w) { + CAMessage.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.address != null && Object.hasOwnProperty.call(m, "address")) - w.uint32(10).string(m.address); + if (m.type != null && Object.hasOwnProperty.call(m, "type")) + w.uint32(8).int32(m.type); + if (m.isResponse != null && Object.hasOwnProperty.call(m, "isResponse")) + w.uint32(16).bool(m.isResponse); + if (m.subMessage != null && Object.hasOwnProperty.call(m, "subMessage")) + w.uint32(26).bytes(m.subMessage); return w; }; /** - * Encodes the specified UDPAddressResponse message, length delimited. Does not implicitly {@link peerInterface.UDPAddressResponse.verify|verify} messages. + * Encodes the specified CAMessage message, length delimited. Does not implicitly {@link peerInterface.CAMessage.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.UDPAddressResponse + * @memberof peerInterface.CAMessage * @static - * @param {peerInterface.IUDPAddressResponse} message UDPAddressResponse message or plain object to encode + * @param {peerInterface.ICAMessage} message CAMessage message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - UDPAddressResponse.encodeDelimited = function encodeDelimited(message, writer) { + CAMessage.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a UDPAddressResponse message from the specified reader or buffer. + * Decodes a CAMessage message from the specified reader or buffer. * @function decode - * @memberof peerInterface.UDPAddressResponse + * @memberof peerInterface.CAMessage * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.UDPAddressResponse} UDPAddressResponse + * @returns {peerInterface.CAMessage} CAMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - UDPAddressResponse.decode = function decode(r, l) { + CAMessage.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.UDPAddressResponse(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.CAMessage(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.address = r.string(); + m.type = r.int32(); + break; + case 2: + m.isResponse = r.bool(); + break; + case 3: + m.subMessage = r.bytes(); break; default: r.skipType(t & 7); @@ -1579,42 +1691,58 @@ $root.peerInterface = (function() { }; /** - * Decodes a UDPAddressResponse message from the specified reader or buffer, length delimited. + * Decodes a CAMessage message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.UDPAddressResponse + * @memberof peerInterface.CAMessage * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.UDPAddressResponse} UDPAddressResponse + * @returns {peerInterface.CAMessage} CAMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - UDPAddressResponse.decodeDelimited = function decodeDelimited(reader) { + CAMessage.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return UDPAddressResponse; + return CAMessage; + })(); + + /** + * PeerDHTMessageType enum. + * @name peerInterface.PeerDHTMessageType + * @enum {number} + * @property {number} PING=0 PING value + * @property {number} FIND_NODE=1 FIND_NODE value + */ + peerInterface.PeerDHTMessageType = (function() { + var valuesById = {}, values = Object.create(valuesById); + values[valuesById[0] = "PING"] = 0; + values[valuesById[1] = "FIND_NODE"] = 1; + return values; })(); - peerInterface.HolePunchRegisterRequest = (function() { + peerInterface.PeerDHTMessage = (function() { /** - * Properties of a HolePunchRegisterRequest. + * Properties of a PeerDHTMessage. * @memberof peerInterface - * @interface IHolePunchRegisterRequest - * @property {string|null} [publicKey] HolePunchRegisterRequest publicKey + * @interface IPeerDHTMessage + * @property {peerInterface.PeerDHTMessageType|null} [type] PeerDHTMessage type + * @property {boolean|null} [isResponse] PeerDHTMessage isResponse + * @property {Uint8Array|null} [subMessage] PeerDHTMessage subMessage */ /** - * Constructs a new HolePunchRegisterRequest. + * Constructs a new PeerDHTMessage. * @memberof peerInterface - * @classdesc Represents a HolePunchRegisterRequest. - * @implements IHolePunchRegisterRequest + * @classdesc Represents a PeerDHTMessage. + * @implements IPeerDHTMessage * @constructor - * @param {peerInterface.IHolePunchRegisterRequest=} [p] Properties to set + * @param {peerInterface.IPeerDHTMessage=} [p] Properties to set */ - function HolePunchRegisterRequest(p) { + function PeerDHTMessage(p) { if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1622,75 +1750,101 @@ $root.peerInterface = (function() { } /** - * HolePunchRegisterRequest publicKey. - * @member {string} publicKey - * @memberof peerInterface.HolePunchRegisterRequest + * PeerDHTMessage type. + * @member {peerInterface.PeerDHTMessageType} type + * @memberof peerInterface.PeerDHTMessage + * @instance + */ + PeerDHTMessage.prototype.type = 0; + + /** + * PeerDHTMessage isResponse. + * @member {boolean} isResponse + * @memberof peerInterface.PeerDHTMessage + * @instance + */ + PeerDHTMessage.prototype.isResponse = false; + + /** + * PeerDHTMessage subMessage. + * @member {Uint8Array} subMessage + * @memberof peerInterface.PeerDHTMessage * @instance */ - HolePunchRegisterRequest.prototype.publicKey = ""; + PeerDHTMessage.prototype.subMessage = $util.newBuffer([]); /** - * Creates a new HolePunchRegisterRequest instance using the specified properties. + * Creates a new PeerDHTMessage instance using the specified properties. * @function create - * @memberof peerInterface.HolePunchRegisterRequest + * @memberof peerInterface.PeerDHTMessage * @static - * @param {peerInterface.IHolePunchRegisterRequest=} [properties] Properties to set - * @returns {peerInterface.HolePunchRegisterRequest} HolePunchRegisterRequest instance + * @param {peerInterface.IPeerDHTMessage=} [properties] Properties to set + * @returns {peerInterface.PeerDHTMessage} PeerDHTMessage instance */ - HolePunchRegisterRequest.create = function create(properties) { - return new HolePunchRegisterRequest(properties); + PeerDHTMessage.create = function create(properties) { + return new PeerDHTMessage(properties); }; /** - * Encodes the specified HolePunchRegisterRequest message. Does not implicitly {@link peerInterface.HolePunchRegisterRequest.verify|verify} messages. + * Encodes the specified PeerDHTMessage message. Does not implicitly {@link peerInterface.PeerDHTMessage.verify|verify} messages. * @function encode - * @memberof peerInterface.HolePunchRegisterRequest + * @memberof peerInterface.PeerDHTMessage * @static - * @param {peerInterface.IHolePunchRegisterRequest} m HolePunchRegisterRequest message or plain object to encode + * @param {peerInterface.IPeerDHTMessage} m PeerDHTMessage message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - HolePunchRegisterRequest.encode = function encode(m, w) { + PeerDHTMessage.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey")) - w.uint32(10).string(m.publicKey); + if (m.type != null && Object.hasOwnProperty.call(m, "type")) + w.uint32(8).int32(m.type); + if (m.isResponse != null && Object.hasOwnProperty.call(m, "isResponse")) + w.uint32(16).bool(m.isResponse); + if (m.subMessage != null && Object.hasOwnProperty.call(m, "subMessage")) + w.uint32(26).bytes(m.subMessage); return w; }; /** - * Encodes the specified HolePunchRegisterRequest message, length delimited. Does not implicitly {@link peerInterface.HolePunchRegisterRequest.verify|verify} messages. + * Encodes the specified PeerDHTMessage message, length delimited. Does not implicitly {@link peerInterface.PeerDHTMessage.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.HolePunchRegisterRequest + * @memberof peerInterface.PeerDHTMessage * @static - * @param {peerInterface.IHolePunchRegisterRequest} message HolePunchRegisterRequest message or plain object to encode + * @param {peerInterface.IPeerDHTMessage} message PeerDHTMessage message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - HolePunchRegisterRequest.encodeDelimited = function encodeDelimited(message, writer) { + PeerDHTMessage.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a HolePunchRegisterRequest message from the specified reader or buffer. + * Decodes a PeerDHTMessage message from the specified reader or buffer. * @function decode - * @memberof peerInterface.HolePunchRegisterRequest + * @memberof peerInterface.PeerDHTMessage * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.HolePunchRegisterRequest} HolePunchRegisterRequest + * @returns {peerInterface.PeerDHTMessage} PeerDHTMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - HolePunchRegisterRequest.decode = function decode(r, l) { + PeerDHTMessage.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.HolePunchRegisterRequest(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.PeerDHTMessage(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.publicKey = r.string(); + m.type = r.int32(); + break; + case 2: + m.isResponse = r.bool(); + break; + case 3: + m.subMessage = r.bytes(); break; default: r.skipType(t & 7); @@ -1701,42 +1855,43 @@ $root.peerInterface = (function() { }; /** - * Decodes a HolePunchRegisterRequest message from the specified reader or buffer, length delimited. + * Decodes a PeerDHTMessage message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.HolePunchRegisterRequest + * @memberof peerInterface.PeerDHTMessage * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.HolePunchRegisterRequest} HolePunchRegisterRequest + * @returns {peerInterface.PeerDHTMessage} PeerDHTMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - HolePunchRegisterRequest.decodeDelimited = function decodeDelimited(reader) { + PeerDHTMessage.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return HolePunchRegisterRequest; + return PeerDHTMessage; })(); - peerInterface.HolePunchRegisterResponse = (function() { + peerInterface.PeerDHTPingNodeMessage = (function() { /** - * Properties of a HolePunchRegisterResponse. + * Properties of a PeerDHTPingNodeMessage. * @memberof peerInterface - * @interface IHolePunchRegisterResponse - * @property {string|null} [connectedAddress] HolePunchRegisterResponse connectedAddress + * @interface IPeerDHTPingNodeMessage + * @property {string|null} [peerId] PeerDHTPingNodeMessage peerId + * @property {string|null} [randomChallenge] PeerDHTPingNodeMessage randomChallenge */ /** - * Constructs a new HolePunchRegisterResponse. + * Constructs a new PeerDHTPingNodeMessage. * @memberof peerInterface - * @classdesc Represents a HolePunchRegisterResponse. - * @implements IHolePunchRegisterResponse + * @classdesc Represents a PeerDHTPingNodeMessage. + * @implements IPeerDHTPingNodeMessage * @constructor - * @param {peerInterface.IHolePunchRegisterResponse=} [p] Properties to set + * @param {peerInterface.IPeerDHTPingNodeMessage=} [p] Properties to set */ - function HolePunchRegisterResponse(p) { + function PeerDHTPingNodeMessage(p) { if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1744,75 +1899,88 @@ $root.peerInterface = (function() { } /** - * HolePunchRegisterResponse connectedAddress. - * @member {string} connectedAddress - * @memberof peerInterface.HolePunchRegisterResponse + * PeerDHTPingNodeMessage peerId. + * @member {string} peerId + * @memberof peerInterface.PeerDHTPingNodeMessage * @instance */ - HolePunchRegisterResponse.prototype.connectedAddress = ""; + PeerDHTPingNodeMessage.prototype.peerId = ""; /** - * Creates a new HolePunchRegisterResponse instance using the specified properties. + * PeerDHTPingNodeMessage randomChallenge. + * @member {string} randomChallenge + * @memberof peerInterface.PeerDHTPingNodeMessage + * @instance + */ + PeerDHTPingNodeMessage.prototype.randomChallenge = ""; + + /** + * Creates a new PeerDHTPingNodeMessage instance using the specified properties. * @function create - * @memberof peerInterface.HolePunchRegisterResponse + * @memberof peerInterface.PeerDHTPingNodeMessage * @static - * @param {peerInterface.IHolePunchRegisterResponse=} [properties] Properties to set - * @returns {peerInterface.HolePunchRegisterResponse} HolePunchRegisterResponse instance + * @param {peerInterface.IPeerDHTPingNodeMessage=} [properties] Properties to set + * @returns {peerInterface.PeerDHTPingNodeMessage} PeerDHTPingNodeMessage instance */ - HolePunchRegisterResponse.create = function create(properties) { - return new HolePunchRegisterResponse(properties); + PeerDHTPingNodeMessage.create = function create(properties) { + return new PeerDHTPingNodeMessage(properties); }; /** - * Encodes the specified HolePunchRegisterResponse message. Does not implicitly {@link peerInterface.HolePunchRegisterResponse.verify|verify} messages. + * Encodes the specified PeerDHTPingNodeMessage message. Does not implicitly {@link peerInterface.PeerDHTPingNodeMessage.verify|verify} messages. * @function encode - * @memberof peerInterface.HolePunchRegisterResponse + * @memberof peerInterface.PeerDHTPingNodeMessage * @static - * @param {peerInterface.IHolePunchRegisterResponse} m HolePunchRegisterResponse message or plain object to encode + * @param {peerInterface.IPeerDHTPingNodeMessage} m PeerDHTPingNodeMessage message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - HolePunchRegisterResponse.encode = function encode(m, w) { + PeerDHTPingNodeMessage.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.connectedAddress != null && Object.hasOwnProperty.call(m, "connectedAddress")) - w.uint32(10).string(m.connectedAddress); + if (m.peerId != null && Object.hasOwnProperty.call(m, "peerId")) + w.uint32(10).string(m.peerId); + if (m.randomChallenge != null && Object.hasOwnProperty.call(m, "randomChallenge")) + w.uint32(18).string(m.randomChallenge); return w; }; /** - * Encodes the specified HolePunchRegisterResponse message, length delimited. Does not implicitly {@link peerInterface.HolePunchRegisterResponse.verify|verify} messages. + * Encodes the specified PeerDHTPingNodeMessage message, length delimited. Does not implicitly {@link peerInterface.PeerDHTPingNodeMessage.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.HolePunchRegisterResponse + * @memberof peerInterface.PeerDHTPingNodeMessage * @static - * @param {peerInterface.IHolePunchRegisterResponse} message HolePunchRegisterResponse message or plain object to encode + * @param {peerInterface.IPeerDHTPingNodeMessage} message PeerDHTPingNodeMessage message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - HolePunchRegisterResponse.encodeDelimited = function encodeDelimited(message, writer) { + PeerDHTPingNodeMessage.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a HolePunchRegisterResponse message from the specified reader or buffer. + * Decodes a PeerDHTPingNodeMessage message from the specified reader or buffer. * @function decode - * @memberof peerInterface.HolePunchRegisterResponse + * @memberof peerInterface.PeerDHTPingNodeMessage * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.HolePunchRegisterResponse} HolePunchRegisterResponse + * @returns {peerInterface.PeerDHTPingNodeMessage} PeerDHTPingNodeMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - HolePunchRegisterResponse.decode = function decode(r, l) { + PeerDHTPingNodeMessage.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.HolePunchRegisterResponse(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.PeerDHTPingNodeMessage(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.connectedAddress = r.string(); + m.peerId = r.string(); + break; + case 2: + m.randomChallenge = r.string(); break; default: r.skipType(t & 7); @@ -1823,42 +1991,44 @@ $root.peerInterface = (function() { }; /** - * Decodes a HolePunchRegisterResponse message from the specified reader or buffer, length delimited. + * Decodes a PeerDHTPingNodeMessage message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.HolePunchRegisterResponse + * @memberof peerInterface.PeerDHTPingNodeMessage * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.HolePunchRegisterResponse} HolePunchRegisterResponse + * @returns {peerInterface.PeerDHTPingNodeMessage} PeerDHTPingNodeMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - HolePunchRegisterResponse.decodeDelimited = function decodeDelimited(reader) { + PeerDHTPingNodeMessage.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return HolePunchRegisterResponse; + return PeerDHTPingNodeMessage; })(); - peerInterface.PeerUdpAddressRequest = (function() { + peerInterface.PeerDHTFindNodeMessage = (function() { /** - * Properties of a PeerUdpAddressRequest. + * Properties of a PeerDHTFindNodeMessage. * @memberof peerInterface - * @interface IPeerUdpAddressRequest - * @property {string|null} [publicKey] PeerUdpAddressRequest publicKey + * @interface IPeerDHTFindNodeMessage + * @property {string|null} [peerId] PeerDHTFindNodeMessage peerId + * @property {Array.|null} [closestPeers] PeerDHTFindNodeMessage closestPeers */ /** - * Constructs a new PeerUdpAddressRequest. + * Constructs a new PeerDHTFindNodeMessage. * @memberof peerInterface - * @classdesc Represents a PeerUdpAddressRequest. - * @implements IPeerUdpAddressRequest + * @classdesc Represents a PeerDHTFindNodeMessage. + * @implements IPeerDHTFindNodeMessage * @constructor - * @param {peerInterface.IPeerUdpAddressRequest=} [p] Properties to set + * @param {peerInterface.IPeerDHTFindNodeMessage=} [p] Properties to set */ - function PeerUdpAddressRequest(p) { + function PeerDHTFindNodeMessage(p) { + this.closestPeers = []; if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1866,75 +2036,92 @@ $root.peerInterface = (function() { } /** - * PeerUdpAddressRequest publicKey. - * @member {string} publicKey - * @memberof peerInterface.PeerUdpAddressRequest + * PeerDHTFindNodeMessage peerId. + * @member {string} peerId + * @memberof peerInterface.PeerDHTFindNodeMessage + * @instance + */ + PeerDHTFindNodeMessage.prototype.peerId = ""; + + /** + * PeerDHTFindNodeMessage closestPeers. + * @member {Array.} closestPeers + * @memberof peerInterface.PeerDHTFindNodeMessage * @instance */ - PeerUdpAddressRequest.prototype.publicKey = ""; + PeerDHTFindNodeMessage.prototype.closestPeers = $util.emptyArray; /** - * Creates a new PeerUdpAddressRequest instance using the specified properties. + * Creates a new PeerDHTFindNodeMessage instance using the specified properties. * @function create - * @memberof peerInterface.PeerUdpAddressRequest + * @memberof peerInterface.PeerDHTFindNodeMessage * @static - * @param {peerInterface.IPeerUdpAddressRequest=} [properties] Properties to set - * @returns {peerInterface.PeerUdpAddressRequest} PeerUdpAddressRequest instance + * @param {peerInterface.IPeerDHTFindNodeMessage=} [properties] Properties to set + * @returns {peerInterface.PeerDHTFindNodeMessage} PeerDHTFindNodeMessage instance */ - PeerUdpAddressRequest.create = function create(properties) { - return new PeerUdpAddressRequest(properties); + PeerDHTFindNodeMessage.create = function create(properties) { + return new PeerDHTFindNodeMessage(properties); }; /** - * Encodes the specified PeerUdpAddressRequest message. Does not implicitly {@link peerInterface.PeerUdpAddressRequest.verify|verify} messages. + * Encodes the specified PeerDHTFindNodeMessage message. Does not implicitly {@link peerInterface.PeerDHTFindNodeMessage.verify|verify} messages. * @function encode - * @memberof peerInterface.PeerUdpAddressRequest + * @memberof peerInterface.PeerDHTFindNodeMessage * @static - * @param {peerInterface.IPeerUdpAddressRequest} m PeerUdpAddressRequest message or plain object to encode + * @param {peerInterface.IPeerDHTFindNodeMessage} m PeerDHTFindNodeMessage message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - PeerUdpAddressRequest.encode = function encode(m, w) { + PeerDHTFindNodeMessage.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey")) - w.uint32(10).string(m.publicKey); + if (m.peerId != null && Object.hasOwnProperty.call(m, "peerId")) + w.uint32(10).string(m.peerId); + if (m.closestPeers != null && m.closestPeers.length) { + for (var i = 0; i < m.closestPeers.length; ++i) + $root.peerInterface.PeerInfoMessage.encode(m.closestPeers[i], w.uint32(18).fork()).ldelim(); + } return w; }; /** - * Encodes the specified PeerUdpAddressRequest message, length delimited. Does not implicitly {@link peerInterface.PeerUdpAddressRequest.verify|verify} messages. + * Encodes the specified PeerDHTFindNodeMessage message, length delimited. Does not implicitly {@link peerInterface.PeerDHTFindNodeMessage.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.PeerUdpAddressRequest + * @memberof peerInterface.PeerDHTFindNodeMessage * @static - * @param {peerInterface.IPeerUdpAddressRequest} message PeerUdpAddressRequest message or plain object to encode + * @param {peerInterface.IPeerDHTFindNodeMessage} message PeerDHTFindNodeMessage message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - PeerUdpAddressRequest.encodeDelimited = function encodeDelimited(message, writer) { + PeerDHTFindNodeMessage.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a PeerUdpAddressRequest message from the specified reader or buffer. + * Decodes a PeerDHTFindNodeMessage message from the specified reader or buffer. * @function decode - * @memberof peerInterface.PeerUdpAddressRequest + * @memberof peerInterface.PeerDHTFindNodeMessage * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.PeerUdpAddressRequest} PeerUdpAddressRequest + * @returns {peerInterface.PeerDHTFindNodeMessage} PeerDHTFindNodeMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - PeerUdpAddressRequest.decode = function decode(r, l) { + PeerDHTFindNodeMessage.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.PeerUdpAddressRequest(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.PeerDHTFindNodeMessage(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.publicKey = r.string(); + m.peerId = r.string(); + break; + case 2: + if (!(m.closestPeers && m.closestPeers.length)) + m.closestPeers = []; + m.closestPeers.push($root.peerInterface.PeerInfoMessage.decode(r, r.uint32())); break; default: r.skipType(t & 7); @@ -1945,42 +2132,51 @@ $root.peerInterface = (function() { }; /** - * Decodes a PeerUdpAddressRequest message from the specified reader or buffer, length delimited. + * Decodes a PeerDHTFindNodeMessage message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.PeerUdpAddressRequest + * @memberof peerInterface.PeerDHTFindNodeMessage * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.PeerUdpAddressRequest} PeerUdpAddressRequest + * @returns {peerInterface.PeerDHTFindNodeMessage} PeerDHTFindNodeMessage * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - PeerUdpAddressRequest.decodeDelimited = function decodeDelimited(reader) { + PeerDHTFindNodeMessage.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return PeerUdpAddressRequest; + return PeerDHTFindNodeMessage; })(); - peerInterface.PeerUdpAddressResponse = (function() { + peerInterface.MTPPacket = (function() { /** - * Properties of a PeerUdpAddressResponse. + * Properties of a MTPPacket. * @memberof peerInterface - * @interface IPeerUdpAddressResponse - * @property {string|null} [address] PeerUdpAddressResponse address + * @interface IMTPPacket + * @property {number|null} [id] MTPPacket id + * @property {string|null} [peerId] MTPPacket peerId + * @property {number|null} [connection] MTPPacket connection + * @property {number|null} [timestamp] MTPPacket timestamp + * @property {number|null} [timediff] MTPPacket timediff + * @property {number|null} [window] MTPPacket window + * @property {number|null} [seq] MTPPacket seq + * @property {number|null} [ack] MTPPacket ack + * @property {Uint8Array|null} [data] MTPPacket data + * @property {number|null} [sent] MTPPacket sent */ /** - * Constructs a new PeerUdpAddressResponse. + * Constructs a new MTPPacket. * @memberof peerInterface - * @classdesc Represents a PeerUdpAddressResponse. - * @implements IPeerUdpAddressResponse + * @classdesc Represents a MTPPacket. + * @implements IMTPPacket * @constructor - * @param {peerInterface.IPeerUdpAddressResponse=} [p] Properties to set + * @param {peerInterface.IMTPPacket=} [p] Properties to set */ - function PeerUdpAddressResponse(p) { + function MTPPacket(p) { if (p) for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) @@ -1988,241 +2184,192 @@ $root.peerInterface = (function() { } /** - * PeerUdpAddressResponse address. - * @member {string} address - * @memberof peerInterface.PeerUdpAddressResponse + * MTPPacket id. + * @member {number} id + * @memberof peerInterface.MTPPacket * @instance */ - PeerUdpAddressResponse.prototype.address = ""; + MTPPacket.prototype.id = 0; /** - * Creates a new PeerUdpAddressResponse instance using the specified properties. - * @function create - * @memberof peerInterface.PeerUdpAddressResponse - * @static - * @param {peerInterface.IPeerUdpAddressResponse=} [properties] Properties to set - * @returns {peerInterface.PeerUdpAddressResponse} PeerUdpAddressResponse instance + * MTPPacket peerId. + * @member {string} peerId + * @memberof peerInterface.MTPPacket + * @instance */ - PeerUdpAddressResponse.create = function create(properties) { - return new PeerUdpAddressResponse(properties); - }; + MTPPacket.prototype.peerId = ""; /** - * Encodes the specified PeerUdpAddressResponse message. Does not implicitly {@link peerInterface.PeerUdpAddressResponse.verify|verify} messages. - * @function encode - * @memberof peerInterface.PeerUdpAddressResponse - * @static - * @param {peerInterface.IPeerUdpAddressResponse} m PeerUdpAddressResponse message or plain object to encode - * @param {$protobuf.Writer} [w] Writer to encode to - * @returns {$protobuf.Writer} Writer + * MTPPacket connection. + * @member {number} connection + * @memberof peerInterface.MTPPacket + * @instance */ - PeerUdpAddressResponse.encode = function encode(m, w) { - if (!w) - w = $Writer.create(); - if (m.address != null && Object.hasOwnProperty.call(m, "address")) - w.uint32(10).string(m.address); - return w; - }; + MTPPacket.prototype.connection = 0; /** - * Encodes the specified PeerUdpAddressResponse message, length delimited. Does not implicitly {@link peerInterface.PeerUdpAddressResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof peerInterface.PeerUdpAddressResponse - * @static - * @param {peerInterface.IPeerUdpAddressResponse} message PeerUdpAddressResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer + * MTPPacket timestamp. + * @member {number} timestamp + * @memberof peerInterface.MTPPacket + * @instance */ - PeerUdpAddressResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; + MTPPacket.prototype.timestamp = 0; /** - * Decodes a PeerUdpAddressResponse message from the specified reader or buffer. - * @function decode - * @memberof peerInterface.PeerUdpAddressResponse - * @static - * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from - * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.PeerUdpAddressResponse} PeerUdpAddressResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing + * MTPPacket timediff. + * @member {number} timediff + * @memberof peerInterface.MTPPacket + * @instance */ - PeerUdpAddressResponse.decode = function decode(r, l) { - if (!(r instanceof $Reader)) - r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.PeerUdpAddressResponse(); - while (r.pos < c) { - var t = r.uint32(); - switch (t >>> 3) { - case 1: - m.address = r.string(); - break; - default: - r.skipType(t & 7); - break; - } - } - return m; - }; + MTPPacket.prototype.timediff = 0; /** - * Decodes a PeerUdpAddressResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof peerInterface.PeerUdpAddressResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.PeerUdpAddressResponse} PeerUdpAddressResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - PeerUdpAddressResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - return PeerUdpAddressResponse; - })(); - - /** - * CAMessageType enum. - * @name peerInterface.CAMessageType - * @enum {number} - * @property {number} ERROR=0 ERROR value - * @property {number} ROOT_CERT=1 ROOT_CERT value - * @property {number} REQUEST_CERT=2 REQUEST_CERT value - */ - peerInterface.CAMessageType = (function() { - var valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "ERROR"] = 0; - values[valuesById[1] = "ROOT_CERT"] = 1; - values[valuesById[2] = "REQUEST_CERT"] = 2; - return values; - })(); - - peerInterface.CAMessage = (function() { - - /** - * Properties of a CAMessage. - * @memberof peerInterface - * @interface ICAMessage - * @property {peerInterface.CAMessageType|null} [type] CAMessage type - * @property {boolean|null} [isResponse] CAMessage isResponse - * @property {Uint8Array|null} [subMessage] CAMessage subMessage + * MTPPacket window. + * @member {number} window + * @memberof peerInterface.MTPPacket + * @instance */ + MTPPacket.prototype.window = 0; /** - * Constructs a new CAMessage. - * @memberof peerInterface - * @classdesc Represents a CAMessage. - * @implements ICAMessage - * @constructor - * @param {peerInterface.ICAMessage=} [p] Properties to set + * MTPPacket seq. + * @member {number} seq + * @memberof peerInterface.MTPPacket + * @instance */ - function CAMessage(p) { - if (p) - for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) - if (p[ks[i]] != null) - this[ks[i]] = p[ks[i]]; - } + MTPPacket.prototype.seq = 0; /** - * CAMessage type. - * @member {peerInterface.CAMessageType} type - * @memberof peerInterface.CAMessage + * MTPPacket ack. + * @member {number} ack + * @memberof peerInterface.MTPPacket * @instance */ - CAMessage.prototype.type = 0; + MTPPacket.prototype.ack = 0; /** - * CAMessage isResponse. - * @member {boolean} isResponse - * @memberof peerInterface.CAMessage + * MTPPacket data. + * @member {Uint8Array} data + * @memberof peerInterface.MTPPacket * @instance */ - CAMessage.prototype.isResponse = false; + MTPPacket.prototype.data = $util.newBuffer([]); /** - * CAMessage subMessage. - * @member {Uint8Array} subMessage - * @memberof peerInterface.CAMessage + * MTPPacket sent. + * @member {number} sent + * @memberof peerInterface.MTPPacket * @instance */ - CAMessage.prototype.subMessage = $util.newBuffer([]); + MTPPacket.prototype.sent = 0; /** - * Creates a new CAMessage instance using the specified properties. + * Creates a new MTPPacket instance using the specified properties. * @function create - * @memberof peerInterface.CAMessage + * @memberof peerInterface.MTPPacket * @static - * @param {peerInterface.ICAMessage=} [properties] Properties to set - * @returns {peerInterface.CAMessage} CAMessage instance + * @param {peerInterface.IMTPPacket=} [properties] Properties to set + * @returns {peerInterface.MTPPacket} MTPPacket instance */ - CAMessage.create = function create(properties) { - return new CAMessage(properties); + MTPPacket.create = function create(properties) { + return new MTPPacket(properties); }; /** - * Encodes the specified CAMessage message. Does not implicitly {@link peerInterface.CAMessage.verify|verify} messages. + * Encodes the specified MTPPacket message. Does not implicitly {@link peerInterface.MTPPacket.verify|verify} messages. * @function encode - * @memberof peerInterface.CAMessage + * @memberof peerInterface.MTPPacket * @static - * @param {peerInterface.ICAMessage} m CAMessage message or plain object to encode + * @param {peerInterface.IMTPPacket} m MTPPacket message or plain object to encode * @param {$protobuf.Writer} [w] Writer to encode to * @returns {$protobuf.Writer} Writer */ - CAMessage.encode = function encode(m, w) { + MTPPacket.encode = function encode(m, w) { if (!w) w = $Writer.create(); - if (m.type != null && Object.hasOwnProperty.call(m, "type")) - w.uint32(8).int32(m.type); - if (m.isResponse != null && Object.hasOwnProperty.call(m, "isResponse")) - w.uint32(16).bool(m.isResponse); - if (m.subMessage != null && Object.hasOwnProperty.call(m, "subMessage")) - w.uint32(26).bytes(m.subMessage); + if (m.id != null && Object.hasOwnProperty.call(m, "id")) + w.uint32(8).int32(m.id); + if (m.peerId != null && Object.hasOwnProperty.call(m, "peerId")) + w.uint32(18).string(m.peerId); + if (m.connection != null && Object.hasOwnProperty.call(m, "connection")) + w.uint32(24).int32(m.connection); + if (m.timestamp != null && Object.hasOwnProperty.call(m, "timestamp")) + w.uint32(32).int32(m.timestamp); + if (m.timediff != null && Object.hasOwnProperty.call(m, "timediff")) + w.uint32(40).int32(m.timediff); + if (m.window != null && Object.hasOwnProperty.call(m, "window")) + w.uint32(48).int32(m.window); + if (m.seq != null && Object.hasOwnProperty.call(m, "seq")) + w.uint32(56).int32(m.seq); + if (m.ack != null && Object.hasOwnProperty.call(m, "ack")) + w.uint32(64).int32(m.ack); + if (m.data != null && Object.hasOwnProperty.call(m, "data")) + w.uint32(74).bytes(m.data); + if (m.sent != null && Object.hasOwnProperty.call(m, "sent")) + w.uint32(80).int32(m.sent); return w; }; /** - * Encodes the specified CAMessage message, length delimited. Does not implicitly {@link peerInterface.CAMessage.verify|verify} messages. + * Encodes the specified MTPPacket message, length delimited. Does not implicitly {@link peerInterface.MTPPacket.verify|verify} messages. * @function encodeDelimited - * @memberof peerInterface.CAMessage + * @memberof peerInterface.MTPPacket * @static - * @param {peerInterface.ICAMessage} message CAMessage message or plain object to encode + * @param {peerInterface.IMTPPacket} message MTPPacket message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - CAMessage.encodeDelimited = function encodeDelimited(message, writer) { + MTPPacket.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a CAMessage message from the specified reader or buffer. + * Decodes a MTPPacket message from the specified reader or buffer. * @function decode - * @memberof peerInterface.CAMessage + * @memberof peerInterface.MTPPacket * @static * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from * @param {number} [l] Message length if known beforehand - * @returns {peerInterface.CAMessage} CAMessage + * @returns {peerInterface.MTPPacket} MTPPacket * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - CAMessage.decode = function decode(r, l) { + MTPPacket.decode = function decode(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); - var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.CAMessage(); + var c = l === undefined ? r.len : r.pos + l, m = new $root.peerInterface.MTPPacket(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: - m.type = r.int32(); + m.id = r.int32(); break; case 2: - m.isResponse = r.bool(); + m.peerId = r.string(); break; case 3: - m.subMessage = r.bytes(); + m.connection = r.int32(); + break; + case 4: + m.timestamp = r.int32(); + break; + case 5: + m.timediff = r.int32(); + break; + case 6: + m.window = r.int32(); + break; + case 7: + m.seq = r.int32(); + break; + case 8: + m.ack = r.int32(); + break; + case 9: + m.data = r.bytes(); + break; + case 10: + m.sent = r.int32(); break; default: r.skipType(t & 7); @@ -2233,22 +2380,22 @@ $root.peerInterface = (function() { }; /** - * Decodes a CAMessage message from the specified reader or buffer, length delimited. + * Decodes a MTPPacket message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof peerInterface.CAMessage + * @memberof peerInterface.MTPPacket * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {peerInterface.CAMessage} CAMessage + * @returns {peerInterface.MTPPacket} MTPPacket * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - CAMessage.decodeDelimited = function decodeDelimited(reader) { + MTPPacket.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; - return CAMessage; + return MTPPacket; })(); return peerInterface; diff --git a/spec/api/API.spec.ts b/spec/api/API.spec.ts new file mode 100644 index 000000000..1ea54255d --- /dev/null +++ b/spec/api/API.spec.ts @@ -0,0 +1,271 @@ +import { Machine } from 'xstate'; + +interface APIStateSchema { + states: { + idle: {}; + gettingCertificateChain: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + gettingSignedCertificate: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + creatingVault: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + gettingVaultsList: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + deletingVault: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + gettingSecretsList: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + creatingSecret: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + gettingSecretContent: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + deletingSecret: { + states: { + checkingAuthorization: {}; + fulfillingRequest: {}; + }; + }; + }; +} + +type APIEvent = + | { type: 'RESPONSE_200' } + | { type: 'RESPONSE_401' } + | { type: 'RESPONSE_403' } + | { type: 'RESPONSE_500' } + | { type: 'CHECK_AUTHORIZATION' } + | { type: 'AUTHORIZED' } + | { type: 'NOT_AUTHORIZED' } + | { type: 'GET_CERTIFICATE_CHAIN' } + | { type: 'GET_SIGNED_CERTIFICATE' } + | { type: 'CREATE_VAULT' } + | { type: 'GET_VAULT_LIST' } + | { type: 'DELETE_VAULT' } + | { type: 'GET_SECRET_LIST' } + | { type: 'CREATE_SECRET' } + | { type: 'GET_SECRET_CONTENT' } + | { type: 'DELETE_SECRET' }; + +const apiMachine = Machine({ + id: 'api', + initial: 'idle', + states: { + idle: { + on: { + CHECK_AUTHORIZATION: 'checkingAuthorization', + }, + }, + checkingAuthorization: { + on: { + RESPONSE_401: { target: 'idle', in: '#api.checkingAuthorization.notAuthorized' }, + GET_CERTIFICATE_CHAIN: { target: 'gettingCertificateChain', in: '#api.checkingAuthorization.authorized' }, + GET_SIGNED_CERTIFICATE: { target: 'gettingSignedCertificate', in: '#api.checkingAuthorization.authorized' }, + CREATE_VAULT: { target: 'creatingVault', in: '#api.checkingAuthorization.authorized' }, + GET_VAULT_LIST: { target: 'gettingVaultsList', in: '#api.checkingAuthorization.authorized' }, + DELETE_VAULT: { target: 'deletingVault', in: '#api.checkingAuthorization.authorized' }, + GET_SECRET_LIST: { target: 'gettingSecretsList', in: '#api.checkingAuthorization.authorized' }, + CREATE_SECRET: { target: 'creatingSecret', in: '#api.checkingAuthorization.authorized' }, + GET_SECRET_CONTENT: { target: 'gettingSecretContent', in: '#api.checkingAuthorization.authorized' }, + DELETE_SECRET: { target: 'deletingSecret', in: '#api.checkingAuthorization.authorized' }, + }, + initial: 'checkingToken', + states: { + checkingToken: { + on: { + AUTHORIZED: 'authorized', + NOT_AUTHORIZED: 'notAuthorized', + }, + }, + authorized: { type: 'final' }, + notAuthorized: { type: 'final' }, + }, + }, + gettingCertificateChain: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.gettingCertificateChain.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.gettingCertificateChain.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + gettingSignedCertificate: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.gettingSignedCertificate.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.gettingSignedCertificate.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + creatingVault: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.creatingVault.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.creatingVault.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + gettingVaultsList: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.gettingVaultsList.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.gettingVaultsList.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + deletingVault: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.deletingVault.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.deletingVault.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + gettingSecretsList: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.gettingSecretsList.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.gettingSecretsList.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + creatingSecret: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.creatingSecret.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.creatingSecret.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + gettingSecretContent: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.gettingSecretContent.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.gettingSecretContent.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + deletingSecret: { + on: { + RESPONSE_200: { target: 'idle', in: '#api.deletingSecret.servingContent' }, + RESPONSE_403: { target: 'idle', in: '#api.deletingSecret.forbidden' }, + }, + initial: 'checkingScopes', + states: { + checkingScopes: { + on: { + AUTHORIZED: 'servingContent', + NOT_AUTHORIZED: 'forbidden', + }, + }, + servingContent: { type: 'final' }, + forbidden: { type: 'final' }, + }, + }, + }, +}); + +export { apiMachine, APIStateSchema, APIEvent }; diff --git a/spec/keys/Keys.spec.ts b/spec/keys/Keys.spec.ts new file mode 100644 index 000000000..66bf76347 --- /dev/null +++ b/spec/keys/Keys.spec.ts @@ -0,0 +1,93 @@ +import { Machine } from 'xstate'; +import { strict as assert } from 'assert'; +import KeyManager from '../../src/keys/KeyManager'; + +interface KeysStateSchema { + states: { + idle: {}; + generateKeyPair: {}; + loadKeyPair: {}; + unlockIdentity: {}; + lockIdentity: {}; + }; +} + +type KeysEvent = + | { type: 'GENERATE_KEYPAIR' } + | { type: 'LOAD_KEYPAIR' } + | { type: 'UNLOCK_IDENTITY' } + | { type: 'LOCK_IDENTITY' } + | { type: 'SUCCESS' } + | { type: 'FAILURE' }; + +const keysMachine = Machine({ + id: 'keys', + initial: 'idle', + states: { + idle: { + on: { + GENERATE_KEYPAIR: 'generateKeyPair', + LOAD_KEYPAIR: 'loadKeyPair', + UNLOCK_IDENTITY: 'unlockIdentity', + LOCK_IDENTITY: 'lockIdentity', + }, + meta: { + test: async (km: KeyManager) => {}, + }, + }, + generateKeyPair: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (km: KeyManager) => { + const status = km.Status; + assert(status.keypairUnlocked === true); + assert(status.keypairLoaded === true); + }, + }, + }, + loadKeyPair: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (km: KeyManager) => { + const status = km.Status; + assert(status.keypairUnlocked === false); + assert(status.keypairLoaded === true); + }, + }, + }, + unlockIdentity: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (km: KeyManager) => { + const status = km.Status; + assert(status.keypairUnlocked === true); + assert(status.keypairLoaded === true); + }, + }, + }, + lockIdentity: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (km: KeyManager) => { + const status = km.Status; + assert(status.keypairUnlocked === false); + assert(status.keypairLoaded === true); + }, + }, + }, + }, +}); + +export {keysMachine, KeysStateSchema, KeysEvent }; diff --git a/spec/peers/PeerDHT.spec.ts b/spec/peers/PeerDHT.spec.ts new file mode 100644 index 000000000..327d27134 --- /dev/null +++ b/spec/peers/PeerDHT.spec.ts @@ -0,0 +1,131 @@ +import { Machine } from 'xstate'; +import { strict as assert } from 'assert'; +import PeerDHT from '../../src/peers/peer-dht/PeerDHT'; + +interface PeerDHTStateSchema { + states: { + idle: {}; + addingPeers: {}; + addingPeer: {}; + deletingingPeer: {}; + findingLocalPeer: {}; + findingPeer: {}; + }; +} + +type PeerDHTEvent = + | { type: 'ADD_PEERS' } + | { type: 'ADD_PEER' } + | { type: 'DELETE_PEER' } + | { type: 'FIND_LOCAL_PEER' } + | { type: 'FIND_PEER' } + | { type: 'SUCCESS' } + | { type: 'FAILURE' }; + +const peerDHTMachine = Machine({ + id: 'peerDHT', + initial: 'idle', + states: { + idle: { + on: { + ADD_PEERS: 'addingPeers', + ADD_PEER: 'addingPeer', + DELETE_PEER: 'deletingingPeer', + FIND_LOCAL_PEER: 'findingLocalPeer', + FIND_PEER: 'findingPeer' + }, + meta: { + test: async (peerDHT: PeerDHT) => { + const status = peerDHT.Status; + assert(status.findingLocalPeer === false); + assert(status.findingPeer === false); + assert(status.addingPeers === false); + assert(status.addingPeer === false); + assert(status.deletingPeer === false); + }, + }, + }, + findingLocalPeer: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (peerDHT: PeerDHT) => { + const status = peerDHT.Status; + assert(status.findingLocalPeer === true); + assert(status.findingPeer === false); + assert(status.addingPeers === false); + assert(status.addingPeer === false); + assert(status.deletingPeer === false); + }, + }, + }, + findingPeer: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (peerDHT: PeerDHT) => { + const status = peerDHT.Status; + assert(status.findingLocalPeer === false); + assert(status.findingPeer === true); + assert(status.addingPeers === false); + assert(status.addingPeer === false); + assert(status.deletingPeer === false); + }, + }, + }, + addingPeers: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (peerDHT: PeerDHT) => { + const status = peerDHT.Status; + assert(status.findingLocalPeer === false); + assert(status.findingPeer === false); + assert(status.addingPeers === true); + assert(status.addingPeer === false); + assert(status.deletingPeer === false); + }, + }, + }, + addingPeer: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (peerDHT: PeerDHT) => { + const status = peerDHT.Status; + assert(status.findingLocalPeer === false); + assert(status.findingPeer === false); + assert(status.addingPeers === false); + assert(status.addingPeer === true); + assert(status.deletingPeer === false); + }, + }, + }, + deletingingPeer: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle', + }, + meta: { + test: async (peerDHT: PeerDHT) => { + const status = peerDHT.Status; + assert(status.findingLocalPeer === false); + assert(status.findingPeer === false); + assert(status.addingPeers === false); + assert(status.addingPeer === false); + assert(status.deletingPeer === true); + }, + }, + }, + }, +}); + +export { peerDHTMachine, PeerDHTStateSchema, PeerDHTEvent }; diff --git a/spec/peers/PeerManager.spec.ts b/spec/peers/PeerManager.spec.ts new file mode 100644 index 000000000..a6a152386 --- /dev/null +++ b/spec/peers/PeerManager.spec.ts @@ -0,0 +1,59 @@ +import { Machine } from 'xstate'; + +interface NatTraversalStateSchema { + states: { + initial: {}; + toggleStealthModeActive: {}; + toggleStealthModeInactive: {}; + connectingToPeer: {}; + }; +} + +type NatTraversalEvent = { type: 'CONNECT' } | { type: 'TIMEOUT' } | { type: 'FAILURE' } | { type: 'CONNECTED' }; + +const natTraversalMachine = Machine({ + id: 'natTraversal', + initial: 'idle', + states: { + idle: { + on: { + CONNECT: 'traversingNat', + }, + }, + traversingNat: { + on: { + CONNECTED: { target: 'idle', in: '#natTraversal.traversingNat.connected' }, + FAILURE: { target: 'idle', in: '#natTraversal.traversingNat.failure' }, + }, + initial: 'requestingDirectConnection', + states: { + requestingDirectConnection: { + on: { + CONNECTED: 'connected', + TIMEOUT: 'requestingHolePunchConnection', + }, + }, + requestingHolePunchConnection: { + on: { + CONNECTED: 'connected', + TIMEOUT: 'requestingDirectRelayConnection', + }, + }, + requestingDirectRelayConnection: { + on: { + CONNECTED: 'connected', + FAILURE: 'failure', + }, + }, + connected: { + type: 'final', + }, + failure: { + type: 'final', + }, + }, + }, + }, +}); + +export { natTraversalMachine, NatTraversalStateSchema, NatTraversalEvent }; diff --git a/spec/vaults/Vaults.spec.ts b/spec/vaults/Vaults.spec.ts new file mode 100644 index 000000000..279d46944 --- /dev/null +++ b/spec/vaults/Vaults.spec.ts @@ -0,0 +1,107 @@ +import { Machine } from 'xstate'; +import { strict as assert } from 'assert'; +import VaultManager from '../../src/vaults/VaultManager'; + +interface VaultsStateSchema { + states: { + idle: {}; + creatingVault: {}; + cloningVault: {}; + pullingVault: {}; + deletingVault: {}; + }; +} + +type VaultsEvent = + | { type: 'CREATE_VAULT' } + | { type: 'CLONE_VAULT' } + | { type: 'PULL_VAULT' } + | { type: 'DELETE_VAULT' } + | { type: 'SUCCESS' } + | { type: 'FAILURE' }; + +const vaultsMachine = Machine({ + id: 'vaults', + initial: 'idle', + states: { + idle: { + on: { + CREATE_VAULT: 'creatingVault', + CLONE_VAULT: 'cloningVault', + PULL_VAULT: 'pullingVault', + DELETE_VAULT: 'deletingVault', + }, + meta: { + test: async (vm: VaultManager) => { + const status = vm.Status; + assert(status.creatingVault === false); + assert(status.cloningVault === false); + assert(status.pullingVault === false); + assert(status.deletingVault === false); + }, + }, + }, + creatingVault: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle' + }, + meta: { + test: async (vm: VaultManager) => { + const status = vm.Status; + assert(status.creatingVault === true); + assert(status.cloningVault === false); + assert(status.pullingVault === false); + assert(status.deletingVault === false); + }, + }, + }, + cloningVault: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle' + }, + meta: { + test: async (vm: VaultManager) => { + const status = vm.Status; + assert(status.creatingVault === false); + assert(status.cloningVault === true); + assert(status.pullingVault === false); + assert(status.deletingVault === false); + }, + }, + }, + pullingVault: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle' + }, + meta: { + test: async (vm: VaultManager) => { + const status = vm.Status; + assert(status.creatingVault === false); + assert(status.cloningVault === false); + assert(status.pullingVault === true); + assert(status.deletingVault === false); + }, + }, + }, + deletingVault: { + on: { + SUCCESS: 'idle', + FAILURE: 'idle' + }, + meta: { + test: async (vm: VaultManager) => { + const status = vm.Status; + assert(status.creatingVault === false); + assert(status.cloningVault === false); + assert(status.pullingVault === false); + assert(status.deletingVault === true); + }, + }, + }, + }, +}); + +export { vaultsMachine, VaultsStateSchema, VaultsEvent }; diff --git a/src/Polykey.ts b/src/Polykey.ts index cfab5e3ab..6e0a1999d 100644 --- a/src/Polykey.ts +++ b/src/Polykey.ts @@ -32,7 +32,14 @@ class Polykey { // Set or Initialize vaultManager this.vaultManager = - vaultManager ?? new VaultManager(this.polykeyPath, fileSystem, this.keyManager, this.peerManager); + vaultManager ?? + new VaultManager( + this.polykeyPath, + fileSystem, + this.keyManager, + this.peerManager.connectToPeer.bind(this.peerManager), + this.peerManager.setGitHandler.bind(this.peerManager), + ); // start the api this.httpApi = new HttpApi( @@ -47,41 +54,23 @@ class Polykey { ((vaultName: string) => this.vaultManager.newVault(vaultName)).bind(this), ((vaultName: string) => this.vaultManager.deleteVault(vaultName)).bind(this), ((vaultName: string) => { - const vault = this.vaultManager.getVault(vaultName) - return vault.listSecrets() + const vault = this.vaultManager.getVault(vaultName); + return vault.listSecrets(); }).bind(this), ((vaultName: string, secretName: string) => { - const vault = this.vaultManager.getVault(vaultName) - return vault.getSecret(secretName).toString() + const vault = this.vaultManager.getVault(vaultName); + return vault.getSecret.bind(vault)(secretName); }).bind(this), - (async (vaultName: string, secretName: string, secretContent: string) => { - try { - const vault = this.vaultManager.getVault(vaultName) - await vault.addSecret(secretName, Buffer.from(secretContent)) - return true - } catch (error) { - return false - } + (async (vaultName: string, secretName: string, secretContent: Buffer) => { + const vault = this.vaultManager.getVault(vaultName); + await vault.addSecret(secretName, secretContent); }).bind(this), (async (vaultName: string, secretName: string) => { - try { - const vault = this.vaultManager.getVault(vaultName) - await vault.removeSecret(secretName) - return true - } catch (error) { - return false - } + const vault = this.vaultManager.getVault(vaultName); + await vault.removeSecret(secretName); }).bind(this), ); } } -export { - Polykey, - KeyManager, - VaultManager, - PeerManager, - PolykeyAgent, - PeerInfo, - Address -}; +export { Polykey, KeyManager, VaultManager, PeerManager, PolykeyAgent, PeerInfo, Address }; diff --git a/src/agent/PolykeyAgent.ts b/src/agent/PolykeyAgent.ts index d2135bf7a..63442de15 100644 --- a/src/agent/PolykeyAgent.ts +++ b/src/agent/PolykeyAgent.ts @@ -46,7 +46,7 @@ class PolykeyAgent implements IAgentServer { } private failOnLocked() { - if (!this.pk.keyManager.identityLoaded) { + if (!this.pk.keyManager.KeypairUnlocked) { throw Error(`polykey is locked at ${this.pk.polykeyPath}`); } } @@ -86,15 +86,12 @@ class PolykeyAgent implements IAgentServer { // don't need to catch errors try { await promisify(this.server.tryShutdown.bind(this))(); - } catch (error) { } + } catch (error) {} // handle port const portString = this.configStore.get('port') ?? process.env.PK_AGENT_PORT ?? 0; const hostString = process.env.PK_AGENT_HOST ?? 'localhost'; - const port = await getPort( - parseInt(portString), - hostString - ); + const port = await getPort(parseInt(portString), hostString); // bind server to port and start const boundPort = await new Promise((resolve, reject) => { @@ -111,15 +108,15 @@ class PolykeyAgent implements IAgentServer { // agent is only discoverable if the pid in the pk state matches // the pid of the current running pid. this also prevents memory leaks this.pidCheckInterval = setInterval(() => { - let shutdown: boolean = false + let shutdown: boolean = false; try { - const pid = this.configStore.get('pid') + const pid = this.configStore.get('pid'); if (pid !== this.pid) { - shutdown = true + shutdown = true; console.log('agent process pid does not match pk state pid, shutting down'); } } catch (error) { - shutdown = true + shutdown = true; console.log('pid is not set in pk state, shutting down'); } finally { if (shutdown) { @@ -127,25 +124,32 @@ class PolykeyAgent implements IAgentServer { if (err) { console.log(`ran into errors when shutting down grpc server: ${err}`); } - process.kill(this.pid) - }) + process.kill(this.pid); + }); } } - }, 10000) + }, 10000); this.server.start(); this.configStore.set('port', boundPort); console.log(`Agent started on: 'localhost:${boundPort}'`); } + private noThrowRefreshTimeout() { + try { + this.pk.keyManager.refreshTimeout(); + } catch (error) {} + } + async addPeer( call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); - const { publicKey, peerAddress, relayPublicKey, apiAddress } = call.request!.toObject(); - this.pk.peerManager.addPeer(new PeerInfo(publicKey, peerAddress, relayPublicKey, apiAddress)); + const { publicKey, rootCertificate, peerAddress, apiAddress } = call.request!.toObject(); + this.pk.peerManager.addPeer(new PeerInfo(publicKey, rootCertificate, peerAddress, apiAddress)); const response = new agent.BooleanMessage(); response.setB(true); callback(null, response); @@ -158,17 +162,18 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { filePath, privateKeyPath, passphrase } = call.request!.toObject(); const response = new agent.StringMessage(); if (privateKeyPath && passphrase) { - const privateKey = fs.readFileSync(privateKeyPath) + const privateKey = fs.readFileSync(privateKeyPath); const decryptedPath = await this.pk.keyManager.decryptFile(filePath, privateKey, passphrase); - response.setS(decryptedPath) + response.setS(decryptedPath); } else { const decryptedPath = await this.pk.keyManager.decryptFile(filePath); - response.setS(decryptedPath) + response.setS(decryptedPath); } callback(null, response); } catch (error) { @@ -180,6 +185,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { s } = call.request!.toObject(); @@ -196,6 +202,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { s } = call.request!.toObject(); @@ -212,6 +219,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { vaultName, secretName } = call.request!.toObject(); @@ -219,9 +227,9 @@ class PolykeyAgent implements IAgentServer { await vault.removeSecret(secretName); const response = new agent.BooleanMessage(); response.setB(true); - callback(null, response) + callback(null, response); } catch (error) { - callback(error, null) + callback(error, null); } } @@ -229,6 +237,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { keyName, passphrase } = call.request!.toObject(); @@ -245,6 +254,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { filePath, publicKeyPath } = call.request!.toObject(); @@ -261,6 +271,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { publicKeyOrHandle, timeout } = call.request!.toObject(); @@ -277,6 +288,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { publicKeyOrHandle, timeout } = call.request!.toObject(); @@ -298,6 +310,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const client = this.pk.httpApi.getOAuthClient(); @@ -314,6 +327,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { s } = call.request!.toObject(); @@ -330,15 +344,14 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { s } = call.request!.toObject(); const peerInfo = this.pk.peerManager.peerInfo; const response = new agent.PeerInfoMessage(); response.setPublicKey(peerInfo.publicKey); - if (peerInfo.relayPublicKey) { - response.setRelayPublicKey(peerInfo.relayPublicKey); - } + response.setRootCertificate(peerInfo.rootCertificate); if (peerInfo.peerAddress) { response.setPeerAddress(peerInfo.peerAddress?.toString()); } @@ -355,6 +368,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { s } = call.request!.toObject(); @@ -364,9 +378,7 @@ class PolykeyAgent implements IAgentServer { const peerInfo = this.pk.peerManager.getPeer(s)!; const response = new agent.PeerInfoMessage(); response.setPublicKey(peerInfo.publicKey); - if (peerInfo.relayPublicKey) { - response.setRelayPublicKey(peerInfo.relayPublicKey); - } + response.setRootCertificate(peerInfo.rootCertificate); if (peerInfo.peerAddress) { response.setPeerAddress(peerInfo.peerAddress?.toString()); } @@ -383,6 +395,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { b } = call.request!.toObject(); @@ -402,6 +415,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { vaultName, secretName } = call.request!.toObject(); @@ -419,6 +433,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { const response = new agent.AgentStatusMessage(); response.setStatus(agent.AgentStatusType.ONLINE); @@ -432,6 +447,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const tokens = this.pk.httpApi.listOAuthTokens(); @@ -447,6 +463,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const keyNames = this.pk.keyManager.listKeys(); @@ -462,6 +479,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { const { b } = call.request!.toObject(); const response = new agent.StringListMessage(); @@ -476,6 +494,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const rootCert = this.pk.keyManager.pki.RootCert; @@ -491,11 +510,13 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const publicKeys = this.pk.peerManager.listPeers(); const response = new agent.StringListMessage(); response.setSList(publicKeys); + callback(null, response); } catch (error) { callback(error, null); } @@ -505,6 +526,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { const { s } = call.request!.toObject(); const vault = this.pk.vaultManager.getVault(s); @@ -521,6 +543,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const vaultNames = this.pk.vaultManager.getVaultNames(); @@ -532,14 +555,28 @@ class PolykeyAgent implements IAgentServer { } } + async lockNode( + call: grpc.ServerUnaryCall, + callback: grpc.sendUnaryData, + ) { + try { + this.failOnLocked(); + this.pk.keyManager.lockIdentity(); + callback(null, new agent.EmptyMessage()); + } catch (error) { + callback(error, null); + } + } + async newOAuthToken( call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { scopesList, expiry } = call.request!.toObject(); - const token = this.pk.httpApi.newOAuthToken(scopesList, expiry) + const token = this.pk.httpApi.newOAuthToken(scopesList, expiry); const response = new agent.StringMessage(); response.setS(token); callback(null, response); @@ -551,17 +588,18 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { domain, certFile, keyFile } = call.request!.toObject(); - const pki = this.pk.keyManager.pki - const keypair = pki.createKeypair() + const pki = this.pk.keyManager.pki; + const keypair = pki.createKeypair(); const csr = pki.createCSR(domain, '', keypair); - const cert = pki.handleCSR(csr) - fs.mkdirSync(path.dirname(certFile), { recursive: true }) - fs.mkdirSync(path.dirname(keyFile), { recursive: true }) - fs.writeFileSync(certFile, cert) - fs.writeFileSync(keyFile, pki.privateKeyToPem(keypair.privateKey)) + const cert = pki.handleCSR(csr); + fs.mkdirSync(path.dirname(certFile), { recursive: true }); + fs.mkdirSync(path.dirname(keyFile), { recursive: true }); + fs.writeFileSync(certFile, cert); + fs.writeFileSync(keyFile, pki.privateKeyToPem(keypair.privateKey)); const response = new agent.NewClientCertificateMessage(); response.setCertFile(cert); response.setKeyFile(pki.privateKeyToPem(keypair.privateKey)); @@ -576,7 +614,7 @@ class PolykeyAgent implements IAgentServer { callback: grpc.sendUnaryData, ) { try { - const { userid, passphrase, nbits } = call.request!.toObject(); + const { userid, passphrase } = call.request!.toObject(); // check node is already initialized if (this.pk.keyManager.hasPrivateKey()) { @@ -585,9 +623,7 @@ class PolykeyAgent implements IAgentServer { const km = new KeyManager(this.pk.polykeyPath, fs); - const resolvedNBits = nbits && nbits != 0 ? nbits : undefined; - - await km.generateKeyPair(userid, passphrase, resolvedNBits, true); + await km.generateKeyPair(userid, passphrase, true); this.pk = new Polykey(this.pk.polykeyPath, fs, km); @@ -609,6 +645,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { secretPath, secretFilePath, secretContent } = call.request!.toObject(); @@ -632,6 +669,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { s } = call.request!.toObject(); @@ -648,6 +686,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { publicKeyOrHandle, timeout } = call.request!.toObject(); @@ -664,6 +703,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { vaultName, publicKey } = call.request!.toObject(); @@ -682,68 +722,11 @@ class PolykeyAgent implements IAgentServer { } } - async registerNode( - call: grpc.ServerUnaryCall, - callback: grpc.sendUnaryData, - ) { - try { - if (this.pk.keyManager.identityLoaded) { - throw Error('node is already unlocked'); - } - const { s } = call.request!.toObject(); - await this.pk.keyManager.unlockIdentity(s); - - // re-load all meta data - await this.pk.keyManager.loadEncryptedMetadata(); - this.pk.peerManager.loadMetadata(); - await this.pk.vaultManager.loadEncryptedMetadata(); - await this.pk.httpApi.start(); - - // send response - const response = new agent.BooleanMessage(); - response.setB(true); - callback(null, response); - } catch (error) { - callback(error, null); - } - } - - async requestHolePunch( - call: grpc.ServerUnaryCall, - callback: grpc.sendUnaryData, - ) { - try { - this.failOnLocked(); - const { s } = call.request!.toObject(); - const address = await this.pk.peerManager.turnClient.requestLocalHolePunchAddress(s); - const response = new agent.BooleanMessage(); - response.setB(true); - callback(null, response); - } catch (error) { - callback(error, null); - } - } - - async requestRelay( - call: grpc.ServerUnaryCall, - callback: grpc.sendUnaryData, - ) { - try { - this.failOnLocked(); - const { s } = call.request!.toObject(); - await this.pk.peerManager.turnClient.requestRelayConnection(s); - const response = new agent.BooleanMessage(); - response.setB(true); - callback(null, response); - } catch (error) { - callback(error, null); - } - } - async revokeOAuthToken( call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { s } = call.request!.toObject(); @@ -760,6 +743,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { s } = call.request!.toObject(); @@ -776,6 +760,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { filePath, privateKeyPath, passphrase } = call.request!.toObject(); @@ -793,7 +778,7 @@ class PolykeyAgent implements IAgentServer { callback: grpc.sendUnaryData, ) { try { - clearInterval(this.pidCheckInterval) + clearInterval(this.pidCheckInterval); this.pk.peerManager.multicastBroadcaster.stopBroadcasting(); const response = new agent.BooleanMessage(); response.setB(true); @@ -814,6 +799,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { b } = call.request!.toObject(); @@ -826,16 +812,53 @@ class PolykeyAgent implements IAgentServer { } } + async unlockNode( + call: grpc.ServerUnaryCall, + callback: grpc.sendUnaryData, + ) { + try { + const { passphrase, timeout } = call.request!.toObject(); + if (this.pk.keyManager.KeypairUnlocked) { + this.pk.keyManager.refreshTimeout(timeout); + } else { + await this.pk.keyManager.unlockIdentity(passphrase, timeout); + } + + // re-load all meta data + await this.pk.keyManager.loadEncryptedMetadata(); + this.pk.peerManager.loadMetadata(); + await this.pk.vaultManager.loadEncryptedMetadata(); + await this.pk.httpApi.start(); + + // send response + const response = new agent.BooleanMessage(); + response.setB(true); + callback(null, response); + } catch (error) { + callback(error, null); + } + } + async updateLocalPeerInfo( call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); - const { publicKey, relayPublicKey, peerAddress, apiAddress } = call.request!.toObject(); - this.pk.peerManager.peerInfo.relayPublicKey = relayPublicKey; - this.pk.peerManager.peerInfo.peerAddress = Address.parse(peerAddress); - this.pk.peerManager.peerInfo.apiAddress = Address.parse(apiAddress); + const { publicKey, rootCertificate, peerAddress, apiAddress } = call.request!.toObject(); + if (this.pk.peerManager.peerInfo.publicKey != publicKey) { + throw Error("public keys don't match"); + } + if (rootCertificate && rootCertificate != '') { + this.pk.peerManager.peerInfo.rootCertificate = rootCertificate; + } + if (peerAddress && peerAddress != '') { + this.pk.peerManager.peerInfo.peerAddress = Address.parse(peerAddress); + } + if (apiAddress && apiAddress != '') { + this.pk.peerManager.peerInfo.apiAddress = Address.parse(apiAddress); + } const response = new agent.BooleanMessage(); response.setB(true); callback(null, response); @@ -848,16 +871,23 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); - const { publicKey, relayPublicKey, peerAddress, apiAddress } = call.request!.toObject(); - if (!this.pk.peerManager.hasPeer(publicKey)) { + const { publicKey: peerId, rootCertificate, peerAddress, apiAddress } = call.request!.toObject(); + if (!this.pk.peerManager.hasPeer(peerId)) { throw Error('peer does not exist in store'); } - const peerInfo = this.pk.peerManager.getPeer(publicKey)!; - peerInfo.relayPublicKey = relayPublicKey; - peerInfo.peerAddress = Address.parse(peerAddress); - peerInfo.apiAddress = Address.parse(apiAddress); + const peerInfo = this.pk.peerManager.getPeer(peerId)!; + if (rootCertificate && rootCertificate != '') { + peerInfo.rootCertificate = rootCertificate; + } + if (peerAddress && peerAddress != '') { + peerInfo.peerAddress = Address.parse(peerAddress); + } + if (apiAddress && apiAddress != '') { + peerInfo.apiAddress = Address.parse(apiAddress); + } this.pk.peerManager.updatePeer(peerInfo); const response = new agent.BooleanMessage(); response.setB(true); @@ -871,6 +901,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { secretPath, secretFilePath, secretContent } = call.request!.toObject(); @@ -894,6 +925,7 @@ class PolykeyAgent implements IAgentServer { call: grpc.ServerUnaryCall, callback: grpc.sendUnaryData, ) { + this.noThrowRefreshTimeout(); try { this.failOnLocked(); const { publicKeyPath, filePath } = call.request!.toObject(); @@ -947,9 +979,11 @@ class PolykeyAgent implements IAgentServer { ////////////////////// // Agent Operations // ////////////////////// - private static DAEMON_SCRIPT_PATH_PREFIX = path.resolve(__dirname, 'internal', 'daemon-script.'); - private static DAEMON_SCRIPT_PATH_SUFFIX = fs.existsSync(PolykeyAgent.DAEMON_SCRIPT_PATH_PREFIX + 'js') ? 'js' : 'ts'; - static DAEMON_SCRIPT_PATH = PolykeyAgent.DAEMON_SCRIPT_PATH_PREFIX + PolykeyAgent.DAEMON_SCRIPT_PATH_SUFFIX; + static get DAEMON_SCRIPT_PATH(): string { + const prefix = path.resolve(__dirname, 'internal', 'daemon-script.'); + const suffix = fs.existsSync(prefix + 'js') ? 'js' : 'ts'; + return prefix + suffix; + } private static AgentIsRunning(polykeyPath: string): boolean { const existingPid = PolykeyAgent.AgentPid(polykeyPath); diff --git a/src/api/AuthorizationServer/OAuth2.ts b/src/api/AuthorizationServer/OAuth2.ts index eb32d492b..6868d4988 100644 --- a/src/api/AuthorizationServer/OAuth2.ts +++ b/src/api/AuthorizationServer/OAuth2.ts @@ -47,9 +47,6 @@ class OAuth2 { tokenInfo(req, res) { try { - console.log(req); - console.log(req.query); - const accessToken = this.validation.tokenForHttp(req.query.access_token) this.validation.tokenExistsForHttp(accessToken) const client = this.store.getClient(accessToken.clientId!) diff --git a/src/api/HttpApi.ts b/src/api/HttpApi.ts index f82c79614..397cec2ac 100644 --- a/src/api/HttpApi.ts +++ b/src/api/HttpApi.ts @@ -4,7 +4,7 @@ import path from 'path'; import http from 'http'; import https from 'https'; import jsyaml from 'js-yaml'; -import express from 'express'; +import express, { RequestHandler } from 'express'; import passport from 'passport' import { getPort } from '../utils'; import session from 'express-session' @@ -19,6 +19,7 @@ import { User, Client } from './AuthorizationServer/OAuth2Store'; import { Strategy as BearerStrategy } from 'passport-http-bearer'; import { TLSCredentials } from '../keys/pki/PublicKeyInfrastructure'; import { Strategy as ClientPasswordStrategy } from 'passport-oauth2-client-password'; +import { DEFAULT_ENCODING } from 'crypto'; class HttpApi { private openApiPath: string @@ -31,9 +32,9 @@ class HttpApi { private newVault: (vaultName: string) => Promise; private deleteVault: (vaultName: string) => Promise; private listSecrets: (vaultName: string) => string[]; - private getSecret: (vaultName: string, secretName: string) => string; - private newSecret: (vaultName: string, secretName: string, secretContent: string) => Promise; - private deleteSecret: (vaultName: string, secretName: string) => Promise; + private getSecret: (vaultName: string, secretName: string) => Buffer; + private newSecret: (vaultName: string, secretName: string, secretContent: Buffer) => Promise; + private deleteSecret: (vaultName: string, secretName: string) => Promise; private tlsCredentials: TLSCredentials private oauth: OAuth2 @@ -50,9 +51,9 @@ class HttpApi { newVault: (vaultName: string) => Promise, deleteVault: (vaultName: string) => Promise, listSecrets: (vaultName: string) => string[], - getSecret: (vaultName: string, secretName: string) => string, - newSecret: (vaultName: string, secretName: string, secretContent: string) => Promise, - deleteSecret: (vaultName: string, secretName: string) => Promise, + getSecret: (vaultName: string, secretName: string) => Buffer, + newSecret: (vaultName: string, secretName: string, secretContent: string | Buffer) => Promise, + deleteSecret: (vaultName: string, secretName: string) => Promise, ) { // this code is needed as we can't require yaml files const fromSrcFolderPath = path.join(__dirname, '../../openapi.yaml') @@ -109,7 +110,7 @@ class HttpApi { this.expressServer.use(passport.session()); // redirect from base url to docs - this.expressServer.get('/',(req, res, next) => { + this.expressServer.get('/', (req, res, next) => { res.redirect('/docs') }) @@ -261,120 +262,158 @@ class HttpApi { } // === openapi endpoints === // - private handleCertificateSigningRequest = async (req, res, next) => { + private handleRootCertificateRequest: RequestHandler = async (req, res, next) => { try { - const body = req.body; - const response = this.handleCSR(body); - this.writeJson(res, response); + const response = this.getRootCertificate(); + this.writeString(res, response); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleRootCertificateRequest = async (req, res, next) => { + private handleCertificateChainRequest: RequestHandler = async (req, res, next) => { try { - const response = this.getRootCertificate(); - this.writeJson(res, response); + const response = this.getCertificateChain(); + this.writeStringList(res, response); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleCertificateChainRequest = async (req, res, next) => { + private handleCertificateSigningRequest: RequestHandler = async (req, res, next) => { try { - const response = this.getCertificateChain(); - this.writeJson(res, response); + const body = req.body; + const response = this.handleCSR(body); + this.writeString(res, response); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleVaultsListRequest = async (req, res, next) => { + private handleVaultsListRequest: RequestHandler = async (req, res, next) => { try { const response = this.getVaultNames() - this.writeJson(res, response); + this.writeStringList(res, response); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleNewVaultRequest = async (req, res, next) => { + private handleNewVaultRequest: RequestHandler = async (req, res, next) => { try { - const vaultName = req.openapi.pathParams.vaultName; + const vaultName = (req).openapi.pathParams.vaultName; await this.newVault(vaultName) - this.writeJson(res); + this.writeSuccess(res); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleDeleteVaultRequest = async (req, res, next) => { + private handleDeleteVaultRequest: RequestHandler = async (req, res, next) => { try { - const vaultName = req.openapi.pathParams.vaultName; + const vaultName = (req).openapi.pathParams.vaultName; await this.deleteVault(vaultName) - this.writeJson(res); + this.writeSuccess(res); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleSecretsListRequest = async (req, res, next) => { + private handleSecretsListRequest: RequestHandler = async (req, res, next) => { try { - const vaultName = req.openapi.pathParams.vaultName; + const vaultName = (req).openapi.pathParams.vaultName; const response = this.listSecrets(vaultName); - this.writeJson(res, response); + this.writeStringList(res, response); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleGetSecretRequest = async (req, res, next) => { + private handleGetSecretRequest: RequestHandler = async (req, res, next) => { try { - const vaultName = req.openapi.pathParams.vaultName; - const secretName = req.openapi.pathParams.secretName; + + const vaultName = (req).openapi.pathParams.vaultName; + const secretName = (req).openapi.pathParams.secretName; const response = this.getSecret(vaultName, secretName) - this.writeJson(res, response); + + const accepts = req.accepts()[0] + if (!accepts || accepts == 'text/plain' || accepts == '*/*') { + this.writeString(res, response.toString()) + } else if (accepts == 'application/octet-stream') { + this.writeBinary(res, secretName, response); + } else { + throw Error(`MIME type not supported: ${accepts}`) + } } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleNewSecretRequest = async (req, res, next) => { + private handleNewSecretRequest: RequestHandler = async (req, res, next) => { try { - const vaultName = req.openapi.pathParams.vaultName; - const secretName = req.openapi.pathParams.secretName; - const secretContent = req.body + const vaultName = (req).openapi.pathParams.vaultName; + const secretName = (req).openapi.pathParams.secretName; + + let secretContent: Buffer + const contentType = req.headers['content-type'] + if (contentType == 'text/plain') { + secretContent = Buffer.from(req.body) + } else if (contentType == 'application/octet-stream') { + secretContent = await new Promise((resolve, reject) => { + const bufferList: Buffer[] = [] + req.on('data', (data) => bufferList.push(data)) + req.on('error', (err) => reject(err)) + req.on('end', () => resolve(Buffer.concat(bufferList))) + }) + } else { + throw Error(`MIME type not supported: ${contentType}`) + } + await this.newSecret(vaultName, secretName, secretContent); - this.writeJson(res); + this.writeSuccess(res); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; - private handleDeleteSecretRequest = async (req, res, next) => { + private handleDeleteSecretRequest: RequestHandler = async (req, res, next) => { try { - const vaultName = req.openapi.pathParams.vaultName; - const secretName = req.openapi.pathParams.secretName; + const vaultName = (req).openapi.pathParams.vaultName; + const secretName = (req).openapi.pathParams.secretName; await this.deleteSecret(vaultName, secretName); - this.writeJson(res); + this.writeSuccess(res); } catch (error) { - this.writeJson(res, error); + this.writeError(res, error); } }; // === Helper methods === // - private writeJson(response: http.ServerResponse, payload?: string | Object | Error | Array, code: number = 200) { - let responseString: string | undefined - if (!payload) { - responseString = undefined - } else if (payload instanceof Error) { - code = 500 - responseString = JSON.stringify({ error: payload.message }, null, 2); - } else { - responseString = JSON.stringify(payload, null, 2); - } - response.writeHead(code, { 'Content-Type': 'application/json' }); - response.end(responseString); + private writeSuccess(res: http.ServerResponse) { + res.writeHead(200); + res.end(); + } + private writeError(res: http.ServerResponse, error: Error) { + res.writeHead(500, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: error.message }, null, 2)); + } + private writeString(res: http.ServerResponse, text: string) { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end(text); + } + private writeStringList(res: http.ServerResponse, list: string[]) { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(list, null, 2)); + } + private writeJson(res: http.ServerResponse, payload: Object) { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(payload, null, 2)); + } + private writeBinary(res: http.ServerResponse, filename: string, payload: Buffer) { + res.writeHead(200, { + 'Content-Type': 'application/octet-stream', + 'Content-Disposition': `file; filename="${filename}"` + }); + res.end(payload, 'binary'); } private checkScope(scope: string[]) { diff --git a/src/bin/agent/index.ts b/src/bin/agent/index.ts index 083fd028b..66eb89b1a 100644 --- a/src/bin/agent/index.ts +++ b/src/bin/agent/index.ts @@ -1,16 +1,18 @@ import commander from 'commander'; import { PolykeyAgent } from '../../Polykey'; import * as pb from '../../../proto/compiled/Agent_pb'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; +import { actionRunner, getPKLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; function makeStartAgentCommand() { return new commander.Command('start') .description('start the agent') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .option('-d, --daemon', 'start the agent as a daemon process') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) try { const client = PolykeyAgent.connectToAgent(nodePath); @@ -19,7 +21,7 @@ function makeStartAgentCommand() { new pb.EmptyMessage(), )) as pb.AgentStatusMessage; if (res.getStatus() == pb.AgentStatusType.ONLINE) { - pkLogger(`agent is already running`, PKMessageType.INFO); + pkLogger.logV1(`agent is already running`, PKMessageType.INFO); } else { throw Error(`agent is not running`); } @@ -30,9 +32,9 @@ function makeStartAgentCommand() { new pb.EmptyMessage(), )) as pb.AgentStatusMessage; if (res.getStatus() == pb.AgentStatusType.ONLINE) { - pkLogger(`agent has started with a pid of ${pid}`, PKMessageType.SUCCESS); + pkLogger.logV1(`agent has started with a pid of ${pid}`, PKMessageType.SUCCESS); } else { - pkLogger(`agent could not be started`, PKMessageType.ERROR); + throw Error('agent could not be started') } } }), @@ -43,15 +45,17 @@ function makeRestartAgentCommand() { return new commander.Command('restart') .description('restart the agent') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .option('-d, --daemon', 'start the agent as a daemon process') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath, options.daemon, false, false); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, options.daemon, false, false, pkLogger); // Tell agent to stop await promisifyGrpc(client.stopAgent.bind(client))(new pb.EmptyMessage()); const pid = await PolykeyAgent.startAgent(nodePath, options.daemon); - pkLogger(`agent has restarted with pid of ${pid}`, PKMessageType.SUCCESS); + pkLogger.logV1(`agent has restarted with pid of ${pid}`, PKMessageType.SUCCESS); }), ); } @@ -60,20 +64,22 @@ function makeAgentStatusCommand() { return new commander.Command('status') .description('retrieve the status of the agent') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) try { - const client = await getAgentClient(nodePath, undefined, false); + const client = await getAgentClient(nodePath, undefined, false, undefined, pkLogger); const res = (await promisifyGrpc(client.getStatus.bind(client))( new pb.EmptyMessage(), )) as pb.AgentStatusMessage; const status = res.getStatus(); const statusString = Object.keys(pb.AgentStatusType).find((k) => pb.AgentStatusType[k] === status); - pkLogger(`agent status is: '${statusString?.toLowerCase()}'`, PKMessageType.INFO); + pkLogger.logV0(`agent status is: '${statusString?.toLowerCase()}'`, PKMessageType.INFO); } catch (error) { - pkLogger(`agent status is: 'offline'`, PKMessageType.INFO); + pkLogger.logV0(`agent status is: 'offline'`, PKMessageType.INFO); } }), ); @@ -83,12 +89,14 @@ function makeStopAgentCommand() { return new commander.Command('stop') .description('stop the agent') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .option('-f, --force', 'forcibly stop the agent') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) try { - const client = await getAgentClient(nodePath, undefined, false); + const client = await getAgentClient(nodePath, undefined, false, undefined, pkLogger); // see if agent returns with online status const res = (await promisifyGrpc(client.getStatus.bind(client))( @@ -97,12 +105,12 @@ function makeStopAgentCommand() { if (res.getStatus() == pb.AgentStatusType.ONLINE) { // Tell agent to stop await promisifyGrpc(client.stopAgent.bind(client))(new pb.EmptyMessage()); - pkLogger('agent has successfully stopped', PKMessageType.SUCCESS); + pkLogger.logV1('agent has successfully stopped', PKMessageType.SUCCESS); } else { throw Error('agent failed to stop'); } } catch (error) { - pkLogger('agent is already stopped', PKMessageType.INFO); + pkLogger.logV1('agent is already stopped', PKMessageType.INFO); } }), ); @@ -112,25 +120,21 @@ function makeInitNodeCommand() { return new commander.Command('init') .description('initialize a new polykey node') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-ui, --user-id ', '(required) provide an identifier for the keypair to be generated') .requiredOption('-pp, --private-passphrase ', '(required) provide the passphrase to the private key') - .option('-nb, --number-of-bits ', 'number of bits to use for key pair generation') - .option('-v, --verbose', 'increase verbosity by one level') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - - const client = await getAgentClient(nodePath, undefined, true, false); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, true, false, pkLogger); const request = new pb.NewNodeMessage(); request.setUserid(options.userId); request.setPassphrase(options.privatePassphrase); - if (options.numberOfBits) { - request.setNbits(options.numberOfBits); - } const res = (await promisifyGrpc(client.newNode.bind(client))(request)) as pb.BooleanMessage; - pkLogger(`node was successfully initialized at: '${nodePath}'`, PKMessageType.SUCCESS); + pkLogger.logV1(`node was successfully initialized at: '${nodePath}'`, PKMessageType.SUCCESS); }), ); } @@ -139,17 +143,24 @@ function makeUnlockNodeCommand() { return new commander.Command('unlock') .description('unlock polykey') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-pp, --private-passphrase ', '(required) provide the passphrase to the private key') + .option('-t, --timeout ', 'minutes of inactivity after which keynode is locked again, defaults to 15 minutes. setting to 0 will set no timeout', '15') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); - const request = new pb.StringMessage(); - request.setS(options.privatePassphrase!); - const res = (await promisifyGrpc(client.registerNode.bind(client))(request)) as pb.BooleanMessage; - + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); + const request = new pb.UnlockNodeMessage(); + request.setPassphrase(options.privatePassphrase!); + request.setTimeout(options.timeout!); + const res = (await promisifyGrpc(client.unlockNode.bind(client))(request)) as pb.BooleanMessage; if (res.getB()) { - pkLogger(`node was successfully loaded at: '${nodePath}'`, PKMessageType.SUCCESS); + if (options.timeout == 0) { + pkLogger.logV1(`polykey is unlocked indefinitely at: '${nodePath}'`, PKMessageType.SUCCESS); + } else { + pkLogger.logV1(`polykey is unlocked for ${options.timeout} minute(s) at: '${nodePath}'`, PKMessageType.SUCCESS); + } } else { throw Error('something went wrong when loading node'); } @@ -157,6 +168,22 @@ function makeUnlockNodeCommand() { ); } +function makeLockNodeCommand() { + return new commander.Command('lock') + .description('lock polykey') + .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) + .action( + actionRunner(async (options) => { + const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath,undefined,undefined,undefined,pkLogger); + const res = (await promisifyGrpc(client.lockNode.bind(client))(new pb.EmptyMessage)) as pb.EmptyMessage; + pkLogger.logV1(`polykey is now locked at: '${nodePath}'`, PKMessageType.SUCCESS); + }), + ); +} + function makeAgentCommand() { return new commander.Command('agent') .description('control the polykey agent') @@ -165,6 +192,7 @@ function makeAgentCommand() { .addCommand(makeAgentStatusCommand()) .addCommand(makeStopAgentCommand()) .addCommand(makeInitNodeCommand()) + .addCommand(makeLockNodeCommand()) .addCommand(makeUnlockNodeCommand()); } diff --git a/src/bin/ca/index.ts b/src/bin/ca/index.ts index f023b5e08..260ba06f0 100644 --- a/src/bin/ca/index.ts +++ b/src/bin/ca/index.ts @@ -2,21 +2,24 @@ import fs from 'fs'; import path from 'path'; import commander from 'commander'; import * as pb from '../../../proto/compiled/Agent_pb'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; +import { actionRunner, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient, getPKLogger } from '../utils'; function makeGetRootCertificateCommand() { return new commander.Command('root') .description('retrieve the root certificate') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) - const client = await getAgentClient(nodePath); + const client = await getAgentClient(nodePath,undefined,undefined,undefined,pkLogger); const res = (await promisifyGrpc(client.getRootCertificate.bind(client))( new pb.EmptyMessage(), )) as pb.StringMessage; - pkLogger(res.getS(), PKMessageType.SUCCESS); + pkLogger.logV1('Current Node Root Certificate:', PKMessageType.INFO); + pkLogger.logV0(res.getS(), PKMessageType.SUCCESS); }), ); } @@ -25,14 +28,16 @@ function makeNewCertCommand() { return new commander.Command('cert') .description('create a new certificate signed by the polykey ca') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-ch, --client-host ', '(required) host of the client') .requiredOption('-cp, --cert-path ', '(required) where to write the cert file') .requiredOption('-kp, --key-path ', '(required) where to write the private key file') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) - const client = await getAgentClient(nodePath); + const client = await getAgentClient(nodePath,undefined,undefined,undefined,pkLogger); const request = new pb.NewClientCertificateMessage() request.setDomain(options.clientHost) @@ -43,10 +48,10 @@ function makeNewCertCommand() { const res = (await promisifyGrpc(client.newClientCertificate.bind(client))( request, )) as pb.NewClientCertificateMessage; - pkLogger('Certificate:', PKMessageType.INFO); - pkLogger(res.getCertFile(), PKMessageType.SUCCESS); - pkLogger('Private Key:', PKMessageType.INFO); - pkLogger(res.getKeyFile(), PKMessageType.SUCCESS); + pkLogger.logV1('Certificate:', PKMessageType.INFO); + pkLogger.logV0(res.getCertFile(), PKMessageType.SUCCESS); + pkLogger.logV1('Private Key:', PKMessageType.INFO); + pkLogger.logV0(res.getKeyFile(), PKMessageType.SUCCESS); }), ); } diff --git a/src/bin/crypto/index.ts b/src/bin/crypto/index.ts index 5c6fd5d83..0fbe1d1ab 100644 --- a/src/bin/crypto/index.ts +++ b/src/bin/crypto/index.ts @@ -1,18 +1,20 @@ import commander from 'commander'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; +import { actionRunner, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient, getPKLogger } from '../utils'; import * as pb from '../../../proto/compiled/Agent_pb'; function makeSignCommand() { return new commander.Command('sign') .description('signing operations [files]') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .option('-k, --signing-key ', 'path to private key that will be used to sign files') .option('-p, --key-passphrase ', 'passphrase to unlock the provided signing key') .arguments('file(s) to be signed') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const signingKeyPath = options.signingKey; const keyPassphrase = options.keyPassphrase; @@ -33,7 +35,7 @@ function makeSignCommand() { request.setPrivateKeyPath(signingKeyPath); request.setPassphrase(keyPassphrase); const res = (await promisifyGrpc(client.signFile.bind(client))(request)) as pb.StringMessage; - pkLogger(`file '${filePath}' successfully signed at '${res.getS()}'`, PKMessageType.SUCCESS); + pkLogger.logV1(`file '${filePath}' successfully signed at '${res.getS()}'`, PKMessageType.SUCCESS); } catch (err) { throw Error(`failed to sign '${filePath}': ${err}`); } @@ -54,7 +56,8 @@ function makeVerifyCommand() { .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const filePath = options.signedFile; @@ -63,9 +66,9 @@ function makeVerifyCommand() { request.setPublicKeyPath(options.publicKey); const res = (await promisifyGrpc(client.verifyFile.bind(client))(request)) as pb.BooleanMessage; if (res.getB()) { - pkLogger(`file '${filePath}' was successfully verified`, PKMessageType.SUCCESS); + pkLogger.logV1(`file '${filePath}' was successfully verified`, PKMessageType.SUCCESS); } else { - pkLogger(`file '${filePath}' was not verified`, PKMessageType.WARNING); + throw Error(`file '${filePath}' was not verified`) } }), ); @@ -83,7 +86,8 @@ function makeEncryptCommand() { .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const filePath = options.filePath; @@ -92,7 +96,7 @@ function makeEncryptCommand() { request.setFilePath(filePath); request.setPublicKeyPath(options.publicKey); const res = (await promisifyGrpc(client.encryptFile.bind(client))(request)) as pb.StringMessage; - pkLogger(`file successfully encrypted: '${res.getS()}'`, PKMessageType.SUCCESS); + pkLogger.logV1(`file successfully encrypted: '${res.getS()}'`, PKMessageType.SUCCESS); } catch (err) { throw Error(`failed to encrypt '${filePath}': ${err}`); } @@ -113,7 +117,8 @@ function makeDecryptCommand() { .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const filePath = options.filePath; @@ -123,7 +128,7 @@ function makeDecryptCommand() { request.setPrivateKeyPath(options.privateKey); request.setPassphrase(options.keyPassphrase); const res = (await promisifyGrpc(client.decryptFile.bind(client))(request)) as pb.StringMessage; - pkLogger(`file successfully decrypted: '${res.getS()}'`, PKMessageType.SUCCESS); + pkLogger.logV1(`file successfully decrypted: '${res.getS()}'`, PKMessageType.SUCCESS); } catch (err) { throw Error(`failed to decrypt '${filePath}': ${err}`); } diff --git a/src/bin/keys/index.ts b/src/bin/keys/index.ts index a1c1627ec..5689f6c8a 100644 --- a/src/bin/keys/index.ts +++ b/src/bin/keys/index.ts @@ -1,17 +1,19 @@ import commander from 'commander'; import * as pb from '../../../proto/compiled/Agent_pb'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc } from '../utils'; +import { actionRunner, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc, getPKLogger } from '../utils'; function makeNewKeyCommand() { return new commander.Command('new') .description('derive a new symmetric key') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-n, --key-name ', '(required) the name of the new key') .requiredOption('-p, --key-passphrase ', '(required) the passphrase for the new key') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const keyName = options.keyName; @@ -19,7 +21,7 @@ function makeNewKeyCommand() { request.setKeyName(keyName); request.setPassphrase(options.keyPassphrase); const res = (await promisifyGrpc(client.deriveKey.bind(client))(request)) as pb.BooleanMessage; - pkLogger(`'${keyName}' was added to the Key Manager`, PKMessageType.SUCCESS); + pkLogger.logV1(`'${keyName}' was added to the Key Manager`, PKMessageType.SUCCESS); }), ); } @@ -28,19 +30,21 @@ function makeDeleteKeyCommand() { return new commander.Command('delete') .description('delete a symmetric key from the key manager') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-n, --key-name ', '(required) the name of the symmetric key to be deleted') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const keyName = options.keyName; const request = new pb.StringMessage(); request.setS(keyName); const res = (await promisifyGrpc(client.deleteKey.bind(client))(request)) as pb.BooleanMessage; - pkLogger( - `key '${keyName}' was ${res.getB() ? '' : 'un-'}successfully deleted`, + pkLogger.logV1( + `key '${keyName}' was successfully deleted`, res.getB() ? PKMessageType.SUCCESS : PKMessageType.INFO, ); }), @@ -52,19 +56,21 @@ function makeListKeysCommand() { .alias('ls') .description('list all symmetric keys in the keynode') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const res = (await promisifyGrpc(client.listKeys.bind(client))(new pb.EmptyMessage())) as pb.StringListMessage; const keyNames = res.getSList(); if (keyNames === undefined || keyNames.length == 0) { - pkLogger('no keys exist', PKMessageType.INFO); + pkLogger.logV0('no keys exist', PKMessageType.INFO); } else { keyNames.forEach((keyName: string, index: number) => { - pkLogger(`${index + 1}: ${keyName}`, PKMessageType.INFO); + pkLogger.logV0(`${index + 1}: ${keyName}`, PKMessageType.SUCCESS); }); } }), @@ -75,16 +81,18 @@ function makeGetKeyCommand() { return new commander.Command('get') .description('get the contents of a specific symmetric key') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-kn, --key-name ', '(required) the name of the new key') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const request = new pb.StringMessage(); request.setS(options.keyName); const res = (await promisifyGrpc(client.getKey.bind(client))(request)) as pb.StringMessage; - pkLogger(res.getS(), PKMessageType.INFO); + pkLogger.logV0(res.getS(), PKMessageType.SUCCESS); }), ); } @@ -93,12 +101,14 @@ function makeListPrimaryKeyPairCommand() { return new commander.Command('primary') .description('get the contents of the primary keypair') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .option('-pk, --private-key', 'include private key') .option('-oj, --output-json', 'output in JSON format') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const privateKey: boolean = options.privateKey; @@ -107,13 +117,13 @@ function makeListPrimaryKeyPairCommand() { const res = (await promisifyGrpc(client.getPrimaryKeyPair.bind(client))(request)) as pb.KeyPairMessage; const keypair = { publicKey: res.getPublicKey(), privateKey: res.getPrivateKey() }; if (options.outputJson) { - pkLogger(JSON.stringify(keypair), PKMessageType.INFO); + pkLogger.logV0(JSON.stringify(keypair), PKMessageType.INFO); } else { - pkLogger('Public Key:', PKMessageType.SUCCESS); - pkLogger(keypair.publicKey, PKMessageType.INFO); + pkLogger.logV1('Public Key:', PKMessageType.SUCCESS); + pkLogger.logV0(keypair.publicKey, PKMessageType.INFO); if (privateKey) { - pkLogger('Private Key:', PKMessageType.SUCCESS); - pkLogger(keypair.privateKey, PKMessageType.INFO); + pkLogger.logV1('Private Key:', PKMessageType.SUCCESS); + pkLogger.logV0(keypair.privateKey, PKMessageType.INFO); } } }), diff --git a/src/bin/oauth/clientCommands.ts b/src/bin/oauth/clientCommands.ts index 7b270816e..2819f6ad9 100644 --- a/src/bin/oauth/clientCommands.ts +++ b/src/bin/oauth/clientCommands.ts @@ -1,27 +1,29 @@ import commander from 'commander'; import * as pb from '../../../proto/compiled/Agent_pb'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; +import { actionRunner, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient, getPKLogger } from '../utils'; function makeClientCommand() { return new commander.Command('client') .description('get oauth client details for the http api (useful for client credentials authorization flow on swagger docs)') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); - const client = await getAgentClient(nodePath); const req = new pb.StringMessage req.setS(options.id) const res = (await promisifyGrpc(client.getOAuthClient.bind(client))( new pb.EmptyMessage, )) as pb.OAuthClientMessage; - pkLogger('client id:', PKMessageType.INFO); - pkLogger(res.getId(), PKMessageType.SUCCESS); + pkLogger.logV1('client id:', PKMessageType.INFO); + pkLogger.logV0(res.getId(), PKMessageType.SUCCESS); - pkLogger('client secret:', PKMessageType.INFO); - pkLogger(res.getSecret(), PKMessageType.SUCCESS); + pkLogger.logV1('client secret:', PKMessageType.INFO); + pkLogger.logV0(res.getSecret(), PKMessageType.SUCCESS); }), ); } diff --git a/src/bin/oauth/tokenCommands.ts b/src/bin/oauth/tokenCommands.ts index 7fd485abb..6a30b8965 100644 --- a/src/bin/oauth/tokenCommands.ts +++ b/src/bin/oauth/tokenCommands.ts @@ -1,18 +1,20 @@ import commander from 'commander'; import * as pb from '../../../proto/compiled/Agent_pb'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; +import { actionRunner, getPKLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; function makeNewTokenCommand() { return new commander.Command('new') .description('create a new bearer token for the api') - .option('--node-path ', 'node path') + .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-s, --scopes ', "(required) scopes for new bearer token, must be string of space-separated scopes: 'write_vault read_vault'") .option('-e, --expiry ', 'expiry for the new token in seconds') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); - const client = await getAgentClient(nodePath); const scopes: string[] = options.scopes.split(' ') const req = new pb.NewOAuthTokenMessage req.setScopesList(scopes) @@ -20,7 +22,7 @@ function makeNewTokenCommand() { const res = (await promisifyGrpc(client.newOAuthToken.bind(client))( req, )) as pb.StringMessage; - pkLogger(res.getS(), PKMessageType.SUCCESS); + pkLogger.logV0(res.getS(), PKMessageType.SUCCESS); }), ); } @@ -29,18 +31,24 @@ function makeRevokeTokenCommand() { return new commander.Command('revoke') .description('revoke an existing bearer token for the api') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-t, --token ', '(required) token to be revoked') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); - const client = await getAgentClient(nodePath); const req = new pb.StringMessage req.setS(options.token) const res = (await promisifyGrpc(client.revokeOAuthToken.bind(client))( req, )) as pb.BooleanMessage; - pkLogger(`token was ${res.getB() ? '' : 'un-'}successfully revoked`, res.getB() ? PKMessageType.SUCCESS : PKMessageType.ERROR); + if (res.getB()) { + pkLogger.logV1(`token was successfully revoked`, PKMessageType.SUCCESS); + } else { + throw Error('something went wrong and token was not revoked') + } }), ); } @@ -50,16 +58,18 @@ function makeListTokensCommand() { .alias('ls') .description('list all bearer tokens for the api') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); - const client = await getAgentClient(nodePath); const res = (await promisifyGrpc(client.listOAuthTokens.bind(client))( new pb.EmptyMessage(), )) as pb.StringListMessage; for (const s of res.getSList()) { - pkLogger(s, PKMessageType.SUCCESS); + pkLogger.logV0(s, PKMessageType.SUCCESS); } }), ); diff --git a/src/bin/peers/index.ts b/src/bin/peers/index.ts index 0b7dfbc38..db37c450d 100644 --- a/src/bin/peers/index.ts +++ b/src/bin/peers/index.ts @@ -1,5 +1,4 @@ import commander from 'commander'; -import { makePunchCommand, makeRelayCommand } from './natCommands'; import { makeAddPeerCommand, makeFindPeerCommand, @@ -21,9 +20,7 @@ function makePeersCommand() { .addCommand(makePingPeerCommand()) .addCommand(makeFindPeerCommand()) .addCommand(makeFindSocialPeerCommand()) - .addCommand(makeStealthCommand()) - .addCommand(makeRelayCommand()) - .addCommand(makePunchCommand()); + .addCommand(makeStealthCommand()); } export default makePeersCommand; diff --git a/src/bin/peers/natCommands.ts b/src/bin/peers/natCommands.ts deleted file mode 100644 index 36c53a334..000000000 --- a/src/bin/peers/natCommands.ts +++ /dev/null @@ -1,55 +0,0 @@ -import fs from 'fs'; -import commander from 'commander'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc } from '../utils'; -import * as pb from '../../../proto/compiled/Agent_pb'; - -function makeRelayCommand() { - return new commander.Command('relay') - .description('request a relay connection from a public peer') - .option('-k, --node-path ', 'provide the polykey path') - .requiredOption('-pk, --public-key ', '(required) path to the file which contains the public key') - .option('-v, --verbose', 'increase verbosity level by one') - .action( - actionRunner(async (options) => { - const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); - - // read in publicKey if it exists - const publicKey = fs.readFileSync(options.publicKey).toString(); - - const request = new pb.StringMessage(); - request.setS(publicKey); - const res = (await promisifyGrpc(client.requestRelay.bind(client))(request)) as pb.BooleanMessage; - if (res.getB()) { - pkLogger('peer server successfully relayed', PKMessageType.SUCCESS); - } else { - pkLogger('something went wrong', PKMessageType.WARNING); - } - }), - ); -} - -function makePunchCommand() { - return new commander.Command('punch') - .description('request a udp hole punched address from a peer') - .option('-k, --node-path ', 'provide the polykey path') - .requiredOption('-pk, --public-key ', '(required) path to the file which contains the public key') - .option('-v, --verbose', 'increase verbosity level by one') - .action( - actionRunner(async (options) => { - const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); - - // read in publicKey if it exists - const publicKey = fs.readFileSync(options.publicKey).toString(); - - const request = new pb.StringMessage(); - request.setS(publicKey); - const res = (await promisifyGrpc(client.requestHolePunch.bind(client))(request)) as pb.BooleanMessage; - - pkLogger(`peer address successfully hole punched`, PKMessageType.SUCCESS); - }), - ); -} - -export { makePunchCommand, makeRelayCommand }; diff --git a/src/bin/peers/peerCommands.ts b/src/bin/peers/peerCommands.ts index 1be33dcba..80390c09c 100644 --- a/src/bin/peers/peerCommands.ts +++ b/src/bin/peers/peerCommands.ts @@ -2,46 +2,45 @@ import fs from 'fs'; import commander from 'commander'; import { PeerInfo } from '../../Polykey'; import * as pb from '../../../proto/compiled/Agent_pb'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc } from '../utils'; +import { actionRunner, getPKLogger, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc } from '../utils'; function makeAddPeerCommand() { return new commander.Command('add') .description('add a new peer to the store') + .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .option('-b64, --base64 ', 'decode the peer info from a base64 string') .option('-pk, --public-key ', 'path to the file which contains the public key') - .option('-rk, --relay-key ', 'path to the file which contains the public key of the relay peer') + .option('-rc, --root-certificate ', 'path to the file which contains the peer root certificate') .option('-pa, --peer-address ', 'address on which the node can be contacted') .option('-aa, --api-address ', 'address on which the HTTP API is served') - .option('-k, --node-path ', 'provide the polykey path') - .option('-v, --verbose', 'increase verbosity level by one') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const base64String = options?.base64?.replace('\r', '')?.replace('\n', ''); const request = new pb.PeerInfoMessage(); if (base64String != undefined) { // read in peer info string - const { publicKey, peerAddress, relayPublicKey, apiAddress } = PeerInfo.parseB64(base64String); + const { publicKey, rootCertificate, peerAddress, apiAddress } = PeerInfo.parseB64(base64String); request.setPublicKey(publicKey); - if (relayPublicKey) { - request.setRelayPublicKey(relayPublicKey); - } + request.setRootCertificate(rootCertificate); if (peerAddress) { request.setPeerAddress(peerAddress?.toString()); } if (apiAddress) { - request.setPeerAddress(apiAddress?.toString()); + request.setApiAddress(apiAddress?.toString()); } } else { // read in publicKey if it exists const publicKey = fs.readFileSync(options.publicKey).toString(); - const relayPublicKey = fs.readFileSync(options.relayKey).toString(); + const rootCertificate = fs.readFileSync(options.rootCertificate).toString(); request.setPublicKey(publicKey); - request.setRelayPublicKey(relayPublicKey); + request.setRootCertificate(rootCertificate); request.setPeerAddress(options.peerAddress); request.setApiAddress(options.apiAddress); } @@ -49,9 +48,9 @@ function makeAddPeerCommand() { const res = (await promisifyGrpc(client.addPeer.bind(client))(request)) as pb.BooleanMessage; if (res.getB()) { - pkLogger('peer successfully added to peer store', PKMessageType.SUCCESS); + pkLogger.logV1('peer successfully added to peer store', PKMessageType.SUCCESS); } else { - pkLogger('something went wrong, peer was not added to peer store', PKMessageType.WARNING); + throw Error('something went wrong, peer was not added to peer store'); } }), ); @@ -61,13 +60,14 @@ function makeFindPeerCommand() { return new commander.Command('find') .description('find a peer based on a public key') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-pk, --public-key ', '(required) path to the file which contains the public key') .requiredOption('-t, --timeout ', '(required) timeout of the request in milliseconds') - .option('-v, --verbose', 'increase verbosity level by one') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); // read in publicKey if it exists const publicKey = fs.readFileSync(options.publicKey).toString(); @@ -78,9 +78,9 @@ function makeFindPeerCommand() { const res = (await promisifyGrpc(client.findPeer.bind(client))(request)) as pb.BooleanMessage; if (res.getB()) { - pkLogger('peer successfully pinged', PKMessageType.SUCCESS); + pkLogger.logV1('peer successfully pinged', PKMessageType.SUCCESS); } else { - pkLogger('ping timed out', PKMessageType.WARNING); + throw Error('ping timed out'); } }), ); @@ -90,21 +90,15 @@ function makeGetPeerInfoCommand() { return new commander.Command('get') .description('get the peer info for a particular public key') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .option('-b64, --base64', 'output peer info as a base64 string') .option('-cn, --current-node', 'only list the peer information for the current node, useful for sharing') - .option('-pk, --public-key ', 'path to the file which contains the public key') - .option('-v, --verbose', 'increase verbosity level by one') + .option('-pi, --peer-id ', 'unique hash of public key that identifies the peer') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); - - const publicKeyPath = options.publicKey; - // read in publicKey if it exists - let publicKey: string | undefined; - if (publicKeyPath) { - publicKey = fs.readFileSync(publicKeyPath).toString(); - } + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); let res: pb.PeerInfoMessage; if (options.currentNode) { @@ -113,30 +107,33 @@ function makeGetPeerInfoCommand() { )) as pb.PeerInfoMessage; } else { const request = new pb.StringMessage(); - request.setS(publicKey!); + request.setS(options.peerId!); res = (await promisifyGrpc(client.getPeerInfo.bind(client))(request)) as pb.PeerInfoMessage; } const peerInfo = new PeerInfo( res.getPublicKey(), - res.getRelayPublicKey(), + res.getRootCertificate(), res.getPeerAddress(), res.getApiAddress(), ); if (options.base64) { - pkLogger(peerInfo.toStringB64(), PKMessageType.SUCCESS); + pkLogger.logV0(peerInfo.toStringB64(), PKMessageType.SUCCESS); } else { - pkLogger('Peer Public Key:', PKMessageType.INFO); - pkLogger(peerInfo.publicKey, PKMessageType.SUCCESS); + pkLogger.logV0('Peer Id:', PKMessageType.INFO); + pkLogger.logV0(peerInfo.id, PKMessageType.SUCCESS); + + pkLogger.logV0('Peer Public Key:', PKMessageType.INFO); + pkLogger.logV0(peerInfo.publicKey, PKMessageType.SUCCESS); - pkLogger('Relay Public Key:', PKMessageType.INFO); - pkLogger(peerInfo.relayPublicKey ?? '', PKMessageType.SUCCESS); + pkLogger.logV0('Peer Root Certificate:', PKMessageType.INFO); + pkLogger.logV0(peerInfo.rootCertificate, PKMessageType.SUCCESS); - pkLogger('Peer Address:', PKMessageType.INFO); - pkLogger(peerInfo.peerAddress?.toString() ?? '', PKMessageType.SUCCESS); + pkLogger.logV0('Peer Address:', PKMessageType.INFO); + pkLogger.logV0(peerInfo.peerAddress?.toString() ?? '', PKMessageType.SUCCESS); - pkLogger('API Address:', PKMessageType.INFO); - pkLogger(peerInfo.apiAddress?.toString() ?? '', PKMessageType.SUCCESS); + pkLogger.logV0('API Address:', PKMessageType.INFO); + pkLogger.logV0(peerInfo.apiAddress?.toString() ?? '', PKMessageType.SUCCESS); } }), ); @@ -147,20 +144,21 @@ function makeListPeersCommand() { .description('list all connected peers') .alias('ls') .option('-k, --node-path ', 'provide the polykey path') - .option('-v, --verbose', 'increase verbosity level by one') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const res = (await promisifyGrpc(client.listPeers.bind(client))(new pb.EmptyMessage())) as pb.StringListMessage; const publicKeys = res.getSList(); if (publicKeys === undefined || publicKeys.length == 0) { - pkLogger('no peers exist', PKMessageType.INFO); + pkLogger.logV1('no peers exist', PKMessageType.INFO); } else { publicKeys.forEach((publicKey: string, index: number) => { - pkLogger(`${index + 1}: ${publicKey}`, PKMessageType.INFO); + pkLogger.logV0(`${index + 1}: ${publicKey}`, PKMessageType.SUCCESS); }); } }), @@ -171,12 +169,13 @@ function makePingPeerCommand() { return new commander.Command('ping') .description('ping a connected peer') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-pk, --public-key ', '(required) path to the file which contains the public key') - .option('-v, --verbose', 'increase verbosity level by one') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); // read in publicKey if it exists const publicKey = fs.readFileSync(options.publicKey).toString(); @@ -186,9 +185,9 @@ function makePingPeerCommand() { const res = (await promisifyGrpc(client.pingPeer.bind(client))(request)) as pb.BooleanMessage; if (res.getB()) { - pkLogger('peer successfully pinged', PKMessageType.SUCCESS); + pkLogger.logV1('peer successfully pinged', PKMessageType.SUCCESS); } else { - pkLogger('ping timed out', PKMessageType.WARNING); + throw Error('ping timed out'); } }), ); @@ -199,34 +198,36 @@ function makeStealthCommand() { const activeStealthCommand = new commander.Command('active') .command('active') .option('-k, --node-path ', 'provide the polykey path') - .option('-v, --verbose', 'increase verbosity level by one') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const request = new pb.BooleanMessage(); request.setB(true); const res = (await promisifyGrpc(client.toggleStealthMode.bind(client))(request)) as pb.BooleanMessage; - pkLogger(`stealth mode toggled to 'active'`, PKMessageType.SUCCESS); + pkLogger.logV1(`stealth mode toggled to 'active'`, PKMessageType.SUCCESS); }), ); // add inactive command const inactiveStealthCommand = new commander.Command('inactive') - .option('-k, --node-path ', 'provide the polykey path') - .option('-v, --verbose', 'increase verbosity level by one') + .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const request = new pb.BooleanMessage(); request.setB(false); const res = (await promisifyGrpc(client.toggleStealthMode.bind(client))(request)) as pb.BooleanMessage; - pkLogger(`stealth mode toggled to 'inactive'`, PKMessageType.SUCCESS); + pkLogger.logV1(`stealth mode toggled to 'inactive'`, PKMessageType.SUCCESS); }), ); @@ -242,17 +243,18 @@ function makeUpdatePeerInfoCommand() { return new commander.Command('update') .description('update the peer info for a particular public key') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .option('-cn, --current-node', 'only list the peer information for the current node, useful for sharing') .option('-b64, --base64 ', 'decode the peer info from a base64 string') - .option('-pk, --public-key ', 'path to the file which contains the public key') - .option('-rk, --relay-key ', 'path to the file which contains the public key of the relay peer') + .option('-pi, --peer-id ', 'the id of the peer to be updated') + .option('-rc, --root-certificate ', 'path to the file which contains the peer root certificate') .option('-pa, --peer-address ', 'update the peer address') .option('-aa, --api-address ', 'update the api address') - .option('-v, --verbose', 'increase verbosity level by one') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const publicKeyPath = options.publicKey; // read in publicKey if it exists @@ -261,23 +263,14 @@ function makeUpdatePeerInfoCommand() { publicKey = fs.readFileSync(publicKeyPath).toString(); } - const relayPublicKeyPath = options.relayKey; - // read in relay publicKey if it exists - let relayPublicKey: string | undefined = undefined; - if (relayPublicKeyPath) { - relayPublicKey = fs.readFileSync(relayPublicKeyPath).toString(); - } - const request = new pb.PeerInfoMessage(); const base64String = options?.base64?.replace('\r', '')?.replace('\n', ''); if (base64String != undefined) { // read in peer info string - const { publicKey, relayPublicKey, peerAddress, apiAddress } = PeerInfo.parseB64(base64String); - request.setPublicKey(publicKey); - if (relayPublicKey) { - request.setRelayPublicKey(relayPublicKey); - } + const { publicKey, rootCertificate, peerAddress, apiAddress } = PeerInfo.parseB64(base64String); + request.setPublicKey(PeerInfo.publicKeyToId(publicKey)); + request.setRootCertificate(rootCertificate); if (peerAddress) { request.setPeerAddress(peerAddress?.toString()); } @@ -285,10 +278,11 @@ function makeUpdatePeerInfoCommand() { request.setApiAddress(apiAddress?.toString()); } } else { - request.setPublicKey(options.publicKey!); - if (options.relayPublicKey) { - request.setRelayPublicKey(options.relayPublicKey); + if (!options.peerId) { + throw Error('must specify peer id') } + request.setPublicKey(options.peerId); + request.setRootCertificate(options.rootCertificate); if (options.peerAddress) { request.setPeerAddress(options.peerAddress); } @@ -307,9 +301,9 @@ function makeUpdatePeerInfoCommand() { } if (successful) { - pkLogger('peer info was successfully updated', PKMessageType.SUCCESS); + pkLogger.logV1('peer info was successfully updated', PKMessageType.SUCCESS); } else { - pkLogger('something went wrong, peer info could not be updated', PKMessageType.WARNING); + throw Error('something went wrong, peer info could not be updated'); } }), ); diff --git a/src/bin/peers/socialCommands.ts b/src/bin/peers/socialCommands.ts index d1e99f12d..163da380b 100644 --- a/src/bin/peers/socialCommands.ts +++ b/src/bin/peers/socialCommands.ts @@ -1,29 +1,28 @@ import commander from 'commander'; -import { PolykeyAgent } from '../../Polykey'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; -import { agentInterface } from '../../../proto/js/Agent'; +import { actionRunner, getPKLogger, PKMessageType, determineNodePath, promisifyGrpc, getAgentClient } from '../utils'; import * as pb from '../../../proto/compiled/Agent_pb'; function makeFindSocialPeerCommand() { return new commander.Command('social') .description('find a peer based on a handle and service, e.g. john.smith and github') .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .requiredOption('-h, --handle ', '(required) handle of the user on the specified service, e.g. john.smith') .requiredOption('-s, --service ', '(required) service where the handle can be found, e.g. github') - .option('-v, --verbose', 'increase verbosity level by one') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const request = new pb.ContactPeerMessage(); request.setPublicKeyOrHandle(`@${options.service}/${options.handle}`); const res = (await promisifyGrpc(client.findSocialPeer.bind(client))(request)) as pb.BooleanMessage; if (res.getB()) { - pkLogger('peer successfully pinged', PKMessageType.SUCCESS); + pkLogger.logV0('peer successfully pinged', PKMessageType.SUCCESS); } else { - pkLogger('ping timed out', PKMessageType.WARNING); + throw Error('ping timed out'); } }), ); diff --git a/src/bin/secrets/index.ts b/src/bin/secrets/index.ts index 3b29fe11b..357e2c71b 100644 --- a/src/bin/secrets/index.ts +++ b/src/bin/secrets/index.ts @@ -2,7 +2,7 @@ import process from 'process'; import commander from 'commander'; import { spawn } from 'child_process'; import * as pb from '../../../proto/compiled/Agent_pb'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc } from '../utils'; +import { actionRunner, getPKLogger, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc } from '../utils'; const pathRegex = /^([a-zA-Z0-9_ -]+)(?::)([a-zA-Z0-9_ -]+)(?:=)?([a-zA-Z_][a-zA-Z0-9_]+)?$/; @@ -11,14 +11,15 @@ function makeListSecretsCommand() { .description('list all available secrets for a given vault') .alias('ls') .option('-k, --node-path ', 'provide the polykey path') - .option('--verbose', 'increase verbosity level by one') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .arguments('vault name(s) to list') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); + - const isVerbose: boolean = options.verbose ?? false; const vaultNames: string[] = Array.from(options.args.values()); if (!vaultNames.length) { @@ -33,15 +34,11 @@ function makeListSecretsCommand() { const secretNames = res.getSList(); // List secrets - if (secretNames.length == 0 && isVerbose) { - pkLogger(`no secrets found for vault '${vaultName}'`, PKMessageType.INFO); + if (secretNames.length == 0) { + pkLogger.logV1(`no secrets found for vault '${vaultName}'`, PKMessageType.INFO); } else { - if (isVerbose) { - pkLogger(`secrets contained within the ${vaultName} vault:`, PKMessageType.INFO); - } - secretNames.forEach((secretName) => { - pkLogger(`${vaultName}:${secretName}`, PKMessageType.INFO); - }); + pkLogger.logV1(`secrets contained within the ${vaultName} vault:`, PKMessageType.INFO); + secretNames.forEach((secretName) => pkLogger.logV0(`${vaultName}:${secretName}`, PKMessageType.SUCCESS)); } } }), @@ -52,15 +49,15 @@ function makeNewSecretCommand() { return new commander.Command('new') .description("create a secret within a given vault, specify a secret path with ':'") .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .arguments("secret path of the format ':'") .requiredOption('-f, --file-path ', '(required) path to the secret to be added') - .option('--verbose', 'increase verbosity level by one') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); - const isVerbose: boolean = options.verbose ?? false; const secretPath: string[] = Array.from(options.args.values()); if (secretPath.length < 1 || (secretPath.length == 1 && !pathRegex.test(secretPath[0]))) { throw Error("please specify a new secret name using the format: ':'"); @@ -79,8 +76,8 @@ function makeNewSecretCommand() { request.setSecretFilePath(options.filePath); const res = (await promisifyGrpc(client.newSecret.bind(client))(request)) as pb.BooleanMessage; - pkLogger( - `secret '${secretName}' was ${res.getB() ? '' : 'un-'}successfully added to vault '${vaultName}'`, + pkLogger.logV1( + `secret '${secretName}' was successfully added to vault '${vaultName}'`, PKMessageType.SUCCESS, ); } catch (err) { @@ -94,15 +91,16 @@ function makeUpdateSecretCommand() { return new commander.Command('update') .description("update a secret within a given vault, specify a secret path with ':'") .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .arguments("secret path of the format ':'") .requiredOption('-f, --file-path ', '(required) path to the new secret') - .option('--verbose', 'increase verbosity level by one') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); + - const isVerbose: boolean = options.verbose ?? false; const secretPath: string[] = Array.from(options.args.values()); if (secretPath.length < 1 || (secretPath.length == 1 && !pathRegex.test(secretPath[0]))) { throw Error("please specify the secret using the format: ':'"); @@ -121,8 +119,8 @@ function makeUpdateSecretCommand() { request.setSecretFilePath(options.filePath); const res = (await promisifyGrpc(client.updateSecret.bind(client))(request)) as pb.BooleanMessage; - pkLogger( - `secret '${secretName}' was ${res.getB() ? '' : 'un-'}successfully updated in vault '${vaultName}'`, + pkLogger.logV1( + `secret '${secretName}' was successfully updated in vault '${vaultName}'`, res.getB() ? PKMessageType.SUCCESS : PKMessageType.WARNING, ); } catch (err) { @@ -137,14 +135,15 @@ function makeDeleteSecretCommand() { .alias('del') .description("delete a secret from a given vault, specify a secret path with ':'") .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .arguments("secret path of the format ':'") - .option('--verbose', 'increase verbosity level by one') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); + - const isVerbose: boolean = options.verbose ?? false; const secretPath: string[] = Array.from(options.args.values()); if (secretPath.length < 1 || (secretPath.length == 1 && !pathRegex.test(secretPath[0]))) { throw Error("please specify the secret using the format: ':'"); @@ -160,8 +159,8 @@ function makeDeleteSecretCommand() { request.setSecretName(secretName); const res = (await promisifyGrpc(client.deleteSecret.bind(client))(request)) as pb.BooleanMessage; - pkLogger( - `secret '${secretName}' was ${res.getB() ? '' : 'un-'}successfully removed from vault '${vaultName}'`, + pkLogger.logV1( + `secret '${secretName}' was successfully removed from vault '${vaultName}'`, PKMessageType.SUCCESS, ); } catch (err) { @@ -175,15 +174,17 @@ function makeGetSecretCommand() { return new commander.Command('get') .description("retrieve a secret from a given vault, specify a secret path with ':'") .option('-k, --node-path ', 'provide the polykey path') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .arguments("secret path of the format ':'") .option('-e, --env', 'wrap the secret in an environment variable declaration') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const isEnv: boolean = options.env ?? false; - const isVerbose: boolean = options.verbose ?? false; + const secretPath: string[] = Array.from(options.args.values()); if (secretPath.length < 1 || (secretPath.length == 1 && !pathRegex.test(secretPath[0]))) { throw Error("please specify the secret using the format: ':'"); @@ -201,9 +202,9 @@ function makeGetSecretCommand() { const secret = res.getS(); if (isEnv) { - pkLogger(`export ${secretName.toUpperCase().replace('-', '_')}='${secret}'`, PKMessageType.none); + pkLogger.logV0(`export ${secretName.toUpperCase().replace('-', '_')}='${secret}'`, PKMessageType.none); } else { - pkLogger(secret.toString(), PKMessageType.none); + pkLogger.logV0(secret.toString(), PKMessageType.none); } } catch (err) { throw Error(`Error when retrieving secret: ${err.message}`); @@ -235,9 +236,9 @@ function makeSecretEnvCommand() { const options = cmd.opts(); const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); - const isVerbose: boolean = options.verbose ?? false; const command: string | undefined = options.command; const run: string | undefined = options.run; @@ -296,7 +297,7 @@ function makeSecretEnvCommand() { }); shell.on('close', (code) => { if (code != 0) { - pkLogger(`polykey: environment terminated with code: ${code}`, PKMessageType.WARNING); + pkLogger.logV1(`polykey: environment terminated with code: ${code}`, PKMessageType.WARNING); } }); } catch (err) { diff --git a/src/bin/utils.ts b/src/bin/utils.ts index 352b58e5c..fa2070816 100644 --- a/src/bin/utils.ts +++ b/src/bin/utils.ts @@ -1,3 +1,4 @@ +import path from 'path' import os from 'os'; import chalk from 'chalk'; import * as grpc from '@grpc/grpc-js'; @@ -10,7 +11,7 @@ function actionRunner(fn: (...args: any) => Promise) { return (...args: any) => fn(...args) .catch((error: Error) => { - pkLogger(error.message, PKMessageType.ERROR); + console.error(chalk.redBright(error.message)); }) .finally(() => { if (process.env.NODE_ENV !== 'test') { @@ -32,32 +33,48 @@ enum PKMessageType { SUCCESS, INFO, WARNING, - ERROR, none, } -function pkLogger(message: string, type?: PKMessageType) { - switch (type) { - case PKMessageType.SUCCESS: - console.log(chalk.greenBright(message)); - break; - case PKMessageType.INFO: - console.info(chalk.blueBright(message)); - break; - case PKMessageType.WARNING: - console.warn(chalk.yellowBright(message)); - break; - case PKMessageType.ERROR: - console.error(chalk.redBright(message)); - break; - default: - console.debug(message); - break; +type PKLogger = { + logV0: (message: string, type?: PKMessageType) => void + logV1: (message: string, type?: PKMessageType) => void + logV2: (message: string, type?: PKMessageType) => void +} + +function getPKLogger(verbosityLevel: number = 0): PKLogger { + const log = (message: string, type?: PKMessageType) => { + switch (type) { + case PKMessageType.SUCCESS: + console.log(chalk.greenBright(message)); + break; + case PKMessageType.INFO: + console.info(chalk.blueBright(message)); + break; + case PKMessageType.WARNING: + console.warn(chalk.yellowBright(message)); + break; + default: + console.debug(message); + break; + } + } + return { + logV0: (message: string, type?: PKMessageType) => log(message, type), + logV1: (message: string, type?: PKMessageType) => (verbosityLevel <= 1) ? log(message, type) : undefined, + logV2: (message: string, type?: PKMessageType) => (verbosityLevel <= 2) ? log(message, type) : undefined, } } function determineNodePath(nodePath?: string) { - const resolvedNodePath = nodePath ?? process.env.PK_PATH; + let defaultPath: string = '/' + if (os.platform() === 'win32') { + defaultPath = process.env.APPDATA ?? os.homedir() + } else if (os.homedir()) { + defaultPath = os.homedir() + } + + const resolvedNodePath = nodePath ?? process.env.PK_PATH ?? path.join(defaultPath, '.polykey'); if (!resolvedNodePath) { throw Error('no keynode path, set as an environment variable "export PK_PATH=\'\'", or as a argument "--node-path \'\'"'); } @@ -86,12 +103,13 @@ async function getAgentClient( daemon: boolean = false, restartOnStopped: boolean = true, failOnNotInitialized: boolean = true, + pkLogger: PKLogger ) { if (restartOnStopped) { // make sure agent is running const pid = await PolykeyAgent.startAgent(polykeyPath, daemon, failOnNotInitialized); if (typeof pid == 'number') { - pkLogger(`agent has started with a pid of ${pid}`, PKMessageType.SUCCESS); + pkLogger.logV1(`agent has started with a pid of ${pid}`, PKMessageType.SUCCESS); } } @@ -104,4 +122,4 @@ async function getAgentClient( } } -export { pkLogger, actionRunner, PKMessageType, determineNodePath, resolveTilde, promisifyGrpc, getAgentClient }; +export { getPKLogger, actionRunner, PKMessageType, determineNodePath, resolveTilde, promisifyGrpc, getAgentClient }; diff --git a/src/bin/vaults/index.ts b/src/bin/vaults/index.ts index 9921384f0..e8dede32a 100644 --- a/src/bin/vaults/index.ts +++ b/src/bin/vaults/index.ts @@ -1,18 +1,19 @@ import fs from 'fs'; import commander from 'commander'; import * as pb from '../../../proto/compiled/Agent_pb'; -import { actionRunner, pkLogger, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc } from '../utils'; +import { actionRunner, getPKLogger, PKMessageType, determineNodePath, getAgentClient, promisifyGrpc } from '../utils'; function makeListVaultsCommand() { return new commander.Command('list') .description('list all available vaults') .alias('ls') .option('-k, --node-path ', 'provide the polykey path') - .option('-v, --verbose', 'increase verbosity level by one') + .option('-v, --verbosity, ', 'set the verbosity level, can choose from levels 1, 2 or 3', str => parseInt(str), 1) .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const res = (await promisifyGrpc(client.listVaults.bind(client))( new pb.EmptyMessage(), @@ -20,11 +21,9 @@ function makeListVaultsCommand() { const vaultNames = res.getSList(); if (vaultNames === undefined || vaultNames.length == 0) { - pkLogger('no vaults found', PKMessageType.INFO); + pkLogger.logV1('no vaults found', PKMessageType.INFO); } else { - vaultNames.forEach((vaultName: string, index: number) => { - pkLogger(`${index + 1}: ${vaultName}`, PKMessageType.INFO); - }); + vaultNames.forEach((vaultName: string, index: number) => pkLogger.logV0(`${index + 1}: ${vaultName}`, PKMessageType.SUCCESS)); } }), ); @@ -39,9 +38,8 @@ function makeScanVaultsCommand() { .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); - - const verbose: boolean = options.verbose ?? false; + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const publicKey = fs.readFileSync(options.publicKey).toString(); @@ -51,11 +49,11 @@ function makeScanVaultsCommand() { const vaultNames = res.getSList(); if (!vaultNames || vaultNames.length == 0) { - pkLogger(`no vault names were provided`, PKMessageType.INFO); + throw Error(`no vault names were provided`) } for (const vaultName of vaultNames) { - pkLogger(vaultName, PKMessageType.SUCCESS); + pkLogger.logV0(vaultName, PKMessageType.SUCCESS); } }), ); @@ -69,12 +67,13 @@ function makeNewVaultCommand() { .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const request = new pb.StringMessage(); request.setS(options.vaultName); const res = (await promisifyGrpc(client.newVault.bind(client))(request)) as pb.BooleanMessage; - pkLogger(`vault created at '${nodePath}/${options.vaultName}'`, PKMessageType.SUCCESS); + pkLogger.logV1(`vault created at '${nodePath}/${options.vaultName}'`, PKMessageType.SUCCESS); }), ); } @@ -83,24 +82,22 @@ function makePullVaultCommand() { return new commander.Command('pull') .description('pull a vault from a peer') .option('-k, --node-path ', 'provide the polykey path') - .requiredOption('-pk, --public-key ', '(required) public key file path of the peer who has the vault') + .requiredOption('-pi, --peer-id ', '(required) id string of the peer who has the vault') .requiredOption('-vn, --vault-name ', '(required) name of the vault to be cloned') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const vaultName = options.vaultName; - // read in public key - const publicKey = fs.readFileSync(options.publicKey).toString(); - const request = new pb.VaultPathMessage(); - request.setPublicKey(publicKey.toString()); + request.setPublicKey(options.peerId); request.setVaultName(vaultName); const res = (await promisifyGrpc(client.pullVault.bind(client))(request)) as pb.BooleanMessage; - pkLogger(`vault '${vaultName}' pulled ${res.getB() ? 'un-' : ''}successfully`, PKMessageType.SUCCESS); + pkLogger.logV1(`vault '${vaultName}' pulled ${res.getB() ? '' : 'un-'}successfully`, PKMessageType.SUCCESS); }), ); } @@ -109,15 +106,14 @@ function makeDeleteVaultCommand() { return new commander.Command('delete') .alias('del') .description('delete an existing vault') - .option('-n, --vault-name ', 'name of vault') + .requiredOption('-vn, --vault-name ', 'name of vault') .option('-v, --verbose', 'increase verbosity by one level') .arguments('name of vault to remove') .action( actionRunner(async (options) => { const nodePath = determineNodePath(options.nodePath); - const client = await getAgentClient(nodePath); - - const verbose: boolean = options.verbose ?? false; + const pkLogger = getPKLogger(options.verbosity) + const client = await getAgentClient(nodePath, undefined, undefined, undefined, pkLogger); const vaultNames = options.args.values(); if (!vaultNames) { @@ -129,7 +125,7 @@ function makeDeleteVaultCommand() { request.setS(vaultName); const res = (await promisifyGrpc(client.deleteVault.bind(client))(request)) as pb.BooleanMessage; - pkLogger(`vault '${vaultName}' deleted ${res.getB() ? 'un-' : ''}successfully`, PKMessageType.SUCCESS); + pkLogger.logV1(`vault '${vaultName}' deleted ${res.getB() ? '' : 'un-'}successfully`, PKMessageType.SUCCESS); } }), ); diff --git a/src/git/GitBackend.ts b/src/git/GitBackend.ts index 012f5822a..16d6defb5 100644 --- a/src/git/GitBackend.ts +++ b/src/git/GitBackend.ts @@ -19,7 +19,7 @@ import packObjects from './pack-objects/packObjects'; class GitBackend { private repoDirectoryPath: string; private getFileSystem: (repoName: string) => EncryptedFS; - private getVaultNames: (publicKey: string) => string[]; + private getVaultNames: (peerId: string) => string[]; constructor( repoDirectoryPath: string, @@ -136,8 +136,8 @@ class GitBackend { }); } - async handleVaultNamesRequest(publicKey: string): Promise { - return this.getVaultNames(publicKey); + async handleVaultNamesRequest(peerId: string): Promise { + return this.getVaultNames(peerId); } // ============ Helper functions ============ // diff --git a/src/git/GitFrontend.ts b/src/git/GitFrontend.ts index ea1ab1572..1e441017d 100644 --- a/src/git/GitFrontend.ts +++ b/src/git/GitFrontend.ts @@ -1,6 +1,5 @@ import GitRequest from './GitRequest'; import { gitInterface } from '../../proto/js/Git'; -import PeerManager from '../peers/PeerManager'; import PeerConnection from '../peers/peer-connection/PeerConnection'; import { SubServiceType } from '../../proto/compiled/Peer_pb'; @@ -8,10 +7,10 @@ import { SubServiceType } from '../../proto/compiled/Peer_pb'; * Responsible for converting HTTP messages from isomorphic-git into requests and sending them to a specific peer. */ class GitFrontend { - private peerManager: PeerManager; + private connectToPeer: (peerId: string) => PeerConnection; - constructor(peerManager: PeerManager) { - this.peerManager = peerManager; + constructor(connectToPeer: (peerId: string) => PeerConnection) { + this.connectToPeer = connectToPeer; } /** @@ -72,8 +71,8 @@ class GitFrontend { return vaultNameList; } - connectToPeerGit(publicKey: string): GitRequest { - const peerConnection = this.peerManager.connectToPeer(publicKey); + connectToPeerGit(peerId: string): GitRequest { + const peerConnection = this.connectToPeer(peerId); const gitRequest = new GitRequest( ((vaultName: string) => this.requestInfo(vaultName, peerConnection)).bind(this), ((vaultName: string, body: Buffer) => this.requestPack(vaultName, body, peerConnection)).bind(this), diff --git a/src/keys/KeyManager.ts b/src/keys/KeyManager.ts index f32e47264..e6a13ba47 100644 --- a/src/keys/KeyManager.ts +++ b/src/keys/KeyManager.ts @@ -22,6 +22,7 @@ type KeyPair = { class KeyManager { private primaryKeyPair: KeyPair = { private: null, public: null }; private primaryIdentity?: Object; + private primaryIdentityTimeout?: NodeJS.Timeout private derivedKeys: Map; private derivedKeysPath: string; private useWebWorkers: boolean; @@ -74,7 +75,18 @@ class KeyManager { this.pki = new PublicKeyInfrastructure(this.polykeyPath, this.fileSystem); } - public get identityLoaded(): boolean { + public get Status() { + return { + keypairUnlocked: this.KeypairUnlocked, + keypairLoaded: this.KeypairLoaded, + }; + } + + public get KeypairLoaded(): boolean { + return this.primaryKeyPair.private != null && this.primaryKeyPair.public != null; + } + + public get KeypairUnlocked(): boolean { return this.primaryIdentity ? true : false; } @@ -90,29 +102,17 @@ class KeyManager { async generateKeyPair( userId: string, passphrase: string, - nbits: number = 4096, replacePrimary: boolean = false, progressCallback?: (info) => void, ): Promise { - // kbpgp doesn't seem to work for small nbits so set a minimum of 1024 - if (nbits < 1024) { - throw Error('nbits must be greater than 1024 for keypair generation'); - } // Define options - const flags = kbpgp['const'].openpgp; const params = { asp: progressCallback ? new kbpgp.ASP({ progress_hook: progressCallback }) : undefined, userid: userId, - primary: { - nbits: nbits, - flags: flags.certify_keys | flags.sign_data | flags.auth | flags.encrypt_comm | flags.encrypt_storage, - expire_in: 0, // never expire - }, - subkeys: [], }; - const identity = await promisify(kbpgp.KeyManager.generate)(params); - + // generateecc key pair with sensible defaults + const identity = await promisify(kbpgp.KeyManager.generate_ecc)(params); await promisify(identity.sign.bind(identity))({}); // Export pub key first @@ -228,20 +228,57 @@ class KeyManager { /** * Loads the primary identity into the key manager from the existing keypair * @param passphrase Passphrase to unlock the private key + * @param timeout Minutes of inactivity after which identity is locked again */ - async unlockIdentity(passphrase: string): Promise { - const publicKey: string = this.getPublicKey(); - const privateKey: string = this.getPrivateKey(); + async unlockIdentity(passphrase: string, timeout: number = 15): Promise { + // check if already unlocked + if (this.primaryIdentityTimeout && this.primaryIdentity) { + clearTimeout(this.primaryIdentityTimeout) + } else { + const publicKey: string = this.getPublicKey(); + const privateKey: string = this.getPrivateKey(); - const identity = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({ armored: publicKey }); + const identity = await promisify(kbpgp.KeyManager.import_from_armored_pgp)({ armored: publicKey }); - await promisify(identity.merge_pgp_private.bind(identity))({ armored: privateKey }); + await promisify(identity.merge_pgp_private.bind(identity))({ armored: privateKey }); - if (identity.is_pgp_locked.bind(identity)()) { - await promisify(identity.unlock_pgp.bind(identity))({ passphrase: passphrase }); + if (identity.is_pgp_locked.bind(identity)()) { + await promisify(identity.unlock_pgp.bind(identity))({ passphrase: passphrase }); + } + + this.primaryIdentity = identity; } + if (timeout !== 0) { + // set new timeout + this.primaryIdentityTimeout = setTimeout(() => { + this.lockIdentity() + }, timeout * 60 * 1000) + } + } - this.primaryIdentity = identity; + refreshTimeout(timeout: number = 15) { + if (!this.primaryIdentityTimeout) { + if (!this.primaryIdentity) { + throw Error('node is locked') + } + } else { + clearTimeout(this.primaryIdentityTimeout) + } + if (this.primaryIdentityTimeout) { + this.primaryIdentityTimeout = this.primaryIdentityTimeout.refresh() + } else { + // set new timeout + this.primaryIdentityTimeout = setTimeout(() => { + this.lockIdentity() + }, timeout * 60 * 1000) + } + } + + /** + * Locks the primary identity + */ + lockIdentity(): void { + this.primaryIdentity = undefined; } /** @@ -683,7 +720,7 @@ class KeyManager { private async writeEncryptedMetadata(): Promise { // Store the keys if identity is loaded - if (this.identityLoaded) { + if (this.KeypairUnlocked) { const derivedKeys = JSON.stringify(this.derivedKeys); const encryptedMetadata = await this.encryptData(Buffer.from(derivedKeys)); await this.fileSystem.promises.writeFile(this.derivedKeysPath, encryptedMetadata); @@ -700,7 +737,7 @@ class KeyManager { } async loadEncryptedMetadata(): Promise { - if (this.identityLoaded && this.fileSystem.existsSync(this.derivedKeysPath)) { + if (this.KeypairUnlocked && this.fileSystem.existsSync(this.derivedKeysPath)) { const encryptedMetadata = this.fileSystem.readFileSync(this.derivedKeysPath); const metadata = (await this.decryptData(encryptedMetadata)).toString(); const derivedKeys = JSON.parse(metadata); diff --git a/src/keys/pki/PublicKeyInfrastructure.ts b/src/keys/pki/PublicKeyInfrastructure.ts index ed6fcadea..0e6b3fa18 100644 --- a/src/keys/pki/PublicKeyInfrastructure.ts +++ b/src/keys/pki/PublicKeyInfrastructure.ts @@ -23,7 +23,7 @@ class PublicKeyInfrastructure { // certificate signed by another private keypair: pki.rsa.KeyPair; - private certificate?: pki.Certificate; + private certificate: pki.Certificate; public get CACertificates(): string { return this.CAStore.listAllCertificates() @@ -31,34 +31,26 @@ class PublicKeyInfrastructure { .join('\n'); } - public get TLSClientCredentials(): TLSCredentials | undefined { - if (this.certificate) { - return { - rootCertificate: this.CACertificates, - certificate: pki.certificateToPem(this.certificate), - keypair: { - public: pki.publicKeyToPem(this.keypair.publicKey), - private: pki.privateKeyToPem(this.keypair.privateKey), - } - }; - } else { - return undefined; - } + public get TLSClientCredentials(): TLSCredentials { + return { + rootCertificate: this.RootCert, + certificate: pki.certificateToPem(this.certificate), + keypair: { + public: pki.publicKeyToPem(this.keypair.publicKey), + private: pki.privateKeyToPem(this.keypair.privateKey), + } + }; } - public get TLSServerCredentials(): TLSCredentials | undefined { - if (this.certificate) { - return { - rootCertificate: this.CACertificates, - certificate: pki.certificateToPem(this.certificate), - keypair: { - public: pki.publicKeyToPem(this.keypair.publicKey), - private: pki.privateKeyToPem(this.keypair.privateKey), - } - }; - } else { - return undefined; - } + public get TLSServerCredentials(): TLSCredentials { + return { + rootCertificate: this.RootCert, + certificate: pki.certificateToPem(this.certificate), + keypair: { + public: pki.publicKeyToPem(this.keypair.publicKey), + private: pki.privateKeyToPem(this.keypair.privateKey), + } + }; } private CAStore: pki.CAStore; @@ -105,14 +97,16 @@ class PublicKeyInfrastructure { } // private createCACertificate( - createCACertificate(organizationName: string = 'MatrixAI') { + createTLSCredentials(organizationName: string = 'MatrixAI', isCA: boolean = false): TLSCredentials { const certificate = pki.createCertificate(); - certificate.publicKey = this.rootKeypair.publicKey; + const keypair = pki.rsa.generateKeyPair(); + certificate.publicKey = keypair.publicKey; certificate.serialNumber = '01'; certificate.validity.notBefore = new Date(); certificate.validity.notAfter = new Date(); certificate.validity.notAfter.setMonth(certificate.validity.notBefore.getMonth() + 3); + isCA=true const attrs = [ { name: 'commonName', @@ -128,7 +122,7 @@ class PublicKeyInfrastructure { certificate.setExtensions([ { name: 'basicConstraints', - cA: true, + cA: isCA, }, { name: 'keyUsage', @@ -152,19 +146,31 @@ class PublicKeyInfrastructure { server: true, email: true, objsign: true, - sslCA: true, - emailCA: true, - objCA: true, + sslCA: isCA, + emailCA: isCA, + objCA: isCA, }, { name: 'subjectKeyIdentifier', }, ]); + if (isCA) { + certificate.sign(keypair.privateKey, md.sha512.create()); + } else { + certificate.sign(this.rootKeypair.privateKey, md.sha512.create()); + } - certificate.sign(this.rootKeypair.privateKey, md.sha512.create()); + const certificatePem = pki.certificateToPem(certificate) - return certificate; + return { + rootCertificate: isCA ? certificatePem : this.RootCert, + certificate: certificatePem, + keypair: { + private: pki.privateKeyToPem(keypair.privateKey), + public: pki.publicKeyToPem(keypair.publicKey), + }, + }; } privateKeyToPem(privateKey: pki.rsa.PrivateKey): string { @@ -215,7 +221,7 @@ class PublicKeyInfrastructure { return pki.certificationRequestToPem(csr); } - createServerCredentials() { + createServerCredentials(): TLSCredentials { const keypair = pki.rsa.generateKeyPair(); // create a certification request (CSR) const certificate = pki.createCertificate(); @@ -279,7 +285,7 @@ class PublicKeyInfrastructure { }; } - createClientCredentials() { + createClientCredentials(): TLSCredentials { const keypair = pki.rsa.generateKeyPair(); // create a certification request (CSR) const certificate = pki.createCertificate(); @@ -429,38 +435,39 @@ class PublicKeyInfrastructure { // make the pkiPath directory this.pkiFs.mkdirSync(this.pkiPath, { recursive: true }); - // load keypair - const keypairPath = path.join(this.pkiPath, 'keypair'); - if (this.pkiFs.existsSync(keypairPath)) { - this.keypair = this.jsonToKeyPair(this.pkiFs.readFileSync(keypairPath).toString()); - } else { - // create the keypair if it doesn't exist - this.keypair = pki.rsa.generateKeyPair(); - } - // load root keypair + // load root keypair and certificate const rootKeypairPath = path.join(this.pkiPath, 'root_keypair'); - if (this.pkiFs.existsSync(rootKeypairPath)) { + const rootCertificatePath = path.join(this.pkiPath, 'root_certificate'); + if (this.pkiFs.existsSync(rootKeypairPath) && this.pkiFs.existsSync(rootCertificatePath)) { this.rootKeypair = this.jsonToKeyPair(this.pkiFs.readFileSync(rootKeypairPath).toString()); + this.rootCertificate = pki.certificateFromPem(this.pkiFs.readFileSync(rootCertificatePath).toString()); } else { - // create the keypair if it doesn't exist - this.rootKeypair = pki.rsa.generateKeyPair(); + // create the keypair and cert if it doesn't exist + const tlsCredentials = this.createTLSCredentials(undefined, true) + this.rootKeypair = { + privateKey: pki.privateKeyFromPem(tlsCredentials.keypair.private), + publicKey: pki.publicKeyFromPem(tlsCredentials.keypair.public), + } + this.rootCertificate = pki.certificateFromPem(tlsCredentials.certificate) } - // load certificate + // load keypair and certificate + const keypairPath = path.join(this.pkiPath, 'keypair'); const certificatePath = path.join(this.pkiPath, 'certificate'); - if (this.pkiFs.existsSync(certificatePath)) { + if (this.pkiFs.existsSync(keypairPath) && this.pkiFs.existsSync(certificatePath)) { + this.keypair = this.jsonToKeyPair(this.pkiFs.readFileSync(keypairPath).toString()); this.certificate = pki.certificateFromPem(this.pkiFs.readFileSync(certificatePath).toString()); - } - - // load root certificate - const rootCertificatePath = path.join(this.pkiPath, 'root_certificate'); - if (this.pkiFs.existsSync(rootCertificatePath)) { - this.rootCertificate = pki.certificateFromPem(this.pkiFs.readFileSync(rootCertificatePath).toString()); } else { - // create the certificate if it doesn't exist - this.rootCertificate = this.createCACertificate(); + // create the keypair and cert if it doesn't exist + const tlsCredentials = this.createTLSCredentials(undefined, false) + this.keypair = { + privateKey: pki.privateKeyFromPem(tlsCredentials.keypair.private), + publicKey: pki.publicKeyFromPem(tlsCredentials.keypair.public), + } + this.certificate = pki.certificateFromPem(tlsCredentials.certificate) } + // load certificate chain const certificateChainPath = path.join(this.pkiPath, 'certificate_chain'); if (this.pkiFs.existsSync(certificateChainPath)) { diff --git a/src/peers/MulticastBroadcaster.ts b/src/peers/MulticastBroadcaster.ts index f1729f869..4d2e7df30 100644 --- a/src/peers/MulticastBroadcaster.ts +++ b/src/peers/MulticastBroadcaster.ts @@ -1,7 +1,6 @@ import dgram from 'dgram'; import PeerInfo from './PeerInfo'; import { EventEmitter } from 'events'; -import PeerManager from './PeerManager'; import { peerInterface } from '../../proto/js/Peer'; import KeyManager from '../keys/KeyManager'; import { protobufToString, stringToProtobuf } from '../utils'; @@ -22,17 +21,26 @@ const UDP_MULTICAST_PORT = parseInt(process.env.UDP_MULTICAST_PORT ?? '5353'); const UDP_MULTICAST_ADDR = process.env.UDP_MULTICAST_ADDR ?? '224.0.0.251'; class MulticastBroadcaster extends EventEmitter { - private peerManager: PeerManager; + getPeerInfo: () => PeerInfo; + hasPeer: (id: string) => boolean; + updatePeer: (peerInfo: PeerInfo) => void; private keyManager: KeyManager; private socket: dgram.Socket; private interval: number = 1e3; private broadcastInterval: NodeJS.Timeout | null = null; - constructor(peerManager: PeerManager, keyManager: KeyManager) { + constructor( + getPeerInfo: () => PeerInfo, + hasPeer: (id: string) => boolean, + updatePeer: (peerInfo: PeerInfo) => void, + keyManager: KeyManager, + ) { super(); - this.peerManager = peerManager; + this.getPeerInfo = getPeerInfo; + this.hasPeer = hasPeer; + this.updatePeer = updatePeer; this.keyManager = keyManager; // Create socket @@ -67,20 +75,20 @@ class MulticastBroadcaster extends EventEmitter { startBroadcasting() { const broadcast = async () => { - if (!this.keyManager.identityLoaded) { + if (!this.keyManager.KeypairUnlocked) { return; } - const peerInfo = this.peerManager.peerInfo; + const peerInfo = this.getPeerInfo(); const encodedPeerInfo = peerInterface.PeerInfoMessage.encodeDelimited({ publicKey: peerInfo.publicKey, peerAddress: peerInfo.peerAddress?.toString(), - relayPublicKey: peerInfo.relayPublicKey, + apiAddress: peerInfo.apiAddress?.toString(), }).finish(); // sign it for authenticity const signedPeerInfo = await this.keyManager.signData(Buffer.from(protobufToString(encodedPeerInfo))); const encodedPeerMessage = peerInterface.PeerMessage.encodeDelimited({ type: peerInterface.SubServiceType.PING_PEER, - publicKey: this.peerManager.peerInfo.publicKey, + publicKey: this.getPeerInfo().publicKey, subMessage: signedPeerInfo.toString(), }).finish(); this.socket.send(encodedPeerMessage, 0, encodedPeerMessage.length, UDP_MULTICAST_PORT, UDP_MULTICAST_ADDR); @@ -96,9 +104,9 @@ class MulticastBroadcaster extends EventEmitter { const { publicKey: signingKey, type, subMessage } = peerInterface.PeerMessage.decodeDelimited(request); // only relevant if peer public key exists in store and type is of PING - if (!this.peerManager.hasPeer(signingKey)) { + if (!this.hasPeer(signingKey)) { throw Error('peer does not exist in store'); - } else if (this.peerManager.peerInfo.publicKey == signingKey) { + } else if (this.getPeerInfo().publicKey == signingKey) { throw Error('peer message is from self'); } else if (!(type == peerInterface.SubServiceType.PING_PEER)) { throw Error(`peer message is not of type PING, type is: ${peerInterface.SubServiceType[type]}`); @@ -108,14 +116,14 @@ class MulticastBroadcaster extends EventEmitter { const verifiedMessage = await this.keyManager.verifyData(subMessage, Buffer.from(signingKey)); const encodedMessage = stringToProtobuf(verifiedMessage.toString()); - const { publicKey, relayPublicKey, peerAddress, apiAddress } = peerInterface.PeerInfoMessage.decodeDelimited( + const { publicKey, rootCertificate, peerAddress, apiAddress } = peerInterface.PeerInfoMessage.decodeDelimited( encodedMessage, ); // construct a peer info object - const peerInfo = new PeerInfo(publicKey, relayPublicKey, peerAddress, apiAddress); + const peerInfo = new PeerInfo(publicKey, rootCertificate, peerAddress, apiAddress); // update the peer store - this.peerManager.updatePeer(peerInfo); + this.updatePeer(peerInfo); this.emit('found', publicKey); } catch (err) { diff --git a/src/peers/PeerInfo.ts b/src/peers/PeerInfo.ts index d98e5c08a..4f2cba2f3 100644 --- a/src/peers/PeerInfo.ts +++ b/src/peers/PeerInfo.ts @@ -1,3 +1,4 @@ +import crypto from 'crypto' import { AddressInfo } from 'net'; import { peerInterface } from '../../proto/js/Peer'; import { protobufToString, stringToProtobuf } from '../utils'; @@ -71,19 +72,19 @@ class Address { } class PeerInfo { - publicKey: string; - // Public key that the peer connection is relayed over - relayPublicKey?: string; + id: string + private readonlyPublicKey: string; + // peer root certificate for trusted connections + rootCertificate: string; // Address where all peer operations occur over (might be obscured by NAT) peerAddress?: Address; // Address over which the polykey HTTP API is server apiAddress?: Address; - constructor(publicKey: string, relayPublicKey?: string, peerAddress?: string, apiAddress?: string) { - this.publicKey = PeerInfo.formatPublicKey(publicKey); - if (relayPublicKey) { - this.relayPublicKey = PeerInfo.formatPublicKey(relayPublicKey); - } + constructor(publicKey: string, rootCertificate: string, peerAddress?: string, apiAddress?: string) { + this.readonlyPublicKey = PeerInfo.formatPublicKey(publicKey); + this.id = PeerInfo.publicKeyToId(this.readonlyPublicKey) + this.rootCertificate = PeerInfo.formatCertificate(rootCertificate) if (peerAddress) { const addr = Address.parse(peerAddress); this.peerAddress = addr; @@ -94,20 +95,39 @@ class PeerInfo { } } + public get publicKey() : string { + return this.readonlyPublicKey + } + + public set publicKey(publicKey: string) { + throw Error('cannot change public key once set') + } + + static publicKeyToId(publicKey: string) { + const formatedPublicKey = PeerInfo.formatPublicKey(publicKey) + return crypto.createHash('sha256').update(formatedPublicKey).digest('base64') + } + static formatPublicKey(str: string): string { const startString = '-----BEGIN PGP PUBLIC KEY BLOCK-----'; const endString = '-----END PGP PUBLIC KEY BLOCK-----'; return str.slice(str.indexOf(startString), str.indexOf(endString) + endString.length); } + static formatCertificate(str: string): string { + const startString = '-----BEGIN CERTIFICATE-----'; + const endString = '-----END CERTIFICATE-----'; + return str.slice(str.indexOf(startString), str.indexOf(endString) + endString.length); + } + deepCopy(): PeerInfo { - return new PeerInfo(this.publicKey, this.relayPublicKey, this.peerAddress?.toString(), this.apiAddress?.toString()); + return new PeerInfo(this.publicKey, this.rootCertificate, this.peerAddress?.toString(), this.apiAddress?.toString()); } toStringB64(): string { const message = peerInterface.PeerInfoMessage.encodeDelimited({ publicKey: this.publicKey, - relayPublicKey: this.relayPublicKey, + rootCertificate: this.rootCertificate, peerAddress: this.peerAddress?.toString(), apiAddress: this.apiAddress?.toString(), }).finish(); @@ -119,7 +139,7 @@ class PeerInfo { const decoded = peerInterface.PeerInfoMessage.decodeDelimited(message); - return new PeerInfo(decoded.publicKey, decoded.relayPublicKey, decoded.peerAddress, decoded.apiAddress); + return new PeerInfo(decoded.publicKey, decoded.rootCertificate, decoded.peerAddress, decoded.apiAddress); } } diff --git a/src/peers/PeerManager.ts b/src/peers/PeerManager.ts index b00074613..c70657ef1 100644 --- a/src/peers/PeerManager.ts +++ b/src/peers/PeerManager.ts @@ -1,11 +1,12 @@ import os from 'os'; import fs from 'fs'; import path from 'path'; -import TurnClient from './turn/TurnClient'; +import PeerDHT from './peer-dht/PeerDHT'; +import PeerInfo from '../peers/PeerInfo'; import KeyManager from '../keys/KeyManager'; import { peerInterface } from '../../proto/js/Peer'; -import PeerInfo from '../peers/PeerInfo'; import PeerServer from './peer-connection/PeerServer'; +import NatTraversal from './nat-traversal/NatTraversal'; import PeerConnection from './peer-connection/PeerConnection'; import MulticastBroadcaster from '../peers/MulticastBroadcaster'; @@ -32,10 +33,6 @@ const keybaseDiscovery: SocialDiscovery = { }, }; -type PeerManagerMetadata = { - peerInfo: PeerInfo | null; -}; - class PeerManager { private fileSystem: typeof fs; @@ -43,6 +40,7 @@ class PeerManager { private peerStoreMetadataPath: string; peerInfo: PeerInfo; + // peerId -> PeerInfo private peerStore: Map; private keyManager: KeyManager; multicastBroadcaster: MulticastBroadcaster; @@ -51,7 +49,8 @@ class PeerManager { // Peer connections peerServer: PeerServer; private peerConnections: Map; - turnClient: TurnClient; + peerDHT: PeerDHT; + natTraversal: NatTraversal; private stealthMode: boolean; @@ -67,8 +66,8 @@ class PeerManager { this.peerStore = new Map(); this.fileSystem.mkdirSync(polykeyPath, { recursive: true }); - this.peerInfoMetadataPath = path.join(polykeyPath, '.peerInfo'); - this.peerStoreMetadataPath = path.join(polykeyPath, '.peerStore'); + this.peerInfoMetadataPath = path.join(polykeyPath, '.peers', '.peerInfo'); + this.peerStoreMetadataPath = path.join(polykeyPath, '.peers', '.peerStore'); // Set given variables this.keyManager = keyManager; @@ -81,8 +80,8 @@ class PeerManager { if (peerInfo) { this.peerInfo = peerInfo; this.writeMetadata(); - } else if (this.keyManager.hasPublicKey()) { - this.peerInfo = new PeerInfo(this.keyManager.getPublicKey()); + } else if (this.keyManager.hasPublicKey() && !this.peerInfo) { + this.peerInfo = new PeerInfo(this.keyManager.getPublicKey(), this.keyManager.pki.RootCert); } this.socialDiscoveryServices = []; @@ -91,7 +90,12 @@ class PeerManager { this.socialDiscoveryServices.push(service); } - this.multicastBroadcaster = new MulticastBroadcaster(this, this.keyManager); + this.multicastBroadcaster = new MulticastBroadcaster( + (() => this.peerInfo).bind(this), + this.hasPeer.bind(this), + this.updatePeer.bind(this), + this.keyManager, + ); //////////// // Server // @@ -99,10 +103,36 @@ class PeerManager { this.peerServer = new PeerServer(this, this.keyManager); this.peerConnections = new Map(); - ///////////////// - // TURN Client // - ///////////////// - this.turnClient = new TurnClient(this); + ////////////// + // Peer DHT // + ////////////// + this.peerDHT = new PeerDHT( + () => this.peerInfo.id, + this.connectToPeer.bind(this), + ((id: string) => this.getPeer(id)).bind(this), + ((peerInfo: PeerInfo) => { + if (!this.hasPeer(peerInfo.id)) { + this.addPeer(peerInfo); + } + }).bind(this), + ); + this.peerDHT.addPeers(this.listPeers()); + this.natTraversal = new NatTraversal( + this.listPeers.bind(this), + this.getPeer.bind(this), + this.connectToPeer.bind(this), + (() => this.peerInfo).bind(this), + this.hasPeer.bind(this), + this.updatePeer.bind(this), + ); + this.setNatHandler(this.natTraversal.handleNatMessageGRPC.bind(this.natTraversal)); + } + + // Gets the status of the BackupService + public get Status() { + return { + stealthMode: this.stealthMode, + }; } toggleStealthMode(active: boolean) { @@ -130,11 +160,15 @@ class PeerManager { * @param peerInfo Info of the peer to be added */ addPeer(peerInfo: PeerInfo): void { - const publicKey = PeerInfo.formatPublicKey(peerInfo.publicKey); - if (this.hasPeer(publicKey)) { + const peerId = peerInfo.id; + if (this.hasPeer(peerId)) { throw Error('peer already exists in peer store'); } - this.peerStore.set(publicKey, peerInfo.deepCopy()); + if (peerId == this.peerInfo.id) { + throw Error('cannot add self to store'); + } + this.peerStore.set(peerInfo.id, peerInfo.deepCopy()); + this.peerDHT.addPeer(peerInfo.id); this.writeMetadata(); } @@ -143,35 +177,47 @@ class PeerManager { * @param peerInfo Info of the peer to be updated */ updatePeer(peerInfo: PeerInfo): void { - const publicKey = PeerInfo.formatPublicKey(peerInfo.publicKey); - if (!this.hasPeer(publicKey)) { + if (!this.hasPeer(peerInfo.id)) { throw Error('peer does not exist in peer store'); } - this.peerStore.set(publicKey, peerInfo.deepCopy()); + this.peerStore.set(peerInfo.id, peerInfo.deepCopy()); + this.writeMetadata(); + } + + /** + * Delete a peer from the peerStore + * @param peerInfo Info of the peer to be updated + */ + deletePeer(id: string): void { + if (!this.hasPeer(id)) { + throw Error('peer does not exist in peer store'); + } + this.peerStore.delete(id); + this.peerDHT.deletePeer(id) this.writeMetadata(); } /** * Retrieves a peer for the given public key - * @param publicKey Public key of the desired peer + * @param publicKey ID of the desired peer */ - getPeer(publicKey: string): PeerInfo | null { - return this.peerStore.get(PeerInfo.formatPublicKey(publicKey))?.deepCopy() ?? null; + getPeer(id: string): PeerInfo | null { + return this.peerStore.get(id)?.deepCopy() ?? null; } /** * Determines if the peerStore contains the desired peer - * @param publicKey Public key of the desired peer + * @param id ID of the desired peer */ - hasPeer(publicKey: string): boolean { - return this.peerStore.has(PeerInfo.formatPublicKey(publicKey)); + hasPeer(id: string): boolean { + return this.peerStore.has(id); } /** * List all peer public keys in the peer store */ listPeers(): string[] { - return Array.from(this.peerStore.values()).map((p) => p.publicKey); + return Array.from(this.peerStore.values()).map((p) => p.id); } ////////////////////// @@ -218,21 +264,28 @@ class PeerManager { * Get a secure connection to the peer * @param publicKey Public key of an existing peer or address of new peer */ - connectToPeer(publicKey: string): PeerConnection { + connectToPeer(peerId: string): PeerConnection { // Throw error if trying to connect to self - if (publicKey == this.peerInfo.publicKey) { + if (peerId == this.peerInfo.id) { throw Error('Cannot connect to self'); } - const existingSocket = this.peerConnections.get(publicKey); + const existingSocket = this.peerConnections.get(peerId); if (existingSocket) { return existingSocket; } // try to create a connection to the address - const peerConnection = new PeerConnection(publicKey, this.keyManager, this); + const peerConnection = new PeerConnection( + peerId, + this.keyManager, + (() => this.peerInfo).bind(this), + this.getPeer.bind(this), + this.peerDHT.findPeer.bind(this.peerDHT), + this.natTraversal.requestUDPHolePunch.bind(this), + ); - this.peerConnections.set(publicKey, peerConnection); + this.peerConnections.set(peerId, peerConnection); return peerConnection; } @@ -243,23 +296,26 @@ class PeerManager { } /* ============ HELPERS =============== */ - private writeMetadata(): void { + writeMetadata(): void { // write peer info - const peerInfo = this.peerInfo; const metadata = peerInterface.PeerInfoMessage.encodeDelimited({ - publicKey: peerInfo.publicKey, - peerAddress: peerInfo.peerAddress?.toString(), - relayPublicKey: peerInfo.relayPublicKey, + publicKey: this.peerInfo.publicKey, + rootCertificate: this.peerInfo.rootCertificate!, + peerAddress: this.peerInfo.peerAddress?.toString(), + apiAddress: this.peerInfo.apiAddress?.toString(), }).finish(); + + this.fileSystem.mkdirSync(path.dirname(this.peerInfoMetadataPath), { recursive: true }); this.fileSystem.writeFileSync(this.peerInfoMetadataPath, metadata); // write peer store const peerInfoList: peerInterface.PeerInfoMessage[] = []; - for (const [publicKey, peerInfo] of this.peerStore) { + for (const [_, peerInfo] of this.peerStore) { peerInfoList.push( new peerInterface.PeerInfoMessage({ publicKey: peerInfo.publicKey, + rootCertificate: peerInfo.rootCertificate!, peerAddress: peerInfo.peerAddress?.toString(), - relayPublicKey: peerInfo.relayPublicKey, + apiAddress: peerInfo.apiAddress?.toString(), }), ); } @@ -271,10 +327,10 @@ class PeerManager { // load peer info if path exists if (this.fileSystem.existsSync(this.peerInfoMetadataPath)) { const metadata = this.fileSystem.readFileSync(this.peerInfoMetadataPath); - const { publicKey, relayPublicKey, peerAddress, apiAddress } = peerInterface.PeerInfoMessage.decodeDelimited( + const { publicKey, rootCertificate, peerAddress, apiAddress } = peerInterface.PeerInfoMessage.decodeDelimited( metadata, ); - this.peerInfo = new PeerInfo(publicKey, relayPublicKey, peerAddress, apiAddress); + this.peerInfo = new PeerInfo(publicKey, rootCertificate, peerAddress, apiAddress); } // load peer store if path exists if (this.fileSystem.existsSync(this.peerStoreMetadataPath)) { @@ -283,11 +339,11 @@ class PeerManager { for (const peerInfoMessage of peerInfoList) { const peerInfo = new PeerInfo( peerInfoMessage.publicKey!, - peerInfoMessage.relayPublicKey ?? undefined, + peerInfoMessage.rootCertificate!, peerInfoMessage.peerAddress ?? undefined, peerInfoMessage.apiAddress ?? undefined, ); - this.peerStore.set(peerInfo.publicKey, peerInfo); + this.peerStore.set(peerInfo.id, peerInfo); } } } diff --git a/src/peers/nat-traversal/NatTraversal.ts b/src/peers/nat-traversal/NatTraversal.ts new file mode 100644 index 000000000..85845dbc8 --- /dev/null +++ b/src/peers/nat-traversal/NatTraversal.ts @@ -0,0 +1,449 @@ +import net from 'net' +import dgram from 'dgram' +import PeerInfo, { Address } from "../PeerInfo"; +import { EventEmitter } from 'events'; +import { promiseAll } from "../../utils"; +import { peerInterface } from "../../../proto/js/Peer"; +import { MTPConnection, MTPServer } from './micro-transport-protocol/MTPServer' +import PeerConnection from '../peer-connection/PeerConnection'; + +class NatTraversal extends EventEmitter { + private listPeers: () => string[]; + private getPeer: (id: string) => PeerInfo | null; + private connectToPeer: (id: string) => PeerConnection; + private getPeerInfo: () => PeerInfo; + private hasPeer: (id: string) => boolean; + private updatePeer: (peerInfo: PeerInfo) => void; + + server: MTPServer + + // peerId -> connection + private holePunchedConnections: Map = new Map + // peerId -> dgram.Socket + private pendingHolePunchedSockets: Map = new Map + // peerId -> tcp relay server + private outgoingTCPHolePunchedRelayServers: Map = new Map + // peerId -> peer relay servers + private peerTCPHolePunchedRelayServers: Map = new Map + // interval with which the server requests new direct hole punched connections + // from adjacent peers that are in the store but have not yet been requested yet + private intermittentConnectionInterval: NodeJS.Timeout + + constructor( + listPeers: () => string[], + getPeer: (id: string) => PeerInfo | null, + connectToPeer: (id: string) => PeerConnection, + getPeerInfo: () => PeerInfo, + hasPeer: (id: string) => boolean, + updatePeer: (peerInfo: PeerInfo) => void, + ) { + super() + + this.listPeers = listPeers + this.getPeer = getPeer + this.connectToPeer = connectToPeer + this.getPeerInfo = getPeerInfo + this.hasPeer = hasPeer + this.updatePeer = updatePeer + this.server = new MTPServer( + this.connectionHandler.bind(this), + this.handleNATMessageUDP.bind(this) + ) + this.server.listenPort(0, () => { + const address = this.server.address() + console.log(`main MTP server is now listening on address: '${address.toString()}'`); + }) + + // this is just to make sure every other peer has a back connection to this node + // the idea behind this is that if we are a node that is behind a NAT, then if + // another node wants to connect via an adjacent node were already connected to, + // then that node that has to be able to notify us of the connection attempt for + // coordination purposes. + // TODO: this should only be done if the node detects that it is behind a NAT layer + this.intermittentConnectionInterval = setInterval(async () => { + const promiseList: Promise[] = [] + for (const peerId of this.listPeers()) { + if (!this.server.incomingConnections.has(peerId)) { + const peerInfo = this.getPeer(peerId)! + const udpAddress = await this.requestUDPAddress(peerInfo.id) + promiseList.push(this.sendDirectHolePunchConnectionRequest(udpAddress)) + } + } + await promiseAll(promiseList) + }, 10000) + } + + // request the MTP UDP address of a peer + // there are only two addresses for a peer: + // 1) the tcp address which is where the raw gRPC service is exposed + // 2) the udp address which is where that gRPC service is relayed on using MTP + async requestUDPAddress(peerId: string): Promise
{ + const pc = this.connectToPeer(peerId) + + const request = peerInterface.NatMessage.encodeDelimited({ type: peerInterface.NatMessageType.UDP_ADDRESS }).finish() + const response = await pc.sendPeerRequest(peerInterface.SubServiceType.NAT_TRAVERSAL, request) + const { type, subMessage } = peerInterface.NatMessage.decodeDelimited(response) + if (type != peerInterface.NatMessageType.UDP_ADDRESS) { + throw Error('peer did not send back proper response') + } + const { address } = peerInterface.UDPAddressMessage.decodeDelimited(subMessage) + + return Address.parse(address) + } + + // This request will timeout after 'timeout' milliseconds (defaults to 10 seconds) + async requestUDPHolePunch(targetPeerId: string, adjacentPeerId: string, timeout: number = 10000): Promise
{ + return new Promise(async (resolve, reject) => { + setTimeout(() => reject(Error('hole punch connection request timed out')), timeout) + try { + if (!this.hasPeer(targetPeerId)) { + throw Error(`target peer id does not exist in store: ${targetPeerId}`) + } else if (!this.hasPeer(adjacentPeerId)) { + throw Error(`adjacent peer id does not exist in store: ${adjacentPeerId}`) + } + const udpAddress = await this.requestUDPAddress(adjacentPeerId) + await this.sendHolePunchRequest(udpAddress, targetPeerId) + + this.on('hole-punch-connection', (peerId: string, conn: MTPConnection) => { + // need to set up a local relay server between the new connection and the gRPC server! + // this will include 2 socket pipes: + // 1. one from the grpc connection to the local relay server (tcp packets) + // 2. another one from the local relay server to the hole punched server address (udp/mtp packets) + const newServer = net.createServer((tcpConn) => { + tcpConn.on('data', (data) => conn.write(data)) + conn.on('data', (data) => tcpConn.write(data)) + }).listen(0, '127.0.01', () => { + this.outgoingTCPHolePunchedRelayServers.set(peerId, newServer) + resolve(Address.fromAddressInfo(newServer.address())) + }) + }) + } catch (error) { + reject(error) + } + }) + } + + // This request will timeout after 'timeout' milliseconds (defaults to 10 seconds) + async requestUDPRelay(targetPeerId: string, adjacentPeerId: string, timeout: number = 10000): Promise
{ + return new Promise(async (resolve, reject) => { + setTimeout(() => reject(Error('relay connection request timed out')), timeout) + try { + if (!this.hasPeer(targetPeerId)) { + throw Error(`target peer id does not exist in store: ${targetPeerId}`) + } else if (!this.hasPeer(adjacentPeerId)) { + throw Error(`adjacent peer id does not exist in store: ${adjacentPeerId}`) + } + const udpAddress = await this.requestUDPAddress(adjacentPeerId) + await this.sendHolePunchRequest(udpAddress, targetPeerId) + + this.on('hole-punch-connection', (peerId: string, conn: MTPConnection) => { + // need to set up a local relay server between the new connection and the gRPC server! + // this will include 2 socket pipes: + // 1. one from the grpc connection to the local relay server (tcp packets) + // 2. another one from the local relay server to the hole punched server address (udp/mtp packets) + const newServer = net.createServer((tcpConn) => { + tcpConn.on('data', (data) => conn.write(data)) + conn.on('data', (data) => tcpConn.write(data)) + }).listen(0, '127.0.01', () => { + this.outgoingTCPHolePunchedRelayServers.set(peerId, newServer) + resolve(Address.fromAddressInfo(newServer.address())) + }) + }) + } catch (error) { + reject(error) + } + }) + } + + // ===================================================== // + // ================ initiation messages ================ // + // ===================================================== // + // these messages are the first step in nat traversal + // the handlers at the bottom of this file are the last step + // this method is for creating a direct hole punch from an + // adjacent peers back to this one in case of a restrictive NAT layer + // the resulting connection will be used in coordinating NAT traversal + // requests from other peers via the peer adjacent to this one + async sendDirectHolePunchConnectionRequest(udpAddress: Address) { + const message = peerInterface.PeerInfoMessage.encodeDelimited({ + publicKey: this.getPeerInfo().publicKey, + rootCertificate: this.getPeerInfo().rootCertificate, + peerAddress: this.getPeerInfo().peerAddress?.toString(), + apiAddress: this.getPeerInfo().apiAddress?.toString(), + }).finish() + this.sendNATMessage(udpAddress, peerInterface.NatMessageType.DIRECT_CONNECTION, message) + } + + // this request is for when the current node cannot connect directly + // to the target peer and wants to use an adjacent node. Note the adjacent + // node must also be known before requesting and that is what the udpAddress + // parameter is for + async sendHolePunchRequest(udpAddress: Address, targetPeerId: string) { + return new Promise((resolve, reject) => { + try { + // create socket + const socket = dgram.createSocket('udp4') + socket.bind() + socket.on('listening', () => { + // create request + const request = peerInterface.HolePunchConnectionMessage.encodeDelimited({ + originPeerId: this.getPeerInfo().id, + targetPeerId: targetPeerId, + udpAddress: Address.fromAddressInfo(socket.address()).toString() + }).finish() + + this.sendNATMessage(udpAddress, peerInterface.NatMessageType.HOLE_PUNCH_CONNECTION, request, socket) + resolve() + }) + + socket.on('message', (message: Buffer, rinfo: dgram.RemoteInfo) => { + const address = new Address(rinfo.address, rinfo.port) + this.handleNATMessageUDP(message, address) + }) + } catch (error) { + reject(error) + } + }) + } + + // this is just a convenience function to wrap a message in a NATMessage + private sendNATMessage(udpAddress: Address, type: peerInterface.NatMessageType, message: Uint8Array, socket?: dgram.Socket) { + const request = peerInterface.NatMessage.encodeDelimited({ + type, + subMessage: message + }).finish() + if (socket) { + socket.send(request, udpAddress.port, udpAddress.host) + } else { + this.server.socket.send(request, udpAddress.port, udpAddress.host) + } + } + + // ==== Handler Methods ==== // + connectionHandler(conn: MTPConnection) { + // first check if the connection is for nat message handler + // if it isn't try to send it to the gRPC service relayed via an internal MTP connection + const grpcAddress = this.getPeerInfo().peerAddress! + const grpcConn = net.createConnection({ port: grpcAddress?.port, host: grpcAddress?.host }) + grpcConn.on('data', (data) => conn.write(data)) + conn.on('data', async (data) => { + // first try the nat message handler, might be a hole punch or relay request + try { + return await this.handleNATMessageUDP(data, conn.address()) + } catch (error) { + // don't want to throw so just log + } + // this is now assumed to be a message for grpc so need to pipe it over + grpcConn.write(data) + }) + } + + async handleNatMessageGRPC(request: Uint8Array): Promise { + const { type, subMessage } = peerInterface.NatMessage.decodeDelimited(request); + let response: Uint8Array; + switch (type) { + case peerInterface.NatMessageType.UDP_ADDRESS: + { + response = peerInterface.UDPAddressMessage.encodeDelimited({ + address: this.server.address().toString(), + }).finish(); + } + break; + case peerInterface.NatMessageType.DIRECT_CONNECTION: + throw Error('not implemented') + break; + case peerInterface.NatMessageType.HOLE_PUNCH_CONNECTION: + throw Error('not implemented') + break; + case peerInterface.NatMessageType.RELAY_CONNECTION: + // the relay connection request will come through the grpc channel + response = await this.handleRelayRequest(subMessage) + break; + default: { + throw Error('git message type not supported'); + } + } + // encode a git response + return peerInterface.NatMessage.encodeDelimited({ type, subMessage: response }).finish(); + } + + private async handleNATMessageUDP(message: Buffer, address: Address) { + const { type, isResponse, subMessage } = peerInterface.NatMessage.decodeDelimited(message) + switch (type) { + case peerInterface.NatMessageType.UDP_ADDRESS: + throw Error('message type not supported via udp, try grpc connection') + case peerInterface.NatMessageType.DIRECT_CONNECTION: + await this.handleDirectConnectionRequest(address, isResponse, subMessage) + break; + case peerInterface.NatMessageType.HOLE_PUNCH_CONNECTION: + await this.handleHolePunchRequest(address, isResponse, subMessage) + break; + case peerInterface.NatMessageType.RELAY_CONNECTION: + throw Error('message type not supported via udp, try grpc connection') + break; + default: + break; + } + } + + private async handleDirectConnectionRequest(address: Address, isResponse: boolean, request: Uint8Array) { + const { + publicKey, + rootCertificate, + peerAddress, + apiAddress + } = peerInterface.PeerInfoMessage.decodeDelimited(request) + const peerInfo = new PeerInfo(publicKey, rootCertificate, peerAddress, apiAddress) + if (this.hasPeer(peerInfo.id)) { + this.updatePeer(peerInfo) + } + + if (!isResponse) { + // create a punched connection + const conn = MTPConnection.connect(this.getPeerInfo().id, address.port, address.host) + // write back response + const subMessage = peerInterface.DirectConnectionMessage.encodeDelimited({ peerId: this.getPeerInfo().id }).finish() + const response = peerInterface.NatMessage.encodeDelimited({ + type: peerInterface.NatMessageType.DIRECT_CONNECTION, + isResponse: true, + subMessage + }).finish() + conn.write(response) + this.holePunchedConnections.set(peerInfo.id, conn) + } + } + + private async handleHolePunchRequest(address: Address, isResponse: boolean, request: Uint8Array) { + return await new Promise(async (resolve, reject) => { + const { originPeerId, targetPeerId, udpAddress } = peerInterface.HolePunchConnectionMessage.decodeDelimited(request) + // TODO: make sure origin peer id is known + const parsedAddress = Address.parse(udpAddress) + if (isResponse) { + // case: hole punch has already been requested and adjacent peer has returned a message + if (this.pendingHolePunchedSockets.has(targetPeerId)) { + throw Error(`there are no pending hole punching requests for peerId: ${targetPeerId}`) + } + // set a timeout + const timeout = 10000 + setTimeout(() => reject(Error(`hole punching request timed out after ${timeout / 1000}s`)), timeout) + // now we can start sending packets to the target for creating the entry in the translation table + const socket = this.pendingHolePunchedSockets.get(targetPeerId)! + // send a message at interval for creating the entry in the translation table + // TODO: not sure if its completely necessary to do this multiple times + const conn = MTPConnection.connect(this.getPeerInfo().id, parsedAddress.port, parsedAddress.host, socket) + + while (conn.connecting) { + await new Promise((r, _) => setTimeout(() => r(), 1000)) + } + + this.emit('hole-punch-connection', targetPeerId, conn) + + resolve() + } else { + if (targetPeerId == this.getPeerInfo().id) { + // case: some other node is trying to connect to this node via an adjacent node + // start sending packets to udpAddress to create entry in NAT translation table + this.server.socket.send(this.getPeerInfo().id, parsedAddress.port, parsedAddress.host) + // send a message at interval for creating the entry in the translation table + // TODO: not sure if its completely necessary to do this multiple times + const sendPacketInterval = setInterval(() => { + // check if node has already connected + // okay to just send peerId of current node + this.server.socket.send(this.getPeerInfo().id, parsedAddress.port, parsedAddress.host) + }, 1000) + + while (!this.server.incomingConnections.has(originPeerId)) { + // check if connection has been made + await new Promise((r, _) => setTimeout(() => r(), 1000)) + } + // if our code has reached here, the origin peer's hole punch has been successful! + clearInterval(sendPacketInterval) + } else { + // case: this node is the adjacent node and target peer is assumed to be connected to this node + // first check if adjacent peer has a hole punched connection for coordination, if not then throw + if (this.holePunchedConnections.has(targetPeerId)) { + // if this node has a connection to target peer, then tell the target peer to initiate a connection with the origin peer! + const targetConn = this.holePunchedConnections.get(targetPeerId)! + const targetSubMessage = peerInterface.HolePunchConnectionMessage.encodeDelimited({ + originPeerId: originPeerId, + targetPeerId: targetPeerId, + udpAddress: address?.toString() + }).finish() + const targetRequest = peerInterface.NatMessage.encodeDelimited({ + type: peerInterface.NatMessageType.HOLE_PUNCH_CONNECTION, + subMessage: targetSubMessage + }).finish() + targetConn.write(targetRequest) + + // finally tell the origin peer the target peers udp address + const originSubMessage = peerInterface.HolePunchConnectionMessage.encodeDelimited({ + originPeerId: originPeerId, + targetPeerId: targetPeerId, + udpAddress: targetConn.address().toString() + }).finish() + const originRequest = peerInterface.NatMessage.encodeDelimited({ + type: peerInterface.NatMessageType.HOLE_PUNCH_CONNECTION, + isResponse: true, + subMessage: originSubMessage + }).finish() + this.server.socket.send(originRequest, address.port, address.host, (err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + } else { + throw Error('no connection exists to target peer so cannot coordinate hole punching') + } + } + } + }) + } + + private async handleRelayRequest(request: Uint8Array): Promise { + return await new Promise(async (resolve, reject) => { + try { + const { originPeerId, targetPeerId } = peerInterface.RelayConnectionMessage.decodeDelimited(request) + // first check if there is already a relay set up for the peer + if (this.peerTCPHolePunchedRelayServers.has(targetPeerId)) { + const addressInfo = this.peerTCPHolePunchedRelayServers.get(targetPeerId)!.address() + const relayAddress = Address.fromAddressInfo(addressInfo).toString() + const response = peerInterface.RelayConnectionMessage.encodeDelimited({ + originPeerId: originPeerId, + targetPeerId: targetPeerId, + relayAddress: relayAddress + }).finish() + resolve(response) + } else { + // otherwise we need to make sure tell target peer to setup a relay + if (!this.holePunchedConnections.has(targetPeerId)) { + throw Error(`no hole punched connection exists to target peer id: ${targetPeerId}`) + } + const udpConnection = this.holePunchedConnections.get(targetPeerId)! + + const newRelayServer = net.createServer((newConn) => { + udpConnection.on('data', (data) => newConn.write(data)) + newConn.on('data', (data) => udpConnection.write(data)) + }).listen(0, '0.0.0.0', () => { + // set the server + this.peerTCPHolePunchedRelayServers.set(targetPeerId, newRelayServer) + // send the address back to the origin peer + const addressInfo = newRelayServer.address() + const relayAddress = Address.fromAddressInfo(addressInfo).toString() + const response = peerInterface.RelayConnectionMessage.encodeDelimited({ + originPeerId: originPeerId, + targetPeerId: targetPeerId, + relayAddress: relayAddress + }).finish() + resolve(response) + }) + } + } catch (error) { + reject(error) + } + }) + } +} + +export default NatTraversal diff --git a/src/peers/nat-traversal/micro-transport-protocol/MTPConnection.ts b/src/peers/nat-traversal/micro-transport-protocol/MTPConnection.ts new file mode 100644 index 000000000..7398a8833 --- /dev/null +++ b/src/peers/nat-traversal/micro-transport-protocol/MTPConnection.ts @@ -0,0 +1,420 @@ + +import cyclist from 'cyclist' +import dgram from 'dgram' +import { Duplex } from 'readable-stream'; +import { Address } from '../../PeerInfo'; +import { + BUFFER_SIZE, + uint16, + UINT16, + PACKET_STATE, + PACKET_SYN, + PACKET_FIN, + CLOSE_GRACE, + PACKET_DATA, + MTU, + uint32, + PACKET_RESET, + VERSION, + EXTENSION, + DEFAULT_WINDOW_SIZE, + MIN_PACKET_SIZE, + bufferToPacket, + packetToBuffer +} from './utils' +import { peerInterface } from '../../../../proto/js/Peer'; + +class MTPConnection extends Duplex { + private peerId: string; + + private port: number; + private host: string; + socket: dgram.Socket; + remoteAddress: Address; + private outgoing: any; + private incoming: any; + closed: boolean; + private inflightPackets: number; + private alive: boolean; + connecting: boolean; + private recvId: number; + public get RecvID(): number { + return this.recvId; + } + + private sendId: number; + private seq: number; + private ack: number; + private synack?: peerInterface.MTPPacket; + + + + constructor(peerId: string, port: number, host: string, socket: dgram.Socket, syn?: peerInterface.MTPPacket) { + super(); + + this.peerId = peerId + + this.remoteAddress = new Address(host, port); + + if (isNaN(port)) { + throw Error('port cannot be NaN'); + } + this.port = port; + this.host = host; + this.socket = socket; + + this.outgoing = cyclist(BUFFER_SIZE); + this.incoming = cyclist(BUFFER_SIZE); + this.closed = false; + + this.inflightPackets = 0; + this.closed = false; + this.alive = false; + + if (syn) { + this.connecting = false; + this.recvId = uint16(syn.connection + 1); + this.sendId = syn.connection; + this.seq = (Math.random() * UINT16) | 0; + this.ack = syn.seq; + this.synack = MTPConnection.createPacket( + this.peerId, + this.recvId, + this.sendId, + this.seq, + this.ack, + PACKET_STATE, + null + ); + + this.transmit(this.synack); + } else { + this.connecting = true; + this.recvId = 0; // tmp value for v8 opt + this.sendId = 0; // tmp value for v8 opt + this.seq = (Math.random() * UINT16) | 0; + this.ack = 0; + this.synack = undefined; + + socket.on('listening', () => { + this.recvId = socket.address().port; // using the port gives us system wide clash protection + this.sendId = uint16(this.recvId + 1); + + const initialPacket = MTPConnection.createPacket( + this.peerId, + this.recvId, + this.sendId, + this.seq, + this.ack, + PACKET_SYN, + null + ); + + this.sendOutgoing(initialPacket); + }) + + socket.on('error', (err) => { + this.emit('error', err); + }); + + socket.bind(); + } + + const resend = setInterval(this.resend.bind(this), 500); + const keepAlive = setInterval(this.keepAlive.bind(this), 10 * 1000); + let tick = 0; + + const closed = () => { + if (++tick === 2) { + this.closing(); + } + }; + + const sendFin = () => { + if (this.connecting) { + return this.once('connect', sendFin); + } + this.sendOutgoing(MTPConnection.createPacket( + this.peerId, + this.recvId, + this.sendId, + this.seq, + this.ack, + PACKET_FIN, + null + )); + this.once('flush', closed); + }; + + this.once('finish', sendFin); + this.once('close', () => { + if (!syn) { + setTimeout(socket.close.bind(socket), CLOSE_GRACE); + } + clearInterval(resend); + clearInterval(keepAlive); + }); + this.once('end', () => { + process.nextTick(closed); + }); + } + + destroy(err?: Error | undefined, callback?: ((error: Error | null) => void) | undefined) { + this.end(); + return this; + } + + address() { + return new Address(this.host, this.port); + } + + _read() { + // do nothing... + } + + _write(data: any[], enc: string, callback: (error?: Error | null | undefined) => void): void { + if (this.connecting) { + return this.writeOnce('connect', data, enc, callback); + } + + while (this._writable) { + const payload = this.payload(data); + this.sendOutgoing(MTPConnection.createPacket( + this.peerId, + this.recvId, + this.sendId, + this.seq, + this.ack, + PACKET_DATA, + payload + )); + + if (payload.length === data.length) { + return callback(); + } + data = data.slice(payload.length); + } + + this.writeOnce('flush', data, enc, callback); + } + + private writeOnce(event, data, enc, callback) { + this.once(event, () => { + this._write(data, enc, callback); + }); + } + + + public _writable(): boolean { + return this.inflightPackets < BUFFER_SIZE - 1; + } + + private payload(data) { + if (data.length > MTU) { + return data.slice(0, MTU); + } + return data; + } + + private resend() { + const offset = this.seq - this.inflightPackets; + const first = this.outgoing.get(offset); + if (!first) { + return; + } + + const timeout = 500000; + const now = MTPConnection.timestamp(); + + if (uint32(first.sent - now) < timeout) { + return; + } + + for (let i = 0; i < this.inflightPackets; i++) { + const packet = this.outgoing.get(offset + i); + if (uint32(packet.sent - now) >= timeout) { + this.transmit(packet); + } + } + } + + private keepAlive() { + if (this.alive) { + return (this.alive = false); + } + this.sendAck(); + } + + private closing() { + if (this.closed) { + return; + } + this.closed = true; + process.nextTick(this.emit.bind(this, 'close')); + } + + // packet handling + private recvAck(ack: number) { + const offset = this.seq - this.inflightPackets; + const acked = uint16(ack - offset) + 1; + + if (acked >= BUFFER_SIZE) { + return; // sanity check + } + + for (let i = 0; i < acked; i++) { + this.outgoing.del(offset + i); + this.inflightPackets--; + } + + if (!this.inflightPackets) { + this.emit('flush'); + } + } + + recvIncoming(packet: peerInterface.MTPPacket) { + if (this.closed) { + return; + } + + if (packet.id === PACKET_SYN && this.connecting) { + this.transmit(this.synack!); + return; + } + + if (packet.id === PACKET_RESET) { + this.push(null); + this.end(); + this.closing(); + return; + } + + if (this.connecting) { + if (packet.id !== PACKET_STATE) { + return this.incoming.put(packet.seq, packet); + } + + this.ack = uint16(packet.seq - 1); + this.recvAck(packet.ack); + this.connecting = false; + this.emit('connect'); + + packet = this.incoming.del(packet.seq); + if (!packet) { + return; + } + } + + if (uint16(packet.seq - this.ack) >= BUFFER_SIZE) { + return this.sendAck(); // old packet + } + + this.recvAck(packet.ack); // TODO: other calcs as well + + if (packet.id === PACKET_STATE) { + return; + } + this.incoming.put(packet.seq, packet); + + while ((packet = this.incoming.del(this.ack + 1))) { + this.ack = uint16(this.ack + 1); + + if (packet.id === PACKET_DATA) { + this.push(packet.data); + } + if (packet.id === PACKET_FIN) { + this.push(null); + } + } + + this.sendAck(); + } + + private sendAck() { + const packet = MTPConnection.createPacket( + this.peerId, + this.recvId, + this.sendId, + this.seq, + this.ack, + PACKET_STATE, + null + ) + this.transmit(packet); // TODO: make this delayed + } + + private sendOutgoing(packet) { + this.outgoing.put(packet.seq, packet); + this.seq = uint16(this.seq + 1); + this.inflightPackets++; + this.transmit(packet); + } + + private transmit(packet: peerInterface.MTPPacket) { + try { + packet.sent = packet.sent === 0 ? packet.timestamp : MTPConnection.timestamp(); + const message = packetToBuffer(packet); + this.alive = true; + this.socket.send(message, 0, message.length, this.port, this.host); + } catch (error) { } + } + + // ==== Helper methods ==== // + public static createPacket( + peerId: string, + recvId: number, + sendId: number, + seq: number, + ack: number, + id: number, + data: Uint8Array | null + ): peerInterface.MTPPacket { + return new peerInterface.MTPPacket({ + id: id, + peerId: peerId, + connection: id === PACKET_SYN ? recvId : sendId, + seq: seq, + ack: ack, + timestamp: MTPConnection.timestamp(), + timediff: 0, + window: DEFAULT_WINDOW_SIZE, + data: data ? data : undefined, + sent: 0, + }) + }; + + public static timestamp = (() => { + const offset = process.hrtime(); + const then = Date.now() * 1000; + return () => { + const diff = process.hrtime(offset); + return uint32(then + 1000000 * diff[0] + ((diff[1] / 1000) | 0)); + } + })() + + public static connect(localPeerId: string, port: number, host?: string, socket: dgram.Socket = dgram.createSocket('udp4')) { + const connection = new MTPConnection(localPeerId, port, host || '127.0.0.1', socket); + + socket.on('message', (message) => { + + if (message.length < MIN_PACKET_SIZE) { + return; + } + + const packet = bufferToPacket(message); + if (packet.id === PACKET_SYN) { + return; + } + + if (packet.connection !== connection.RecvID) { + return; + } + + connection.recvIncoming(packet); + }); + + return connection; + } +} + +export default MTPConnection diff --git a/src/peers/nat-traversal/micro-transport-protocol/MTPServer.ts b/src/peers/nat-traversal/micro-transport-protocol/MTPServer.ts new file mode 100644 index 000000000..5be8a7fde --- /dev/null +++ b/src/peers/nat-traversal/micro-transport-protocol/MTPServer.ts @@ -0,0 +1,136 @@ +// adapted from https://github.com/mafintosh/utp +import net from 'net'; +import dgram from 'dgram'; +import { EventEmitter } from 'events'; +import { Address } from '../../PeerInfo'; +import MTPConnection from './MTPConnection'; +import { + PACKET_SYN, + MIN_PACKET_SIZE, + bufferToPacket, +} from './utils' + +class MTPServer extends EventEmitter { + socket: dgram.Socket; + closed: boolean; + + // peerId -> connection + incomingConnections: Map; + tertiaryMessageHandler?: (message: Uint8Array, address: Address) => Promise + + constructor( + handleIncomingConnection: (conn: MTPConnection) => void, + tertiaryMessageHandler?: (message: Uint8Array, address: Address) => Promise, + ) { + super(); + this.tertiaryMessageHandler = tertiaryMessageHandler + + this.on('connection', handleIncomingConnection); + + this.incomingConnections = new Map; + } + + + // this is the udp address for the MTP server + address() { + return Address.fromAddressInfo(this.socket.address()); + } + + // this is the method where both listenConnection and listPort call + private listenSocket(socket: dgram.Socket, onListening: (address: Address) => void) { + this.socket = socket; + + socket.on('message', (message, rinfo) => this.handleMessage(message, rinfo)); + + socket.once('listening', () => { + onListening(this.address()) + }); + } + + // can either listen on an existing connection + listenConnection(connection: MTPConnection, onListening: (address: Address) => void) { + this.listenSocket(connection.socket, onListening); + } + + // or listen on a port + listenPort(port: number, onListening: (address: Address) => void) { + const socket = dgram.createSocket('udp4'); + this.listenSocket(socket, onListening); + socket.bind(port); + } + + close(cb: () => void) { + let openConnections = 0; + this.closed = true; + + const onClose = () => { + if (--openConnections === 0) { + if (this.socket) { + this.socket.close(); + } + if (cb) { + cb(); + } + } + } + + for (const id in this.incomingConnections.keys()) { + const connection = this.incomingConnections.get(id) + if (!connection) { + this.incomingConnections.delete(id) + continue + } + if (this.incomingConnections.get(id)?.closed) { + continue; + } + openConnections++; + connection.once('close', onClose); + connection.end(); + } + } + + // ==== Handler Methods ==== // + private async handleMessage(message: Buffer, rinfo: dgram.RemoteInfo) { + // ================================// + // handle additional request handler + // ================================// + if (this.tertiaryMessageHandler) { + try { + const address = new Address(rinfo.address, rinfo.port) + return await this.tertiaryMessageHandler(message, address) + } catch (error) { + // if anything went wrong, assume it is a direct connection request and move on + } + } + + // ============================================================================// + // handle all other messages! they are direct connection requests to gRPC server + // ============================================================================// + if (message.length < MIN_PACKET_SIZE) { + return; + } + const packet = bufferToPacket(message); + + // // not sure if this id is required but it has now been replaced with peerId pending further testing: + // const id = rinfo.address + ':' + (packet.id === PACKET_SYN ? uint16(packet.connection + 1) : packet.connection); + + const peerId = packet.peerId + if (this.incomingConnections.has(peerId) && this.incomingConnections.get(peerId)) { + return this.incomingConnections.get(peerId)!.recvIncoming(packet); + } + if (packet.id !== PACKET_SYN || this.closed) { + return; + } + + const newConnection = new MTPConnection(peerId, rinfo.port, rinfo.address, this.socket, packet) + this.incomingConnections.set(peerId, newConnection) + newConnection.on('close', () => { + this.incomingConnections.delete(peerId); + }); + + this.emit('connection', newConnection); + } +} + + +export { MTPConnection, MTPServer }; diff --git a/src/peers/nat-traversal/micro-transport-protocol/utils.ts b/src/peers/nat-traversal/micro-transport-protocol/utils.ts new file mode 100644 index 000000000..ca7dd37b5 --- /dev/null +++ b/src/peers/nat-traversal/micro-transport-protocol/utils.ts @@ -0,0 +1,56 @@ +import { peerInterface } from "../../../../proto/js/Peer"; + +const EXTENSION = 0; +const VERSION = 1; +const UINT16 = 0xffff; +const ID_MASK = 0xf << 4; +const MTU = 1400; + +const PACKET_DATA = 0 << 4; +const PACKET_FIN = 1 << 4; +const PACKET_STATE = 2 << 4; +const PACKET_RESET = 3 << 4; +const PACKET_SYN = 4 << 4; + +const MIN_PACKET_SIZE = 20; +const DEFAULT_WINDOW_SIZE = 1 << 18; +const CLOSE_GRACE = 5000; + +const BUFFER_SIZE = 512; + +const uint32 = function (n) { + return n >>> 0; +}; + +const uint16 = function (n) { + return n & UINT16; +}; + +function bufferToPacket(buffer: Uint8Array): peerInterface.MTPPacket { + return peerInterface.MTPPacket.decodeDelimited(buffer) +}; + +function packetToBuffer(packet: peerInterface.MTPPacket): Uint8Array { + return peerInterface.MTPPacket.encodeDelimited(packet).finish() +}; + +export { + EXTENSION, + VERSION, + UINT16, + ID_MASK, + MTU, + PACKET_DATA, + PACKET_FIN, + PACKET_STATE, + PACKET_RESET, + PACKET_SYN, + MIN_PACKET_SIZE, + DEFAULT_WINDOW_SIZE, + CLOSE_GRACE, + BUFFER_SIZE, + uint32, + uint16, + bufferToPacket, + packetToBuffer +} diff --git a/src/peers/nat-traversal/stages.md b/src/peers/nat-traversal/stages.md new file mode 100644 index 000000000..b26bb62c5 --- /dev/null +++ b/src/peers/nat-traversal/stages.md @@ -0,0 +1,8 @@ +the first stage is having both clients connect to a known intermediary peer via udp. So this would require there being a MTP relay server and that the public node can retransmit connection requests back to that MTP address + +1) create a direct hole punch with every peer and keep it alive: +- send peer your udp address via tcp +- it will respond with its udp address +- you will send a ping packet with public key attached to peers' udp address +- peer will receive that packet and open a connection back through the address it saw and store it as an open connection against your public key +- peer will send back ping message confirming connection and you will store that socket as diff --git a/src/peers/peer-connection/PeerConnection.ts b/src/peers/peer-connection/PeerConnection.ts index 949f4a27b..e8bb5b780 100644 --- a/src/peers/peer-connection/PeerConnection.ts +++ b/src/peers/peer-connection/PeerConnection.ts @@ -1,113 +1,145 @@ -import PeerInfo from '../PeerInfo'; +import PeerInfo, { Address } from '../PeerInfo'; import { randomBytes } from 'crypto'; import * as grpc from '@grpc/grpc-js'; -import PeerManager from '../PeerManager'; import KeyManager from '../../keys/KeyManager'; -import { stringToProtobuf, protobufToString } from '../../utils'; import { PeerClient } from '../../../proto/compiled/Peer_grpc_pb'; +import { stringToProtobuf, protobufToString, promiseAny } from '../../utils'; import { PeerMessage, SubServiceType } from '../../../proto/compiled/Peer_pb'; class PeerConnection { - private publicKey: string; + private peerId: string; private keyManager: KeyManager; - private peerManager: PeerManager; + private getPeerInfo: () => PeerInfo; + private getPeer: (id: string) => PeerInfo | null; + private findPeerDHT: ( + peerId: string, + ) => Promise<{ adjacentPeerInfo?: PeerInfo | undefined; targetPeerInfo?: PeerInfo | undefined }>; + private requestUDPHolePunch: ( + targetPeerId: string, + adjacentPeerId: string, + timeout?: number | undefined, + ) => Promise
; private peerClient: PeerClient; private connected: boolean = false; private credentials: grpc.ChannelCredentials; - constructor(publicKey: string, keyManager: KeyManager, peerManager: PeerManager) { - this.publicKey = publicKey; + constructor( + peerId: string, + keyManager: KeyManager, + getLocalPeerInfo: () => PeerInfo, + getPeer: (id: string) => PeerInfo | null, + findPeerDHT: ( + peerId: string, + ) => Promise<{ + adjacentPeerInfo?: PeerInfo | undefined; + targetPeerInfo?: PeerInfo | undefined; + }>, + requestUDPHolePunch: (targetPeerId: string, adjacentPeerId: string, timeout?: number) => Promise
, + ) { + this.peerId = peerId; this.keyManager = keyManager; - this.peerManager = peerManager; - - const credentials = this.keyManager.pki?.TLSClientCredentials; - if (credentials) { - this.credentials = grpc.ChannelCredentials.createSsl( - Buffer.from(credentials.rootCertificate), - Buffer.from(credentials.keypair.private), - Buffer.from(credentials.certificate), - ); - } else { - this.credentials = grpc.credentials.createInsecure(); - } + this.getPeerInfo = getLocalPeerInfo; + this.getPeer = getPeer; + this.findPeerDHT = findPeerDHT; + this.requestUDPHolePunch = requestUDPHolePunch; + + const credentials = this.keyManager.pki.TLSClientCredentials; + const peerInfo = this.getPeer(peerId); + this.credentials = grpc.ChannelCredentials.createInsecure(); + // this.credentials = grpc.ChannelCredentials.createSsl( + // Buffer.from(peerInfo!.rootCertificate), + // Buffer.from(credentials.keypair.private), + // Buffer.from(credentials.certificate), + // ); } + // 1st connection option: peerInfo already in peerStore and peerAddress is connected private async connectDirectly(): Promise { // try to create a direct connection - if (this.getPeerInfo().peerAddress) { + if (this.getPeer(this.peerId)!.peerAddress) { // direct connection attempt - const address = this.getPeerInfo().peerAddress!; + const address = this.getPeer(this.peerId)!.peerAddress!; const peerClient = new PeerClient(address.toString(), this.credentials); this.connected = true; return peerClient; - } else if (!this.getPeerInfo().peerAddress) { - throw Error('peer does not have a connected address'); } else { - throw Error('peer is already connected'); + throw Error('peer does not have a connected address'); + } + } + + // 2nd connection option: kademlia dht + private async connectDHT(): Promise { + // try to find peer directly from intermediary peers + const { targetPeerInfo, adjacentPeerInfo } = await this.findPeerDHT(this.getPeer(this.peerId)!.id); + // const { targetPeerInfo, adjacentPeerInfo } = await this.peerManager..findPeer(this.getPeer(this.peerId)!.id); + if (targetPeerInfo?.peerAddress) { + try { + // case 1: target peer has been found and has a peerAddress + const address = targetPeerInfo.peerAddress; + const peerClient = new PeerClient(address.toString(), this.credentials); + this.connected = true; + return peerClient; + } catch (error) { + // don't want to throw, just try next method + } } + + if (adjacentPeerInfo?.peerAddress) { + // case 2: target peer has an adjacent peer that can be contacted for nat traversal + const promiseList = [this.connectHolePunch(adjacentPeerInfo), this.connectRelay(adjacentPeerInfo)]; + const client = await promiseAny(promiseList); + return client; + } + throw Error('could not find peer via dht'); } - private async connectHolePunch(): Promise { + // 3rd connection option: hole punch facilitated by a peer adjacent (i.e. connected) to the target peer + // triggered by 2nd option + private async connectHolePunch(adjacentPeerInfo: PeerInfo): Promise { // try to hole punch to peer via relay peer - if (!this.connected && this.getPeerInfo().relayPublicKey) { + if (adjacentPeerInfo.peerAddress) { // connect to relay and ask it to create a relay - console.log('requesting udp hole punch connection'); - const connectedAddress = await this.peerManager.turnClient.requestHolePunchConnection( - this.getPeerInfo().relayPublicKey!, - this.getPeerInfo().publicKey, + const connectedAddress = await this.requestUDPHolePunch( + this.getPeer(this.peerId)!.id, + adjacentPeerInfo.id, + 10000, ); const peerClient = new PeerClient(connectedAddress.toString(), this.credentials); this.connected = true; return peerClient; - } else if (!this.getPeerInfo().relayPublicKey) { - throw Error('peer does not have relay public key specified'); } else { throw Error('peer is already connected'); } } - private async connectRelay(): Promise { - // try to relay to peer via relay peer - if (!this.connected && this.getPeerInfo().relayPublicKey) { - // turn relay + // 4th connection option: relay connection facilitated by a peer adjacent (i.e. connected) to the target peer + // triggered by 2nd option + private async connectRelay(adjacentPeerInfo: PeerInfo): Promise { + // try to hole punch to peer via relay peer + if (adjacentPeerInfo.peerAddress) { // connect to relay and ask it to create a relay - const connectedAddress = await this.peerManager.turnClient.requestPeerConnection( - this.getPeerInfo().publicKey, - this.getPeerInfo().relayPublicKey!, + const connectedAddress = await this.requestUDPHolePunch( + this.getPeer(this.peerId)!.id, + adjacentPeerInfo.id, + 10000, ); const peerClient = new PeerClient(connectedAddress.toString(), this.credentials); + this.connected = true; return peerClient; - } else if (!this.getPeerInfo().relayPublicKey) { - throw Error('peer does not have relay public key specified'); } else { throw Error('peer is already connected'); } } async connectFirstChannel() { - return await new Promise((resolve, reject) => { - const promiseList = [this.connectDirectly(), this.connectHolePunch(), this.connectRelay()]; - - const errorList: Error[] = []; - for (const promise of promiseList) { - promise - .then((p) => { - resolve(p); - }) - .catch((error) => null); - - promise.catch((error) => { - errorList.push(error); - // check if all have failed - if (errorList.length == promiseList.length) { - reject(errorList); - } - }); - } - }); + if (!this.connected) { + const promiseList = [this.connectDirectly(), this.connectDHT()]; + return await promiseAny(promiseList); + } + throw Error('peer is already connected!'); } private async connect(): Promise { @@ -130,19 +162,12 @@ class PeerConnection { } } - private getPeerInfo() { - if (!this.peerManager.hasPeer(this.publicKey)) { - throw Error('peer does not exist in peer store'); - } - return this.peerManager.getPeer(this.publicKey)!; - } - - private async sendPingRequest(timeout?: number): Promise { + private async sendPingRequest(timeout?: number, directConnectionOnly: boolean = false): Promise { // eslint-disable-next-line - return await new Promise(async (resolve, reject) => { + return await new Promise(async (resolve, _) => { try { if (timeout) { - setTimeout(() => reject('ping timed out'), timeout); + setTimeout(() => resolve(false), timeout); } const challenge = randomBytes(16).toString('base64'); @@ -150,24 +175,28 @@ class PeerConnection { // encode request const peerRequest = await this.encodeRequest(SubServiceType.PING_PEER, stringToProtobuf(challenge)); + let peerClient: PeerClient; + if (directConnectionOnly) { + peerClient = await this.connectDirectly(); + } else { + peerClient = this.peerClient; + } + // send request - const peerResponse = await new Promise((resolve, reject) => { - this.peerClient.messagePeer(peerRequest, (err, response) => { - if (err) { - reject(err); - } else { - resolve(response); - } - }); + peerClient.messagePeer(peerRequest, async (error, peerResponse) => { + if (error) { + console.log(error); + resolve(false); + } else { + // decode response + const { type: responseType, response } = await this.decodeResponse(peerResponse); + const challengeResponse = protobufToString(response); + resolve(challenge == challengeResponse); + } }); - - // decode response - const { type: responseType, response } = await this.decodeResponse(peerResponse); - const challengeResponse = protobufToString(response); - - resolve(challenge == challengeResponse); } catch (error) { - reject(error); + console.log(error); + resolve(false); } }); } @@ -208,14 +237,17 @@ class PeerConnection { private async encodeRequest(type: SubServiceType, request: Uint8Array): Promise { // encrypt message const requestString = protobufToString(request); - const encryptedMessage = await this.keyManager.encryptData(Buffer.from(requestString), Buffer.from(this.publicKey)); + const encryptedMessage = await this.keyManager.encryptData( + Buffer.from(requestString), + Buffer.from(this.getPeer(this.peerId)!.publicKey), + ); // sign message const signedMessage = await this.keyManager.signData(encryptedMessage); const subMessage = signedMessage.toString(); // encode and send message const peerRequest = new PeerMessage(); - peerRequest.setPublicKey(this.peerManager.peerInfo.publicKey); + peerRequest.setPublicKey(this.getPeerInfo().publicKey); peerRequest.setType(type); peerRequest.setSubMessage(subMessage); return peerRequest; @@ -224,7 +256,7 @@ class PeerConnection { private async decodeResponse(response: PeerMessage): Promise<{ type: SubServiceType; response: Uint8Array }> { const { publicKey, type: responseType, subMessage } = response.toObject(); // decode peerResponse - if (PeerInfo.formatPublicKey(this.getPeerInfo().publicKey) != PeerInfo.formatPublicKey(publicKey)) { + if (PeerInfo.formatPublicKey(this.getPeer(this.peerId)!.publicKey) != PeerInfo.formatPublicKey(publicKey)) { // drop packet throw Error('response public key does not match request public key'); } diff --git a/src/peers/peer-connection/PeerServer.ts b/src/peers/peer-connection/PeerServer.ts index 9db482958..332934cc2 100644 --- a/src/peers/peer-connection/PeerServer.ts +++ b/src/peers/peer-connection/PeerServer.ts @@ -1,7 +1,6 @@ -import { Address } from '../PeerInfo'; +import PeerInfo, { Address } from '../PeerInfo'; import * as grpc from '@grpc/grpc-js'; import PeerManager from '../PeerManager'; -import TurnServer from '../turn/TurnServer'; import KeyManager from '../../keys/KeyManager'; import { stringToProtobuf, protobufToString } from '../../utils'; import { PeerService, IPeerServer } from '../../../proto/compiled/Peer_grpc_pb'; @@ -13,7 +12,6 @@ class PeerServer implements IPeerServer { private server: grpc.Server; private credentials: grpc.ServerCredentials; - private turnServer: TurnServer; started: boolean = false; handleGitRequest: (request: Uint8Array, publicKey: string) => Promise; @@ -30,21 +28,18 @@ class PeerServer implements IPeerServer { this.server.addService(PeerService, (this)); // Create the server credentials. SSL only if ca cert exists - const credentials = this.keyManager.pki?.TLSServerCredentials; - if (credentials) { - this.credentials = grpc.ServerCredentials.createSsl( - Buffer.from(credentials.rootCertificate), - [ - { - private_key: Buffer.from(credentials.keypair.private), - cert_chain: Buffer.from(credentials.certificate), - }, - ], - true, - ); - } else { - this.credentials = grpc.ServerCredentials.createInsecure(); - } + const credentials = this.keyManager.pki.TLSServerCredentials; + this.credentials = grpc.ServerCredentials.createInsecure() + // this.credentials = grpc.ServerCredentials.createSsl( + // Buffer.from(credentials.rootCertificate), + // [ + // { + // private_key: Buffer.from(credentials.keypair.private), + // cert_chain: Buffer.from(credentials.certificate), + // }, + // ], + // false, + // ); const port = process.env.PK_PEER_PORT ?? this.peerManager.peerInfo?.peerAddress?.port ?? 0; const host = process.env.PK_PEER_HOST ?? this.peerManager.peerInfo?.peerAddress?.host ?? 'localhost'; @@ -56,10 +51,10 @@ class PeerServer implements IPeerServer { this.server.start(); if (this.peerManager.peerInfo) { this.peerManager.peerInfo.peerAddress = address; + this.peerManager.writeMetadata() } console.log(`Peer Server running on: ${address}`); this.started = true; - this.turnServer = new TurnServer(this.peerManager); } }); } @@ -70,7 +65,8 @@ class PeerServer implements IPeerServer { const { publicKey, type, subMessage: requestMessage } = peerRequest.toObject(); // if we don't know publicKey, end connection - if (!this.peerManager.hasPeer(publicKey)) { + const peerId = PeerInfo.publicKeyToId(publicKey) + if (!this.peerManager.hasPeer(peerId)) { throw Error('unknown public key'); } @@ -93,6 +89,9 @@ class PeerServer implements IPeerServer { case SubServiceType.CERTIFICATE_AUTHORITY: response = await this.keyManager.pki.handleGRPCRequest(request) break; + case SubServiceType.PEER_DHT: + response = await this.peerManager.peerDHT.handleGRPCRequest(request) + break; default: throw Error('peer message type not identified'); } diff --git a/src/peers/peer-dht/KBucket.ts b/src/peers/peer-dht/KBucket.ts new file mode 100644 index 000000000..d0afe9c99 --- /dev/null +++ b/src/peers/peer-dht/KBucket.ts @@ -0,0 +1,425 @@ +import { arrayEquals } from "../../utils" + +// this is an adaptation of the awesome k-buckets library but with specific polykey use in mind: +// https://github.com/tristanls/k-bucket +// Background reading: +// https://docs.google.com/presentation/d/11qGZlPWu6vEAhA7p3qsQaQtWH7KofEC9dMeBFZ1gYeA/edit#slide=id.g1718cc2bc_0643 + +function createNode(): Node { + return { contacts: [], dontSplit: false, left: null, right: null } +} + +type Node = { + contacts: Uint8Array[] | null + dontSplit: boolean + left: Node | null + right: Node | null +} + +/** + * Implementation of a Kademlia DHT k-bucket used for storing + * contact (peer node) information. + */ +class KBucket { + private getPeerId: () => string + + private pingNode: (oldContacts: string[], newContact: string) => void + + numberOfNodesPerKBucket: number + private numberOfNodesToPing: number + private root: Node + + constructor( + getPeerId: () => string, + pingNode: (oldContacts: string[], newContact: string) => void + ) { + this.getPeerId = getPeerId + this.pingNode = pingNode + + // standard configuration + this.numberOfNodesPerKBucket = 20 + this.numberOfNodesToPing = 3 + + // create the root node + this.root = createNode() + } + + public get localPeerId() : Uint8Array { + const id = this.getPeerId() + return this.peerIdToU8(id) + } + + /** + * Default arbiter function for contacts with the same id. Uses + * contact.vectorClock to select which contact to update the k-bucket with. + * Contact with larger vectorClock field will be selected. If vectorClock is + * the same, candidate will be selected. + * + * @param {Object} incumbent Contact currently stored in the k-bucket. + * @param {Object} candidate Contact being added to the k-bucket. + * @return {Object} Contact to updated the k-bucket with. + */ + arbiter(incumbent: Uint8Array, candidate: Uint8Array): Uint8Array { + // this would neeed to be calculated from some kind of vectorClock + return candidate + // return incumbent.vectorClock > candidate.vectorClock ? incumbent : candidate + } + + /** + * Default distance function. Finds the XOR + * distance between firstId and secondId. + * + * @param firstId first id. + * @param secondId second id. + * @return Integer The XOR distance between firstId and secondId. + */ + private distance(firstId: Uint8Array, secondId: Uint8Array): number { + let distance = 0 + let i = 0 + const min = Math.min(firstId.length, secondId.length) + const max = Math.max(firstId.length, secondId.length) + for (; i < min; ++i) { + distance = distance * 256 + (firstId[i] ^ secondId[i]) + } + for (; i < max; ++i) distance = distance * 256 + 255 + return distance + } + + /** + * Adds a contact to the k-bucket. + * + * @param contact the contact object to add + */ + async add(peerId: string): Promise { + const id = this.peerIdToU8(peerId) + let bitIndex = 0 + let node = this.root + + while (node.contacts === null) { + // this is not a leaf node but an inner node with 'low' and 'high' + // branches; we will check the appropriate bit of the identifier and + // delegate to the appropriate node for further processing + const innerNode = this.determineNode(node, id, bitIndex++) + if (innerNode) { + node = innerNode + } + } + + // check if the contact already exists + const index = this.indexOf(node, id) + if (index >= 0) { + this.update(node, index, id) + return + } + + if (node.contacts.length < this.numberOfNodesPerKBucket) { + node.contacts.push(id) + // this.emit('added', contact) + return + } + + // the bucket is full + if (node.dontSplit) { + // we are not allowed to split the bucket + // we need to ping the first this.numberOfNodesToPing + // in order to determine if they are alive + // only if one of the pinged nodes does not respond, can the new contact + // be added (this prevents DoS flodding with new invalid contacts) + this.pingNode( + node.contacts.slice(0, this.numberOfNodesToPing).map(i => this.u8ToPeerId(i)), + this.u8ToPeerId(id) + ) + return + } + + this.split(node, bitIndex) + return await this.add(this.u8ToPeerId(id)) + } + + /** + * Get the n closest contacts to the provided node id. "Closest" here means: + * closest according to the XOR metric of the contact node id. + * + * @param publicKey Contact node id + * @param num Integer (Default: Infinity) The maximum number of all closest contacts to return + * @return Array Maximum of n closest public keys to the provided public key + */ + closest(peerId: string, num: number = Infinity): string[] { + const idU8 = this.peerIdToU8(peerId) + if ((!Number.isInteger(num) && num !== Infinity) || num <= 0) { + throw new TypeError('n is not positive number') + } + + let contacts: Uint8Array[] = [] + + for (let nodes = [this.root], bitIndex = 0; nodes.length > 0 && contacts.length < num;) { + + const node = nodes.pop() + + if (node) { + if (node.contacts === null) { + const detNode = this.determineNode(node, idU8, bitIndex++) + const nodeToBePushed = (node.left === detNode) ? node.right : node.left + if (nodeToBePushed) { + nodes.push(nodeToBePushed) + } + if (detNode) { + nodes.push(detNode) + } + } else { + contacts = contacts.concat(node.contacts) + } + } + } + + return contacts + .map(a => ({ distance: this.distance(a, idU8), node: a })) + .sort((a, b) => a.distance - b.distance) + .slice(0, num) + .map(a => this.u8ToPeerId(a.node)) + } + + /** + * Counts the total number of contacts in the tree. + * + * @return {Number} The number of contacts held in the tree + */ + count(): number { + let count = 0 + for (const nodes = [this.root]; nodes.length > 0;) { + const node = nodes.pop() + if (node) { + if (node.contacts === null) { + nodes.push({ contacts: [], right: node.right, left: node.left, dontSplit: true }) + } else { + count += node.contacts.length + } + } + } + return count + } + + /** + * Determines whether the id at the bitIndex is 0 or 1. + * Return left leaf if `id` at `bitIndex` is 0, right leaf otherwise + * + * @param {Object} node internal object that has 2 leafs: left and right + * @param {Uint8Array} id Id to compare localNodeId with. + * @param {Number} bitIndex Integer (Default: 0) The bit index to which bit + * to check in the id Uint8Array. + * @return {Object} left leaf if id at bitIndex is 0, right leaf otherwise. + */ + private determineNode(node: Node, id: Uint8Array, bitIndex: number): Node | null { + // **NOTE** remember that id is a Uint8Array and has granularity of + // bytes (8 bits), whereas the bitIndex is the _bit_ index (not byte) + + // id's that are too short are put in low bucket (1 byte = 8 bits) + // (bitIndex >> 3) finds how many bytes the bitIndex describes + // bitIndex % 8 checks if we have extra bits beyond byte multiples + // if number of bytes is <= no. of bytes described by bitIndex and there + // are extra bits to consider, this means id has less bits than what + // bitIndex describes, id therefore is too short, and will be put in low + // bucket + const bytesDescribedByBitIndex = bitIndex >> 3 + const bitIndexWithinByte = bitIndex % 8 + if ((id.length <= bytesDescribedByBitIndex) && (bitIndexWithinByte !== 0)) { + return node.left + } + + const byteUnderConsideration = id[bytesDescribedByBitIndex] + + // byteUnderConsideration is an integer from 0 to 255 represented by 8 bits + // where 255 is 11111111 and 0 is 00000000 + // in order to find out whether the bit at bitIndexWithinByte is set + // we construct (1 << (7 - bitIndexWithinByte)) which will consist + // of all bits being 0, with only one bit set to 1 + // for example, if bitIndexWithinByte is 3, we will construct 00010000 by + // (1 << (7 - 3)) -> (1 << 4) -> 16 + if (byteUnderConsideration & (1 << (7 - bitIndexWithinByte))) { + return node.right + } + + return node.left + } + + /** + * Get a contact by its exact ID. + * If this is a leaf, loop through the bucket contents and return the correct + * contact if we have it or null if not. If this is an inner node, determine + * which branch of the tree to traverse and repeat. + * + * @param {Uint8Array} id The ID of the contact to fetch. + * @return {PeerInfo|Null} The contact if available, otherwise null + */ + get(id: Uint8Array): Uint8Array | null { + let bitIndex = 0 + + let node = this.root + while (node.contacts === null) { + const innerNode = this.determineNode(node, id, bitIndex++) + if (innerNode) { + node = innerNode + } + } + + // index of uses contact id for matching + const index = this.indexOf(node, id) + return index >= 0 ? node.contacts[index] : null + } + + /** + * Returns the index of the contact with provided + * id if it exists, returns -1 otherwise. + * + * @param {Object} node internal object that has 2 leafs: left and right + * @param {Uint8Array} id Contact node id. + * @return {Number} Integer Index of contact with provided id if it + * exists, -1 otherwise. + */ + private indexOf(node: Node, id: Uint8Array): number { + if (node.contacts) { + for (let i = 0; i < node.contacts.length; ++i) { + const foundId = node.contacts[i] + if (arrayEquals(foundId, id)) return i + } + } + + return -1 + } + + /** + * Removes contact with the provided id. + * + * @param {Uint8Array} id The ID of the contact to remove. + * @return {Object} The k-bucket itself. + */ + remove(peerId: string): KBucket { + const idU8 = this.peerIdToU8(peerId) + let bitIndex = 0 + let node = this.root + + while (node.contacts === null) { + const innerNode = this.determineNode(node, idU8, bitIndex++) + if (innerNode) { + node = innerNode + } + } + + const index = this.indexOf(node, idU8) + if (index >= 0) { + const contact = node.contacts.splice(index, 1)[0] + // this.emit('removed', contact) + } + + return this + } + + /** + * Splits the node, redistributes contacts to the new nodes, and marks the + * node that was split as an inner node of the binary tree of nodes by + * setting this.root.contacts = null + * + * @param {Object} node node for splitting + * @param {Number} bitIndex the bitIndex to which byte to check in the + * Uint8Array for navigating the binary tree + */ + private split(node: Node, bitIndex: number): void { + node.left = createNode() + node.right = createNode() + + // redistribute existing contacts amongst the two newly created nodes + if (node.contacts) { + for (const contact of node.contacts) { + const innerNode = this.determineNode(node, contact, bitIndex) + if (innerNode && innerNode.contacts) { + innerNode.contacts.push(contact) + } + } + } + + node.contacts = [] // mark as inner tree node + + // don't split the "far away" node + // we check where the local node would end up and mark the other one as + // "dontSplit" (i.e. "far away") + const detNode = this.determineNode(node, this.localPeerId, bitIndex) + const otherNode = node.left === detNode ? node.right : node.left + otherNode.dontSplit = true + } + + /** + * Returns all the contacts contained in the tree as an array. + * If this is a leaf, return a copy of the bucket. `slice` is used so that we + * don't accidentally leak an internal reference out that might be + * accidentally misused. If this is not a leaf, return the union of the low + * and high branches (themselves also as arrays). + * + * @return {Array} All of the contacts in the tree, as an array + */ + toArray(): string[] { + let result: string[] = [] + for (const nodes = [this.root]; nodes.length > 0;) { + const node = nodes.pop() + if (node) { + if (node.contacts === null) { + if (node.right) { + nodes.push(node.right) + } + if (node.left) { + nodes.push(node.left) + } + } + else { + result = result.concat(node.contacts.map(i => this.u8ToPeerId(i))) + } + } + } + return result + } + + /** + * Updates the contact selected by the arbiter. + * If the selection is our old contact and the candidate is some new contact + * then the new contact is abandoned (not added). + * If the selection is our old contact and the candidate is our old contact + * then we are refreshing the contact and it is marked as most recently + * contacted (by being moved to the right/end of the bucket array). + * If the selection is our new contact, the old contact is removed and the new + * contact is marked as most recently contacted. + * + * @param {Object} node internal object that has 2 leafs: left and right + * @param {Number} index the index in the bucket where contact exists + * (index has already been computed in a previous + * calculation) + * @param {Object} contact The contact object to update. + */ + private update(node: Node, index: number, contact: Uint8Array) { + // sanity check + if (node.contacts && (!arrayEquals(node.contacts[index], contact))) { + throw new Error('wrong index for update') + } + + const incumbent = node.contacts![index] + const selection = this.arbiter(incumbent, contact) + // if the selection is our old contact and the candidate is some new + // contact, then there is nothing to do + if (selection === incumbent && incumbent !== contact) return + + node.contacts!.splice(index, 1) // remove old contact + node.contacts!.push(selection) // add more recent contact version + // this.emit('updated', incumbent, selection) + } + + // ==== Helper methods ==== // + private peerIdToU8(id: string) { + const b = Buffer.from(id) + return new Uint8Array(b.buffer, b.byteOffset, b.byteLength / Uint8Array.BYTES_PER_ELEMENT); + } + + private u8ToPeerId(ui8: Uint8Array) { + return Buffer.from(ui8).toString() + } +} + + +export default KBucket diff --git a/src/peers/peer-dht/PeerDHT.ts b/src/peers/peer-dht/PeerDHT.ts new file mode 100644 index 000000000..c70e3cf28 --- /dev/null +++ b/src/peers/peer-dht/PeerDHT.ts @@ -0,0 +1,332 @@ +import KBucket from './KBucket'; +import PeerInfo from '../PeerInfo'; +import { Mutex } from 'async-mutex'; +import { promiseAll } from '../../utils'; +import { peerInterface } from '../../../proto/js/Peer'; +import { SubServiceType } from '../../../proto/compiled/Peer_pb'; + +// this implements a very basic map of known peer connections +// TODO: implement full kademlia algorithm for distributed peer connection table +class PeerDHT { + private getPeerId: () => string; + private getPeerInfo: (id: string) => PeerInfo; + private updatePeerStore: (peerInfo: PeerInfo) => void; + + // state + private findingLocalPeer: boolean = false; + private findingPeer: boolean = false; + private addingPeers: boolean = false; + private addingPeer: boolean = false; + private deletingPeer: boolean = false; + + // Concurrency + private mutex: Mutex = new Mutex(); + + kBucket: KBucket; + connectToPeer: ( + id: string, + ) => { + pingPeer: (timeout?: number | undefined) => Promise; + sendPeerRequest: (type: SubServiceType, request: Uint8Array) => Promise; + }; + + constructor( + getPeerId: () => string, + connectToPeer: ( + id: string, + ) => { + pingPeer: (timeout?: number | undefined) => Promise; + sendPeerRequest: (type: SubServiceType, request: Uint8Array) => Promise; + }, + getPeerInfo: (id: string) => PeerInfo, + updatePeerStore: (peerInfo: PeerInfo) => void, + ) { + this.getPeerId = getPeerId; + this.connectToPeer = connectToPeer; + this.getPeerInfo = getPeerInfo; + this.updatePeerStore = updatePeerStore; + + this.kBucket = new KBucket(this.getPeerId, this.pingNodeUpdate.bind(this)); + } + + + public get Status() { + return { + findingLocalPeer: this.findingLocalPeer, + findingPeer: this.findingPeer, + addingPeers: this.addingPeers, + addingPeer: this.addingPeer, + deletingPeer: this.deletingPeer, + }; + } + + // This should use the peer communications channel to check if the peer is still alive + private async peerIsAlive(peerId: string) { + const pc = this.connectToPeer(peerId); + return await pc.pingPeer(); + } + + private async pingNodeUpdate(oldContacts: string[], newContact: string) { + // oldContacts and newContact both contain publicKeys + // ping from oldest the newest + // if an old contact does not respond, remove it + // if there is an opening, add the new contact if it responds + for (const oldContact of oldContacts) { + if (!(await this.peerIsAlive(oldContact))) { + // we can remove this one and add the new contact + this.kBucket.remove(oldContact); + this.kBucket.add(newContact); + return; + } + } + } + + private closestPeer(id: string): string | null { + const res = this.closestPeers(id, 1); + if (res.length > 0) { + return res[0]; + } else { + return null; + } + } + + private closestPeers(id: string, count?: number): string[] { + return this.kBucket.closest(id, count); + } + + async addPeer(id: string) { + const release = await this.mutex.acquire(); + this.addingPeer = true; + try { + if (this.getPeerId() != id) { + await this.kBucket.add(id); + } + } catch (error) { + throw error; + } finally { + this.addingPeer = false; + release(); + } + } + + async addPeers(ids: string[]) { + const release = await this.mutex.acquire(); + this.addingPeers = true; + const promiseList = ids + .filter((v) => { + v != this.getPeerId(); + }) + .map((id) => this.kBucket.add(id)); + await promiseAll(promiseList).finally(() => { + this.addingPeers = false; + release(); + }); + } + + async deletePeer(id: string) { + const release = await this.mutex.acquire(); + this.deletingPeer = true; + try { + this.kBucket.remove(id); + } catch (error) { + throw error; + } finally { + this.deletingPeer = false; + release(); + } + } + + private toPeerInfoMessageList(peerIds: string[]): peerInterface.IPeerInfoMessage[] { + return peerIds + .filter((p) => { + try { + const pi = this.getPeerInfo(p); + return pi ? true : false; + } catch { + return false; + } + }) + .map((p) => { + const pi = this.getPeerInfo(p); + return { + publicKey: pi.publicKey, + rootCertificate: pi.rootCertificate, + peerAddress: pi.peerAddress?.toString(), + apiAddress: pi.apiAddress?.toString(), + }; + }); + } + + async findLocalPeer(peerId: string): Promise { + const release = await this.mutex.acquire(); + this.findingLocalPeer = true; + const closestPeerId = this.closestPeer(peerId); + if (closestPeerId && closestPeerId == peerId) { + const foundPeerInfo = this.getPeerInfo(peerId); + // Found local peer + this.findingLocalPeer = false; + release(); + return foundPeerInfo ?? null; + } else { + // Either can't find public key in k bucket or + // PeerInfo doesn't exist in store. Either way, + // we just return null + this.findingLocalPeer = false; + release(); + return null; + } + } + + // This function either returns the peer info from + // a locally found peer or uses the FIND_NODE protocol + // from kademlia to query peers until it finds the one + // its looking for + async findPeer( + peerId: string, + ): Promise<{ + adjacentPeerInfo?: PeerInfo; + targetPeerInfo?: PeerInfo; + }> { + const release = await this.mutex.acquire(); + this.findingPeer = true; + // Return local peer if it exists in routing table and has a connected peerAddress + const localPeerInfo = await this.findLocalPeer(peerId); + if (localPeerInfo && localPeerInfo?.peerAddress != undefined) { + this.findingPeer = false; + release(); + return { + targetPeerInfo: localPeerInfo, + }; + } + + // If local peer was not found, get closest peers and + // start querying the network + const kBucketSize = this.kBucket.numberOfNodesPerKBucket; + // get rid of the target peer id as it is not onsidered a close peer + const closestPeerIds = this.closestPeers(peerId, kBucketSize).filter((pi) => pi != peerId); + + // If there are no closest peers, we have failed to find that peer + if (closestPeerIds.length === 0) { + throw Error('peer lookup failed, no close peers found'); + } + + // Query the network until the peer public key is found + for (const closePeerId of closestPeerIds) { + if (closePeerId == this.getPeerId()) { + continue; + } + try { + const pc = this.connectToPeer(closePeerId); + + // encode request + // note the request is also an opportunity to notify the target node of the closes + // peers that the local node knows about so the target node kbucket can be updated. + const subMessage = peerInterface.PeerDHTFindNodeMessage.encodeDelimited({ + peerId: peerId, + closestPeers: this.toPeerInfoMessageList(closestPeerIds), + }).finish(); + + const request = peerInterface.PeerDHTMessage.encodeDelimited({ + type: peerInterface.PeerDHTMessageType.FIND_NODE, + isResponse: false, + subMessage: subMessage, + }).finish(); + // send request + const response = await pc.sendPeerRequest(SubServiceType.PEER_DHT, request); + + // decode response + const { subMessage: responseSubMessage } = peerInterface.PeerDHTMessage.decodeDelimited(response); + const { peerId: responsePeerId, closestPeers } = peerInterface.PeerDHTFindNodeMessage.decodeDelimited( + responseSubMessage, + ); + + // make sure request and response public keys are the same + if (peerId != responsePeerId) { + throw Error('request and response public keys are not the same!'); + } + + const closestFoundPeerInfoMessageList = closestPeers.map( + (p) => new PeerInfo(p.publicKey!, p.rootCertificate!, p.peerAddress ?? undefined, p.apiAddress ?? undefined), + ); + + // Add peers to routing table + this.addPeers(closestPeers.map((p) => PeerInfo.publicKeyToId(p.publicKey!))); + + // add peers to peer store + let foundPeerInfo: PeerInfo | null = null; + for (const peerInfo of closestFoundPeerInfoMessageList) { + if (this.getPeerId() != peerInfo.id) { + this.updatePeerStore(peerInfo); + } + if (peerInfo.id == peerId) { + foundPeerInfo = peerInfo; + } + } + + if (foundPeerInfo) { + this.findingPeer = false; + release(); + return { + adjacentPeerInfo: this.getPeerInfo(closePeerId)!, + targetPeerInfo: foundPeerInfo, + }; + } else { + throw Error('peer id was not found'); + } + } catch (error) { + // don't want to throw if peer contact failed so just log it + continue; + } + } + this.findingPeer = false; + release(); + return {}; + } + + /////////////////// + // gRPC Handlers // + /////////////////// + async handleGRPCRequest(request: Uint8Array): Promise { + const { type, subMessage } = peerInterface.PeerDHTMessage.decodeDelimited(request); + let response: Uint8Array; + switch (type) { + case peerInterface.PeerDHTMessageType.PING: + throw Error('dht ping is not implemented, use peer ping channel as a proxy for a peer aliveness'); + break; + case peerInterface.PeerDHTMessageType.FIND_NODE: + response = await this.handleFindNodeMessage(subMessage); + break; + default: + throw Error(`type not supported: ${type}`); + } + const encodedResponse = peerInterface.PeerDHTMessage.encodeDelimited({ + type, + isResponse: true, + subMessage: response, + }).finish(); + return encodedResponse; + } + + private async handleFindNodeMessage(request: Uint8Array): Promise { + const { peerId, closestPeers } = peerInterface.PeerDHTFindNodeMessage.decodeDelimited(request); + const closestPeerInfoList = closestPeers + .map((p) => new PeerInfo(p.publicKey!, p.rootCertificate!, p.peerAddress ?? undefined, p.apiAddress ?? undefined)) + .filter((p) => p.id != this.getPeerId()); + + const response = peerInterface.PeerDHTFindNodeMessage.encodeDelimited({ + peerId: peerId, + closestPeers: this.toPeerInfoMessageList(this.closestPeers(peerId)), + }).finish(); + + // update the peer store + for (const peerInfo of closestPeerInfoList) { + if (this.getPeerId() != peerInfo.id) { + this.updatePeerStore(peerInfo); + this.addPeer(peerInfo.id); + } + } + return response; + } +} + +export default PeerDHT; diff --git a/src/peers/turn/TurnClient.ts b/src/peers/turn/TurnClient.ts deleted file mode 100644 index 772aa1abf..000000000 --- a/src/peers/turn/TurnClient.ts +++ /dev/null @@ -1,322 +0,0 @@ -// adapted from https://github.com/advance512/nat-traversal -import net from 'net'; -import { EventEmitter } from 'events'; -import { Address } from '../PeerInfo'; -import PeerManager from '../PeerManager'; -import { peerInterface } from '../../../proto/js/Peer'; -import { SubServiceType } from '../../../proto/compiled/Peer_pb'; -import UDPHolePunchClient from '../udp-hole-punch/UDPHolePunchClient'; - -let socketPipeId = 1; - -class SocketPipe extends EventEmitter { - id: number; - localAddress: Address; - relayAddress: Address; - - targetSocket: net.Socket; - targetSocketPending: boolean; - buffer: Buffer[]; - relaySocket: net.Socket; - - constructor(localAddress: Address, relayAddress: Address) { - super(); - - this.id = socketPipeId; - socketPipeId += 1; - - this.localAddress = localAddress; - this.relayAddress = relayAddress; - - this.targetSocketPending = true; - this.buffer = []; - - console.log(`[client-relay:${this.id}] Created new pending SocketPipe.`); - - this.openRelayEnd(); - } - - private openRelayEnd() { - console.log(`[client-relay:${this.id}] Socket pipe will TCP connection to connect to relay server.`); - - this.relaySocket = net.connect(this.relayAddress.port, this.relayAddress.host, () => { - console.log(`[client-relay:${this.id}] Created new TCP connection.`); - // Configure socket for keeping connections alive - this.relaySocket.setKeepAlive(true, 120 * 1000); - }); - - // We have a relay socket - now register its handlers - - // On data - this.relaySocket.on('data', (data) => { - // Got data - do we have a target socket? - if (this.targetSocket === undefined) { - // Create a target socket for the relay socket - connecting to the target - this.openTargetEnd(); - this.emit('pair'); - } - - // Is the target socket still connecting? If so, are we buffering data? - if (this.targetSocketPending) { - // Store the data until we have a target socket - this.buffer[this.buffer.length] = data; - } else { - try { - // Or just pass it directly - this.targetSocket.write(data); - } catch (ex) { - console.error(`[client-relay:${this.id}] Error writing to target socket: `, ex); - } - } - }); - - // On closing - this.relaySocket.on('close', (hadError) => { - if (hadError) { - console.error(`[client-relay:${this.id}] Relay socket closed with error.`); - } - - if (this.targetSocket !== undefined) { - // Destroy the other socket - this.targetSocket.destroy(); - } else { - // Signal we are closing - server closed the connection - this.emit('close'); - } - }); - - this.relaySocket.on('error', (error) => { - console.error(`[client-relay:${this.id}] Error with relay socket: `, error); - }); - } - - private openTargetEnd() { - console.log( - `[client-relay:${ - this.id - }] Authorized by relay server. Creating new connection to target ${this.localAddress.toString()}...`, - ); - console.log(`[client-target:${this.id}] Socket pipe will TCP connection to connect to target server.`); - - // Or use TCP - this.targetSocket = net.connect(this.localAddress.port, this.localAddress.host, () => { - console.log(`[client-target:${this.id}] Successfully connected to target ${this.localAddress.toString()}.`); - - // Configure socket for keeping connections alive - this.targetSocket.setKeepAlive(true, 120 * 1000); - - // Connected, not pending anymore - this.targetSocketPending = false; - - // And if we have any buffered data, forward it - try { - for (const bufferItem of this.buffer) { - this.targetSocket.write(bufferItem); - } - } catch (ex) { - console.error(`[client-target:${this.id}] Error writing to target socket: `, ex); - } - - // Clear the array - this.buffer.length = 0; - }); - - // Got data from the target socket? - this.targetSocket.on('data', (data) => { - try { - // Forward it! - this.relaySocket.write(data); - } catch (ex) { - console.error(`target:${this.id}] Error writing to target socket: `, ex); - } - }); - - this.targetSocket.on('error', (hadError) => { - if (hadError) { - console.error(`[target:${this.id}] Target socket was closed with error: `, hadError); - } - - this.terminate(); - }); - } - - terminate() { - console.log(`[client-relay:${this.id}] Terminating socket pipe...`); - this.removeAllListeners(); - this.relaySocket.destroy(); - } -} - -class TurnClient { - peerManager: PeerManager; - - socketPipes: SocketPipe[]; - terminating: boolean; - udpHolePunchClient: UDPHolePunchClient; - - // default is to support up to 10 connections at once, change this with 'numSockets' parameter - constructor(peerManager: PeerManager) { - this.peerManager = peerManager; - - // create udp hole punch client - this.udpHolePunchClient = new UDPHolePunchClient(this.peerManager); - - this.socketPipes = []; - } - - private async sendMessage( - type: peerInterface.NatMessageType, - publicKey: string, - message?: Uint8Array, - ): Promise { - const peerConnection = this.peerManager.connectToPeer(publicKey); - const encodedMessage = peerInterface.NatMessage.encodeDelimited({ - type, - isResponse: false, - subMessage: message, - }).finish(); - const responseMessage = await peerConnection.sendPeerRequest(SubServiceType.NAT_TRAVERSAL, encodedMessage); - const { type: responseType, isResponse, subMessage } = peerInterface.NatMessage.decodeDelimited(responseMessage); - return subMessage; - } - - async requestPeerConnection(peerPublicKey: string, relayPublicKey: string): Promise
{ - const requestMessage = peerInterface.PeerConnectionRequest.encodeDelimited({ publicKey: peerPublicKey }).finish(); - - const responseMessage = await this.sendMessage( - peerInterface.NatMessageType.PEER_CONNECTION, - relayPublicKey, - requestMessage, - ); - - const { peerAddress } = peerInterface.PeerConnectionResponse.decodeDelimited(responseMessage); - - if (!peerAddress) { - throw Error('relay does not know of requested peer'); - } - const address = Address.parse(peerAddress); - const relayPeerInfo = this.peerManager.getPeer(relayPublicKey); - address.updateHost(relayPeerInfo?.peerAddress?.host); - return address; - } - - async requestRelayConnection(relayPublicKey: string) { - const requestMessage = peerInterface.RelayConnectionRequest.encodeDelimited({ - publicKey: this.peerManager.peerInfo.publicKey, - }).finish(); - - const responseMessage = await this.sendMessage( - peerInterface.NatMessageType.RELAY_CONNECTION, - relayPublicKey, - requestMessage, - ); - - const { serverAddress } = peerInterface.RelayConnectionResponse.decodeDelimited(responseMessage); - - const incoming = Address.parse(serverAddress); - console.log(incoming); - - incoming.host = this.peerManager.getPeer(relayPublicKey)?.peerAddress?.host ?? incoming.host; - // add relay node to turn server address - this.peerManager.peerInfo.relayPublicKey = relayPublicKey; - - // Create pending socketPipes - this.createSocketPipe(incoming); - } - - async requestLocalHolePunchAddress(relayPublicKey: string) { - // request hole punch - const udpAddress = await this.requestUDPAddress(relayPublicKey); - - const localUdpAddress = await this.udpHolePunchClient.requestHolePunch( - udpAddress, - this.peerManager.peerInfo.peerAddress!, - ); - - // add to peer info as relay node - this.peerManager.peerInfo.relayPublicKey = relayPublicKey; - - return localUdpAddress; - } - - async requestHolePunchConnection(relayPublicKey: string, peerPublicKey: string) { - const peerUDPAddress = await this.requestPeerUDPAddress(relayPublicKey, peerPublicKey); - - return this.udpHolePunchClient.createPipeServer(peerUDPAddress); - } - - // returns the address for a local tcp server that is routed via UTP - private async requestPeerUDPAddress(relayPublicKey: string, peerPublicKey: string): Promise
{ - const requestMessage = peerInterface.PeerUdpAddressRequest.encodeDelimited({ publicKey: peerPublicKey }).finish(); - - const responseMessage = await this.sendMessage( - peerInterface.NatMessageType.PEER_UDP_ADDRESS, - relayPublicKey, - requestMessage, - ); - - const { address } = peerInterface.PeerUdpAddressResponse.decodeDelimited(responseMessage); - - return Address.parse(address); - } - - private async requestUDPAddress(relayPublicKey: string) { - const responseMessage = await this.sendMessage(peerInterface.NatMessageType.UDP_ADDRESS, relayPublicKey); - - const { address } = peerInterface.UDPAddressResponse.decodeDelimited(responseMessage); - - return Address.parse(address); - } - - private async createSocketPipe(relayAddress: Address) { - const localAddress = this.peerManager.peerInfo.peerAddress!; - // wait for local address - while (!localAddress) { - await new Promise((resolve, reject) => setTimeout(() => resolve(), 1000)); - } - - // Create a new socketPipe - const socketPipe = new SocketPipe(localAddress, relayAddress); - this.socketPipes.push(socketPipe); - - socketPipe.on('pair', () => { - // Create a new pending socketPipe - this.createSocketPipe(relayAddress); - }); - - socketPipe.on('close', () => { - // Server closed the connection - // Remove paired pipe - this.removeSocketPipe(socketPipe); - - // Create a new replacement socketPipe, that is pending and waiting, if required - setTimeout(() => { - if (this.terminating) { - return; - } - - // Create a new pending socketPipe - this.createSocketPipe(relayAddress); - }, 5000); - }); - } - - private removeSocketPipe(socketPipe: SocketPipe) { - // SocketPipe closed - is it still stored by us? - const i = this.socketPipes.indexOf(socketPipe); - // If so, remove it - if (i !== -1) { - this.socketPipes.splice(i, 1); - } - socketPipe.terminate(); - } - - terminate() { - this.terminating = true; - for (const socketPipe of this.socketPipes) { - socketPipe.terminate(); - } - } -} - -export default TurnClient; diff --git a/src/peers/turn/TurnServer.ts b/src/peers/turn/TurnServer.ts deleted file mode 100644 index a990afaf3..000000000 --- a/src/peers/turn/TurnServer.ts +++ /dev/null @@ -1,300 +0,0 @@ -// adapted from https://github.com/advance512/nat-traversal -import PeerInfo, { Address } from '../PeerInfo'; -import { EventEmitter } from 'events'; -import net, { AddressInfo } from 'net'; -import PeerManager from '../PeerManager'; -import { peerInterface } from '../../../proto/js/Peer'; -import UDPHolePunchServer from '../udp-hole-punch/UDPHolePunchServer'; - -class SocketPipe extends EventEmitter { - serverSocket: net.Socket; - clientSocket: net.Socket; - bufferQueue: Buffer[]; - - id: number; - - constructor(serverSocket: net.Socket, id: number) { - super(); - this.id = id; - this.serverSocket = serverSocket; - this.bufferQueue = []; - // Configure socket for keeping connections alive - this.serverSocket.setKeepAlive(true, 120 * 1000); - // New data - this.serverSocket.on('data', (data) => { - // if outgoing socket is connected, write data - this.bufferQueue.push(data); - if (this.clientSocket) { - this.writeBuffer(); - } - }); - - this.serverSocket.on('close', (hadError: any) => { - if (hadError) { - console.error(`[${this}] Socket was closed due to error.`); - } - // Destroy the paired socket too - if (this.clientSocket !== undefined) { - this.clientSocket.destroy(); - } - // Mark this socketPipe is closing - this.emit('close'); - }); - - this.serverSocket.on('error', (err: any) => { - console.error(`Socket error: ${err}`); - }); - } - - terminate() { - this.serverSocket.destroy(); - } - - activate(outgoingSocket: net.Socket) { - if (this.clientSocket) { - throw new Error(`[${this}] Attempted to pair socket more than once.`); - } - - console.log(`[socket-pipe: ${this.id}] Socket pipe activated!`); - - this.clientSocket = outgoingSocket; - - // Configure socket for keeping connections alive - this.clientSocket.setKeepAlive(true, 120 * 1000); - - // If we have any data in the buffer, write it - this.writeBuffer(); - } - - private writeBuffer() { - while (this.bufferQueue.length > 0) { - const buffer = this.bufferQueue.shift()!; - this.clientSocket.write(buffer); - } - } -} - -class EndpointServer extends EventEmitter { - address: Address; - edgeType: 'server' | 'client'; - pendingSocketPipes: SocketPipe[] = []; - activeSocketPipes: SocketPipe[] = []; - server: net.Server; - - constructor(edgeType: 'server' | 'client') { - super(); - - this.edgeType = edgeType; - } - - async start(port: number = 0) { - await new Promise((resolve, reject) => { - console.log(`[${this.edgeType}] endpoint server Will listen to incoming TCP connections.`); - - this.server = net - .createServer((socket) => { - console.log( - `[endpoint-server: ${this.edgeType}] Incoming TCP connection from ${socket.remoteAddress}:${socket.remotePort}`, - ); - this.createSocketPipe(socket); - }) - .listen(port, '0.0.0.0', () => { - this.address = Address.fromAddressInfo(this.server.address()); - console.log(`[${this.edgeType}] Listening on adress ${this.address.toString()}...`); - resolve(); - }); - }); - } - - private async createSocketPipe(incomingSocket: net.Socket) { - const id = Math.max(0, ...this.activeSocketPipes.map((v) => v.id), ...this.pendingSocketPipes.map((v) => v.id)) + 1; - - const newSocketPipe = new SocketPipe(incomingSocket, id); - - console.log(`[${this.edgeType}-server-socket-pipe: ${newSocketPipe.id}] SocketPipe authorized.`); - this.emit('new', newSocketPipe); - - newSocketPipe.on('close', () => { - console.log(`[${this.edgeType}-server-socket-pipe: ${newSocketPipe.id}] SocketPipe closed connection`); - this.removeSocketPipe(newSocketPipe); - }); - - return; - } - - activateSocketPipe(pairServer: EndpointServer, connectingSocketPipe: SocketPipe) { - // Do we have a pending socketPipe waiting? - if (this.hasPendingSocketPipes()) { - // Get the current pending socketPipe - const pendingSocketPipe = this.getPendingSocketPipe(); - - console.log( - `[${this.edgeType}-server] Activating pending SocketPipe: connecting SocketPipes ${this.edgeType}-${pendingSocketPipe.id} and ${pairServer.edgeType}-${connectingSocketPipe.id}`, - ); - - // Pair the connecting socketPipe with the pending socketPipe, allow data flow in one direction - connectingSocketPipe.activate(pendingSocketPipe.serverSocket); - this.addActiveSocketPipe(pendingSocketPipe); - - // And vice versa, for the second direction - pendingSocketPipe.activate(connectingSocketPipe.serverSocket); - pairServer.addActiveSocketPipe(connectingSocketPipe); - } else { - console.log( - `[${this.edgeType}-server-socket-pipe: ${pairServer.edgeType}-${connectingSocketPipe.id}] SocketPipe will be pending until a parallel connection occurs`, - ); - // If we don't then our new connecting socketPipe is now pending and waiting for another connecting socketPipe - pairServer.addPendingSocketPipe(connectingSocketPipe); - } - } - - private getPendingSocketPipe() { - const pendingSocketPipe = this.pendingSocketPipes[0]; - this.pendingSocketPipes.splice(0, 1); - return pendingSocketPipe; - } - - private addActiveSocketPipe(socketPipe: SocketPipe) { - this.activeSocketPipes.push(socketPipe); - } - - private addPendingSocketPipe(socketPipe: SocketPipe) { - this.pendingSocketPipes.push(socketPipe); - } - - private removeSocketPipe(newSocketPipe: SocketPipe) { - let i = this.pendingSocketPipes.indexOf(newSocketPipe); - if (i !== -1) { - this.pendingSocketPipes.splice(i, 1); - } else { - i = this.activeSocketPipes.indexOf(newSocketPipe); - if (i !== -1) { - this.activeSocketPipes.splice(i, 1); - } - } - } - - private hasPendingSocketPipes() { - return this.pendingSocketPipes.length > 0; - } - - terminate() { - console.log(`[${this.edgeType}] Terminating SocketListener.`); - - this.server.close(); - for (const socketPipe of this.pendingSocketPipes) { - socketPipe.terminate(); - } - for (const socketPipe of this.activeSocketPipes) { - socketPipe.terminate(); - } - this.server.unref(); - } -} - -class TurnServer { - private peerManager: PeerManager; - private relayServer: net.Server; - private udpHolePunchServer: UDPHolePunchServer; - // public key -> {incoming, outgoing} - private connectionMap: Map = new Map(); - - constructor(peerManager: PeerManager) { - this.peerManager = peerManager; - this.peerManager.setNatHandler(this.handleNatMessage.bind(this)); - - this.udpHolePunchServer = new UDPHolePunchServer(this.peerManager); - } - - private async handleNatMessage(request: Uint8Array): Promise { - const { type, subMessage } = peerInterface.NatMessage.decodeDelimited(request); - let response: Uint8Array; - switch (type) { - case peerInterface.NatMessageType.PEER_CONNECTION: - response = await this.handlePeerConnectionRequest(subMessage); - break; - case peerInterface.NatMessageType.RELAY_CONNECTION: - response = await this.handleRelayConnectionRequest(subMessage); - break; - case peerInterface.NatMessageType.UDP_ADDRESS: - response = await this.handleUDPAddressRequest(); - break; - case peerInterface.NatMessageType.PEER_UDP_ADDRESS: - response = await this.handlePeerUDPAddressRequest(subMessage); - break; - default: - throw Error(`type not supported: ${type}`); - } - const encodedResponse = peerInterface.NatMessage.encodeDelimited({ - type, - isResponse: true, - subMessage: response, - }).finish(); - return encodedResponse; - } - - private async handlePeerConnectionRequest(request: Uint8Array): Promise { - const { publicKey } = peerInterface.PeerConnectionRequest.decodeDelimited(request); - - const peerAddress = this.connectionMap.get(publicKey)?.client.address.toString() ?? ''; - - const responseMessage = peerInterface.PeerConnectionResponse.encodeDelimited({ peerAddress }).finish(); - - return responseMessage; - } - - private async handleRelayConnectionRequest(request: Uint8Array): Promise { - const { publicKey } = peerInterface.RelayConnectionRequest.decodeDelimited(request); - - let server: EndpointServer; - let client: EndpointServer; - - server = new EndpointServer('server'); - server.on('new', (connectingSocketPipe: SocketPipe) => { - client.activateSocketPipe(server, connectingSocketPipe); - }); - await server.start(); - - client = new EndpointServer('client'); - client.on('new', (connectingSocketPipe: SocketPipe) => { - server.activateSocketPipe(client, connectingSocketPipe); - }); - await client.start(); - - this.connectionMap.set(publicKey, { server, client }); - - // send back response message - const serverAddress = server.address.toString(); - const responseMessage = peerInterface.RelayConnectionResponse.encodeDelimited({ serverAddress }).finish(); - - return responseMessage; - } - - private async handleUDPAddressRequest(): Promise { - // send back response message - const address = this.udpHolePunchServer.server.address().toString(); - const responseMessage = peerInterface.UDPAddressResponse.encodeDelimited({ address }).finish(); - - return responseMessage; - } - - private async handlePeerUDPAddressRequest(request: Uint8Array): Promise { - const { publicKey } = peerInterface.PeerUdpAddressRequest.decodeDelimited(request); - - // send back response message - const address = this.udpHolePunchServer.getAddress(publicKey); - const responseMessage = peerInterface.PeerUdpAddressResponse.encodeDelimited({ address }).finish(); - - return responseMessage; - } - - terminate() { - this.connectionMap.forEach(({ server, client }) => { - server.terminate(); - client.terminate(); - }); - this.relayServer.close(); - } -} - -export default TurnServer; diff --git a/src/peers/udp-hole-punch/MicroTransportProtocol.ts b/src/peers/udp-hole-punch/MicroTransportProtocol.ts deleted file mode 100644 index ec8bee6e1..000000000 --- a/src/peers/udp-hole-punch/MicroTransportProtocol.ts +++ /dev/null @@ -1,503 +0,0 @@ -// adapted from https://github.com/mafintosh/utp -import net from 'net'; -import dgram from 'dgram'; -import cyclist from 'cyclist'; -import { EventEmitter } from 'events'; -import { Duplex } from 'readable-stream'; -import { Address } from '../PeerInfo'; - -const EXTENSION = 0; -const VERSION = 1; -const UINT16 = 0xffff; -const ID_MASK = 0xf << 4; -const MTU = 1400; - -const PACKET_DATA = 0 << 4; -const PACKET_FIN = 1 << 4; -const PACKET_STATE = 2 << 4; -const PACKET_RESET = 3 << 4; -const PACKET_SYN = 4 << 4; - -const MIN_PACKET_SIZE = 20; -const DEFAULT_WINDOW_SIZE = 1 << 18; -const CLOSE_GRACE = 5000; - -const BUFFER_SIZE = 512; - -const uint32 = function (n) { - return n >>> 0; -}; - -const uint16 = function (n) { - return n & UINT16; -}; - -const timestamp = (function () { - const offset = process.hrtime(); - const then = Date.now() * 1000; - - return function () { - const diff = process.hrtime(offset); - return uint32(then + 1000000 * diff[0] + ((diff[1] / 1000) | 0)); - }; -})(); - -type Packet = { - id: number; - connection: number; - timestamp: number; - timediff: number; - window: number; - seq: number; - ack: number; - data: Buffer | null; - sent?: number; -}; -const bufferToPacket = function (buffer: Buffer) { - const packet: Packet = { - id: buffer[0] & ID_MASK, - connection: buffer.readUInt16BE(2), - timestamp: buffer.readUInt32BE(4), - timediff: buffer.readUInt32BE(8), - window: buffer.readUInt32BE(12), - seq: buffer.readUInt16BE(16), - ack: buffer.readUInt16BE(18), - data: buffer.length > 20 ? buffer.slice(20) : null, - }; - return packet; -}; - -const packetToBuffer = function (packet: Packet) { - const buffer = Buffer.alloc(20 + (packet.data ? packet.data.length : 0)); - buffer[0] = packet.id | VERSION; - buffer[1] = EXTENSION; - buffer.writeUInt16BE(packet.connection, 2); - buffer.writeUInt32BE(packet.timestamp, 4); - buffer.writeUInt32BE(packet.timediff, 8); - buffer.writeUInt32BE(packet.window, 12); - buffer.writeUInt16BE(packet.seq, 16); - buffer.writeUInt16BE(packet.ack, 18); - if (packet.data) { - packet.data.copy(buffer, 20); - } - return buffer; -}; - -const createPacket = function (connection, id, data): Packet { - return { - id: id, - connection: id === PACKET_SYN ? connection._recvId : connection._sendId, - seq: connection._seq, - ack: connection._ack, - timestamp: timestamp(), - timediff: 0, - window: DEFAULT_WINDOW_SIZE, - data: data, - sent: 0, - }; -}; - -class MTPConnection extends Duplex { - private port: number; - private host: string; - socket: dgram.Socket; - remoteAddress: Address; - private _outgoing: any; - private _incoming: any; - private _closed: boolean; - private _inflightPackets: number; - private _alive: boolean; - private _connecting: boolean; - private _recvId: number; - public get RecvID(): number { - return this._recvId; - } - - private _sendId: number; - private _seq: number; - private _ack: number; - private _synack?: Packet; - constructor(port: number, host: string, socket: dgram.Socket, syn?: Packet) { - super(); - - this.remoteAddress = new Address(host, port); - - if (isNaN(port)) { - throw Error('port cannot be NaN'); - } - this.port = port; - this.host = host; - this.socket = socket; - - this._outgoing = cyclist(BUFFER_SIZE); - this._incoming = cyclist(BUFFER_SIZE); - this._closed = false; - - this._inflightPackets = 0; - this._closed = false; - this._alive = false; - - if (syn) { - this._connecting = false; - this._recvId = uint16(syn.connection + 1); - this._sendId = syn.connection; - this._seq = (Math.random() * UINT16) | 0; - this._ack = syn.seq; - this._synack = createPacket(this, PACKET_STATE, null); - - this._transmit(this._synack); - } else { - this._connecting = true; - this._recvId = 0; // tmp value for v8 opt - this._sendId = 0; // tmp value for v8 opt - this._seq = (Math.random() * UINT16) | 0; - this._ack = 0; - this._synack = undefined; - - socket.on('listening', () => { - this._recvId = socket.address().port; // using the port gives us system wide clash protection - this._sendId = uint16(this._recvId + 1); - this._sendOutgoing(createPacket(this, PACKET_SYN, null)); - }); - - socket.on('error', (err) => { - this.emit('error', err); - }); - - socket.bind(); - } - - const resend = setInterval(this._resend.bind(this), 500); - const keepAlive = setInterval(this._keepAlive.bind(this), 10 * 1000); - let tick = 0; - - const closed = () => { - if (++tick === 2) { - this._closing(); - } - }; - - const sendFin = () => { - if (this._connecting) { - return this.once('connect', sendFin); - } - this._sendOutgoing(createPacket(this, PACKET_FIN, null)); - this.once('flush', closed); - }; - - this.once('finish', sendFin); - this.once('close', () => { - if (!syn) { - setTimeout(socket.close.bind(socket), CLOSE_GRACE); - } - clearInterval(resend); - clearInterval(keepAlive); - }); - this.once('end', () => { - process.nextTick(closed); - }); - } - - destroy(err?: Error | undefined, callback?: ((error: Error | null) => void) | undefined) { - this.end(); - return this; - } - - address() { - return new Address(this.host, this.port); - } - - _read() { - // do nothing... - } - - _write(data: any[], enc: string, callback: () => void) { - if (this._connecting) { - return this._writeOnce('connect', data, enc, callback); - } - - while (this._writable()) { - const payload = this._payload(data); - - this._sendOutgoing(createPacket(this, PACKET_DATA, payload)); - - if (payload.length === data.length) { - return callback(); - } - data = data.slice(payload.length); - } - - this._writeOnce('flush', data, enc, callback); - } - - _writeOnce(event, data, enc, callback) { - this.once(event, () => { - this._write(data, enc, callback); - }); - } - - _writable() { - return this._inflightPackets < BUFFER_SIZE - 1; - } - - _payload(data) { - if (data.length > MTU) { - return data.slice(0, MTU); - } - return data; - } - - _resend() { - const offset = this._seq - this._inflightPackets; - const first = this._outgoing.get(offset); - if (!first) { - return; - } - - const timeout = 500000; - const now = timestamp(); - - if (uint32(first.sent - now) < timeout) { - return; - } - - for (let i = 0; i < this._inflightPackets; i++) { - const packet = this._outgoing.get(offset + i); - if (uint32(packet.sent - now) >= timeout) { - this._transmit(packet); - } - } - } - - _keepAlive() { - if (this._alive) { - return (this._alive = false); - } - this._sendAck(); - } - - _closing() { - if (this._closed) { - return; - } - this._closed = true; - process.nextTick(this.emit.bind(this, 'close')); - } - - // packet handling - - _recvAck(ack) { - const offset = this._seq - this._inflightPackets; - const acked = uint16(ack - offset) + 1; - - if (acked >= BUFFER_SIZE) { - return; // sanity check - } - - for (let i = 0; i < acked; i++) { - this._outgoing.del(offset + i); - this._inflightPackets--; - } - - if (!this._inflightPackets) { - this.emit('flush'); - } - } - - _recvIncoming(packet) { - if (this._closed) { - return; - } - - if (packet.id === PACKET_SYN && this._connecting) { - this._transmit(this._synack); - return; - } - if (packet.id === PACKET_RESET) { - this.push(null); - this.end(); - this._closing(); - return; - } - if (this._connecting) { - if (packet.id !== PACKET_STATE) { - return this._incoming.put(packet.seq, packet); - } - - this._ack = uint16(packet.seq - 1); - this._recvAck(packet.ack); - this._connecting = false; - this.emit('connect'); - - packet = this._incoming.del(packet.seq); - if (!packet) { - return; - } - } - - if (uint16(packet.seq - this._ack) >= BUFFER_SIZE) { - return this._sendAck(); // old packet - } - - this._recvAck(packet.ack); // TODO: other calcs as well - - if (packet.id === PACKET_STATE) { - return; - } - this._incoming.put(packet.seq, packet); - - while ((packet = this._incoming.del(this._ack + 1))) { - this._ack = uint16(this._ack + 1); - - if (packet.id === PACKET_DATA) { - this.push(packet.data); - } - if (packet.id === PACKET_FIN) { - this.push(null); - } - } - - this._sendAck(); - } - - _sendAck() { - this._transmit(createPacket(this, PACKET_STATE, null)); // TODO: make this delayed - } - - _sendOutgoing(packet) { - this._outgoing.put(packet.seq, packet); - this._seq = uint16(this._seq + 1); - this._inflightPackets++; - this._transmit(packet); - } - - _transmit(packet) { - try { - packet.sent = packet.sent === 0 ? packet.timestamp : timestamp(); - const message = packetToBuffer(packet); - this._alive = true; - this.socket.send(message, 0, message.length, this.port, this.host); - } catch (error) {} - } -} - -class UTPServer extends EventEmitter { - _socket: dgram.Socket; - _connections: {}; - _closed: boolean; - constructor() { - super(); - - this._connections = {}; - } - - address() { - return Address.fromAddressInfo(this._socket.address()); - } - - listenSocket(socket: dgram.Socket, onlistening: (...args: any[]) => void) { - this._socket = socket; - - const connections = this._connections; - - socket.on('message', (message, rinfo) => { - if (message.length < MIN_PACKET_SIZE) { - return; - } - const packet = bufferToPacket(message); - - const id = rinfo.address + ':' + (packet.id === PACKET_SYN ? uint16(packet.connection + 1) : packet.connection); - - if (connections[id]) { - return connections[id]._recvIncoming(packet); - } - if (packet.id !== PACKET_SYN || this._closed) { - return; - } - - connections[id] = new MTPConnection(rinfo.port, rinfo.address, socket, packet); - connections[id].on('close', () => { - delete connections[id]; - }); - - this.emit('connection', connections[id]); - }); - - socket.once('listening', () => { - this.emit('listening'); - }); - - if (onlistening) { - this.once('listening', onlistening); - } - } - - listen(connection: MTPConnection, onlistening: (...args: any[]) => void) { - this.listenSocket(connection.socket, onlistening); - } - - listenPort(port: number, onlistening: (...args: any[]) => void) { - const socket = dgram.createSocket('udp4'); - this.listenSocket(socket, onlistening); - socket.bind(port); - } - - close(cb) { - let openConnections = 0; - this._closed = true; - - function onClose() { - if (--openConnections === 0) { - if (this._socket) { - this._socket.close(); - } - if (cb) { - cb(); - } - } - } - - for (const id in this._connections) { - if (this._connections[id]._closed) { - continue; - } - openConnections++; - this._connections[id].once('close', onClose); - this._connections[id].end(); - } - } -} - -function createServer(onconnection) { - const server = new UTPServer(); - if (onconnection) { - server.on('connection', onconnection); - } - return server; -} - -function connect(port: number, host?: string) { - const socket = dgram.createSocket('udp4'); - - const connection = new MTPConnection(port, host || '127.0.0.1', socket, undefined); - - socket.on('message', (message) => { - if (message.length < MIN_PACKET_SIZE) { - return; - } - const packet = bufferToPacket(message); - - if (packet.id === PACKET_SYN) { - return; - } - if (packet.connection !== connection.RecvID) { - return; - } - - connection._recvIncoming(packet); - }); - - return connection; -} - -export { connect, MTPConnection, createServer, UTPServer }; diff --git a/src/peers/udp-hole-punch/UDPHolePunchClient.ts b/src/peers/udp-hole-punch/UDPHolePunchClient.ts deleted file mode 100644 index e017d5c07..000000000 --- a/src/peers/udp-hole-punch/UDPHolePunchClient.ts +++ /dev/null @@ -1,74 +0,0 @@ -// based on https://github.com/SamDecrock/node-udp-hole-punching - -import net from 'net'; -import { Address } from '../PeerInfo'; -import PeerManager from '../PeerManager'; -import { peerInterface } from '../../../proto/js/Peer'; -import UDPToTCPSocketPipe from './socket-pipes/UDPToTCPSocketPipe'; -import TCPToUDPSocketPipe from './socket-pipes/TCPToUDPSocketPipe'; -import { connect, MTPConnection, createServer } from './MicroTransportProtocol'; - -class UDPHolePunchClient { - private peerManager: PeerManager; - - private outgoingSocketPipes: Map = new Map(); - private incomingSocketPipes: Map = new Map(); - - constructor(peerManager: PeerManager) { - this.peerManager = peerManager; - } - - async requestHolePunch(address: Address, peerServerAddress: Address) { - const relayConnection = connect(address.port, address.host); - // const relayConnection = connect(address.port, address.host) - const relayServer = createServer((conn: MTPConnection) => { - const socketPipe = new TCPToUDPSocketPipe(peerServerAddress, conn); - this.outgoingSocketPipes.set(socketPipe.id, socketPipe); - }); - await new Promise((resolve, reject) => { - relayServer.listen(relayConnection, () => { - console.log(`relay connection listening on: ${relayServer.address().host}:${relayServer.address().port}`); - resolve(); - }); - }); - - const request = peerInterface.HolePunchRegisterRequest.encodeDelimited({ - publicKey: this.peerManager.peerInfo.publicKey, - }).finish(); - relayConnection.write(request); - - const connectedAddress = await new Promise
((resolve, reject) => { - let buf: Buffer[] = []; - relayConnection.on('data', (data) => { - buf.push(data); - try { - const { connectedAddress } = peerInterface.HolePunchRegisterResponse.decodeDelimited(Buffer.concat(buf)); - resolve(Address.parse(connectedAddress)); - } catch (error) {} - }); - }); - - return connectedAddress; - } - - // returns the address for a local tcp server that is routed via UTP - async createPipeServer(peerUDPAddress: Address): Promise
{ - console.log('connecting to', peerUDPAddress); - - // create a TCP server and bind it to a random port - const server = net.createServer((socket) => { - // create a new socket pipe - const socketPipe = new UDPToTCPSocketPipe(socket, peerUDPAddress); - this.incomingSocketPipes.set(socketPipe.id, socketPipe); - }); - - return await new Promise((resolve, reject) => { - server.listen(0, () => { - console.log('TCP server routing to UDP server'); - resolve(Address.fromAddressInfo(server.address())); - }); - }); - } -} - -export default UDPHolePunchClient; diff --git a/src/peers/udp-hole-punch/UDPHolePunchServer.ts b/src/peers/udp-hole-punch/UDPHolePunchServer.ts deleted file mode 100644 index c9b3369c2..000000000 --- a/src/peers/udp-hole-punch/UDPHolePunchServer.ts +++ /dev/null @@ -1,47 +0,0 @@ -import PeerInfo from '../PeerInfo'; -import PeerManager from '../PeerManager'; -import { peerInterface } from '../../../proto/js/Peer'; -import { MTPConnection, createServer, UTPServer, connect } from './MicroTransportProtocol'; - -class UDPHolePunchServer { - peerManager: PeerManager; - - server: UTPServer; - // publicKey -> Server - private clientList: Map = new Map(); - - getAddress(publicKey: string) { - return this.clientList.get(PeerInfo.formatPublicKey(publicKey))?.remoteAddress.toString(); - } - - constructor(peerManager: PeerManager) { - this.peerManager = peerManager; - this.server = createServer((conn: MTPConnection) => { - this.handleConnection(conn); - }); - this.server.listenPort(0, () => { - console.log(`UDP Server listening on ` + this.server.address().host + ':' + this.server.address().port); - }); - } - - private handleConnection(conn: MTPConnection) { - let buf: Buffer[] = []; - conn.on('data', (data: Buffer) => { - buf.push(data); - // try decoding - try { - const { publicKey } = peerInterface.HolePunchRegisterRequest.decodeDelimited(Buffer.concat(buf)); - - const remote = conn.remoteAddress; - this.clientList.set(PeerInfo.formatPublicKey(publicKey), connect(remote.port, remote.host)); - - const response = peerInterface.HolePunchRegisterResponse.encodeDelimited({ - connectedAddress: remote.toString(), - }).finish(); - conn.write(response); - } catch (error) {} - }); - } -} - -export default UDPHolePunchServer; diff --git a/src/peers/udp-hole-punch/socket-pipes/TCPToUDPSocketPipe.ts b/src/peers/udp-hole-punch/socket-pipes/TCPToUDPSocketPipe.ts deleted file mode 100644 index 21fa71066..000000000 --- a/src/peers/udp-hole-punch/socket-pipes/TCPToUDPSocketPipe.ts +++ /dev/null @@ -1,142 +0,0 @@ -import net from 'net'; -import { EventEmitter } from 'events'; -import { Address } from '../../PeerInfo'; -import { MTPConnection } from '../MicroTransportProtocol'; - -let socketPipeId = 1; - -class TCPToUDPSocketPipe extends EventEmitter { - id: number; - localAddress: Address; - - tcpSocket: net.Socket; - targetSocketPending: boolean; - buffer: Buffer[]; - udpSocket: MTPConnection; - - constructor(localAddress: Address, relaySocket: MTPConnection) { - super(); - - this.id = socketPipeId; - socketPipeId += 1; - - this.localAddress = localAddress; - if (localAddress == undefined) { - throw Error('localAddress cannot be undefined'); - } - this.udpSocket = relaySocket; - - this.targetSocketPending = true; - this.buffer = []; - - console.log(`[tcp-udp-relay:${this.id}] Created new pending SocketPipe.`); - - this.openRelayEnd(); - } - - private openRelayEnd() { - console.log(`[tcp-udp-relay:${this.id}] Socket pipe will TCP connection to connect to relay server.`); - - // We have a relay socket - now register its handlers - - // On data - this.udpSocket.on('data', (data) => { - // Got data - do we have a target socket? - if (this.tcpSocket === undefined) { - // Create a target socket for the relay socket - connecting to the target - this.openTargetEnd(); - this.emit('pair'); - } - - // Is the target socket still connecting? If so, are we buffering data? - if (this.targetSocketPending) { - // Store the data until we have a target socket - this.buffer[this.buffer.length] = data; - } else { - try { - // Or just pass it directly - this.tcpSocket.write(data); - } catch (ex) { - console.error(`[tcp-udp-relay:${this.id}] Error writing to target socket: `, ex); - } - } - }); - - // On closing - this.udpSocket.on('close', (hadError) => { - if (hadError) { - console.error(`[tcp-udp-relay:${this.id}] Relay socket closed with error.`); - } - - if (this.tcpSocket !== undefined) { - // Destroy the other socket - this.tcpSocket.destroy(); - } else { - // Signal we are closing - server closed the connection - this.emit('close'); - } - }); - - this.udpSocket.on('error', (error) => { - console.error(`[tcp-udp-relay:${this.id}] Error with relay socket: `, error); - }); - } - - private openTargetEnd() { - console.log( - `[tcp-udp-relay:${ - this.id - }] Authorized by relay server. Creating new connection to target ${this.localAddress.toString()}...`, - ); - console.log(`[tcp-udp-target:${this.id}] Socket pipe will TCP connection to connect to target server.`); - - // Or use TCP - this.tcpSocket = net.connect(this.localAddress.port, this.localAddress.host, () => { - console.log(`[tcp-udp-target:${this.id}] Successfully connected to target ${this.localAddress.toString()}.`); - - // Configure socket for keeping connections alive - this.tcpSocket.setKeepAlive(true, 120 * 1000); - - // Connected, not pending anymore - this.targetSocketPending = false; - - // And if we have any buffered data, forward it - try { - for (const bufferItem of this.buffer) { - this.tcpSocket.write(bufferItem); - } - } catch (ex) { - console.error(`[tcp-udp-target:${this.id}] Error writing to target socket: `, ex); - } - - // Clear the array - this.buffer.length = 0; - }); - - // Got data from the target socket? - this.tcpSocket.on('data', (data) => { - try { - // Forward it! - this.udpSocket.write(data); - } catch (ex) { - console.error(`target:${this.id}] Error writing to target socket: `, ex); - } - }); - - this.tcpSocket.on('error', (hadError) => { - if (hadError) { - console.error(`[target:${this.id}] Target socket was closed with error: `, hadError); - } - - this.terminate(); - }); - } - - terminate() { - console.log(`[tcp-udp-relay:${this.id}] Terminating socket pipe...`); - this.removeAllListeners(); - this.udpSocket.destroy(); - } -} - -export default TCPToUDPSocketPipe; diff --git a/src/peers/udp-hole-punch/socket-pipes/UDPToTCPSocketPipe.ts b/src/peers/udp-hole-punch/socket-pipes/UDPToTCPSocketPipe.ts deleted file mode 100644 index 2bf08a8ec..000000000 --- a/src/peers/udp-hole-punch/socket-pipes/UDPToTCPSocketPipe.ts +++ /dev/null @@ -1,138 +0,0 @@ -import net from 'net'; -import { EventEmitter } from 'events'; -import { Address } from '../../PeerInfo'; -import { MTPConnection, connect } from '../MicroTransportProtocol'; - -let socketPipeId = 0; - -class UDPToTCPSocketPipe extends EventEmitter { - id: number; - udpAddress: Address; - - udpSocket: MTPConnection; - targetSocketPending: boolean; - buffer: Buffer[]; - tcpSocket: net.Socket; - - constructor(tcpSocket: net.Socket, udpAddress: Address) { - super(); - - this.id = socketPipeId; - socketPipeId += 1; - - this.udpAddress = udpAddress; - this.tcpSocket = tcpSocket; - - this.targetSocketPending = true; - this.buffer = []; - - console.log(`[udp-tcp-relay:${this.id}] Created new pending SocketPipe.`); - - this.openRelayEnd(); - } - - private openRelayEnd() { - console.log(`[udp-tcp-relay:${this.id}] Socket pipe will TCP connection to connect to relay server.`); - - // We have a relay socket - now register its handlers - - // On data - this.tcpSocket.on('data', (data) => { - // Got data - do we have a target socket? - if (this.udpSocket === undefined) { - // Create a target socket for the relay socket - connecting to the target - this.openTargetEnd(); - this.emit('pair'); - } - - // Is the target socket still connecting? If so, are we buffering data? - if (this.targetSocketPending) { - // Store the data until we have a target socket - this.buffer[this.buffer.length] = data; - } else { - try { - // Or just pass it directly - this.udpSocket.write(data); - } catch (ex) { - console.error(`[udp-tcp-relay:${this.id}] Error writing to target socket: `, ex); - } - } - }); - - // On closing - this.tcpSocket.on('close', (hadError) => { - if (hadError) { - console.error(`[udp-tcp-relay:${this.id}] Relay socket closed with error.`); - } - - if (this.udpSocket !== undefined) { - // Destroy the other socket - this.udpSocket.destroy(); - } else { - // Signal we are closing - server closed the connection - this.emit('close'); - } - }); - - this.tcpSocket.on('error', (error) => { - console.error(`[udp-tcp-relay:${this.id}] Error with relay socket: `, error); - }); - } - - private openTargetEnd() { - console.log( - `[udp-tcp-relay:${ - this.id - }] Authorized by relay server. Creating new connection to target ${this.udpAddress.toString()}...`, - ); - console.log(`[udp-tcp-target:${this.id}] Socket pipe will TCP connection to connect to target server.`); - - // connect udp socket - this.udpSocket = connect(this.udpAddress.port, this.udpAddress.host); - - console.log(`[udp-tcp-target:${this.id}] Successfully connected to target ${this.udpAddress.toString()}.`); - - // Connected, not pending anymore - this.targetSocketPending = false; - - // And if we have any buffered data, forward it - try { - for (const bufferItem of this.buffer) { - this.udpSocket.write(bufferItem); - } - } catch (ex) { - console.error(`[udp-tcp-target:${this.id}] Error writing to target socket: `, ex); - } - - // Clear the array - this.buffer.length = 0; - - // Got data from the target socket? - this.udpSocket.on('data', (data) => { - try { - // Forward it! - if (!this.tcpSocket.destroyed) { - this.tcpSocket.write(data); - } - } catch (ex) { - console.error(`target:${this.id}] Error writing to target socket: `, ex); - } - }); - - this.udpSocket.on('error', (hadError) => { - if (hadError) { - console.error(`[target:${this.id}] Target socket was closed with error: `, hadError); - } - - this.terminate(); - }); - } - - terminate() { - console.log(`[udp-tcp-relay:${this.id}] Terminating socket pipe...`); - this.removeAllListeners(); - this.tcpSocket.destroy(); - } -} - -export default UDPToTCPSocketPipe; diff --git a/src/utils.ts b/src/utils.ts index 6f3fcb4b9..a41081dfd 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -57,6 +57,37 @@ async function promiseAny(promiseList: Promise[]): Promise { }); } +/** + * Waits until all promises are fulfiled + * @param promiseList List of promises + */ +async function promiseAll(promiseList: Promise[]): Promise { + return await new Promise((resolve, reject) => { + const outputList: T[] = []; + const errorList: Error[] = []; + let count = 0 + for (const promise of promiseList) { + promise + .then((p) => { + outputList.push(p) + }) + .catch((error) => { + errorList.push(error) + }).finally(() => { + count += 1 + if (count >= promiseList.length) { + // check if all have failed + if (errorList.length == promiseList.length) { + reject(errorList.reduceRight((p, c) => Error(`${p.message}||${c.message}`))); + } else { + resolve(outputList) + } + } + }) + } + }); +} + function protobufToString(message: Uint8Array): string { return protobufjs.util.base64.encode(message, 0, message.length); } @@ -98,4 +129,56 @@ async function getPort(defaultPort?: number, defaultHost?: string): Promise PeerConnection; + private setGitHandler: (handler: (request: Uint8Array, publicKey: string) => Promise) => void; private metadataPath: string; private vaults: Map; @@ -22,16 +23,24 @@ class VaultManager { private gitBackend: GitBackend; private gitFrontend: GitFrontend; + // status + private creatingVault: boolean = false; + private cloningVault: boolean = false; + private pullingVault: boolean = false; + private deletingVault: boolean = false; + constructor( polykeyPath: string = `${os.homedir()}/.polykey`, fileSystem: typeof fs, keyManager: KeyManager, - peerManager: PeerManager, + connectToPeer: (peerId: string) => PeerConnection, + setGitHandler: (handler: (request: Uint8Array, publicKey: string) => Promise) => void, ) { this.polykeyPath = polykeyPath; this.fileSystem = fileSystem; this.keyManager = keyManager; - this.peerManager = peerManager; + this.connectToPeer = connectToPeer; + this.setGitHandler = setGitHandler; this.metadataPath = path.join(polykeyPath, '.vaultKeys'); // Make polykeyPath if it doesn't exist @@ -46,23 +55,32 @@ class VaultManager { ((repoName: string) => this.getVault(repoName).EncryptedFS).bind(this), this.getVaultNames.bind(this), ); - this.gitFrontend = new GitFrontend(peerManager); + this.gitFrontend = new GitFrontend(this.connectToPeer.bind(this)); - this.peerManager.setGitHandler(this.gitBackend.handleGitMessage.bind(this.gitBackend)); + this.setGitHandler(this.gitBackend.handleGitMessage.bind(this.gitBackend)); // Read in vault keys this.loadEncryptedMetadata(); } + public get Status() { + return { + creatingVault: this.creatingVault, + cloningVault: this.cloningVault, + pullingVault: this.pullingVault, + deletingVault: this.deletingVault, + }; + } + /** * Get the names of all vaults in memory */ - getVaultNames(publicKey?: string): string[] { + getVaultNames(peerId?: string): string[] { const vaultNames = Array.from(this.vaults.keys()); - if (publicKey) { + if (peerId) { const allowedVaultNames: string[] = []; for (const vaultName of vaultNames) { - if (this.getVault(vaultName).peerCanAccess(publicKey)) { + if (this.getVault(vaultName).peerCanAccess(peerId)) { allowedVaultNames.push(vaultName); } } @@ -100,7 +118,9 @@ class VaultManager { * @param key Optional key to use for the vault encryption, otherwise it is generated */ async newVault(vaultName: string, key?: Buffer): Promise { + this.creatingVault = true; if (this.vaultExists(vaultName)) { + this.creatingVault = false; throw Error('Vault already exists!'); } @@ -126,10 +146,13 @@ class VaultManager { // Set vault this.vaults.set(vaultName, vault); - return this.getVault(vaultName); + const retrievedVault = this.getVault(vaultName); + this.creatingVault = false; + return retrievedVault; } catch (err) { // Delete vault dir and garbage collect await this.deleteVault(vaultName); + this.creatingVault = false; throw err; } } @@ -141,8 +164,10 @@ class VaultManager { * @param getSocket Function to get an active connection to provided address */ async cloneVault(vaultName: string, publicKey: string): Promise { + this.cloningVault = true; // Confirm it doesn't exist locally already if (this.vaultExists(vaultName)) { + this.cloningVault = false; throw Error('Vault name already exists locally, try pulling instead'); } @@ -156,6 +181,7 @@ class VaultManager { }); if (!info.refs) { + this.cloningVault = false; throw Error(`Peer does not have vault: '${vaultName}'`); } @@ -181,6 +207,9 @@ class VaultManager { // Finally return the vault const vault = new Vault(vaultName, vaultKey, this.polykeyPath, this.gitFrontend); this.vaults.set(vaultName, vault); + this.vaultKeys.set(vaultName, vaultKey); + await this.writeEncryptedMetadata(); + this.cloningVault = false; return vault; } @@ -196,8 +225,10 @@ class VaultManager { * @param publicKey Public key of polykey node that owns vault to be pulled */ async pullVault(vaultName: string, publicKey: string) { + this.pullingVault = true; const vault = this.getVault(vaultName); await vault.pullVault(publicKey); + this.pullingVault = false; } /** @@ -216,6 +247,7 @@ class VaultManager { * @param vaultName Name of vault to be destroyed */ async deleteVault(vaultName: string) { + this.deletingVault = true; // this is convenience function for removing all tags // and triggering garbage collection // destruction is a better word as we should ensure all traces are removed @@ -234,6 +266,7 @@ class VaultManager { await this.writeEncryptedMetadata(); const vaultPathExists = this.fileSystem.existsSync(vaultPath); + this.deletingVault = false; if (vaultPathExists) { throw Error('Vault folder could not be deleted!'); } @@ -261,7 +294,7 @@ class VaultManager { async loadEncryptedMetadata(): Promise { // Check if file exists - if (this.fileSystem.existsSync(this.metadataPath) && this.keyManager.identityLoaded) { + if (this.fileSystem.existsSync(this.metadataPath) && this.keyManager.KeypairUnlocked) { const encryptedMetadata = this.fileSystem.readFileSync(this.metadataPath); const metadata = (await this.keyManager.decryptData(encryptedMetadata)).toString(); diff --git a/tests/lib/agent/Agent.test.ts b/tests/lib/agent/Agent.test.ts index a3f215ee9..44d901d80 100644 --- a/tests/lib/agent/Agent.test.ts +++ b/tests/lib/agent/Agent.test.ts @@ -24,7 +24,6 @@ describe('Agent and Client class', () => { const request = new pb.NewNodeMessage request.setUserid('john.smith@email.com') request.setPassphrase('passphrase') - request.setNbits(1024) const res = await promisifyGrpc(client.newNode.bind(client))(request) as pb.BooleanMessage expect(res.getB()).toEqual(true) diff --git a/tests/lib/api/API.test.ts b/tests/lib/api/API.test.ts index 93c18a694..be36bd15f 100644 --- a/tests/lib/api/API.test.ts +++ b/tests/lib/api/API.test.ts @@ -20,19 +20,20 @@ describe('HTTP API', () => { let accessToken: string let vaultSet: Set - let secretMap: Map + let secretMap: Map beforeEach(async () => { tempDir = fs.mkdtempSync(`${os.tmpdir}/pktest${randomString()}`) tlsCredentials = createTLSCredentials() peerInfo = new PeerInfo( - await generatePublicKey() + await generatePublicKey(), + 'rootCertificate' ) // initialize data sets vaultSet = new Set() secretMap = new Map() - secretMap.set('secret1', 'secret 1 content') + secretMap.set('secret1', Buffer.from('secret 1 content')) api = new HttpApi( (apiAddress: Address) => { peerInfo.apiAddress = apiAddress; }, @@ -45,8 +46,8 @@ describe('HTTP API', () => { async (vaultName: string) => { vaultSet.delete(vaultName); }, (vaultName: string) => Array.from(secretMap.entries()).map((e) => e[0]), (vaultName: string, secretName: string) => secretMap.get(secretName)!, - async (vaultName: string, secretName: string, secretContent: string) => { secretMap.set(secretName, secretContent); return true }, - async (vaultName: string, secretName: string) => { return secretMap.delete(secretName) } + async (vaultName: string, secretName: string, secretContent: Buffer) => { secretMap.set(secretName, secretContent) }, + async (vaultName: string, secretName: string) => { secretMap.delete(secretName) } ) await api.start() accessToken = api.newOAuthToken(['admin']) @@ -102,7 +103,7 @@ describe('HTTP API', () => { test('can get secret content', async () => { const response = await makeRequest('GET', '/secrets/vault1/secret1') const expectedSecretContent = secretMap.get('secret1') - expect(response).toEqual(expectedSecretContent) + expect(response).toEqual(expectedSecretContent?.toString()) }) test('can add new secret', async () => { @@ -130,8 +131,9 @@ describe('HTTP API', () => { const flags = kbpgp['const'].openpgp; const params = { userid: `John Smith `, + ecc: true, primary: { - nbits: 1024, + nbits: 384, flags: flags.certify_keys | flags.sign_data | flags.auth | flags.encrypt_comm | flags.encrypt_storage, expire_in: 0, // never expire }, @@ -148,12 +150,12 @@ describe('HTTP API', () => { return publicKey } - const makeRequest = async (method: string, path: string, body?: Object | string): Promise => { + const makeRequest = async (method: string, path: string, body?: string): Promise => { return await new Promise((resolve, reject) => { const headers = {} headers['Authorization'] = `Bearer ${accessToken}` if (body) { - headers['Content-Type'] = (typeof body === 'string') ? 'text/plain' : 'application/json' + headers['Content-Type'] = 'text/plain' } const options: http.RequestOptions = { hostname: peerInfo?.apiAddress?.host, @@ -161,7 +163,7 @@ describe('HTTP API', () => { path, method, ca: [tlsCredentials.rootCertificate], - headers + headers, } const req = http.request(options, (res) => { @@ -169,9 +171,8 @@ describe('HTTP API', () => { res.on('data', (data) => { try { resolve(JSON.parse(data)) - } catch (error) { - reject(data) - } + } catch (error) {} + resolve(data) }); res.on('error', (err) => { reject(err) diff --git a/tests/lib/keys/KeyManager.test.ts b/tests/lib/keys/KeyManager.test.ts index 9e57eddd0..fecbcfb39 100644 --- a/tests/lib/keys/KeyManager.test.ts +++ b/tests/lib/keys/KeyManager.test.ts @@ -14,7 +14,7 @@ describe('KeyManager class', () => { // Create keyManager km = new KeyManager(tempDir, fs) - await km.generateKeyPair('John Smith', 'passphrase', 1024, true) + await km.generateKeyPair('John Smith', 'passphrase', true) }) afterAll(() => { @@ -23,7 +23,7 @@ describe('KeyManager class', () => { test('can create keypairs', async () => { // Create private keys (async) - expect(km.generateKeyPair('John Smith', 'passphrase', 1024)).resolves.not.toThrow() + expect(km.generateKeyPair('John Smith', 'passphrase')).resolves.not.toThrow() }) test('can create symmetric keys', async () => { @@ -36,7 +36,7 @@ describe('KeyManager class', () => { test('can load an identity from a public key', async () => { - const keypair = await km.generateKeyPair('John Smith', 'passphrase', 1024) + const keypair = await km.generateKeyPair('John Smith', 'passphrase') const identity = await km.getIdentityFromPublicKey(Buffer.from(keypair.public!)) @@ -45,7 +45,7 @@ describe('KeyManager class', () => { test('can load an identity from a private key', async () => { - const keypair = await km.generateKeyPair('John Smith', 'passphrase', 1024) + const keypair = await km.generateKeyPair('John Smith', 'passphrase') const identity = await km.getIdentityFromPrivateKey(Buffer.from(keypair.private!), 'passphrase') diff --git a/tests/lib/keys/PKI.test.ts b/tests/lib/keys/PKI.test.ts index f12994bbe..91e903fa2 100644 --- a/tests/lib/keys/PKI.test.ts +++ b/tests/lib/keys/PKI.test.ts @@ -28,7 +28,7 @@ describe('PKI testing', () => { // Create pki kmCA = new KeyManager(tempDirPeerCA, fs) - await kmCA.generateKeyPair('kmCA', 'passphrase', 1024) + await kmCA.generateKeyPair('kmCA', 'passphrase') // ======== PEER A ======== // // Define temp directory @@ -36,7 +36,7 @@ describe('PKI testing', () => { // Create pki kmA = new KeyManager(tempDirPeerA, fs) - await kmA.generateKeyPair('kmA', 'passphrase', 1024) + await kmA.generateKeyPair('kmA', 'passphrase') kmA.pki.addCA(kmCA.pki.RootCert) // ======== PEER B ======== // @@ -45,7 +45,7 @@ describe('PKI testing', () => { // Create pki kmB = new KeyManager(tempDirPeerB, fs) - await kmB.generateKeyPair('kmB', 'passphrase', 1024) + await kmB.generateKeyPair('kmB', 'passphrase') kmB.pki.addCA(kmCA.pki.RootCert) }) @@ -110,8 +110,6 @@ describe('PKI testing', () => { }) req.on('error', (e) => { - console.log(e); - expect(e).toBeUndefined() done() }); diff --git a/tests/lib/peers/PeerInfo.test.ts b/tests/lib/peers/PeerInfo.test.ts index 128bcc663..8e8434e04 100644 --- a/tests/lib/peers/PeerInfo.test.ts +++ b/tests/lib/peers/PeerInfo.test.ts @@ -11,8 +11,9 @@ describe('PeerInfo class', () => { const flags = kbpgp['const'].openpgp; const params = { userid: `John Smith `, + ecc: true, primary: { - nbits: 1024, + nbits: 384, flags: flags.certify_keys | flags.sign_data | flags.auth | flags.encrypt_comm | flags.encrypt_storage, expire_in: 0, // never expire }, @@ -32,11 +33,10 @@ describe('PeerInfo class', () => { beforeAll(async () => { // generate a kbpgp keypair - const mockPublicKey1 = await generatePublicKey() - const mockPublicKey2 = await generatePublicKey() + const mockPublicKey = await generatePublicKey() peerInfoA = new PeerInfo( - mockPublicKey1, - mockPublicKey2, + mockPublicKey, + 'rootCertificate', '0.0.0.0:3298', '0.0.0.0:2356', ) diff --git a/tests/lib/peers/PeerManager.test.ts b/tests/lib/peers/PeerManager.test.ts index 76164c8ec..3f8a6520d 100644 --- a/tests/lib/peers/PeerManager.test.ts +++ b/tests/lib/peers/PeerManager.test.ts @@ -17,7 +17,7 @@ describe('PeerManager class', () => { // Create keyManager const keyManagerA = new KeyManager(tempDirPeerA, fs) - await keyManagerA.generateKeyPair('John Smith', 'some passphrase', 1024, true) + await keyManagerA.generateKeyPair('John Smith', 'some passphrase', true) // Initialize polykey const peerA = new Polykey( @@ -37,7 +37,7 @@ describe('PeerManager class', () => { // Create keyManager const keyManagerB = new KeyManager(tempDirPeerB, fs) - await keyManagerB.generateKeyPair('Jane Doe', 'some different passphrase', 1024, true) + await keyManagerB.generateKeyPair('Jane Doe', 'some different passphrase', true) // Initialize polykey const peerB = new Polykey( @@ -127,7 +127,6 @@ describe('PeerManager class', () => { tempDirPeerB = nodes.nodeB.tempDir // open relay connection from peerB to peerA - await peerB.peerManager.turnClient.requestRelayConnection(peerA.peerManager.peerInfo.publicKey) peerA.peerManager.updatePeer(peerB.peerManager.peerInfo) peerB.peerManager.updatePeer(peerA.peerManager.peerInfo) // ======== PEER C ======== // @@ -136,7 +135,7 @@ describe('PeerManager class', () => { // Create keyManager const keyManagerC = new KeyManager(tempDirPeerC, fs) - await keyManagerC.generateKeyPair('John Smith', 'some passphrase', 1024, true) + await keyManagerC.generateKeyPair('John Smith', 'some passphrase', true) // Initialize polykey peerC = new Polykey( @@ -214,8 +213,6 @@ describe('PeerManager class', () => { peerB = nodes.nodeB.pk tempDirPeerB = nodes.nodeB.tempDir - // open relay connection from peerB to peerA - await peerB.peerManager.turnClient.requestLocalHolePunchAddress(peerA.peerManager.peerInfo.publicKey) peerA.peerManager.updatePeer(peerB.peerManager.peerInfo) peerB.peerManager.updatePeer(peerA.peerManager.peerInfo) @@ -225,7 +222,7 @@ describe('PeerManager class', () => { // Create keyManager const keyManagerC = new KeyManager(tempDirPeerC, fs) - await keyManagerC.generateKeyPair('John Smith', 'some passphrase', 1024, true) + await keyManagerC.generateKeyPair('John Smith', 'some passphrase', true) // Initialize polykey peerC = new Polykey( diff --git a/tests/lib/vaults/Vaults.test.ts b/tests/lib/vaults/Vaults.test.ts index 4d73231c3..20167812b 100644 --- a/tests/lib/vaults/Vaults.test.ts +++ b/tests/lib/vaults/Vaults.test.ts @@ -22,7 +22,7 @@ describe('VaultManager class', () => { // Create CA keyManager caKm = new KeyManager(caTempDir, fs) - await caKm.generateKeyPair('John Smith', 'passphrase', 1024, true) + await caKm.generateKeyPair('John Smith', 'passphrase', true) // Define temp directory tempDir = fs.mkdtempSync(`${os.tmpdir}/pktest${randomString()}`) @@ -31,7 +31,7 @@ describe('VaultManager class', () => { const km = new KeyManager(tempDir, fs) // Generate keypair - await km.generateKeyPair('John Smith', 'passphrase', 1024, true) + await km.generateKeyPair('John Smith', 'passphrase', true) // request certificate from CA km.pki.addCA(caKm.pki.RootCert) @@ -119,7 +119,7 @@ describe('VaultManager class', () => { const km2 = new KeyManager(tempDir2, fs) // Generate keypair - await km2.generateKeyPair('Jane Doe', 'passphrase', 1024, true) + await km2.generateKeyPair('Jane Doe', 'passphrase', true) // request certificate from CA km2.pki.addCA(caKm.pki.RootCert) diff --git a/tests/spec/keys/KeyManager.model.ts b/tests/spec/keys/KeyManager.model.ts new file mode 100644 index 000000000..9a03d078d --- /dev/null +++ b/tests/spec/keys/KeyManager.model.ts @@ -0,0 +1,40 @@ +import { createModel } from '@xstate/test'; +import { KeyManager } from '../../../src/Polykey'; +import { keysMachine, KeysStateSchema } from '../../../spec/keys/Keys.spec' +import { randomString } from '../../../src/utils'; + +const keysModel = createModel(keysMachine).withEvents({ + GENERATE_KEYPAIR: { + exec: async (km: KeyManager) => { + return await km.generateKeyPair(randomString(), 'passphrase', true) + } + }, + LOAD_KEYPAIR: { + exec: async (km: KeyManager) => { + const keypair = await km.generateKeyPair(randomString(), 'passphrase') + return km.loadKeyPair(Buffer.from(keypair.public), Buffer.from(keypair.private)) + } + }, + UNLOCK_IDENTITY: { + exec: async (km: KeyManager) => { + return await km.unlockIdentity('passphrase') + } + }, + LOCK_IDENTITY: { + exec: async (km: KeyManager) => { + return km.lockIdentity() + } + }, + SUCCESS: { + exec: async (km: KeyManager) => { + + } + }, + FAILURE: { + exec: async (km: KeyManager) => { + + } + }, +}); + +export { keysModel } diff --git a/tests/spec/keys/KeyManager.test.ts b/tests/spec/keys/KeyManager.test.ts new file mode 100644 index 000000000..d440b23d6 --- /dev/null +++ b/tests/spec/keys/KeyManager.test.ts @@ -0,0 +1,26 @@ +import os from 'os' +import fs from 'fs' +import { keysModel } from './KeyManager.model'; +import { KeyManager } from '../../../src/Polykey'; +import { randomString } from '../../../src/utils'; + + +describe('KeyManager spec testing', () => { + const testPlans = keysModel.getSimplePathPlans(); + + testPlans.forEach((plan) => { + describe(plan.description, () => { + plan.paths.forEach((path) => { + test(path.description, async () => { + const tempDir = fs.mkdtempSync(`${os.tmpdir}/pktest${randomString()}`) + const km = new KeyManager(tempDir, fs) + await path.test(km); + }); + }); + }); + }); + + test('should have full coverage', () => { + return keysModel.testCoverage(); + }); +}); diff --git a/tests/spec/peers/PeerDHT.model.ts b/tests/spec/peers/PeerDHT.model.ts new file mode 100644 index 000000000..9d5ee01ee --- /dev/null +++ b/tests/spec/peers/PeerDHT.model.ts @@ -0,0 +1,240 @@ +import { createModel } from '@xstate/test'; +import PeerInfo from '../../../src/peers/PeerInfo'; +import { peerInterface } from '../../../proto/js/Peer'; +import PeerDHT from '../../../src/peers/peer-dht/PeerDHT'; +import { SubServiceType } from '../../../proto/compiled/Peer_pb'; +import { peerDHTMachine, PeerDHTStateSchema } from '../../../spec/peers/PeerDHT.spec'; + +function toPeerInfoMessageList(peerInfos: PeerInfo[]): peerInterface.IPeerInfoMessage[] { + return peerInfos + .map((p) => { + return { + publicKey: p.publicKey, + rootCertificate: p.rootCertificate, + peerAddress: p.peerAddress?.toString(), + apiAddress: p.apiAddress?.toString(), + }; + }); +} + +function createMockPeerStore() { + const localPeerInfo = new PeerInfo( + ` + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: Keybase OpenPGP v2.0.82 + Comment: https://keybase.io/crypto + + xm8EX4/nNRMFK4EEACIDAwQ1Nb9xkYaansKNgu0nVobzT3NFpSLJFuPJN7eFgR3F + MCRxH8cIBqdnzNZ5qysw5MAau+RWx7LZzkmQVAThDcQDhvfIpkufBtEwsoNxA4F2 + esmrYKthcd5s1J79G3klyTDNBlJvYmJpZcKWBBMTCgAeBQJfj+c1AhsBAwsJBwMV + CggCHgECF4ADFgIBAhkBAAoJEOqDKVJzZAKR2VkBgKBhcFmMsI9Dkx+6pHWfN7dW + 6uR2b4ZBZqYBmTt3zcwXV04SCp0+/oYesrG0J6WU7wF+KYv0C4FlltolpAyCbV3o + vXjBs068fcrsRIP9K8UtDJdwKTtotE8Rakr7QCwjgQy3zlYEX4/nNRIIKoZIzj0D + AQcCAwRPxgwMfXu7V3b3fwMWNoVkIlyUfEmj0wmP6ZF4eUNYcp7t389ny+iYuXrT + Pf0h+zi6eV4pDhdwWEYsl0EGp4TSAwEKCcKHBBgTCgAPBQJfj+c1BQkPCZwAAhsM + AAoJEOqDKVJzZAKRVlMBf2Rf9rJohxKJvxL7ZW06+KWal0BAemXM/rl0yinhGNg/ + R3DwoTD0XGyrVj4Wc73saAGA314hhallOJzpQ6evZAOEsiokZeOMDqre6wJpH4/w + +ErUWcqe0MSksPQGAmV2xgnwzlIEX4/nNRMIKoZIzj0DAQcCAwTKjFLVrl6KMj9A + 7jZPJaTWiEBaCNz7N2BAgnItu86yWAYLDR3Dod6knoUs3s4JyIiAkHhY1YV6FtN1 + JpmdhYrpwsAnBBgTCgAPBQJfj+c1BQkPCZwAAhsiAGoJEOqDKVJzZAKRXyAEGRMK + AAYFAl+P5zUACgkQrvSMxa2e7bGJTwEAiIz9s6VDCiwnXsVoNzHDAFwulAkn1Yqk + zYSB0xi84uEBAJ2qEZznS3zvzg4WZweaX6pu25b6qolP0GYaT9D/oouxR6YBgI1s + ibM44XDnvb2guY07zUN7RXZBZrUwCyHwCfEfsZg0vwkHXD1ib530HgKcZIF21gGA + rP6oio2zgC7v/WgGPcu1qwOADZCEwYY4BVBIJOEDZ16pVH701JFoBRkBih/sMjAc + =97N3 + -----END PGP PUBLIC KEY BLOCK----- + `, + 'rootCertiicate', + '0.0.0.0:0', + '0.0.0.0:0', + ) + const peerInfo1 = new PeerInfo( + + ` + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: Keybase OpenPGP v2.0.82 + Comment: https://keybase.io/crypto + + xm8EX4/nNxMFK4EEACIDAwQxOGBYM6yuUgb4fdaYws0Fmmq3JJerQsMRBcMej53b + UhJZHnlWICh1jvCPBrRTrEg3AMHypaBeDfLJxOBSBFAOflsWQ1wlgjjBQ2IIIgOC + K5Y5eAcSWzgjni1OLMkiZDXNBlJvYmJpZcKWBBMTCgAeBQJfj+c3AhsBAwsJBwMV + CggCHgECF4ADFgIBAhkBAAoJEG/32vAUft0JsMkBgMXXNTxqPTkQPEsXpZylclbE + yVrX2+RwnaR972MtPMkpysMc0NRZC09V8sY1S051RAGA/VKUphAQ75/nlJMYEINp + 7F9Dt4v0XgfHOk495CG3gbtF6GCpDeAF+7UnP7id9+VAzlYEX4/nNxIIKoZIzj0D + AQcCAwSukjWy3W3km7f3UqDmmUHCtEHVegurJW592YPg8OPBFUbI+Fnprjg04pp9 + Y9MYtOkdzJiytrJVRGJqe797ejJsAwEKCcKHBBgTCgAPBQJfj+c3BQkPCZwAAhsM + AAoJEG/32vAUft0J1pUBfRdZGUSwS3G9+n56R01aof/5Gs1lmoevn5q6wxxbWask + DQtgizk+fSRP1MvFtkgxjwGAxvwBblCIZbbFWhSjQvkzVxwyVVy1BO8dt5I8LIja + HHITWfHuy5k4gIiFz/DYupQtzlIEX4/nNxMIKoZIzj0DAQcCAwTU0TihuXfRa0+J + DbaM7g3lLgpxMvxmFqE8kZMt5GMuh9zYMlF7kvK5GnvCI1NA91OYfUPt/m6LY9ro + 2eq9ObA4wsAnBBgTCgAPBQJfj+c3BQkPCZwAAhsiAGoJEG/32vAUft0JXyAEGRMK + AAYFAl+P5zcACgkQEeaJRMyfVoxi4QD/TVvztePuTaStyzQzL5V5SS6LeAcdhT4i + NoaXSaeqBhwBAO00snBJ+7FysYgPDlZG52NWxxBEmbC6Yh8kWkpEVqT+W00Bf0/j + a3RLDOu58urhkd08mOgz9HJKT64dVcnbsPRIyo7UCYSXjJFSlGhSnzLz7u4ELQGA + lpMrop0IhEK5qYHth9z4ew2Rflz1YZfAQeTlYza72LUbKfONKVlyAhiM9SzYvt/+ + =WFki + -----END PGP PUBLIC KEY BLOCK----- + `, + 'rootCertiicate', + '0.0.0.0:0', + '0.0.0.0:0', + ) + const peerInfo2 = new PeerInfo( + + ` + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: Keybase OpenPGP v2.0.82 + Comment: https://keybase.io/crypto + + xm8EX4/nNxMFK4EEACIDAwQxOGBYM6yuUgb4fdaYws0Fmmq3JJerQsMRBcMej53b + UhJZHnlWICh1jvCPBrRTrEg3AMHypaBeDfLJxOBSBFAOflsWQ1wlgjjBQ2IIIgOC + K5Y5eAcSWzgjni1OLMkiZDXNBlJvYmJpZcKWBBMTCgAeBQJfj+c3AhsBAwsJBwMV + CggCHgECF4ADFgIBAhkBAAoJEG/32vAUft0JsMkBgMXXNTxqPTkQPEsXpZylclbE + yVrX2+RwnaR972MtPMkpysMc0NRZC09V8sY1S051RAGA/VKUphAQ75/nlJMYEINp + 7F9Dt4v0XgfHOk495CG3gbtF6GCpDeAF+7UnP7id9+VAzlYEX4/nNxIIKoZIzj0D + AQcCAwSukjWy3W3km7f3UqDmmUHCtEHVegurJW592YPg8OPBFUbI+Fnprjg04pp9 + Y9MYtOkdzJiytrJVRGJqe797ejJsAwEKCcKHBBgTCgAPBQJfj+c3BQkPCZwAAhsM + AAoJEG/32vAUft0J1pUBfRdZGUSwS3G9+n56R01aof/5Gs1lmoevn5q6wxxbWask + DQtgizk+fSRP1MvFtkgxjwGAxvwBblCIZbbFWhSjQvkzVxwyVVy1BO8dt5I8LIja + HHITWfHuy5k4gIiFz/DYupQtzlIEX4/nNxMIKoZIzj0DAQcCAwTU0TihuXfRa0+J + DbaM7g3lLgpxMvxmFqE8kZMt5GMuh9zYMlF7kvK5GnvCI1NA91OYfUPt/m6LY9ro + 2eq9ObA4wsAnBBgTCgAPBQJfj+c3BQkPCZwAAhsiAGoJEG/32vAUft0JXyAEGRMK + AAYFAl+P5zcACgkQEeaJRMyfVoxi4QD/TVvztePuTaStyzQzL5V5SS6LeAcdhT4i + NoaXSaeqBhwBAO00snBJ+7FysYgPDlZG52NWxxBEmbC6Yh8kWkpEVqT+W00Bf0/j + a3RLDOu58urhkd08mOgz9HJKT64dVcnbsPRIyo7UCYSXjJFSlGhSnzLz7u4ELQGA + lpMrop0IhEK5qYHth9z4ew2Rflz1YZfAQeTlYza72LUbKfONKVlyAhiM9SzYvt/+ + =WFki + -----END PGP PUBLIC KEY BLOCK----- + `, + 'rootCertiicate', + '0.0.0.0:0', + '0.0.0.0:0', + ) + const peerStore = new Map() + peerStore.set(peerInfo1.id, peerInfo1) + peerStore.set(peerInfo2.id, peerInfo2) + return {peerStore, localPeerInfo} +} + +async function createMockPeerDHT() { + const {peerStore, localPeerInfo} = createMockPeerStore() + const mockConnectToPeer = (id: string) => { + return { + pingPeer: async (timeout?: number) => true, + sendPeerRequest: async (type: SubServiceType, request: Uint8Array) => { + // decode response + const { subMessage: responseSubMessage } = peerInterface.PeerDHTMessage.decodeDelimited(request); + const { peerId: responsePeerId, closestPeers } = peerInterface.PeerDHTFindNodeMessage.decodeDelimited( + responseSubMessage, + ); + + // encode request + const localPeerId=Array.from(peerStore.keys())[0] + const subMessage = peerInterface.PeerDHTFindNodeMessage.encodeDelimited({ + peerId: localPeerId, + closestPeers: toPeerInfoMessageList(Array.from(peerStore.values())), + }).finish(); + + return peerInterface.PeerDHTMessage.encodeDelimited({ + type: peerInterface.PeerDHTMessageType.FIND_NODE, + isResponse: false, + subMessage: subMessage, + }).finish(); + } + } + } + const peerDHT = new PeerDHT( + () => localPeerInfo.id, + mockConnectToPeer, + () => localPeerInfo, + (peerInfo: PeerInfo) => {peerStore.set(peerInfo.id, peerInfo)} + ) + for (const peerId of peerStore.keys()) { + await peerDHT.addPeer(peerId) + } + return peerDHT +} + +const newPublicKey = ` +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: Keybase OpenPGP v2.1.15 +Comment: https://keybase.io/crypto + +xsFNBF+aZLgBEADmXYEXWJCEWEyYLc6ta1NCHqk1Ghu8rNSfh0jePGAPZBlIQKME +ePrtOjrgtiolD1o4CN8IiRt76H37ncFy3yKSwR+vxufzK//xtm3SJ/naowXKoojy +a5/EXlnasqUj2xqwZvgw4msmxeBBPcQfEbI/JE925z5xjHh3BI0q4fQpCxeUm2V2 +zAnEKMvxfYLn60qnaH0Al+PU+SKp6AYDQTtuIdJt5EoyE761w7A79VbS6kS/CNF7 +DJbcOWFzqsWaglGFq3Jk8nwgKHKNioOTDj9ysoawb7etO1Ya5uK5seWj6l+3XgST +P1jGceoBxtBjX11hAB9BuRg+L/OTyY48UQASGty7s3em8a2XC7Tnt2vpv04U6xAR +mcJNyZcPMHWSo2kYVA7l33Uq4AsVLt+vlVsOnjeKeBYvCbDcvHiXpMHEl2SGZBPy +qg8ENmbAymujt7dI4PKdVCBLpmsRknNU5qPgCGRuh5ihxbfuIiwxTIABbagsT2Fq +hA7INIO2IpAdf0zhd0Jnd7g5eB5jBsp0G8A0kQoxkuHZpuR4XHvPh2/9UWykouTd +HipXIvm92d66tdVchfpJpoz2SUDgIFNdB57g2rERJ4KET22QXP5sTC/guhAUa5a+ +WxoiyV45Jy1rPojm4Vx7kWL7mqA4Otqmn7AubXrI8A6qcxNn3evbayI7vwARAQAB +zQZyb2Jkb2fCwXQEEwEKAB4FAl+aZLgCGy8DCwkHAxUKCAIeAQIXgAMWAgECGQEA +CgkQ4P7GA98+iODvmRAAnHSCJWGniO6+AVlKcQ/UorCvK7X5+u84yzqHr5srB2Oo +Q4dfJjoSy80KchJeHgoSLROL0WmDSrzuUvKLGR4RHLEbC0eYfxQ3yWPFplYxf5+R +CpTmXlmUjgk1jU8TotlEIunwKUe14ChcsvMTKcZI7mQ2YfqyXBHHYPRb0Akt5FnD +6wgQG1faQlvJInuxoB+y9uiGPV+3A730XDrZVMD3QHcMBbXJhSx1gjzbjtZLoAcq +50TDBt3NS/yxMYxaWhocxB9kDYhr+uyCjYxwTke7AU/CsLfRwR14XptWXqcSyTGP +RV48vX1govoxQFpzGPApvp3IW3Od5EHdoqlgRcO0S0zJCOxzB/JzfZ1HK7NTMkWs +NgbwR1yWGq2sdMO0mSjGbcTHsxBHiLCFQQSsOObHGywJnxcd9oPUoHs7yc50YOlJ +oOkCKua7USXLXaqe2mdd7L6P9sBNar/sn2UvQZ6/slXEHfhJyzZ2l2ouFhMZwROK +z+v74j12YdrmN7Gr0DmH3EN0ZdeNTJz1sc8yJ8LK7QLklArjN6OfWzt7uaeabhIb +XBMAKHwuCyZhojaOkJ8Pjo6AVV5G72R26ZT8MRkLLAnRUOGJOzmhkkyxCAlwsPmU +tcOY3a7GKjSDEhZUQ88B6dG3fwbgtpwZfohN8vPYe9oncjsBwvNjq4DI53hSwhU= +=Znu3 +-----END PGP PUBLIC KEY BLOCK----- +` +const peerId = PeerInfo.publicKeyToId(PeerInfo.formatPublicKey(newPublicKey)) + +const peerDHTModel = createModel(peerDHTMachine).withEvents({ + ADD_PEERS: { + exec: async (peerDHT: PeerDHT) => { + // Do not await, must interrogate while service is running. + peerDHT.deletePeer(peerId).finally(async () => { + await peerDHT.addPeers([peerId]) + }) + return + }, + }, + ADD_PEER: { + exec: async (peerDHT: PeerDHT) => { + // Do not await, must interrogate while service is running. + peerDHT.deletePeer(peerId).finally(async () => { + await peerDHT.addPeer(peerId) + }) + return + }, + }, + DELETE_PEER: { + exec: async (peerDHT: PeerDHT) => { + // Do not await, must interrogate while service is running. + peerDHT.deletePeer(peerId) + }, + }, + FIND_LOCAL_PEER: { + exec: async (peerDHT: PeerDHT) => { + // Do not await, must interrogate while service is running. + peerDHT.findLocalPeer(peerId) + }, + }, + FIND_PEER: { + exec: async (peerDHT: PeerDHT) => { + // Do not await, must interrogate while service is running. + peerDHT.findPeer(peerId) + }, + }, + SUCCESS: { + exec: async (peerDHT: PeerDHT) => { + return; + }, + }, + FAILURE: { + exec: async (peerDHT: PeerDHT) => { + return; + }, + }, +}); + +export { peerDHTModel, createMockPeerDHT }; diff --git a/tests/spec/peers/PeerDHT.test.ts b/tests/spec/peers/PeerDHT.test.ts new file mode 100644 index 000000000..982d3222b --- /dev/null +++ b/tests/spec/peers/PeerDHT.test.ts @@ -0,0 +1,20 @@ +import { peerDHTModel, createMockPeerDHT } from './PeerDHT.model'; + +describe('PeerDHT spec testing', () => { + const testPlans = peerDHTModel.getSimplePathPlans(); + + testPlans.forEach((plan) => { + describe(plan.description, () => { + plan.paths.forEach((path) => { + test(path.description, async () => { + const peerDHT = await createMockPeerDHT() + await path.test(peerDHT); + }); + }); + }); + }); + + test('should have full coverage', () => { + return peerDHTModel.testCoverage(); + }); +}); diff --git a/tests/spec/vaults/VaultManager.model.ts b/tests/spec/vaults/VaultManager.model.ts new file mode 100644 index 000000000..f62e01d71 --- /dev/null +++ b/tests/spec/vaults/VaultManager.model.ts @@ -0,0 +1,70 @@ +import os from 'os' +import fs from 'fs' +import { createModel } from '@xstate/test'; +import { Polykey, KeyManager } from '../../../src/Polykey' +import VaultManager from '../../../src/vaults/VaultManager'; +import { vaultsMachine, VaultsStateSchema } from '../../../spec/vaults/Vaults.spec'; +import { randomString } from '../../../src/utils'; + +async function createVaultManagerModel() { + + // pk1 + const tempDir1 = fs.mkdtempSync(`${os.tmpdir}/pktest${randomString()}`) + const km1 = new KeyManager(tempDir1, fs) + await km1.generateKeyPair('km1', 'passphrase', true) + const pk1 = new Polykey(tempDir1, fs, km1) + // pk2 + const tempDir2 = fs.mkdtempSync(`${os.tmpdir}/pktest${randomString()}`) + const km2 = new KeyManager(tempDir2, fs) + await km2.generateKeyPair('km2', 'passphrase', true) + const pk2 = new Polykey(tempDir2, fs, km2) + await pk2.vaultManager.newVault(randomString()) + + // let each know about the other + pk2.peerManager.addPeer(pk1.peerManager.peerInfo) + pk1.peerManager.addPeer(pk2.peerManager.peerInfo) + + const vaultManagerModel = createModel(vaultsMachine).withEvents({ + CREATE_VAULT: { + exec: async (vm: VaultManager) => { + // Do not await, must interrogate while service is running. + vm.newVault(randomString()) + } + }, + CLONE_VAULT: { + // Do not await, must interrogate while service is running. + exec: async (vm: VaultManager) => { + const vaultNames = pk2.vaultManager.getVaultNames() + vm.cloneVault(vaultNames[0], pk2.peerManager.peerInfo.id) + } + }, + PULL_VAULT: { + // Do not await, must interrogate while service is running. + exec: async (vm: VaultManager) => { + const vaultNames = pk2.vaultManager.getVaultNames() + vm.pullVault(vaultNames[0], pk2.peerManager.peerInfo.id) + } + }, + DELETE_VAULT: { + // Do not await, must interrogate while service is running. + exec: async (vm: VaultManager) => { + const vaultNames = vm.getVaultNames() + vm.deleteVault(vaultNames[0]) + } + }, + SUCCESS: { + exec: async (vm: VaultManager) => { + return + } + }, + FAILURE: { + exec: async (vm: VaultManager) => { + return + } + } + }); + + return {vaultManagerModel, vm: pk1.vaultManager} +} + +export { createVaultManagerModel }; diff --git a/tests/spec/vaults/VaultManager.test.ts b/tests/spec/vaults/VaultManager.test.ts new file mode 100644 index 000000000..8a941afbd --- /dev/null +++ b/tests/spec/vaults/VaultManager.test.ts @@ -0,0 +1,20 @@ +import { createVaultManagerModel } from './VaultManager.model'; + +describe('VaultManager spec testing', async () => { + const { vaultManagerModel, vm } = await createVaultManagerModel() + const testPlans = vaultManagerModel.getSimplePathPlans(); + + testPlans.forEach((plan) => { + describe(plan.description, () => { + plan.paths.forEach((path) => { + test(path.description, async () => { + await path.test(vm); + }); + }); + }); + }); + + test('should have full coverage', () => { + return vaultManagerModel.testCoverage(); + }); +});