diff options
| author | Garrett D'Amore <garrett@damore.org> | 2018-03-05 17:27:04 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2018-03-05 19:39:15 -0800 |
| commit | c4da7817b4c8dd71b2a07d4d1c46b486ec57eeb4 (patch) | |
| tree | b1166d49e6673fcbad28c0bd65630f5af37a86ab /src | |
| parent | b6298c28473acbed2f1429176c7cae4fb514d98b (diff) | |
| download | nng-c4da7817b4c8dd71b2a07d4d1c46b486ec57eeb4.tar.gz nng-c4da7817b4c8dd71b2a07d4d1c46b486ec57eeb4.tar.bz2 nng-c4da7817b4c8dd71b2a07d4d1c46b486ec57eeb4.zip | |
fixes #265 nngcat should support persistent ZT nodes
fixes #267 zerotier transport should lock ZT_HOME
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file.c | 28 | ||||
| -rw-r--r-- | src/core/file.h | 6 | ||||
| -rw-r--r-- | src/core/platform.h | 12 | ||||
| -rw-r--r-- | src/platform/posix/posix_file.c | 27 | ||||
| -rw-r--r-- | src/platform/posix/posix_impl.h | 4 | ||||
| -rw-r--r-- | src/platform/windows/win_debug.c | 13 | ||||
| -rw-r--r-- | src/platform/windows/win_file.c | 24 | ||||
| -rw-r--r-- | src/platform/windows/win_impl.h | 4 | ||||
| -rw-r--r-- | src/transport/zerotier/zerotier.c | 71 |
9 files changed, 157 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 |
