Move some out-dated examples to attic, update README.md
This commit is contained in:
2
examples/nodejs/.gitignore
vendored
2
examples/nodejs/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
/.zerotier
|
||||
/libzt
|
||||
@@ -1,35 +0,0 @@
|
||||
## Building from source
|
||||
|
||||
The npm install script will attempt to statically link to `libzt.a`.
|
||||
|
||||
You first need `Cmake` to build the fPIC-version of the `libzt.a` library.
|
||||
|
||||
To build both `release` and `debug` libraries for only your host's architecture use `make host`. Or optionally `make host_release` for release only. To build everything including things like iOS frameworks, Android packages, etc, use `make all`. Possible build targets can be seen by using `make list`. Resultant libraries will be placed in `/lib`:
|
||||
|
||||
```
|
||||
brew install cmake
|
||||
(cd ../.. ; make clean; make update && make patch && make host_release CC=clang CXX=clang++)
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Typical build output:
|
||||
|
||||
```
|
||||
lib
|
||||
├── release
|
||||
| └── linux-x86_64
|
||||
| ├── libzt.a
|
||||
| └── libzt.so
|
||||
| └── macos-x86_64
|
||||
| ├── libzt.a
|
||||
└── debug
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Licensing
|
||||
|
||||
ZeroTier is licensed under the BSL version 1.1. See [LICENSE.txt](./LICENSE.txt) and the ZeroTier pricing page for details. ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license.
|
||||
|
||||
A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md](ext/ZeroTierOne/AUTHORS.md) for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.). If you want a commercial license to use the ZeroTier SDK in your product contact us directly via [contact@zerotier.com](mailto:contact@zerotier.com)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# Automatically generated file. Edits will be lost.
|
||||
# Based on: autogypi.json
|
||||
|
||||
{
|
||||
"includes": [
|
||||
"node_modules/nbind/src/nbind-common.gypi"
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# Automatically generated file. Edits will be lost.
|
||||
# Based on: autogypi.json
|
||||
|
||||
{
|
||||
"include_dirs": [
|
||||
"node_modules/nan"
|
||||
],
|
||||
"includes": [
|
||||
"node_modules/nbind/src/nbind.gypi"
|
||||
]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"dependencies": [
|
||||
"nbind"
|
||||
],
|
||||
"includes": []
|
||||
}
|
||||
@@ -1,731 +0,0 @@
|
||||
/**
|
||||
* libzt binding
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "ZeroTierSockets.h"
|
||||
#include "nbind/api.h"
|
||||
|
||||
struct Node
|
||||
{
|
||||
Node() : online(false), joinedAtLeastOneNetwork(false), id(0) {}
|
||||
|
||||
bool online;
|
||||
bool joinedAtLeastOneNetwork;
|
||||
uint64_t id;
|
||||
// etc
|
||||
|
||||
bool getOnline() { return online; }
|
||||
bool getJoinedAtLeastOneNetwork() { return joinedAtLeastOneNetwork; }
|
||||
uint64_t getId() { return id; }
|
||||
} myNode;
|
||||
|
||||
/* Callback handler, you should return control from this function as quickly as you can
|
||||
to ensure timely receipt of future events. You should not call libzt API functions from
|
||||
this function unless it's something trivial like zts_inet_ntop() or similar that has
|
||||
no state-change implications. */
|
||||
void on_zts_event(void *msgPtr)
|
||||
{
|
||||
struct zts_callback_msg *msg = (struct zts_callback_msg *)msgPtr;
|
||||
|
||||
// Node events
|
||||
if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) {
|
||||
printf("ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address);
|
||||
myNode.id = msg->node->address;
|
||||
myNode.online = true;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) {
|
||||
printf("ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n");
|
||||
myNode.online = false;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NODE_NORMAL_TERMINATION) {
|
||||
printf("ZTS_EVENT_NODE_NORMAL_TERMINATION\n");
|
||||
}
|
||||
|
||||
// Virtual network events
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_NOT_FOUND) {
|
||||
printf("ZTS_EVENT_NETWORK_NOT_FOUND --- Are you sure %llx is a valid network?\n",
|
||||
msg->network->nwid);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) {
|
||||
printf("ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) {
|
||||
printf("ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n",
|
||||
msg->network->nwid);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP4) {
|
||||
printf("ZTS_EVENT_NETWORK_READY_IP4 --- Network config received. IPv4 traffic can now be sent over network %llx\n",
|
||||
msg->network->nwid);
|
||||
myNode.joinedAtLeastOneNetwork = true;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) {
|
||||
printf("ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n",
|
||||
msg->network->nwid);
|
||||
myNode.joinedAtLeastOneNetwork = true;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) {
|
||||
printf("ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid);
|
||||
}
|
||||
|
||||
// Address events
|
||||
if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP4) {
|
||||
char ipstr[ZTS_INET_ADDRSTRLEN];
|
||||
struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr);
|
||||
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN);
|
||||
printf("ZTS_EVENT_ADDR_NEW_IP4 --- This node's virtual address on network %llx is %s\n",
|
||||
msg->addr->nwid, ipstr);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) {
|
||||
char ipstr[ZTS_INET6_ADDRSTRLEN];
|
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr);
|
||||
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN);
|
||||
printf("ZTS_EVENT_ADDR_NEW_IP6 --- This node's virtual address on network %llx is %s\n",
|
||||
msg->addr->nwid, ipstr);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP4) {
|
||||
char ipstr[ZTS_INET_ADDRSTRLEN];
|
||||
struct zts_sockaddr_in *in4 = (struct zts_sockaddr_in*)&(msg->addr->addr);
|
||||
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN);
|
||||
printf("ZTS_EVENT_ADDR_REMOVED_IP4 --- The virtual address %s for this node on network %llx has been removed.\n",
|
||||
ipstr, msg->addr->nwid);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_ADDR_REMOVED_IP6) {
|
||||
char ipstr[ZTS_INET6_ADDRSTRLEN];
|
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr);
|
||||
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN);
|
||||
printf("ZTS_EVENT_ADDR_REMOVED_IP6 --- The virtual address %s for this node on network %llx has been removed.\n",
|
||||
ipstr, msg->addr->nwid);
|
||||
}
|
||||
// Peer events
|
||||
if (msg->peer) {
|
||||
if (msg->peer->role == ZTS_PEER_ROLE_PLANET) {
|
||||
/* Safe to ignore, these are our roots. They orchestrate the P2P connection.
|
||||
You might also see other unknown peers, these are our network controllers. */
|
||||
return;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) {
|
||||
printf("ZTS_EVENT_PEER_DIRECT --- A direct path is known for node=%llx\n",
|
||||
msg->peer->address);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_PEER_RELAY) {
|
||||
printf("ZTS_EVENT_PEER_RELAY --- No direct path to node=%llx\n", msg->peer->address);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_PEER_PATH_DISCOVERED) {
|
||||
printf("ZTS_EVENT_PEER_PATH_DISCOVERED --- A new direct path was discovered for node=%llx\n",
|
||||
msg->peer->address);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_PEER_PATH_DEAD) {
|
||||
printf("ZTS_EVENT_PEER_PATH_DEAD --- A direct path has died for node=%llx\n",
|
||||
msg->peer->address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zts_sockaddr_in sockaddr_in(const char *remoteAddr, const int remotePort)
|
||||
{
|
||||
struct zts_sockaddr_in in4;
|
||||
in4.sin_port = htons(remotePort);
|
||||
#if defined(_WIN32)
|
||||
zts_inet_pton(ZTS_AF_INET, remoteAddr.c_str(), &(in4.sin_addr.S_addr));
|
||||
#else
|
||||
zts_inet_pton(ZTS_AF_INET, remoteAddr.c_str(), &(in4.sin_addr.s_addr));
|
||||
#endif
|
||||
in4.sin_family = ZTS_AF_INET;
|
||||
return in4;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* IDENTITIES and AUTHORIZATION:
|
||||
*
|
||||
* - Upon the first execution of this code, a new identity will be generated and placed in
|
||||
* the location given in the first argument to zts_start(path, ...). If you accidentally
|
||||
* duplicate the identity files and use them simultaneously in a different node instance
|
||||
* you will experience undefined behavior and it is likely nothing will work.
|
||||
*
|
||||
* - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join
|
||||
* your network, otherwise nothing will happen. This can be done manually or via
|
||||
* our web API: https://my.zerotier.com/help/api
|
||||
*
|
||||
* - Exceptions to the above rule are:
|
||||
* 1) Joining a public network (such as "earth")
|
||||
* 2) Joining an Ad-hoc network, (no controller and therefore requires no authorization.)
|
||||
*
|
||||
*
|
||||
* ESTABLISHING A CONNECTION:
|
||||
*
|
||||
* - Creating a standard socket connection generally works the same as it would using
|
||||
* an ordinary socket interface, however with libzt there is a subtle difference in
|
||||
* how connections are established which may cause confusion:
|
||||
*
|
||||
* The underlying virtual ZT layer creates what are called "transport-triggered links"
|
||||
* between nodes. That is, links are not established until an attempt to communicate
|
||||
* with a peer has taken place. The side effect is that the first few packets sent from
|
||||
* a libzt instance are usually relayed via our free infrastructure and it isn't until a
|
||||
* root server has passed contact information to both peers that a direct connection will be
|
||||
* established. Therefore, it is required that multiple connection attempts be undertaken
|
||||
* when initially communicating with a peer. After a transport-triggered link is
|
||||
* established libzt will inform you via ZTS_EVENT_PEER_DIRECT for a specific peer ID. No
|
||||
* action is required on your part for this callback event.
|
||||
*
|
||||
* Note: In these initial moments before ZTS_EVENT_PEER_DIRECT has been received for a
|
||||
* specific peer, traffic may be slow, jittery and there may be high packet loss.
|
||||
* This will subside within a couple of seconds.
|
||||
*
|
||||
*
|
||||
* ERROR HANDLING:
|
||||
*
|
||||
* - libzt's API is actually composed of two categories of functions with slightly
|
||||
* different error reporting mechanisms.
|
||||
*
|
||||
* Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors
|
||||
* returned by these functions can be any of the following:
|
||||
*
|
||||
* ZTS_ERR_OK // No error
|
||||
* ZTS_ERR_SOCKET // Socket error, see zts_errno
|
||||
* ZTS_ERR_SERVICE // You probably did something at the wrong time
|
||||
* ZTS_ERR_ARG // Invalid argument
|
||||
* ZTS_ERR_NO_RESULT // No result (not necessarily an error)
|
||||
* ZTS_ERR_GENERAL // Consider filing a bug report
|
||||
*
|
||||
* Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc).
|
||||
* Errors returned by these functions can be the same as the above. With
|
||||
* the added possibility of zts_errno being set. Much like standard
|
||||
* errno this will provide a more specific reason for an error's occurrence.
|
||||
* See ZeroTierSockets.h for values.
|
||||
*
|
||||
*
|
||||
* API COMPATIBILITY WITH HOST OS:
|
||||
*
|
||||
* - While the ZeroTier socket interface can coexist with your host OS's own interface in
|
||||
* the same file with no type and naming conflicts, try not to mix and match host
|
||||
* OS/libzt structures, functions, or constants. It may look similar and may even work
|
||||
* some of the time but there enough differences that it will cause headaches. Here
|
||||
* are a few guidelines:
|
||||
*
|
||||
* If you are calling a zts_* function, use the appropriate ZTS_* constants:
|
||||
*
|
||||
* zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT)
|
||||
* zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT)
|
||||
*
|
||||
* If you are calling a zts_* function, use the appropriate zts_* structure:
|
||||
*
|
||||
* struct zts_sockaddr_in in4; <------ Note the zts_* prefix
|
||||
* ...
|
||||
* zts_bind(fd, (struct zts_sockaddr *)&in4, sizeof(struct zts_sockaddr_in)) < 0)
|
||||
*
|
||||
*/
|
||||
class ZeroTier
|
||||
{
|
||||
public:
|
||||
static Node getMyNode() { return myNode; }
|
||||
|
||||
/**
|
||||
* @brief Starts the ZeroTier service and notifies user application of events via callback
|
||||
*
|
||||
* @param configPath path directory where configuration files are stored
|
||||
* @param servicePort proit which ZeroTier service will listen on
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE or ZTS_ERR_ARG on failure
|
||||
*/
|
||||
static int start(const char *configPath, uint16_t servicePort)
|
||||
{
|
||||
// Bring up ZeroTier service
|
||||
|
||||
int err = ZTS_ERR_OK;
|
||||
|
||||
if((err = zts_start(configPath, &on_zts_event, servicePort)) != ZTS_ERR_OK) {
|
||||
printf("Unable to start service, error = %d.\n", err);
|
||||
return err;
|
||||
}
|
||||
printf("Waiting for node to come online...\n");
|
||||
while (!myNode.online) { zts_delay_ms(50); }
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the ZeroTier service and brings down all virtual network interfaces
|
||||
*
|
||||
* @usage While the ZeroTier service will stop, the stack driver (with associated timers)
|
||||
* will remain active in case future traffic processing is required. To stop all activity
|
||||
* and free all resources use zts_free() instead.
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE on failure.
|
||||
*/
|
||||
static int stop()
|
||||
{
|
||||
return zts_stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restart the ZeroTier service.
|
||||
*
|
||||
* @usage This call will block until the service has been brought offline. Then
|
||||
* it will return and the user application can then watch for the appropriate
|
||||
* startup callback events.
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE on failure.
|
||||
*/
|
||||
static int restart()
|
||||
{
|
||||
return zts_restart();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop all background services, bring down all interfaces, free all resources. After
|
||||
* calling this function an application restart will be required before the library can be
|
||||
* used again.
|
||||
*
|
||||
* @usage This should be called at the end of your program or when you do not anticipate
|
||||
* communicating over ZeroTier
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE on failure.
|
||||
*/
|
||||
static int free()
|
||||
{
|
||||
return zts_free();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Join a network
|
||||
*
|
||||
* @param networkId A 16-digit hexadecimal virtual network ID
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SERVICE or ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static int join(const char *networkId)
|
||||
{
|
||||
// Join ZeroTier network
|
||||
|
||||
uint64_t nwid = strtoull(networkId,NULL,16); // Network ID to join
|
||||
|
||||
int err = ZTS_ERR_OK;
|
||||
|
||||
if((err = zts_join(nwid)) != ZTS_ERR_OK) {
|
||||
printf("Unable to join network, error = %d.\n", err);
|
||||
return err;
|
||||
}
|
||||
printf("Joining network %llx\n", nwid);
|
||||
printf("Don't forget to authorize this device in my.zerotier.com or the web API!\n");
|
||||
while (!myNode.joinedAtLeastOneNetwork) { zts_delay_ms(50); }
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int openStream()
|
||||
{
|
||||
return open(ZTS_AF_INET, ZTS_SOCK_STREAM, 0);
|
||||
}
|
||||
|
||||
static int openDgram()
|
||||
{
|
||||
return open(ZTS_AF_INET, ZTS_SOCK_DGRAM, 0);
|
||||
}
|
||||
|
||||
static int openRaw(const int protocol)
|
||||
{
|
||||
return open(ZTS_AF_INET, ZTS_SOCK_RAW, protocol);
|
||||
}
|
||||
|
||||
static int openStream6()
|
||||
{
|
||||
return open(ZTS_AF_INET6, ZTS_SOCK_STREAM, 0);
|
||||
}
|
||||
|
||||
static int openDgram6()
|
||||
{
|
||||
return open(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0);
|
||||
}
|
||||
|
||||
static int openRaw6(const int protocol)
|
||||
{
|
||||
return open(ZTS_AF_INET6, ZTS_SOCK_RAW, protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a socket (sets zts_errno)
|
||||
*
|
||||
* @param socket_family Address family (ZTS_AF_INET, ZTS_AF_INET6)
|
||||
* @param socket_type Type of socket (ZTS_SOCK_STREAM, ZTS_SOCK_DGRAM, ZTS_SOCK_RAW)
|
||||
* @param protocol Protocols supported on this socket
|
||||
* @return Numbered file descriptor on success. ZTS_ERR_SERVICE or ZTS_ERR_SOCKET on failure.
|
||||
*/
|
||||
static int open(const int socket_family, const int socket_type, const int protocol)
|
||||
{
|
||||
int fd;
|
||||
if ((fd = zts_socket(socket_family, socket_type, protocol)) < 0) {
|
||||
printf("Error creating ZeroTier socket (fd=%d, zts_errno=%d).\n", fd, zts_errno);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Close a socket (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE on failure.
|
||||
*/
|
||||
static int close(int fd)
|
||||
{
|
||||
return zts_close(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Shut down some aspect of a socket (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static int shutdown(int fd)
|
||||
{
|
||||
return zts_shutdown(fd, ZTS_SHUT_RDWR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bind a socket to a virtual interface (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param remoteAddr Remote Address to connect to
|
||||
* @param remotePort Remote Port to connect to
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static int bind(int fd, const char *localAddr, const int localPort)
|
||||
{
|
||||
struct zts_sockaddr_in in4 = sockaddr_in(localAddr, localPort);
|
||||
|
||||
int err = ZTS_ERR_OK;
|
||||
if ((err = zts_bind(fd, (const struct zts_sockaddr *)&in4, sizeof(in4))) < 0) {
|
||||
printf("Error binding to interface (fd=%d, ret=%d, zts_errno=%d).\n",
|
||||
fd, err, zts_errno);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bind6(int fd, const char *remoteAddr, const int remotePort)
|
||||
{
|
||||
printf("IPv6 NOT IMPLEMENTED.\n");
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connect a socket to a remote host (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param remoteAddr Remote Address to connect to
|
||||
* @param remotePort Remote Port to connect to
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static int connect(int fd, const char *remoteAddr, const int remotePort)
|
||||
{
|
||||
struct zts_sockaddr_in in4 = sockaddr_in(remoteAddr, remotePort);
|
||||
|
||||
// Retries are often required since ZT uses transport-triggered links (explained above)
|
||||
int err = ZTS_ERR_OK;
|
||||
if ((err = zts_connect(fd, (const struct zts_sockaddr *)&in4, sizeof(in4))) < 0) {
|
||||
printf("Error connecting to remote host (fd=%d, ret=%d, zts_errno=%d).\n",
|
||||
fd, err, zts_errno);
|
||||
} else {
|
||||
// Set non-blocking mode
|
||||
fcntl(fd, ZTS_F_SETFL, ZTS_O_NONBLOCK);
|
||||
}
|
||||
return err;
|
||||
|
||||
// int err = ZTS_ERR_OK;
|
||||
// for (;;) {
|
||||
// printf("Connecting to remote host...\n");
|
||||
// if ((err = zts_connect(fd, (const struct zts_sockaddr *)&in4, sizeof(in4))) < 0) {
|
||||
// printf("Error connecting to remote host (fd=%d, ret=%d, zts_errno=%d). Trying again.\n",
|
||||
// fd, err, zts_errno);
|
||||
// zts_close(fd);
|
||||
// // printf("Creating socket...\n");
|
||||
// if ((fd = zts_socket(socket_family, socket_type, protocol)) < 0) {
|
||||
// printf("Error creating ZeroTier socket (fd=%d, zts_errno=%d).\n", fd, zts_errno);
|
||||
// return -1;
|
||||
// }
|
||||
// zts_delay_ms(250);
|
||||
// }
|
||||
// else {
|
||||
// printf("Connected.\n");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
static int connect6(int fd, const char *remoteAddr, const int remotePort)
|
||||
{
|
||||
printf("IPv6 NOT IMPLEMENTED.\n");
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read bytes from socket onto buffer (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param buf Pointer to data buffer
|
||||
* @return Byte count received on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static ssize_t read(int fd, nbind::Buffer buf)
|
||||
{
|
||||
return zts_read(fd, buf.data(), buf.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write bytes from buffer to socket (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param buf Pointer to data buffer
|
||||
* @return Byte count sent on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static ssize_t write(int fd, nbind::Buffer buf)
|
||||
{
|
||||
return zts_write(fd, buf.data(), buf.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data from multiple buffers to socket. (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param bufs Array of source buffers
|
||||
* @return Byte count sent on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static ssize_t writev(int fd, std::vector<nbind::Buffer> bufs)
|
||||
{
|
||||
std::size_t size = bufs.size();
|
||||
zts_iovec iov[size];
|
||||
for (std::size_t i = 0; i != size; ++i) {
|
||||
iov[i].iov_base = bufs[i].data();
|
||||
iov[i].iov_len = bufs[i].length();
|
||||
}
|
||||
return zts_writev(fd, iov, bufs.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive data from remote host (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param buf Pointer to data buffer
|
||||
* @param flags
|
||||
* @return Byte count received on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static ssize_t recv(int fd, nbind::Buffer buf, int flags)
|
||||
{
|
||||
return zts_recv(fd, buf.data(), buf.length(), flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send data to remote host (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param buf data buffer
|
||||
* @param flags
|
||||
* @return Byte count sent on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static ssize_t send(int fd, nbind::Buffer buf, int flags)
|
||||
{
|
||||
return zts_send(fd, buf.data(), buf.length(), flags);
|
||||
}
|
||||
|
||||
static int setBlocking(int fd, bool isBlocking)
|
||||
{
|
||||
int flags = fcntl(fd, ZTS_F_GETFL, 0);
|
||||
if (isBlocking) {
|
||||
flags &= ~ZTS_O_NONBLOCK;
|
||||
} else {
|
||||
flags &= ZTS_O_NONBLOCK;
|
||||
}
|
||||
return fcntl(fd, ZTS_F_SETFL, flags);
|
||||
}
|
||||
|
||||
static int setNoDelay(int fd, bool isNdelay)
|
||||
{
|
||||
int flags = fcntl(fd, ZTS_F_GETFL, 0);
|
||||
if (isNdelay) {
|
||||
flags &= ~ZTS_O_NDELAY;
|
||||
} else {
|
||||
flags &= ZTS_O_NDELAY;
|
||||
}
|
||||
return fcntl(fd, ZTS_F_SETFL, flags);
|
||||
}
|
||||
|
||||
static int setKeepalive(int fd, int yes)
|
||||
{
|
||||
return setsockopt(fd, ZTS_SOL_SOCKET, ZTS_SO_KEEPALIVE, &yes, sizeof(yes));
|
||||
}
|
||||
|
||||
static int setKeepidle(int fd, int idle)
|
||||
{
|
||||
return setsockopt(fd, ZTS_IPPROTO_TCP, ZTS_TCP_KEEPIDLE, &idle, sizeof(idle));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Issue file control commands on a socket
|
||||
*
|
||||
* @param fd File descriptor
|
||||
* @param cmd
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
static int fcntl(int fd, int cmd, int flags)
|
||||
{
|
||||
return zts_fcntl(fd, cmd, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set socket options (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param level Protocol level to which option name should apply
|
||||
* @param optname Option name to set
|
||||
* @param optval Source of option value to set
|
||||
* @param optlen Length of option value
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static int setsockopt(int fd, int level, int optname, const void *optval, zts_socklen_t optlen)
|
||||
{
|
||||
return zts_setsockopt(fd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get socket options (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param level Protocol level to which option name should apply
|
||||
* @param optname Option name to get
|
||||
* @param optval Where option value will be stored
|
||||
* @param optlen Length of value
|
||||
* @return ZTS_ERR_OK on success. ZTS_ERR_SOCKET, ZTS_ERR_SERVICE, ZTS_ERR_ARG on failure.
|
||||
*/
|
||||
static int getsockopt(int fd, int level, int optname, void *optval, zts_socklen_t *optlen)
|
||||
{
|
||||
return zts_getsockopt(fd, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get socket name (sets zts_errno)
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param addr Name associated with this socket
|
||||
* @param addrlen Length of name
|
||||
* @return Sockaddress structure
|
||||
*/
|
||||
static zts_sockaddr_in getsockname(int fd)
|
||||
{
|
||||
struct zts_sockaddr_in in4;
|
||||
zts_socklen_t addrlen;
|
||||
zts_getsockname(fd, (struct zts_sockaddr *)&in4, &addrlen);
|
||||
return in4;
|
||||
}
|
||||
|
||||
static zts_sockaddr_in6 getsockname6(int fd)
|
||||
{
|
||||
struct zts_sockaddr_in6 in6;
|
||||
zts_socklen_t addrlen;
|
||||
zts_getsockname(fd, (struct zts_sockaddr *)&in6, &addrlen);
|
||||
return in6;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the peer name for the remote end of a connected socket
|
||||
*
|
||||
* @param fd Socket file descriptor
|
||||
* @param addr Name associated with remote end of this socket
|
||||
* @param addrlen Length of name
|
||||
* @return Sockaddress structure
|
||||
*/
|
||||
static zts_sockaddr_in getpeername(int fd)
|
||||
{
|
||||
struct zts_sockaddr_in in4;
|
||||
zts_socklen_t addrlen;
|
||||
zts_getpeername(fd, (struct zts_sockaddr *)&in4, &addrlen);
|
||||
return in4;
|
||||
}
|
||||
|
||||
static zts_sockaddr_in6 getpeername6(int fd)
|
||||
{
|
||||
struct zts_sockaddr_in6 in6;
|
||||
zts_socklen_t addrlen;
|
||||
zts_getpeername(fd, (struct zts_sockaddr *)&in6, &addrlen);
|
||||
return in6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert IPv4 and IPv6 address structures to human-readable text form.
|
||||
*
|
||||
* @param af Address family (ZTS_AF_INET, ZTS_AF_INET6)
|
||||
* @param src Pointer to source address structure
|
||||
* @param dst Pointer to destination character array
|
||||
* @param size Size of the destination buffer
|
||||
* @return On success, returns a non-null pointer to the destination character array
|
||||
*/
|
||||
static const char * inet_ntop(const zts_sockaddr in)
|
||||
{
|
||||
if (in.sa_family == ZTS_AF_INET) {
|
||||
const zts_sockaddr_in *in4 = (const zts_sockaddr_in *)∈
|
||||
char ipstr[ZTS_INET_ADDRSTRLEN];
|
||||
zts_inet_ntop(ZTS_AF_INET, &(in4->sin_addr), ipstr, ZTS_INET_ADDRSTRLEN);
|
||||
return ipstr;
|
||||
} else if (in.sa_family == ZTS_AF_INET6) {
|
||||
const zts_sockaddr_in6 *in6 = (const zts_sockaddr_in6 *)∈
|
||||
char ipstr[ZTS_INET6_ADDRSTRLEN];
|
||||
zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ipstr, ZTS_INET6_ADDRSTRLEN);
|
||||
return ipstr;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#include "nbind/nbind.h"
|
||||
|
||||
NBIND_CLASS(Node) {
|
||||
getter(getOnline);
|
||||
getter(getJoinedAtLeastOneNetwork);
|
||||
getter(getId);
|
||||
}
|
||||
|
||||
NBIND_CLASS(ZeroTier) {
|
||||
method(start);
|
||||
method(restart);
|
||||
method(stop);
|
||||
method(free);
|
||||
|
||||
method(join);
|
||||
|
||||
method(openStream);
|
||||
method(openDgram);
|
||||
method(openRaw);
|
||||
method(openStream6);
|
||||
method(openDgram6);
|
||||
method(openRaw6);
|
||||
method(open);
|
||||
method(close);
|
||||
method(shutdown);
|
||||
|
||||
method(bind);
|
||||
method(bind6);
|
||||
method(connect);
|
||||
method(connect6);
|
||||
|
||||
method(read);
|
||||
method(write);
|
||||
method(writev);
|
||||
method(recv);
|
||||
method(send);
|
||||
|
||||
method(setBlocking);
|
||||
method(setNoDelay);
|
||||
method(setKeepalive);
|
||||
method(setKeepidle);
|
||||
method(fcntl);
|
||||
|
||||
method(getsockname);
|
||||
method(getsockname6);
|
||||
method(getpeername);
|
||||
method(getpeername6);
|
||||
method(inet_ntop);
|
||||
|
||||
method(getMyNode);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"include_dirs": [
|
||||
"libzt/include",
|
||||
],
|
||||
"includes": [
|
||||
"auto.gypi"
|
||||
],
|
||||
"sources": [
|
||||
"binding.cc"
|
||||
],
|
||||
"conditions":[
|
||||
["OS=='linux' and target_arch=='x64'", {
|
||||
"libraries": [ "<(module_root_dir)/libzt/lib/release/linux-x86_64/libzt.a" ]
|
||||
}],
|
||||
["OS=='mac' and target_arch=='x64'", {
|
||||
"libraries": [ "<(module_root_dir)/libzt/lib/release/macos-x86_64/libzt.a" ]
|
||||
}],
|
||||
["OS=='win'", {
|
||||
|
||||
}]
|
||||
]
|
||||
}
|
||||
],
|
||||
"includes": [
|
||||
"auto-top.gypi"
|
||||
]
|
||||
}
|
||||
@@ -1,778 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const net = require('net');
|
||||
const stream = require('stream');
|
||||
const { types: { isUint8Array } } = require('util');
|
||||
|
||||
const nbind = require('@mcesystems/nbind')
|
||||
const ZeroTier = nbind.init().lib.ZeroTier
|
||||
|
||||
const {
|
||||
errnoException,
|
||||
writevGeneric,
|
||||
writeGeneric,
|
||||
onStreamRead,
|
||||
kAfterAsyncWrite,
|
||||
kHandle,
|
||||
kUpdateTimer,
|
||||
// setStreamTimeout,
|
||||
kBuffer,
|
||||
kBufferCb,
|
||||
kBufferGen
|
||||
} = require('./stream_commons');
|
||||
|
||||
const kLastWriteQueueSize = Symbol('lastWriteQueueSize');
|
||||
|
||||
|
||||
/*
|
||||
* EXAMPLE of Low-level usage
|
||||
* Usage: `nc -lv 4444`
|
||||
*/
|
||||
|
||||
function example(nwid, address, port) {
|
||||
// Start ZeroTier service
|
||||
ZeroTier.start(".zerotier", 9994);
|
||||
|
||||
// Join virtual network
|
||||
ZeroTier.join(nwid);
|
||||
|
||||
// Connect the socket
|
||||
const _connect = (address, port, callback) => {
|
||||
// Open the socket
|
||||
const fd = ZeroTier.openStream();
|
||||
if (fd < 0) { callback(new Error('Could not open socket, errno: ' + fd)); return; }
|
||||
|
||||
// Try connect
|
||||
const status = ZeroTier.connect(fd, address, port);
|
||||
|
||||
console.log(status);
|
||||
if (status === 0) {
|
||||
callback(null, fd);
|
||||
} else {
|
||||
// Close previous socket
|
||||
ZeroTier.close(fd);
|
||||
setTimeout(_connect, 250, address, port, callback);
|
||||
}
|
||||
}
|
||||
|
||||
// Receive some data
|
||||
const _read = (fd, callback) => {
|
||||
const buf = Buffer.alloc(32)
|
||||
let bytes = -1
|
||||
do {
|
||||
bytes = ZeroTier.recv(fd, buf, 0)
|
||||
if (bytes > 0) { callback(null, buf); }
|
||||
} while (bytes > 0);
|
||||
|
||||
if (!ZeroTier.getMyNode().online || buf.toString('utf8').includes("exit")) {
|
||||
callback('end');
|
||||
} else {
|
||||
setTimeout(_read, 500, fd, callback)
|
||||
}
|
||||
}
|
||||
|
||||
_connect(address, port, (err, fd) => {
|
||||
if (err) { console.error(err); return; }
|
||||
console.debug("Connected.");
|
||||
|
||||
// Send some data
|
||||
ZeroTier.send(fd, Buffer.from("Name?\n", 'utf8'), 0);
|
||||
|
||||
// Set blocking read mode
|
||||
// ZeroTier.setBlocking(fd, true);
|
||||
const heartbeat = setInterval(() => process.stderr.write('.'), 100);
|
||||
|
||||
_read(fd, (stop, buf) => {
|
||||
if (stop) {
|
||||
// Close the socket
|
||||
ZeroTier.close(fd);
|
||||
// Stop ZeroTier service
|
||||
ZeroTier.stop();
|
||||
// Clear the interval
|
||||
clearInterval(heartbeat);
|
||||
return;
|
||||
}
|
||||
|
||||
process.stdout.write(buf.toString('utf8'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Target API:
|
||||
//
|
||||
// let s = net.connect({port: 80, host: 'google.com'}, function() {
|
||||
// ...
|
||||
// });
|
||||
//
|
||||
// There are various forms:
|
||||
//
|
||||
// connect(options, [cb])
|
||||
// connect(port, [host], [cb])
|
||||
// connect(path, [cb]);
|
||||
//
|
||||
function connect(...args) {
|
||||
const normalized = net._normalizeArgs(args);
|
||||
const options = normalized[0];
|
||||
// debug('createConnection', normalized);
|
||||
|
||||
const socket = new Socket(Object.assign({ handle: new ZTCP() }, options));
|
||||
|
||||
if (options.timeout) {
|
||||
socket.setTimeout(options.timeout);
|
||||
}
|
||||
|
||||
return socket.connect(normalized);
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L567
|
||||
*/
|
||||
function tryReadStart(socket) {
|
||||
// Not already reading, start the flow
|
||||
// debug('Socket._handle.readStart');
|
||||
socket._handle.reading = true;
|
||||
const err = socket._handle.readStart();
|
||||
if (err)
|
||||
socket.destroy(errnoException(err, 'read'));
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L1107
|
||||
*/
|
||||
// function afterConnect(status, self, req, readable, writable) {
|
||||
// // const self = handle[owner_symbol];
|
||||
|
||||
// // Callback may come after call to destroy
|
||||
// if (self.destroyed) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // debug('afterConnect');
|
||||
|
||||
// // assert(self.connecting);
|
||||
// self.connecting = false;
|
||||
// self._sockname = null;
|
||||
|
||||
// if (status === 0) {
|
||||
// self.readable = readable;
|
||||
// if (!self._writableState.ended)
|
||||
// self.writable = writable;
|
||||
// self._unrefTimer();
|
||||
|
||||
// self.emit('connect');
|
||||
// self.emit('ready');
|
||||
|
||||
// // Start the first read, or get an immediate EOF.
|
||||
// // this doesn't actually consume any bytes, because len=0.
|
||||
// if (readable && !self.isPaused())
|
||||
// self.read(0);
|
||||
|
||||
// } else {
|
||||
// self.connecting = false;
|
||||
// let details;
|
||||
// if (req.localAddress && req.localPort) {
|
||||
// details = req.localAddress + ':' + req.localPort;
|
||||
// }
|
||||
// const ex = new Error(status,
|
||||
// 'connect',
|
||||
// req.address,
|
||||
// req.port,
|
||||
// details);
|
||||
// if (details) {
|
||||
// ex.localAddress = req.localAddress;
|
||||
// ex.localPort = req.localPort;
|
||||
// }
|
||||
// self.destroy(ex);
|
||||
// }
|
||||
// }
|
||||
|
||||
// function afterShutdown(self, _status) {
|
||||
// // const self = this.handle[owner_symbol];
|
||||
|
||||
// // debug('afterShutdown destroyed=%j', self.destroyed,
|
||||
// // self._readableState);
|
||||
|
||||
// this.callback();
|
||||
|
||||
// // Callback may come after call to destroy.
|
||||
// if (self.destroyed)
|
||||
// return;
|
||||
|
||||
// if (!self.readable || self.readableEnded) {
|
||||
// // debug('readableState ended, destroying');
|
||||
// self.destroy();
|
||||
// }
|
||||
// }
|
||||
|
||||
// function writeGeneric(self, chunk, encoding, callback) {
|
||||
// const decodeStrings = self._writableState && self._writableState.decodeStrings
|
||||
// const buf = (!decodeStrings && !Buffer.isBuffer(chunk)) ? Buffer.from(chunk, encoding) : chunk
|
||||
|
||||
// let bytes
|
||||
// const err = ZeroTier.send(self._fd, buf, 0)
|
||||
// switch (err) {
|
||||
// case -1:
|
||||
// callback(new Error("ZeroTier Socket error"))
|
||||
// break
|
||||
// case -2:
|
||||
// callback(new Error("ZeroTier Service error"))
|
||||
// break
|
||||
// case -3:
|
||||
// callback(new Error("ZeroTier Invalid argument"))
|
||||
// break
|
||||
// default:
|
||||
// bytes = err
|
||||
// callback()
|
||||
// }
|
||||
|
||||
// return {
|
||||
// async: true,
|
||||
// bytes: bytes,
|
||||
// }
|
||||
// }
|
||||
|
||||
// function writevGeneric(self, chunks, callback) {
|
||||
// const decodeStrings = self._writableState && self._writableState.decodeStrings
|
||||
// const bufs = chunks.map(({ chunk, encoding }) => (!decodeStrings && !Buffer.isBuffer(chunk)) ? Buffer.from(chunk, encoding) : chunk)
|
||||
|
||||
// let bytes
|
||||
// const err = ZeroTier.writev(self._fd, bufs)
|
||||
// switch (err) {
|
||||
// case -1:
|
||||
// callback(new Error("ZeroTier Socket error"))
|
||||
// break
|
||||
// case -2:
|
||||
// callback(new Error("ZeroTier Service error"))
|
||||
// break
|
||||
// case -3:
|
||||
// callback(new Error("ZeroTier Invalid argument"))
|
||||
// break
|
||||
// default:
|
||||
// bytes = err
|
||||
// callback()
|
||||
// }
|
||||
|
||||
// return {
|
||||
// async: true,
|
||||
// bytes: bytes,
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
class ZTCP {
|
||||
bytesRead = 0
|
||||
bytesWritten = 0
|
||||
writeQueueSize = 0
|
||||
|
||||
_fd = null
|
||||
_reading = false
|
||||
readTimer = null
|
||||
|
||||
get reading() {
|
||||
return this._reading;
|
||||
}
|
||||
|
||||
set reading(val) {
|
||||
return this._reading = val;
|
||||
}
|
||||
|
||||
readStart() {
|
||||
if (!this._buf) {
|
||||
this._buf = Buffer.alloc(128);
|
||||
}
|
||||
|
||||
let bytes = 0
|
||||
do {
|
||||
bytes = ZeroTier.read(this._fd, this._buf)
|
||||
if (bytes >= 0) {
|
||||
this.bytesRead += bytes;
|
||||
bytes = 0;
|
||||
}
|
||||
switch (bytes) {
|
||||
case -2:
|
||||
throw new Error("ZeroTier Service error")
|
||||
case -3:
|
||||
throw new Error("ZeroTier Invalid argument")
|
||||
default:
|
||||
if (bytes > 0) {
|
||||
this.bytesRead += bytes
|
||||
this._buf = this.onread(this._buf)
|
||||
}
|
||||
}
|
||||
} while (bytes > 0 && this._reading)
|
||||
|
||||
if (this._reading) { readTimer = setTimeout(() => this._read(size), 500) }
|
||||
}
|
||||
|
||||
readStop() {
|
||||
if (readTimer) {
|
||||
clearTimeout(readTimer);
|
||||
readTimer = null;
|
||||
}
|
||||
this._reading = false
|
||||
}
|
||||
|
||||
writev(req, chunks, allBuffers) {
|
||||
let bufs = [];
|
||||
|
||||
if (allBuffers) {
|
||||
bufs = chunks;
|
||||
} else {
|
||||
const arr = chunks;
|
||||
for (let i = 0; i < arr.length; i+=2) {
|
||||
const chunk = arr[i];
|
||||
const encoding = arr[i+1];
|
||||
chunks.push(Buffer.from(chunk, encoding));
|
||||
}
|
||||
}
|
||||
|
||||
let bytes = ZeroTier.writev(this._fd, bufs);
|
||||
if (bytes >= 0) {
|
||||
this.bytesWritten += bytes;
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
const status = bytes;
|
||||
// https://github.com/nodejs/node/blob/v12.18.3/lib/internal/stream_base_commons.js#L80
|
||||
if (req.oncomplete) { req.oncomplete.call(req, status); }
|
||||
return status;
|
||||
}
|
||||
|
||||
writeBuffer(req, buf) {
|
||||
let bytes = ZeroTier.write(this._fd, buf);
|
||||
if (bytes >= 0) {
|
||||
this.bytesWritten += bytes;
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
const status = bytes;
|
||||
// https://github.com/nodejs/node/blob/v12.18.3/lib/internal/stream_base_commons.js#L80
|
||||
if (req.oncomplete) { req.oncomplete.call(req, status); }
|
||||
return status;
|
||||
}
|
||||
|
||||
writeLatin1String(req, data) {
|
||||
return this.writeBuffer(req, Buffer.from(data, 'latin1'));
|
||||
}
|
||||
|
||||
writeUtf8String(req, data) {
|
||||
return this.writeBuffer(req, Buffer.from(data, 'utf8'));
|
||||
}
|
||||
|
||||
writeAsciiString(req, data) {
|
||||
return this.writeBuffer(req, Buffer.from(data, 'ascii'));
|
||||
}
|
||||
|
||||
writeUcs2String(req, data) {
|
||||
return this.writeBuffer(req, Buffer.from(data, 'ucs2'));
|
||||
}
|
||||
|
||||
getAsyncId() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
useUserBuffer(buf) {
|
||||
this._buf = buf;
|
||||
}
|
||||
|
||||
setBlocking(newValue) {
|
||||
return ZeroTier.setBlocking(this._fd, newValue);
|
||||
}
|
||||
|
||||
setNoDelay(newValue) {
|
||||
return ZeroTier.setNoDelay(this._fd, newValue);
|
||||
}
|
||||
|
||||
setKeepalive(enable, initialDelay) {
|
||||
ZeroTier.setKeepidle(initialDelay);
|
||||
return ZeroTier.setKeepalive(this._fd, +enable);
|
||||
}
|
||||
|
||||
bind(localAddress, localPort) {
|
||||
return ZeroTier.bind(this._fd, localAddress, localPort);
|
||||
}
|
||||
|
||||
bind6(localAddress, localPort, _flags) {
|
||||
return ZeroTier.bind6(this._fd, localAddress, localPort);
|
||||
}
|
||||
|
||||
open(fd) {
|
||||
if (fd) {
|
||||
this._fd = fd;
|
||||
return 0;
|
||||
} else {
|
||||
const err = ZeroTier.openStream();
|
||||
if (err < 0) {
|
||||
return err;
|
||||
} else {
|
||||
this._fd = err;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(callback) {
|
||||
const err = ZeroTier.close(this._fd);
|
||||
this._fd = null;
|
||||
if (callback) { callback(err); }
|
||||
}
|
||||
|
||||
shutdown(req) {
|
||||
const status = ZeroTier.shutdown(this._fd);
|
||||
// https://github.com/nodejs/node/blob/v12.18.3/test/parallel/test-tcp-wrap-connect.js
|
||||
if (req.oncomplete) { req.oncomplete.call(req, status, this); }
|
||||
return status;
|
||||
}
|
||||
|
||||
connect(req, address, port) {
|
||||
let status = ZeroTier.connect(this._fd, address, port);
|
||||
|
||||
// Retries are often required since ZT uses transport-triggered links
|
||||
if (status !== 0) {
|
||||
let count = 0;
|
||||
while (count < 10) {
|
||||
// Close previous socket
|
||||
this.close();
|
||||
status = this.open();
|
||||
if (status !== 0) {
|
||||
// Break if reopen-socket fails
|
||||
break;
|
||||
}
|
||||
|
||||
// Reconnect
|
||||
status = ZeroTier.connect(this._fd, address, port);
|
||||
if (status === 0) { break; }
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/nodejs/node/blob/v12.18.3/test/parallel/test-tcp-wrap-connect.js
|
||||
if (req && req.oncomplete) { req.oncomplete.call(status, this, req, true, true); }
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
connect6(req, address, port) {
|
||||
let status = ZeroTier.connect6(this._fd, address, port);
|
||||
|
||||
// Retries are often required since ZT uses transport-triggered links
|
||||
if (status !== 0) {
|
||||
let count = 0;
|
||||
while (count < 10) {
|
||||
// Close previous socket
|
||||
this.close();
|
||||
status = this.open();
|
||||
if (status !== 0) {
|
||||
// Break if reopen-socket fails
|
||||
break;
|
||||
}
|
||||
|
||||
// Reconnect
|
||||
status = ZeroTier.connect6(this._fd, address, port);
|
||||
if (status === 0) { break; }
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/nodejs/node/blob/v12.18.3/test/parallel/test-tcp-wrap-connect.js
|
||||
if (req.oncomplete) { req.oncomplete.call(status, this, req, true, true); }
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
getpeername(out) {
|
||||
const in4 = ZeroTier.getpeername(this._fd);
|
||||
out.address = ZeroTier.inet_ntop(in4);
|
||||
out.family = in4.sin_family;
|
||||
out.port = in4.sin_port;
|
||||
return 0
|
||||
}
|
||||
|
||||
getsockname(out) {
|
||||
const in4 = ZeroTier.getsockname(this._fd);
|
||||
out.address = ZeroTier.inet_ntop(in4);
|
||||
out.family = in4.sin_family;
|
||||
out.port = in4.sin_port;
|
||||
return 0;
|
||||
}
|
||||
|
||||
listen(port) {
|
||||
// TODO
|
||||
// this.onconnection
|
||||
}
|
||||
|
||||
fchmod(mode) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
class Socket extends net.Socket {
|
||||
[kLastWriteQueueSize] = 0;
|
||||
[kBuffer] = null;
|
||||
[kBufferCb] = null;
|
||||
[kBufferGen] = null;
|
||||
|
||||
[kHandle] = null;
|
||||
get _handle() { return this[kHandle]; }
|
||||
set _handle(v) { return this[kHandle] = v; }
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L929
|
||||
*/
|
||||
// connect(...args) {
|
||||
// let normalized;
|
||||
// // If passed an array, it's treated as an array of arguments that have
|
||||
// // already been normalized (so we don't normalize more than once). This has
|
||||
// // been solved before in https://github.com/nodejs/node/pull/12342, but was
|
||||
// // reverted as it had unintended side effects.
|
||||
// if (Array.isArray(args[0])) {
|
||||
// normalized = args[0];
|
||||
// } else {
|
||||
// normalized = net._normalizeArgs(args);
|
||||
// }
|
||||
// const options = normalized[0];
|
||||
// const cb = normalized[1];
|
||||
|
||||
// if (this.write !== net.Socket.prototype.write)
|
||||
// this.write = net.Socket.prototype.write;
|
||||
|
||||
// if (this.destroyed) {
|
||||
// this._handle = null;
|
||||
// this._peername = null;
|
||||
// this._sockname = null;
|
||||
// }
|
||||
|
||||
// if (!this._handle) {
|
||||
// this._handle = new ZTCP();
|
||||
// initSocketHandle(this);
|
||||
// }
|
||||
|
||||
// if (cb !== null) {
|
||||
// this.once('connect', cb);
|
||||
// }
|
||||
|
||||
// this._unrefTimer();
|
||||
|
||||
// this.connecting = true;
|
||||
// this.writable = true;
|
||||
|
||||
// const { host, port } = options;
|
||||
// // If host is an IP, skip performing a lookup
|
||||
// const addressType = net.isIP(host);
|
||||
// if (addressType) {
|
||||
// this._fd = ZeroTier.connectStream(host, port);
|
||||
// afterConnect(0, this, {}, true, true);
|
||||
// } else {
|
||||
// throw new Error("DNS LOOKUP NOT IMPLEMENTED");
|
||||
// }
|
||||
|
||||
// return this;
|
||||
// }
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L596
|
||||
*/
|
||||
pause() {
|
||||
if (this[kBuffer] && !this.connecting && this._handle &&
|
||||
this._handle.reading) {
|
||||
this._handle.reading = false;
|
||||
if (!this.destroyed) {
|
||||
const err = this._handle.readStop();
|
||||
if (err)
|
||||
this.destroy(errnoException(err, 'read'));
|
||||
}
|
||||
}
|
||||
return stream.Duplex.prototype.pause.call(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L610
|
||||
*/
|
||||
resume() {
|
||||
if (this[kBuffer] && !this.connecting && this._handle &&
|
||||
!this._handle.reading) {
|
||||
tryReadStart(this);
|
||||
}
|
||||
return stream.Duplex.prototype.resume.call(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L619
|
||||
*/
|
||||
read(n) {
|
||||
if (this[kBuffer] && !this.connecting && this._handle &&
|
||||
!this._handle.reading) {
|
||||
tryReadStart(this);
|
||||
}
|
||||
return stream.Duplex.prototype.read.call(this, n);
|
||||
}
|
||||
|
||||
/*
|
||||
* https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_readable_read_size_1
|
||||
*/
|
||||
_read(n) {
|
||||
// debug('_read');
|
||||
|
||||
if (this.connecting || !this._handle) {
|
||||
// debug('_read wait for connection');
|
||||
this.once('connect', () => this._read(n));
|
||||
} else if (!this._handle.reading) {
|
||||
tryReadStart(this);
|
||||
}
|
||||
|
||||
// if (!this.readChunk || this.readChunk.length < n) {
|
||||
// this.readChunk = Buffer.alloc(n)
|
||||
// }
|
||||
|
||||
// let bytes = -1
|
||||
// let moreData = true
|
||||
// do {
|
||||
// bytes = ZeroTier.recv(this._fd, this.readChunk, 0)
|
||||
// switch (bytes) {
|
||||
// case -2:
|
||||
// throw new Error("ZeroTier Service error")
|
||||
// case -3:
|
||||
// throw new Error("ZeroTier Invalid argument")
|
||||
// default:
|
||||
// if (bytes > 0) {
|
||||
// // this.bytesRead += bytes
|
||||
// moreData = this.push(this.readChunk)
|
||||
// }
|
||||
// }
|
||||
// } while (bytes > 0 && moreData)
|
||||
|
||||
// if (moreData) { setTimeout(() => this._read(n), 500) }
|
||||
}
|
||||
|
||||
/*
|
||||
* https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_writable_writev_chunks_callback
|
||||
*/
|
||||
_writev(chunks, cb) {
|
||||
this._writeGeneric(true, chunks, '', cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_writable_write_chunk_encoding_callback_1
|
||||
*/
|
||||
_write(data, encoding, cb) {
|
||||
this._writeGeneric(false, data, encoding, cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_writable_final_callback
|
||||
*/
|
||||
// _final(cb) {
|
||||
// // If still connecting - defer handling `_final` until 'connect' will happen
|
||||
// if (this.pending) {
|
||||
// // debug('_final: not yet connected');
|
||||
// return this.once('connect', () => this._final(cb));
|
||||
// }
|
||||
|
||||
// if (!this._handle)
|
||||
// return cb();
|
||||
|
||||
// // debug('_final: not ended, call shutdown()');
|
||||
|
||||
// // const req = new ShutdownWrap();
|
||||
// const req = {};
|
||||
// req.oncomplete = afterShutdown;
|
||||
// req.handle = this._handle;
|
||||
// req.callback = cb;
|
||||
// // const err = this._handle.shutdown(req);
|
||||
// const err = ZeroTier.shutdown(this._fd);
|
||||
// return afterShutdown.call(req, this, 0);
|
||||
// }
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L760
|
||||
*/
|
||||
_writeGeneric(writev, data, encoding, cb) {
|
||||
// If we are still connecting, then buffer this for later.
|
||||
// The Writable logic will buffer up any more writes while
|
||||
// waiting for this one to be done.
|
||||
if (this.connecting) {
|
||||
this._pendingData = data;
|
||||
this._pendingEncoding = encoding;
|
||||
this.once('connect', function connect() {
|
||||
this._writeGeneric(writev, data, encoding, cb);
|
||||
});
|
||||
return;
|
||||
}
|
||||
this._pendingData = null;
|
||||
this._pendingEncoding = '';
|
||||
|
||||
if (!this._handle) {
|
||||
cb(new Error('ERR_SOCKET_CLOSED'));
|
||||
return false;
|
||||
}
|
||||
|
||||
this._unrefTimer();
|
||||
|
||||
let req;
|
||||
if (writev)
|
||||
req = writevGeneric(this, data, cb);
|
||||
else
|
||||
req = writeGeneric(this, data, encoding, cb);
|
||||
if (req.async)
|
||||
this[kLastWriteQueueSize] = req.bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L552
|
||||
*/
|
||||
get bufferSize() {
|
||||
if (this._handle) {
|
||||
return this[kLastWriteQueueSize] + this.writableLength;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L756
|
||||
*/
|
||||
[kAfterAsyncWrite]() {
|
||||
this[kLastWriteQueueSize] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* https://github.com/nodejs/node/blob/v12.18.3/lib/net.js#L468
|
||||
*/
|
||||
_onTimeout() {
|
||||
const handle = this._handle;
|
||||
const lastWriteQueueSize = this[kLastWriteQueueSize];
|
||||
if (lastWriteQueueSize > 0 && handle) {
|
||||
// `lastWriteQueueSize !== writeQueueSize` means there is
|
||||
// an active write in progress, so we suppress the timeout.
|
||||
const { writeQueueSize } = handle;
|
||||
if (lastWriteQueueSize !== writeQueueSize) {
|
||||
this[kLastWriteQueueSize] = writeQueueSize;
|
||||
this._unrefTimer();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// debug('_onTimeout');
|
||||
this.emit('timeout');
|
||||
}
|
||||
|
||||
get [kUpdateTimer]() {
|
||||
return this._unrefTimer;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
start: ZeroTier.start,
|
||||
join: ZeroTier.join,
|
||||
restart: ZeroTier.restart,
|
||||
stop: ZeroTier.stop,
|
||||
free: ZeroTier.free,
|
||||
example,
|
||||
connect,
|
||||
createConnection: connect,
|
||||
Socket,
|
||||
Stream: Socket, // Legacy naming
|
||||
TCP: ZTCP,
|
||||
};
|
||||
788
examples/nodejs/package-lock.json
generated
788
examples/nodejs/package-lock.json
generated
@@ -1,788 +0,0 @@
|
||||
{
|
||||
"name": "libzt",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@mcesystems/nbind": {
|
||||
"version": "0.3.18",
|
||||
"resolved": "https://registry.npmjs.org/@mcesystems/nbind/-/nbind-0.3.18.tgz",
|
||||
"integrity": "sha512-gZFv881rT/nTNNl92K97DqbFVECiniEHg4ABle7WFKklQSCge7ILY58otnKvCgoqrrS/9Mv//mTf+2k3MPSGXA==",
|
||||
"requires": {
|
||||
"emscripten-library-decorator": "~0.2.2",
|
||||
"mkdirp": "~0.5.1",
|
||||
"nan": "^2.9.2"
|
||||
}
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.3",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
|
||||
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
|
||||
},
|
||||
"are-we-there-yet": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
|
||||
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
|
||||
"requires": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^2.0.6"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"autogypi": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/autogypi/-/autogypi-0.2.2.tgz",
|
||||
"integrity": "sha1-JYurX3hXdVsJvqxqZB/qEw/0Yi0=",
|
||||
"requires": {
|
||||
"bluebird": "^3.4.0",
|
||||
"commander": "~2.9.0",
|
||||
"resolve": "~1.1.7"
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz",
|
||||
"integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
|
||||
"integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
|
||||
"requires": {
|
||||
"graceful-readlink": ">= 1.0.0"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"emscripten-library-decorator": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emscripten-library-decorator/-/emscripten-library-decorator-0.2.2.tgz",
|
||||
"integrity": "sha1-0DXwI+KoTGgwXMhCze6jjmdoPEA="
|
||||
},
|
||||
"env-paths": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
|
||||
"integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA=="
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"requires": {
|
||||
"minipass": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"gauge": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
||||
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
|
||||
"requires": {
|
||||
"aproba": "^1.0.3",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wide-align": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
|
||||
},
|
||||
"graceful-readlink": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
|
||||
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"requires": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.44.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
|
||||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.27",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
|
||||
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
|
||||
"requires": {
|
||||
"mime-db": "1.44.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
},
|
||||
"minipass": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
|
||||
"integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"minizlib": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.0.tgz",
|
||||
"integrity": "sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==",
|
||||
"requires": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.14.1",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
|
||||
"integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
|
||||
},
|
||||
"nbind": {
|
||||
"version": "github:charto/nbind#fe3abe05462d1b7559e0933e7f83802e8f05af27",
|
||||
"from": "github:charto/nbind",
|
||||
"requires": {
|
||||
"emscripten-library-decorator": "~0.2.2",
|
||||
"mkdirp": "~0.5.1",
|
||||
"nan": "^2.9.2"
|
||||
}
|
||||
},
|
||||
"node-gyp": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.0.0.tgz",
|
||||
"integrity": "sha512-ZW34qA3CJSPKDz2SJBHKRvyNQN0yWO5EGKKksJc+jElu9VA468gwJTyTArC1iOXU7rN3Wtfg/CMt/dBAOFIjvg==",
|
||||
"requires": {
|
||||
"env-paths": "^2.2.0",
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.2.3",
|
||||
"nopt": "^4.0.3",
|
||||
"npmlog": "^4.1.2",
|
||||
"request": "^2.88.2",
|
||||
"rimraf": "^2.6.3",
|
||||
"semver": "^7.3.2",
|
||||
"tar": "^6.0.1",
|
||||
"which": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
|
||||
"integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
|
||||
"requires": {
|
||||
"abbrev": "1",
|
||||
"osenv": "^0.1.4"
|
||||
}
|
||||
},
|
||||
"npmlog": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
|
||||
"requires": {
|
||||
"are-we-there-yet": "~1.1.2",
|
||||
"console-control-strings": "~1.1.0",
|
||||
"gauge": "~2.7.3",
|
||||
"set-blocking": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"os-homedir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"osenv": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
|
||||
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
|
||||
"requires": {
|
||||
"os-homedir": "^1.0.0",
|
||||
"os-tmpdir": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
||||
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
|
||||
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"tar": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.0.2.tgz",
|
||||
"integrity": "sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg==",
|
||||
"requires": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^3.0.0",
|
||||
"minizlib": "^2.1.0",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
|
||||
"requires": {
|
||||
"string-width": "^1.0.2 || 2"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "libzt",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node test.js",
|
||||
"preinstall": "mkdir -p libzt; cd libzt; ln -sf ../../../include; ln -sf ../../../lib",
|
||||
"autogypi": "autogypi",
|
||||
"node-gyp": "node-gyp",
|
||||
"ndts": "ndts",
|
||||
"install": "autogypi && node-gyp configure build"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mcesystems/nbind": "^0.3.18",
|
||||
"autogypi": "^0.2.2",
|
||||
"nbind": "github:charto/nbind",
|
||||
"node-gyp": "^7.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const kMaybeDestroy = Symbol('kMaybeDestroy');
|
||||
const kUpdateTimer = Symbol('kUpdateTimer');
|
||||
const kAfterAsyncWrite = Symbol('kAfterAsyncWrite');
|
||||
const kHandle = Symbol('kHandle');
|
||||
const kSession = Symbol('kSession');
|
||||
|
||||
// const debug = require('internal/util/debuglog').debuglog('stream');
|
||||
const kBuffer = Symbol('kBuffer');
|
||||
const kBufferGen = Symbol('kBufferGen');
|
||||
const kBufferCb = Symbol('kBufferCb');
|
||||
|
||||
let excludedStackFn;
|
||||
|
||||
function errnoException(err, syscall, original) {
|
||||
// TODO(joyeecheung): We have to use the type-checked
|
||||
// getSystemErrorName(err) to guard against invalid arguments from users.
|
||||
// This can be replaced with [ code ] = errmap.get(err) when this method
|
||||
// is no longer exposed to user land.
|
||||
if (util === undefined) util = require('util');
|
||||
const code = util.getSystemErrorName(err);
|
||||
const message = original ?
|
||||
`${syscall} ${code} ${original}` : `${syscall} ${code}`;
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const ex = new Error(message);
|
||||
// TODO(joyeecheung): errno is supposed to err, like in uvException
|
||||
ex.code = ex.errno = code;
|
||||
ex.syscall = syscall;
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
Error.captureStackTrace(ex, excludedStackFn || errnoException);
|
||||
return ex;
|
||||
}
|
||||
|
||||
function handleWriteReq(req, data, encoding) {
|
||||
const { handle } = req;
|
||||
|
||||
switch (encoding) {
|
||||
case 'buffer':
|
||||
{
|
||||
const ret = handle.writeBuffer(req, data);
|
||||
// if (streamBaseState[kLastWriteWasAsync])
|
||||
// req.buffer = data;
|
||||
return ret;
|
||||
}
|
||||
case 'latin1':
|
||||
case 'binary':
|
||||
return handle.writeLatin1String(req, data);
|
||||
case 'utf8':
|
||||
case 'utf-8':
|
||||
return handle.writeUtf8String(req, data);
|
||||
case 'ascii':
|
||||
return handle.writeAsciiString(req, data);
|
||||
case 'ucs2':
|
||||
case 'ucs-2':
|
||||
case 'utf16le':
|
||||
case 'utf-16le':
|
||||
return handle.writeUcs2String(req, data);
|
||||
default:
|
||||
{
|
||||
const buffer = Buffer.from(data, encoding);
|
||||
const ret = handle.writeBuffer(req, buffer);
|
||||
// if (streamBaseState[kLastWriteWasAsync])
|
||||
// req.buffer = buffer;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onWriteComplete(status) {
|
||||
debug('onWriteComplete', status, this.error);
|
||||
|
||||
const stream = this.handle[owner_symbol];
|
||||
|
||||
if (stream.destroyed) {
|
||||
if (typeof this.callback === 'function')
|
||||
this.callback(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status < 0) {
|
||||
const ex = errnoException(status, 'write', this.error);
|
||||
stream.destroy(ex, this.callback);
|
||||
return;
|
||||
}
|
||||
|
||||
stream[kUpdateTimer]();
|
||||
stream[kAfterAsyncWrite](this);
|
||||
|
||||
if (typeof this.callback === 'function')
|
||||
this.callback(null);
|
||||
}
|
||||
|
||||
function createWriteWrap(handle) {
|
||||
// const req = new WriteWrap();
|
||||
const req = {};
|
||||
|
||||
req.handle = handle;
|
||||
req.oncomplete = onWriteComplete;
|
||||
req.async = false;
|
||||
req.bytes = 0;
|
||||
req.buffer = null;
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
function writevGeneric(self, data, cb) {
|
||||
const req = createWriteWrap(self[kHandle]);
|
||||
const allBuffers = data.allBuffers;
|
||||
let chunks;
|
||||
if (allBuffers) {
|
||||
chunks = data;
|
||||
for (let i = 0; i < data.length; i++)
|
||||
data[i] = data[i].chunk;
|
||||
} else {
|
||||
chunks = new Array(data.length << 1);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const entry = data[i];
|
||||
chunks[i * 2] = entry.chunk;
|
||||
chunks[i * 2 + 1] = entry.encoding;
|
||||
}
|
||||
}
|
||||
const err = req.handle.writev(req, chunks, allBuffers);
|
||||
|
||||
// Retain chunks
|
||||
if (err === 0) req._chunks = chunks;
|
||||
|
||||
afterWriteDispatched(self, req, err, cb);
|
||||
return req;
|
||||
}
|
||||
|
||||
function writeGeneric(self, data, encoding, cb) {
|
||||
const req = createWriteWrap(self[kHandle]);
|
||||
const err = handleWriteReq(req, data, encoding);
|
||||
|
||||
afterWriteDispatched(self, req, err, cb);
|
||||
return req;
|
||||
}
|
||||
|
||||
function afterWriteDispatched(self, req, err, cb) {
|
||||
// req.bytes = streamBaseState[kBytesWritten];
|
||||
// req.async = !!streamBaseState[kLastWriteWasAsync];
|
||||
|
||||
if (err !== 0)
|
||||
return self.destroy(errnoException(err, 'write', req.error), cb);
|
||||
|
||||
if (!req.async) {
|
||||
cb();
|
||||
} else {
|
||||
req.callback = cb;
|
||||
}
|
||||
}
|
||||
|
||||
function onStreamRead(arrayBuffer, offset, nread) {
|
||||
// const nread = streamBaseState[kReadBytesOrError];
|
||||
|
||||
const handle = this;
|
||||
const stream = this[owner_symbol];
|
||||
|
||||
stream[kUpdateTimer]();
|
||||
|
||||
if (nread > 0 && !stream.destroyed) {
|
||||
let ret;
|
||||
let result;
|
||||
const userBuf = stream[kBuffer];
|
||||
if (userBuf) {
|
||||
result = (stream[kBufferCb](nread, userBuf) !== false);
|
||||
const bufGen = stream[kBufferGen];
|
||||
if (bufGen !== null) {
|
||||
const nextBuf = bufGen();
|
||||
if (isUint8Array(nextBuf))
|
||||
stream[kBuffer] = ret = nextBuf;
|
||||
}
|
||||
} else {
|
||||
// const offset = streamBaseState[kArrayBufferOffset];
|
||||
const buf = Buffer.from(arrayBuffer, offset, nread);
|
||||
result = stream.push(buf);
|
||||
}
|
||||
if (!result) {
|
||||
handle.reading = false;
|
||||
if (!stream.destroyed) {
|
||||
const err = handle.readStop();
|
||||
if (err)
|
||||
stream.destroy(errnoException(err, 'read'));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (nread === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (nread !== UV_EOF) {
|
||||
// return stream.destroy(errnoException(nread, 'read'));
|
||||
// }
|
||||
|
||||
// Defer this until we actually emit end
|
||||
if (stream._readableState.endEmitted) {
|
||||
if (stream[kMaybeDestroy])
|
||||
stream[kMaybeDestroy]();
|
||||
} else {
|
||||
if (stream[kMaybeDestroy])
|
||||
stream.on('end', stream[kMaybeDestroy]);
|
||||
|
||||
// TODO(ronag): Without this `readStop`, `onStreamRead`
|
||||
// will be called once more (i.e. after Readable.ended)
|
||||
// on Windows causing a ECONNRESET, failing the
|
||||
// test-https-truncate test.
|
||||
if (handle.readStop) {
|
||||
const err = handle.readStop();
|
||||
if (err)
|
||||
return stream.destroy(errnoException(err, 'read'));
|
||||
}
|
||||
|
||||
// Push a null to signal the end of data.
|
||||
// Do it before `maybeDestroy` for correct order of events:
|
||||
// `end` -> `close`
|
||||
stream.push(null);
|
||||
stream.read(0);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
errnoException,
|
||||
createWriteWrap,
|
||||
writevGeneric,
|
||||
writeGeneric,
|
||||
onStreamRead,
|
||||
kAfterAsyncWrite,
|
||||
kMaybeDestroy,
|
||||
kUpdateTimer,
|
||||
kHandle,
|
||||
kSession,
|
||||
// setStreamTimeout,
|
||||
kBuffer,
|
||||
kBufferCb,
|
||||
kBufferGen
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const libzt = require('./libzt')
|
||||
|
||||
// libzt.example("8056c2e21c000001", "29.49.7.203", 4444)
|
||||
|
||||
libzt.start(".zerotier", 9994)
|
||||
|
||||
libzt.join("8056c2e21c000001")
|
||||
|
||||
// Usage: `nc -lv 4444`
|
||||
let client = libzt.createConnection({ port: 4444, host: '29.49.7.203' }, () => {
|
||||
console.log('connected to server!');
|
||||
});
|
||||
client.on('ready', () => {
|
||||
client.write("Name?\n", 'utf8');
|
||||
});
|
||||
client.on('data', (data) => {
|
||||
console.log(data.toString('utf8').trimEnd());
|
||||
if (data.toString('utf8').includes("exit")) { client.end(); }
|
||||
});
|
||||
client.on('end', () => {
|
||||
console.log('disconnected from server');
|
||||
libzt.stop()
|
||||
});
|
||||
@@ -1,240 +0,0 @@
|
||||
/**
|
||||
* libzt API example
|
||||
*
|
||||
* Specify location of zt.framework and link to standard C++ library:
|
||||
*
|
||||
* clang -lc++ -framework Foundation -F . -framework zt adhoc.m -o adhoc;
|
||||
*
|
||||
* Pingable node joined to controller-less adhoc network with a 6PLANE addressing scheme
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <zt/ZeroTierSockets.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* IDENTITIES and AUTHORIZATION:
|
||||
*
|
||||
* - Upon the first execution of this code, a new identity will be generated and placed in
|
||||
* the location given in the first argument to zts_start(path, ...). If you accidentally
|
||||
* duplicate the identity files and use them simultaneously in a different node instance
|
||||
* you will experience undefined behavior and it is likely nothing will work.
|
||||
*
|
||||
* - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join
|
||||
* your network, otherwise nothing will happen. This can be done manually or via
|
||||
* our web API: https://my.zerotier.com/help/api
|
||||
*
|
||||
* - An exception to the above rule is if you are using an Ad-hoc network, it has no
|
||||
* controller and therefore requires no authorization.
|
||||
*
|
||||
*
|
||||
* ESTABLISHING A CONNECTION:
|
||||
*
|
||||
* - Creating a standard socket connection generally works the same as it would using
|
||||
* an ordinary socket interface, however with libzt there is a subtle difference in
|
||||
* how connections are established which may cause confusion:
|
||||
*
|
||||
* The underlying virtual ZT layer creates what are called "transport-triggered links"
|
||||
* between nodes. That is, links are not established until an attempt to communicate
|
||||
* with a peer has taken place. The side effect is that the first few packets sent from
|
||||
* a libzt instance are usually relayed via our free infrastructure and it isn't until a
|
||||
* root server has passed contact information to both peers that a direct connection will be
|
||||
* established. Therefore, it is required that multiple connection attempts be undertaken
|
||||
* when initially communicating with a peer. After a transport-triggered link is
|
||||
* established libzt will inform you via ZTS_EVENT_PEER_DIRECT for a specific peer ID. No
|
||||
* action is required on your part for this callback event.
|
||||
*
|
||||
* Note: In these initial moments before ZTS_EVENT_PEER_DIRECT has been received for a
|
||||
* specific peer, traffic may be slow, jittery and there may be high packet loss.
|
||||
* This will subside within a couple of seconds.
|
||||
*
|
||||
*
|
||||
* ERROR HANDLING:
|
||||
*
|
||||
* - libzt's API is actually composed of two categories of functions with slightly
|
||||
* different error reporting mechanisms.
|
||||
*
|
||||
* Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors
|
||||
* returned by these functions can be any of the following:
|
||||
*
|
||||
* ZTS_ERR_OK // No error
|
||||
* ZTS_ERR_SOCKET // Socket error, see zts_errno
|
||||
* ZTS_ERR_SERVICE // You probably did something at the wrong time
|
||||
* ZTS_ERR_ARG // Invalid argument
|
||||
* ZTS_ERR_NO_RESULT // No result (not necessarily an error)
|
||||
* ZTS_ERR_GENERAL // Consider filing a bug report
|
||||
*
|
||||
* Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc).
|
||||
* Errors returned by these functions can be the same as the above. With
|
||||
* the added possibility of zts_errno being set. Much like standard
|
||||
* errno this will provide a more specific reason for an error's occurrence.
|
||||
* See ZeroTierSockets.h for values.
|
||||
*
|
||||
*
|
||||
* API COMPATIBILITY WITH HOST OS:
|
||||
*
|
||||
* - While the ZeroTier socket interface can coexist with your host OS's own interface in
|
||||
* the same file with no type and naming conflicts, try not to mix and match host
|
||||
* OS/libzt structures, functions, or constants. It may look similar and may even work
|
||||
* some of the time but there enough differences that it will cause headaches. Here
|
||||
* are a few guidelines:
|
||||
*
|
||||
* If you are calling a zts_* function, use the appropriate ZTS_* constants:
|
||||
*
|
||||
* zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT)
|
||||
* zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT)
|
||||
*
|
||||
* If you are calling a zts_* function, use the appropriate zts_* structure:
|
||||
*
|
||||
* struct zts_sockaddr_in in4; <------ Note the zts_* prefix
|
||||
* ...
|
||||
* zts_bind(fd, (struct zts_sockaddr *)&in4, sizeof(struct zts_sockaddr_in)) < 0)
|
||||
*
|
||||
*/
|
||||
|
||||
void delay_ms(long ms) { usleep(ms*1000); }
|
||||
|
||||
bool nodeReady = false;
|
||||
bool networkReady = false;
|
||||
|
||||
// Example callbacks
|
||||
void on_zts_event(struct zts_callback_msg *msg)
|
||||
{
|
||||
// Node events
|
||||
if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) {
|
||||
NSLog(@"ZTS_EVENT_NODE_ONLINE --- This node's ID is %llx\n", msg->node->address);
|
||||
nodeReady = true;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NODE_OFFLINE) {
|
||||
NSLog(@"ZTS_EVENT_NODE_OFFLINE --- Check your physical Internet connection, router, firewall, etc. What ports are you blocking?\n");
|
||||
nodeReady = false;
|
||||
}
|
||||
// Virtual network events
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_NOT_FOUND) {
|
||||
NSLog(@"ZTS_EVENT_NETWORK_NOT_FOUND --- Are you sure %llx is a valid network?\n",
|
||||
msg->network->nwid);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_REQ_CONFIG) {
|
||||
NSLog(@"ZTS_EVENT_NETWORK_REQ_CONFIG --- Requesting config for network %llx, please wait a few seconds...\n", msg->network->nwid);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_ACCESS_DENIED) {
|
||||
NSLog(@"ZTS_EVENT_NETWORK_ACCESS_DENIED --- Access to virtual network %llx has been denied. Did you authorize the node yet?\n",
|
||||
msg->network->nwid);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_READY_IP6) {
|
||||
NSLog(@"ZTS_EVENT_NETWORK_READY_IP6 --- Network config received. IPv6 traffic can now be sent over network %llx\n",
|
||||
msg->network->nwid);
|
||||
networkReady = true;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETWORK_DOWN) {
|
||||
NSLog(@"ZTS_EVENT_NETWORK_DOWN --- %llx\n", msg->network->nwid);
|
||||
}
|
||||
// Network stack events
|
||||
if (msg->eventCode == ZTS_EVENT_NETIF_UP) {
|
||||
NSLog(@"ZTS_EVENT_NETIF_UP --- network=%llx, mac=%llx, mtu=%d\n",
|
||||
msg->netif->nwid,
|
||||
msg->netif->mac,
|
||||
msg->netif->mtu);
|
||||
networkReady = true;
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_NETIF_DOWN) {
|
||||
NSLog(@"ZTS_EVENT_NETIF_DOWN --- network=%llx, mac=%llx\n",
|
||||
msg->netif->nwid,
|
||||
msg->netif->mac);
|
||||
|
||||
networkReady = true;
|
||||
}
|
||||
// Address events
|
||||
if (msg->eventCode == ZTS_EVENT_ADDR_ADDED_IP6) {
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
struct zts_sockaddr_in6 *in6 = (struct zts_sockaddr_in6*)&(msg->addr->addr);
|
||||
inet_ntop(AF_INET6, &(in6->sin6_addr), ipstr, INET6_ADDRSTRLEN);
|
||||
NSLog(@"ZTS_EVENT_ADDR_NEW_IP6 --- Join %llx and ping me at %s\n",
|
||||
msg->addr->nwid, ipstr);
|
||||
}
|
||||
// Peer events
|
||||
// If you don't recognize the peer ID, don't panic, this is most likely one of our root servers
|
||||
if (msg->eventCode == ZTS_EVENT_PEER_DIRECT) {
|
||||
NSLog(@"ZTS_EVENT_PEER_DIRECT --- There is now a direct path to peer %llx\n",
|
||||
msg->peer->address);
|
||||
}
|
||||
if (msg->eventCode == ZTS_EVENT_PEER_RELAY) {
|
||||
NSLog(@"ZTS_EVENT_PEER_RELAY --- No direct path to peer %llx\n",
|
||||
msg->peer->address);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Ad-hoc Network:
|
||||
|
||||
ffSSSSEEEE000000
|
||||
| | | |
|
||||
| | | Reserved for future use, must be 0
|
||||
| | End of port range (hex)
|
||||
| Start of port range (hex)
|
||||
Reserved ZeroTier address prefix indicating a controller-less network.
|
||||
|
||||
Ad-hoc networks are public (no access control) networks that have no network controller. Instead
|
||||
their configuration and other credentials are generated locally. Ad-hoc networks permit only IPv6
|
||||
UDP and TCP unicast traffic (no multicast or broadcast) using 6plane format NDP-emulated IPv6
|
||||
addresses. In addition an ad-hoc network ID encodes an IP port range. UDP packets and TCP SYN
|
||||
(connection open) packets are only allowed to destination ports within the encoded range.
|
||||
|
||||
For example ff00160016000000 is an ad-hoc network allowing only SSH, while ff0000ffff000000 is an
|
||||
ad-hoc network allowing any UDP or TCP port.
|
||||
|
||||
Keep in mind that these networks are public and anyone in the entire world can join them. Care must
|
||||
be taken to avoid exposing vulnerable services or sharing unwanted files or other resources.
|
||||
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 5) {
|
||||
NSLog(@"\nlibzt example\n");
|
||||
NSLog(@"adhoc <config_file_path> <adhocStartPort> <adhocEndPort> <ztServicePort>\n");
|
||||
exit(0);
|
||||
}
|
||||
int adhocStartPort = atoi(argv[2]); // Start of port range your application will use
|
||||
int adhocEndPort = atoi(argv[3]); // End of port range your application will use
|
||||
int ztServicePort = atoi(argv[4]); // Port ZT uses to send encrypted UDP packets to peers (try something like 9994)
|
||||
|
||||
uint64_t adhoc_nwid = zts_generate_adhoc_nwid_from_range(adhocStartPort, adhocEndPort);
|
||||
int err = ZTS_ERR_OK;
|
||||
|
||||
// If disabled: (network) details will NOT be written to or read from (networks.d/). It may take slightly longer to start the node
|
||||
zts_allow_network_caching(1);
|
||||
// If disabled: (peer) details will NOT be written to or read from (peers.d/). It may take slightly longer to contact a remote peer
|
||||
zts_allow_peer_caching(1);
|
||||
// If disabled: Settings will NOT be read from local.conf
|
||||
zts_allow_local_conf(1);
|
||||
|
||||
if((err = zts_start(argv[1], &on_zts_event, ztServicePort)) != ZTS_ERR_OK) {
|
||||
NSLog(@"Unable to start service, error = %d. Exiting.\n", err);
|
||||
exit(1);
|
||||
}
|
||||
NSLog(@"Waiting for node to come online...\n");
|
||||
while (!nodeReady) { delay_ms(50); }
|
||||
NSLog(@"This node's identity is stored in %s\n", argv[1]);
|
||||
|
||||
if((err = zts_join(adhoc_nwid)) != ZTS_ERR_OK) {
|
||||
NSLog(@"Unable to join network, error = %d. Exiting.\n", err);
|
||||
exit(1);
|
||||
}
|
||||
NSLog(@"Joining network %llx\n", adhoc_nwid);
|
||||
while (!networkReady) { delay_ms(50); }
|
||||
|
||||
// Idle and just show callback events, stack statistics, etc
|
||||
|
||||
NSLog(@"Node will now idle...\n");
|
||||
while (true) { delay_ms(1000); }
|
||||
|
||||
// Shut down service and stack threads
|
||||
|
||||
zts_stop();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
all:
|
||||
swiftc -g -lc++ -import-objc-header ../../include/ZeroTierSockets.h ../../lib/debug/macos-x86_64/zt.framework/zt main.swift -o main
|
||||
@@ -1,353 +0,0 @@
|
||||
/**
|
||||
* I'll order you a pizza if you can rewrite this in modern idomatic Swift
|
||||
*/
|
||||
|
||||
import Swift
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
*
|
||||
* IDENTITIES and AUTHORIZATION:
|
||||
*
|
||||
* - Upon the first execution of this code, a new identity will be generated and placed in
|
||||
* the location given in the first argument to zts_start(path, ...). If you accidentally
|
||||
* duplicate the identity files and use them simultaneously in a different node instance
|
||||
* you will experience undefined behavior and it is likely nothing will work.
|
||||
*
|
||||
* - You must authorize the node ID provided by the ZTS_EVENT_NODE_ONLINE callback to join
|
||||
* your network, otherwise nothing will happen. This can be done manually or via
|
||||
* our web API: https://my.zerotier.com/help/api
|
||||
*
|
||||
* - An exception to the above rule is if you are using an Ad-hoc network, it has no
|
||||
* controller and therefore requires no authorization.
|
||||
*
|
||||
*
|
||||
* ESTABLISHING A CONNECTION:
|
||||
*
|
||||
* - Creating a standard socket connection generally works the same as it would using
|
||||
* an ordinary socket interface, however with libzt there is a subtle difference in
|
||||
* how connections are established which may cause confusion:
|
||||
*
|
||||
* The underlying virtual ZT layer creates what are called "transport-triggered links"
|
||||
* between nodes. That is, links are not established until an attempt to communicate
|
||||
* with a peer has taken place. The side effect is that the first few packets sent from
|
||||
* a libzt instance are usually relayed via our free infrastructure and it isn't until a
|
||||
* root server has passed contact information to both peers that a direct connection will be
|
||||
* established. Therefore, it is required that multiple connection attempts be undertaken
|
||||
* when initially communicating with a peer. After a transport-triggered link is
|
||||
* established libzt will inform you via ZTS_EVENT_PEER_DIRECT for a specific peer ID. No
|
||||
* action is required on your part for this callback event.
|
||||
*
|
||||
* Note: In these initial moments before ZTS_EVENT_PEER_DIRECT has been received for a
|
||||
* specific peer, traffic may be slow, jittery and there may be high packet loss.
|
||||
* This will subside within a couple of seconds.
|
||||
*
|
||||
*
|
||||
* ERROR HANDLING:
|
||||
*
|
||||
* - libzt's API is actually composed of two categories of functions with slightly
|
||||
* different error reporting mechanisms.
|
||||
*
|
||||
* Category 1: Control functions (zts_start, zts_join, zts_get_peer_status, etc). Errors
|
||||
* returned by these functions can be any of the following:
|
||||
*
|
||||
* ZTS_ERR_OK // No error
|
||||
* ZTS_ERR_SOCKET // Socket error, see zts_errno
|
||||
* ZTS_ERR_SERVICE // You probably did something at the wrong time
|
||||
* ZTS_ERR_ARG // Invalid argument
|
||||
* ZTS_ERR_NO_RESULT // No result (not necessarily an error)
|
||||
* ZTS_ERR_GENERAL // Consider filing a bug report
|
||||
*
|
||||
* Category 2: Sockets (zts_socket, zts_bind, zts_connect, zts_listen, etc).
|
||||
* Errors returned by these functions can be the same as the above. With
|
||||
* the added possibility of zts_errno being set. Much like standard
|
||||
* errno this will provide a more specific reason for an error's occurrence.
|
||||
* See ZeroTierSockets.h for values.
|
||||
*
|
||||
*
|
||||
* API COMPATIBILITY WITH HOST OS:
|
||||
*
|
||||
* - While the ZeroTier socket interface can coexist with your host OS's own interface in
|
||||
* the same file with no type and naming conflicts, try not to mix and match host
|
||||
* OS/libzt structures, functions, or constants. It may look similar and may even work
|
||||
* some of the time but there enough differences that it will cause headaches. Here
|
||||
* are a few guidelines:
|
||||
*
|
||||
* If you are calling a zts_* function, use the appropriate ZTS_* constants:
|
||||
*
|
||||
* zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT)
|
||||
* zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT)
|
||||
*
|
||||
* If you are calling a zts_* function, use the appropriate zts_* structure:
|
||||
*
|
||||
* struct zts_sockaddr_in in4; <------ Note the zts_* prefix
|
||||
* ...
|
||||
* zts_bind(fd, (struct zts_sockaddr *)&in4, sizeof(struct zts_sockaddr_in)) < 0)
|
||||
*
|
||||
*/
|
||||
|
||||
let printNodeDetails : @convention(c) (UnsafeMutableRawPointer?) -> Void =
|
||||
{
|
||||
(msgPtr) -> Void in
|
||||
let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1)
|
||||
let d = msg?.pointee.node;
|
||||
print(String(format: "\t- id : %llx", d!.pointee.address));
|
||||
print(String(format: "\t- version : %d.%d.%d", d!.pointee.versionMajor, d!.pointee.versionMinor, d!.pointee.versionRev));
|
||||
print(String(format: "\t- primaryPort : %d", d!.pointee.primaryPort));
|
||||
print(String(format: "\t- secondaryPort : %d", d!.pointee.secondaryPort));
|
||||
}
|
||||
|
||||
/*
|
||||
func convertTupleToArray<Tuple, Value>(from tuple: Tuple) -> [Value] {
|
||||
let tupleMirror = Mirror(reflecting: tuple)
|
||||
func convert(child: Mirror.Child) -> Value? {
|
||||
let valueMirror = Mirror(reflecting: child.value)
|
||||
return child.value as? Value
|
||||
}
|
||||
return tupleMirror.children.flatMap(convert)
|
||||
}
|
||||
*/
|
||||
|
||||
let printNetworkDetails : @convention(c) (UnsafeMutableRawPointer?) -> Void =
|
||||
{
|
||||
(msgPtr) -> Void in
|
||||
let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1)
|
||||
let d = msg?.pointee.network;
|
||||
let name = ""; // String(d!.pointee.name);
|
||||
|
||||
print(String(format: "\t- nwid : %llx", d!.pointee.nwid));
|
||||
print(String(format: "\t- mac : %lx", d!.pointee.mac));
|
||||
print(String(format: "\t- name : %s", name));
|
||||
print(String(format: "\t- type : %d", Int(d!.pointee.type.rawValue)));
|
||||
/* MTU for the virtual network can be set via our web API */
|
||||
print(String(format: "\t- mtu : %d", d!.pointee.mtu));
|
||||
print(String(format: "\t- dhcp : %d", d!.pointee.dhcp));
|
||||
print(String(format: "\t- bridge : %d", d!.pointee.bridge));
|
||||
print(String(format: "\t- broadcastEnabled : %d", d!.pointee.broadcastEnabled));
|
||||
print(String(format: "\t- portError : %d", d!.pointee.portError));
|
||||
print(String(format: "\t- netconfRevision : %d", d!.pointee.netconfRevision));
|
||||
print(String(format: "\t- routeCount : %d", d!.pointee.routeCount));
|
||||
print(String(format: "\t- multicastSubscriptionCount : %d", d!.pointee.multicastSubscriptionCount));
|
||||
/*
|
||||
var addresses: [zts_sockaddr_storage] = convertTupleToArray(from: d!.pointee.assignedAddresses)
|
||||
|
||||
print("\t- addresses:\n");
|
||||
for i in 0...d!.pointee.assignedAddressCount {
|
||||
if (addresses[Int(i)].ss_family == ZTS_AF_INET) {
|
||||
// Allocate a byte array that can hold the largest possible IPv4 human-readable string
|
||||
var ipCharByteArray = Array<Int8>(repeating: 0, count: Int(ZTS_INET_ADDRSTRLEN))
|
||||
// Cast unsafe pointer from zts_sockaddr_storage to zts_sockaddr_in
|
||||
var addr:zts_sockaddr_in = withUnsafePointer(to: &(addresses[Int(i)])) {
|
||||
$0.withMemoryRebound(to: zts_sockaddr_in.self, capacity: 1) {
|
||||
$0.pointee
|
||||
}
|
||||
}
|
||||
// Pass unsafe pointer (addr) to a ntop to convert into human-readable byte array
|
||||
zts_inet_ntop(ZTS_AF_INET, &(addr.sin_addr), &ipCharByteArray, UInt32(ZTS_INET_ADDRSTRLEN))
|
||||
//print(ipCharByteArray) // [49, 55, 50, 46, 50, 55, 46, 49, 49, 54, 46, 49, 54, 55, 0, 0]
|
||||
// Somehow convery Int8 byte array to Swift String ???
|
||||
//let ipString = String(bytes: ipStr, encoding: .utf8)
|
||||
//print(ipString)
|
||||
|
||||
// Pass unsafe pointer (addr) to a ntop to convert into human-readable byte array
|
||||
// convert to UInt8 byte array
|
||||
let uintArray = ipCharByteArray.map { UInt8(bitPattern: $0) }
|
||||
if let string = String(bytes: uintArray, encoding: .utf8) {
|
||||
print("\t\t-", string)
|
||||
}
|
||||
}
|
||||
if (addresses[Int(i)].ss_family == ZTS_AF_INET6) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
print("\t- routes:\n");
|
||||
|
||||
for i in 0...d!.pointee.routeCount {
|
||||
// ...
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
let printPeerDetails : @convention(c) (UnsafeMutableRawPointer?) -> Void =
|
||||
{
|
||||
(msgPtr) -> Void in
|
||||
let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1)
|
||||
let d = msg?.pointee.peer;
|
||||
print(String(format: "\t- peer : %llx", d!.pointee.address));
|
||||
print(String(format: "\t- role : %d", Int(d!.pointee.role.rawValue)));
|
||||
print(String(format: "\t- latency : %llx", d!.pointee.latency));
|
||||
print(String(format: "\t- pathCount : %llx", d!.pointee.pathCount));
|
||||
print(String(format: "\t- version : %d.%d.%d", d!.pointee.versionMajor, d!.pointee.versionMinor, d!.pointee.versionRev));
|
||||
print(String(format: "\t- paths:\n"));
|
||||
|
||||
/*
|
||||
for i in 0...d!.pointee.pathCount {
|
||||
// ...
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
let printNetifDetails : @convention(c) (UnsafeMutableRawPointer?) -> Void =
|
||||
{
|
||||
(msgPtr) -> Void in
|
||||
let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1)
|
||||
let d = msg?.pointee.netif;
|
||||
print(String(format: "\t- nwid : %llx", d!.pointee.nwid));
|
||||
print(String(format: "\t- mac : %llx", d!.pointee.mac));
|
||||
print(String(format: "\t- mtu : %d", d!.pointee.mtu));
|
||||
}
|
||||
|
||||
var nodeReady:Bool = false
|
||||
var networkReady:Bool = false
|
||||
|
||||
let on_zts_event : @convention(c) (UnsafeMutableRawPointer?) -> Void =
|
||||
{
|
||||
(msgPtr) -> Void in
|
||||
let msg = msgPtr?.bindMemory(to: zts_callback_msg.self, capacity: 1)
|
||||
|
||||
let eventCode = msg!.pointee.eventCode
|
||||
let network = msg?.pointee.network;
|
||||
let peer = msg?.pointee.peer;
|
||||
|
||||
switch Int32(eventCode)
|
||||
{
|
||||
case ZTS_EVENT_NODE_UP:
|
||||
print("ZTS_EVENT_NODE_UP (you can ignore this)\n")
|
||||
|
||||
case ZTS_EVENT_NODE_ONLINE:
|
||||
print("ZTS_EVENT_NODE_ONLINE\n")
|
||||
printNodeDetails(msg)
|
||||
nodeReady = true;
|
||||
|
||||
case ZTS_EVENT_NODE_OFFLINE:
|
||||
print("ZTS_EVENT_NODE_OFFLINE\n")
|
||||
nodeReady = false;
|
||||
|
||||
case ZTS_EVENT_NODE_NORMAL_TERMINATION:
|
||||
print("ZTS_EVENT_NODE_NORMAL_TERMINATION\n")
|
||||
|
||||
case ZTS_EVENT_NETWORK_NOT_FOUND:
|
||||
let networkId:UInt64 = network!.pointee.nwid
|
||||
print(String(format: "ZTS_EVENT_NETWORK_NOT_FOUND (%llx)", networkId))
|
||||
|
||||
case ZTS_EVENT_NETWORK_REQ_CONFIG:
|
||||
let networkId:UInt64 = network!.pointee.nwid
|
||||
print(String(format: "ZTS_EVENT_NETWORK_REQ_CONFIG (%llx)", networkId))
|
||||
|
||||
case ZTS_EVENT_NETWORK_ACCESS_DENIED:
|
||||
let networkId:UInt64 = network!.pointee.nwid
|
||||
print(String(format: "ZTS_EVENT_NETWORK_ACCESS_DENIED (%llx)", networkId))
|
||||
|
||||
case ZTS_EVENT_NETWORK_READY_IP4:
|
||||
let networkId:UInt64 = network!.pointee.nwid
|
||||
print(String(format: "ZTS_EVENT_NETWORK_READY_IP4 (%llx)", networkId))
|
||||
networkReady = true;
|
||||
|
||||
case ZTS_EVENT_NETWORK_READY_IP6:
|
||||
let networkId:UInt64 = network!.pointee.nwid
|
||||
print(String(format: "ZTS_EVENT_NETWORK_READY_IP6 (%llx)", networkId))
|
||||
networkReady = true;
|
||||
|
||||
case ZTS_EVENT_NETWORK_DOWN:
|
||||
let networkId:UInt64 = network!.pointee.nwid
|
||||
print(String(format: "ZTS_EVENT_NETWORK_DOWN (%llx)", networkId))
|
||||
|
||||
case ZTS_EVENT_NETWORK_UPDATE:
|
||||
print("ZTS_EVENT_NETWORK_UPDATE\n")
|
||||
printNetworkDetails(msg)
|
||||
|
||||
|
||||
case ZTS_EVENT_ADDR_ADDED_IP4:
|
||||
print("ZTS_EVENT_ADDR_ADDED_IP4\n")
|
||||
|
||||
case ZTS_EVENT_ADDR_ADDED_IP6:
|
||||
print("ZTS_EVENT_ADDR_ADDED_IP6\n")
|
||||
|
||||
case ZTS_EVENT_ADDR_REMOVED_IP4:
|
||||
print("ZTS_EVENT_ADDR_REMOVED_IP4\n")
|
||||
|
||||
case ZTS_EVENT_ADDR_REMOVED_IP6:
|
||||
print("ZTS_EVENT_ADDR_REMOVED_IP6\n")
|
||||
|
||||
|
||||
case ZTS_EVENT_PEER_DIRECT:
|
||||
let peerId:UInt64 = peer!.pointee.address
|
||||
print(String(format: "ZTS_EVENT_PEER_DIRECT (%llx)", peerId))
|
||||
printPeerDetails(msg)
|
||||
|
||||
case ZTS_EVENT_PEER_RELAY:
|
||||
let peerId:UInt64 = peer!.pointee.address
|
||||
print(String(format: "ZTS_EVENT_PEER_RELAY (%llx)", peerId))
|
||||
printPeerDetails(msg)
|
||||
|
||||
case ZTS_EVENT_PEER_PATH_DISCOVERED:
|
||||
let peerId:UInt64 = peer!.pointee.address
|
||||
print(String(format: "ZTS_EVENT_PEER_PATH_DISCOVERED (%llx)", peerId))
|
||||
printPeerDetails(msg)
|
||||
|
||||
case ZTS_EVENT_PEER_PATH_DEAD:
|
||||
let peerId:UInt64 = peer!.pointee.address
|
||||
print(String(format: "ZTS_EVENT_PEER_PATH_DEAD (%llx)", peerId))
|
||||
printPeerDetails(msg)
|
||||
|
||||
|
||||
case ZTS_EVENT_NETIF_UP:
|
||||
print("ZTS_EVENT_NETIF_UP\n")
|
||||
|
||||
case ZTS_EVENT_NETIF_DOWN:
|
||||
print("ZTS_EVENT_NETIF_DOWN\n")
|
||||
|
||||
case ZTS_EVENT_NETIF_REMOVED:
|
||||
print("ZTS_EVENT_NETIF_REMOVED\n")
|
||||
|
||||
case ZTS_EVENT_NETIF_LINK_UP:
|
||||
print("ZTS_EVENT_NETIF_LINK_UP\n")
|
||||
|
||||
case ZTS_EVENT_NETIF_LINK_DOWN:
|
||||
print("ZTS_EVENT_NETIF_LINK_DOWN\n")
|
||||
|
||||
case ZTS_EVENT_STACK_UP:
|
||||
print("ZTS_EVENT_STACK_UP\n")
|
||||
|
||||
case ZTS_EVENT_STACK_DOWN:
|
||||
print("ZTS_EVENT_STACK_DOWN\n")
|
||||
|
||||
default:
|
||||
print("UNKNOWN_EVENT: ", eventCode)
|
||||
}
|
||||
}
|
||||
|
||||
func main()
|
||||
{
|
||||
print("waiting for node to come online...")
|
||||
zts_start("config_path", on_zts_event, 0)
|
||||
while(!nodeReady) {
|
||||
sleep(1)
|
||||
}
|
||||
print("Joining network")
|
||||
|
||||
let nwId : UInt64 = 0x0123456789abcdef; // Specify your network ID here
|
||||
zts_join(nwId);
|
||||
|
||||
// create address structure
|
||||
let addr_str = "0.0.0.0"
|
||||
let port = 8080
|
||||
var in4 = zts_sockaddr_in(sin_len: UInt8(MemoryLayout<zts_sockaddr_in>.size),
|
||||
sin_family: UInt8(ZTS_AF_INET),
|
||||
sin_port: UInt16(port).bigEndian,
|
||||
sin_addr: zts_in_addr(s_addr: 0),
|
||||
sin_zero: (0,0,0,0,0,0,0,0))
|
||||
zts_inet_pton(ZTS_AF_INET, addr_str, &(in4.sin_addr));
|
||||
|
||||
print("fd=", zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0));
|
||||
|
||||
// ...
|
||||
|
||||
while(true) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user