aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/file.c28
-rw-r--r--src/core/file.h6
-rw-r--r--src/core/platform.h12
-rw-r--r--src/platform/posix/posix_file.c27
-rw-r--r--src/platform/posix/posix_impl.h4
-rw-r--r--src/platform/windows/win_debug.c13
-rw-r--r--src/platform/windows/win_file.c24
-rw-r--r--src/platform/windows/win_impl.h4
-rw-r--r--src/transport/zerotier/zerotier.c71
-rw-r--r--tools/nngcat/nngcat.c26
10 files changed, 183 insertions, 32 deletions
diff --git a/src/core/file.c b/src/core/file.c
index 4715be2a..b76fdcda 100644
--- a/src/core/file.c
+++ b/src/core/file.c
@@ -128,4 +128,32 @@ const char *
nni_file_basename(const char *path)
{
return (nni_plat_file_basename(path));
+}
+
+struct nni_file_lockh {
+ nni_plat_flock lk;
+};
+
+int
+nni_file_lock(const char *path, nni_file_lockh **hp)
+{
+ nni_file_lockh *h;
+ int rv;
+ if ((h = NNI_ALLOC_STRUCT(h)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+ rv = nni_plat_file_lock(path, &h->lk);
+ if (rv != 0) {
+ NNI_FREE_STRUCT(h);
+ return (rv);
+ }
+ *hp = h;
+ return (0);
+}
+
+void
+nni_file_unlock(nni_file_lockh *h)
+{
+ nni_plat_file_unlock(&h->lk);
+ NNI_FREE_STRUCT(h);
} \ No newline at end of file
diff --git a/src/core/file.h b/src/core/file.h
index 7969ae5f..3baa1ccd 100644
--- a/src/core/file.h
+++ b/src/core/file.h
@@ -84,4 +84,10 @@ extern bool nni_file_is_file(const char *);
// false if an error occurs, or the path references something else.
extern bool nni_file_is_dir(const char *);
+typedef struct nni_file_lockh nni_file_lockh;
+
+extern int nni_file_lock(const char *, nni_file_lockh **);
+
+extern void nni_file_unlock(nni_file_lockh *);
+
#endif // CORE_FILE_H
diff --git a/src/core/platform.h b/src/core/platform.h
index 3f336f11..d5fc40f7 100644
--- a/src/core/platform.h
+++ b/src/core/platform.h
@@ -434,6 +434,18 @@ typedef int (*nni_plat_file_walker)(const char *, void *);
// with the path name, and the supplied void * argument.
extern int nni_plat_file_walk(const char *, nni_plat_file_walker, void *, int);
+typedef struct nni_plat_flock nni_plat_flock;
+
+// nni_plat_file_lock locks the file. This usually means open it (creating
+// if it does not exist) and doing a lock operation. The nni_plat_flock
+// is our handle for the lock, to unlock. Usually its just a file descriptor,
+// and we can unlock by doing close(). Note that this is a "try-lock"
+// operation -- if the file is already locked then NNG_EBUSY is returned.
+extern int nni_plat_file_lock(const char *path, nni_plat_flock *);
+
+// nni_plat_file_unlock unlocks the previously locked file.
+extern void nni_plat_file_unlock(nni_plat_flock *);
+
// nni_plat_dir_open attempts to "open a directory" for listing. The
// handle for further operations is returned in the first argument, and
// the directory name is supplied in the second.
diff --git a/src/platform/posix/posix_file.c b/src/platform/posix/posix_file.c
index 7863fdee..83d045fa 100644
--- a/src/platform/posix/posix_file.c
+++ b/src/platform/posix/posix_file.c
@@ -260,6 +260,33 @@ nni_plat_file_basename(const char *path)
return (path);
}
+int
+nni_plat_file_lock(const char *path, nni_plat_flock *lk)
+{
+ int fd;
+ if ((fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
+ return (nni_plat_errno(errno));
+ }
+ if (lockf(fd, F_TLOCK, 0) < 0) {
+ int rv = errno;
+ close(fd);
+ if (rv == EAGAIN) {
+ return (NNG_EBUSY);
+ }
+ return (nni_plat_errno(rv));
+ }
+ lk->fd = fd;
+ return (0);
+}
+
+void
+nni_plat_file_unlock(nni_plat_flock *lk)
+{
+ int fd = lk->fd;
+ lk->fd = -1;
+ (void) close(fd);
+}
+
char *
nni_plat_temp_dir(void)
{
diff --git a/src/platform/posix/posix_impl.h b/src/platform/posix/posix_impl.h
index 0b2a09f0..3616c69b 100644
--- a/src/platform/posix/posix_impl.h
+++ b/src/platform/posix/posix_impl.h
@@ -76,6 +76,10 @@ struct nni_plat_thr {
void *arg;
};
+struct nni_plat_flock {
+ int fd;
+};
+
#define NNG_PLATFORM_DIR_SEP "/"
#endif
diff --git a/src/platform/windows/win_debug.c b/src/platform/windows/win_debug.c
index 00e327db..a47e7b41 100644
--- a/src/platform/windows/win_debug.c
+++ b/src/platform/windows/win_debug.c
@@ -1,5 +1,6 @@
//
-// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
@@ -83,9 +84,8 @@ nni_plat_errno(int errnum)
static struct {
int win_err;
int nng_err;
-} nni_win_errnos[] =
- {
- // clang-format off
+} nni_win_errnos[] = {
+ // clang-format off
{ ERROR_FILE_NOT_FOUND, NNG_ENOENT },
{ ERROR_PATH_NOT_FOUND, NNG_ENOENT },
{ ERROR_ACCESS_DENIED, NNG_EPERM },
@@ -104,6 +104,7 @@ static struct {
{ ERROR_NO_DATA, NNG_ECLOSED },
{ ERROR_PIPE_NOT_CONNECTED, NNG_ECLOSED },
{ ERROR_OPERATION_ABORTED, NNG_ECLOSED },
+ { ERROR_SHARING_VIOLATION, NNG_EBUSY },
{ WAIT_TIMEOUT, NNG_ETIMEDOUT },
{ WSAEINTR, NNG_EINTR },
{ WSAEBADF, NNG_ECLOSED },
@@ -143,8 +144,8 @@ static struct {
// Must be Last!!
{ 0, 0 },
- // clang-format on
- };
+ // clang-format on
+};
// This converts a Windows API error (from GetLastError()) to an
// nng standard error code.
diff --git a/src/platform/windows/win_file.c b/src/platform/windows/win_file.c
index 2a9504aa..515647e0 100644
--- a/src/platform/windows/win_file.c
+++ b/src/platform/windows/win_file.c
@@ -342,4 +342,28 @@ nni_plat_file_basename(const char *name)
return (name);
}
+int
+nni_plat_file_lock(const char *path, nni_plat_flock *lk)
+{
+ HANDLE h;
+
+ // On Windows we do not have to explicitly lock the file, the
+ // dwShareMode being set to zeor effectively prevents it.
+ h = CreateFile(path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE) {
+ return (nni_win_error(GetLastError()));
+ }
+ lk->h = h;
+ return (0);
+}
+
+void
+nni_plat_file_unlock(nni_plat_flock *lk)
+{
+ HANDLE h = lk->h;
+ (void) CloseHandle(h);
+ lk->h = INVALID_HANDLE_VALUE;
+}
+
#endif // NNG_PLATFORM_WINDOWS \ No newline at end of file
diff --git a/src/platform/windows/win_impl.h b/src/platform/windows/win_impl.h
index 0c22c240..b3c4738f 100644
--- a/src/platform/windows/win_impl.h
+++ b/src/platform/windows/win_impl.h
@@ -75,6 +75,10 @@ struct nni_win_event {
nni_win_event_ops ops;
};
+struct nni_plat_flock {
+ HANDLE h;
+};
+
extern int nni_win_error(int);
extern int nni_win_event_init(nni_win_event *, nni_win_event_ops *, void *);
diff --git a/src/transport/zerotier/zerotier.c b/src/transport/zerotier/zerotier.c
index e31bf113..8f83881c 100644
--- a/src/transport/zerotier/zerotier.c
+++ b/src/transport/zerotier/zerotier.c
@@ -153,30 +153,31 @@ enum zt_errors {
// them with a reference count, and uniquely identify them using the
// homedir.
struct zt_node {
- char zn_path[NNG_MAXADDRLEN]; // ought to be sufficient
- ZT_Node * zn_znode;
- uint64_t zn_self;
- nni_list_node zn_link;
- int zn_closed;
- nni_plat_udp *zn_udp4;
- nni_plat_udp *zn_udp6;
- nni_list zn_eplist;
- nni_list zn_plist;
- nni_idhash * zn_ports;
- nni_idhash * zn_eps;
- nni_idhash * zn_lpipes;
- nni_idhash * zn_rpipes;
- nni_idhash * zn_peers; // indexed by remote address
- nni_aio * zn_rcv4_aio;
- uint8_t * zn_rcv4_buf;
- nng_sockaddr zn_rcv4_addr;
- nni_aio * zn_rcv6_aio;
- uint8_t * zn_rcv6_buf;
- nng_sockaddr zn_rcv6_addr;
- nni_thr zn_bgthr;
- int64_t zn_bgtime;
- nni_cv zn_bgcv;
- nni_cv zn_snd6_cv;
+ char zn_path[NNG_MAXADDRLEN]; // ought to be sufficient
+ nni_file_lockh *zn_flock;
+ ZT_Node * zn_znode;
+ uint64_t zn_self;
+ nni_list_node zn_link;
+ int zn_closed;
+ nni_plat_udp * zn_udp4;
+ nni_plat_udp * zn_udp6;
+ nni_list zn_eplist;
+ nni_list zn_plist;
+ nni_idhash * zn_ports;
+ nni_idhash * zn_eps;
+ nni_idhash * zn_lpipes;
+ nni_idhash * zn_rpipes;
+ nni_idhash * zn_peers; // indexed by remote address
+ nni_aio * zn_rcv4_aio;
+ uint8_t * zn_rcv4_buf;
+ nng_sockaddr zn_rcv4_addr;
+ nni_aio * zn_rcv6_aio;
+ uint8_t * zn_rcv6_buf;
+ nng_sockaddr zn_rcv6_addr;
+ nni_thr zn_bgthr;
+ int64_t zn_bgtime;
+ nni_cv zn_bgcv;
+ nni_cv zn_snd6_cv;
};
// The fragment list is used to keep track of incoming received
@@ -300,7 +301,7 @@ static void
zt_bgthr(void *arg)
{
zt_node *ztn = arg;
- int64_t now;
+ int64_t now;
nni_mtx_lock(&zt_lk);
for (;;) {
@@ -559,7 +560,7 @@ zt_send(zt_node *ztn, uint64_t nwid, uint8_t op, uint64_t raddr,
{
uint64_t srcmac = zt_node_to_mac(laddr >> 24, nwid);
uint64_t dstmac = zt_node_to_mac(raddr >> 24, nwid);
- int64_t now = zt_now();
+ int64_t now = zt_now();
NNI_ASSERT(len >= zt_size_headers);
data[zt_offset_op] = op;
@@ -1422,6 +1423,9 @@ zt_node_destroy(zt_node *ztn)
if (ztn->zn_rcv6_buf != NULL) {
nni_free(ztn->zn_rcv6_buf, zt_rcv_bufsize);
}
+ if (ztn->zn_flock != NULL) {
+ nni_file_unlock(ztn->zn_flock);
+ }
nni_aio_fini(ztn->zn_rcv4_aio);
nni_aio_fini(ztn->zn_rcv6_aio);
nni_idhash_fini(ztn->zn_eps);
@@ -1480,6 +1484,21 @@ zt_node_create(zt_node **ztnp, const char *path)
return (rv);
}
+ if (strlen(path) > 0) {
+ char *lkfile;
+ if ((lkfile = nni_file_join(path, "lock")) == NULL) {
+ zt_node_destroy(ztn);
+ return (NNG_ENOMEM);
+ }
+
+ if ((rv = nni_file_lock(lkfile, &ztn->zn_flock)) != 0) {
+ zt_node_destroy(ztn);
+ nni_strfree(lkfile);
+ return (rv);
+ }
+ nni_strfree(lkfile);
+ }
+
// Setup for dynamic ephemeral port allocations. We
// set the range to allow for ephemeral ports, but not
// higher than the max port, and starting with an
diff --git a/tools/nngcat/nngcat.c b/tools/nngcat/nngcat.c
index 7459c319..9dfa9561 100644
--- a/tools/nngcat/nngcat.c
+++ b/tools/nngcat/nngcat.c
@@ -31,6 +31,7 @@
#include "supplemental/tls/tls.h"
#include "supplemental/util/options.h"
#include "supplemental/util/platform.h"
+#include "transport/zerotier/zerotier.h"
// Globals. We need this to avoid passing around everything.
int format = 0;
@@ -51,6 +52,7 @@ void * keyfile = NULL;
size_t keylen = 0;
void * certfile = NULL;
size_t certlen = 0;
+const char * zthome = NULL;
// Options, must start at 1 because zero is sentinel.
enum options {
@@ -97,6 +99,7 @@ enum options {
OPT_KEYFILE,
OPT_CERTFILE,
OPT_VERSION,
+ OPT_ZTHOME,
};
static nng_optspec opts[] = {
@@ -180,6 +183,9 @@ static nng_optspec opts[] = {
.o_val = OPT_CERTFILE,
.o_arg = true,
},
+ {
+ .o_name = "zt-home", .o_val = OPT_ZTHOME, .o_arg = true,
+ },
{ .o_name = "version", .o_short = 'V', .o_val = OPT_VERSION },
// Sentinel.
@@ -234,6 +240,7 @@ help(void)
printf(" --verbose (or alias -v)\n");
printf(" --compat\n");
printf(" --async\n");
+ printf(" --zt-home <path>\n");
printf("\n<src> may be one of:\n");
printf(" --file <file> (or alias -F <file>)\n");
printf(" --data <data> (or alias -D <data>)\n");
@@ -783,6 +790,9 @@ main(int ac, const char **av)
}
loadfile(arg, &certfile, &certlen);
break;
+ case OPT_ZTHOME:
+ zthome = arg;
+ break;
case OPT_INSECURE:
insecure = 1;
break;
@@ -1006,6 +1016,14 @@ main(int ac, const char **av)
fatal("Unable to get TLS config: %s",
nng_strerror(rv));
}
+ if (zthome != NULL) {
+ rv = nng_dialer_setopt(d, NNG_OPT_ZT_HOME,
+ zthome, strlen(zthome) + 1);
+ if ((rv != 0) && (rv != NNG_ENOTSUP)) {
+ fatal("Unable to set ZT home: %s",
+ nng_strerror(rv));
+ }
+ }
rv = nng_dialer_start(d, async);
act = "dial";
if ((rv == 0) && (verbose == OPT_VERBOSE)) {
@@ -1034,6 +1052,14 @@ main(int ac, const char **av)
fatal("Unable to get TLS config: %s",
nng_strerror(rv));
}
+ if (zthome != NULL) {
+ rv = nng_listener_setopt(l, NNG_OPT_ZT_HOME,
+ zthome, strlen(zthome) + 1);
+ if ((rv != 0) && (rv != NNG_ENOTSUP)) {
+ fatal("Unable to set ZT home: %s",
+ nng_strerror(rv));
+ }
+ }
rv = nng_listener_start(l, async);
act = "listen";
if ((rv == 0) && (verbose == OPT_VERBOSE)) {