summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-01-03 23:50:12 -0800
committerGarrett D'Amore <garrett@damore.org>2017-01-03 23:50:12 -0800
commit856c5c8e2aa4e07b2b628dd194a63ae13dae7ae3 (patch)
tree881df2438f89137f014d1706124b58d40115a47d /src
parent7ba8f81d551af515864c2c4ca47edf540a5edd32 (diff)
downloadnng-856c5c8e2aa4e07b2b628dd194a63ae13dae7ae3.tar.gz
nng-856c5c8e2aa4e07b2b628dd194a63ae13dae7ae3.tar.bz2
nng-856c5c8e2aa4e07b2b628dd194a63ae13dae7ae3.zip
Working towards TCP support.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/core/defs.h82
-rw-r--r--src/core/platform.h8
-rw-r--r--src/nng.c19
-rw-r--r--src/nng.h86
-rw-r--r--src/platform/posix/posix_debug.c79
-rw-r--r--src/platform/posix/posix_impl.h29
7 files changed, 240 insertions, 64 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 78070cc1..58564291 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -62,6 +62,7 @@ set (NNG_SOURCES
platform/posix/posix_alloc.c
platform/posix/posix_clock.c
platform/posix/posix_debug.c
+ platform/posix/posix_net.c
platform/posix/posix_thread.c
protocol/pair/pair.c
diff --git a/src/core/defs.h b/src/core/defs.h
index 395335d6..be7f71f7 100644
--- a/src/core/defs.h
+++ b/src/core/defs.h
@@ -22,6 +22,7 @@ typedef struct nng_socket nni_sock;
typedef struct nng_endpoint nni_ep;
typedef struct nng_pipe nni_pipe;
typedef struct nng_msg nni_msg;
+typedef struct nng_sockaddr nni_sockaddr;
// These are our own names.
typedef struct nni_tran nni_tran;
@@ -31,10 +32,17 @@ typedef struct nni_tran_pipe nni_tran_pipe;
typedef struct nni_proto_pipe nni_proto_pipe;
typedef struct nni_proto nni_proto;
+
typedef int nni_signal; // Turnstile/wakeup channel.
typedef uint64_t nni_time; // Absolute time (usec).
typedef int64_t nni_duration; // Relative time (usec).
+// Used by transports for scatter gather I/O.
+typedef struct {
+ void * iov_buf;
+ size_t iov_len;
+} nni_iov;
+
// Some default timing things.
#define NNI_TIME_NEVER ((nni_time) -1)
#define NNI_TIME_ZERO ((nni_time) 0)
@@ -44,41 +52,45 @@ typedef int64_t nni_duration; // Relative time (usec).
#define NNI_ALLOC_STRUCT(s) nni_alloc(sizeof (*s))
#define NNI_FREE_STRUCT(s) nni_free((s), sizeof (*s))
-#define NNI_PUT32(ptr, u) \
- do { \
- ptr[0] = (uint8_t)(((uint32_t)u) >> 24); \
- ptr[1] = (uint8_t)(((uint32_t)u) >> 16); \
- ptr[2] = (uint8_t)(((uint32_t)u) >> 8); \
- ptr[3] = (uint8_t)((uint32_t)u); \
- } while (0)
-
-#define NNI_PUT64(ptr, u) \
- do { \
- ptr[0] = (uint8_t)(((uint64_t)u) >> 56); \
- ptr[1] = (uint8_t)(((uint64_t)u) >> 48); \
- ptr[2] = (uint8_t)(((uint64_t)u) >> 40); \
- ptr[3] = (uint8_t)(((uint64_t)u) >> 32); \
- ptr[4] = (uint8_t)(((uint64_t)u) >> 24); \
- ptr[5] = (uint8_t)(((uint64_t)u) >> 16); \
- ptr[6] = (uint8_t)(((uint64_t)u) >> 8); \
- ptr[7] = (uint8_t)((uint64_t)u); \
- } while (0)
-
-#define NNI_GET32(ptr, v) \
- v = (((uint32_t)((uint8_t)ptr[0])) << 24) + \
- (((uint32_t)((uint8_t)ptr[1])) << 16) + \
- (((uint32_t)((uint8_t)ptr[2])) << 8) + \
- (((uint32_t)(uint8_t)ptr[3]))
-
-#define NNI_GET64(ptr, v) \
- v = (((uint64_t)((uint8_t)ptr[0])) << 56) + \
- (((uint64_t)((uint8_t)ptr[1])) << 48) + \
- (((uint64_t)((uint8_t)ptr[2])) << 40) + \
- (((uint64_t)((uint8_t)ptr[3])) << 32) + \
- (((uint64_t)((uint8_t)ptr[4])) << 24) + \
- (((uint64_t)((uint8_t)ptr[5])) << 16) + \
- (((uint64_t)((uint8_t)ptr[6])) << 8) + \
- (((uint64_t)(uint8_t)ptr[7]))
+#define NNI_PUT32(ptr, u) \
+ do { \
+ ptr[0] = (uint8_t) (((uint32_t) u) >> 24); \
+ ptr[1] = (uint8_t) (((uint32_t) u) >> 16); \
+ ptr[2] = (uint8_t) (((uint32_t) u) >> 8); \
+ ptr[3] = (uint8_t) ((uint32_t) u); \
+ } \
+ while (0)
+
+#define NNI_PUT64(ptr, u) \
+ do { \
+ ptr[0] = (uint8_t) (((uint64_t) u) >> 56); \
+ ptr[1] = (uint8_t) (((uint64_t) u) >> 48); \
+ ptr[2] = (uint8_t) (((uint64_t) u) >> 40); \
+ ptr[3] = (uint8_t) (((uint64_t) u) >> 32); \
+ ptr[4] = (uint8_t) (((uint64_t) u) >> 24); \
+ ptr[5] = (uint8_t) (((uint64_t) u) >> 16); \
+ ptr[6] = (uint8_t) (((uint64_t) u) >> 8); \
+ ptr[7] = (uint8_t) ((uint64_t) u); \
+ } \
+ while (0)
+
+#define NNI_GET32(ptr, v) \
+ v = (((uint32_t) ((uint8_t) ptr[0])) << 24) + \
+ (((uint32_t) ((uint8_t) ptr[1])) << 16) + \
+ (((uint32_t) ((uint8_t) ptr[2])) << 8) + \
+ (((uint32_t) (uint8_t) ptr[3]))
+
+#define NNI_GET64(ptr, v) \
+ v = (((uint64_t) ((uint8_t) ptr[0])) << 56) + \
+ (((uint64_t) ((uint8_t) ptr[1])) << 48) + \
+ (((uint64_t) ((uint8_t) ptr[2])) << 40) + \
+ (((uint64_t) ((uint8_t) ptr[3])) << 32) + \
+ (((uint64_t) ((uint8_t) ptr[4])) << 24) + \
+ (((uint64_t) ((uint8_t) ptr[5])) << 16) + \
+ (((uint64_t) ((uint8_t) ptr[6])) << 8) + \
+ (((uint64_t) (uint8_t) ptr[7]))
+// A few assorted other items.
+#define NNI_FLAG_IPV4ONLY 1
#endif // CORE_DEFS_H
diff --git a/src/core/platform.h b/src/core/platform.h
index 15ef6843..2134ed97 100644
--- a/src/core/platform.h
+++ b/src/core/platform.h
@@ -158,6 +158,14 @@ extern void nni_plat_fini(void);
// or under a lock protection.)
extern uint32_t nni_plat_nextid(void);
+// nni_plat_strerror allows the platform to use additional error messages
+// for additional error codes. The err code passed in should be the
+// equivalent of errno or GetLastError, without the NNG_ESYSERR component.
+// The platform should make sure that the returned value will be valid
+// after the call returns. (If necessary, thread-local storage can be
+// used.)
+extern const char *nni_plat_strerror(int);
+
// Actual platforms we support. This is included up front so that we can
// get the specific types that are supplied by the platform.
#if defined(PLATFORM_POSIX)
diff --git a/src/nng.c b/src/nng.c
index 79069723..b0f39222 100644
--- a/src/nng.c
+++ b/src/nng.c
@@ -180,9 +180,24 @@ nng_strerror(int num)
case NNG_ENOENT:
return ("Entry not found");
- default:
- return ("Unknown error");
+ case NNG_EPROTO:
+ return ("Protocol error");
+
+ case NNG_EUNREACHABLE:
+ return ("Destination unreachable");
+
+ case NNG_EADDRINVAL:
+ return ("Address invalid");
+
+ case NNG_EPERM:
+ return ("Permission denied");
}
+
+ if (num & NNG_ESYSERR) {
+ return (nni_plat_strerror(num & ~NNG_ESYSERR));
+ }
+
+ return ("Unknown error");
}
diff --git a/src/nng.h b/src/nng.h
index edb2c66a..61894ce8 100644
--- a/src/nng.h
+++ b/src/nng.h
@@ -355,23 +355,85 @@ NNG_DECL int nng_device(nng_socket *, nng_socket *);
// Error codes. These may happen to align to errnos used on your platform,
// but do not count on this.
-#define NNG_EINTR (-1)
-#define NNG_ENOMEM (-2)
-#define NNG_EINVAL (-3)
-#define NNG_EBUSY (-4)
-#define NNG_ETIMEDOUT (-5)
-#define NNG_ECONNREFUSED (-6)
-#define NNG_ECLOSED (-7)
-#define NNG_EAGAIN (-8)
-#define NNG_ENOTSUP (-9)
-#define NNG_EADDRINUSE (-10)
-#define NNG_ESTATE (-11)
-#define NNG_ENOENT (-12)
+#define NNG_EINTR (1)
+#define NNG_ENOMEM (2)
+#define NNG_EINVAL (3)
+#define NNG_EBUSY (4)
+#define NNG_ETIMEDOUT (5)
+#define NNG_ECONNREFUSED (6)
+#define NNG_ECLOSED (7)
+#define NNG_EAGAIN (8)
+#define NNG_ENOTSUP (9)
+#define NNG_EADDRINUSE (10)
+#define NNG_ESTATE (11)
+#define NNG_ENOENT (12)
+#define NNG_EPROTO (13)
+#define NNG_EUNREACHABLE (14)
+#define NNG_EADDRINVAL (15)
+#define NNG_EPERM (16)
+
+// NNG_SYSERR is a special code, which allows us to wrap errors from the
+// underlyuing operating system. We generally prefer to map errors to one
+// of the above, but if we cannot, then we just encode an error this way.
+// The bit is large enough to accommodate all known UNIX and Win32 error
+// codes. We try hard to match things semantically to one of our standard
+// errors. For example, a connection reset or aborted we treat as a
+// closed connection, because that's basically what it means. (The remote
+// peer closed the connection.) For certain kinds of resource exhaustion
+// we treat it the same as memory. But for files, etc. that's OS-specific,
+// and we use the generic below. Some of the above error codes we use
+// internally, and the application should never see (e.g. NNG_EINTR).
+#define NNG_ESYSERR (0x10000000)
// Maximum length of a socket address. This includes the terminating NUL.
// This limit is built into other implementations, so do not change it.
#define NNG_MAXADDRLEN (128)
+// Some address details. This is in some ways like a traditional sockets
+// sockaddr, but we have our own to cope with our unique families, etc.
+// The details of this structure are directly exposed to applications.
+// These structures can be obtained via property lookups, etc.
+struct nng_sockaddr_path {
+ uint16_t sa_family;
+ uint8_t sa_path[NNG_MAXADDRLEN];
+};
+typedef struct nng_sockaddr_path nng_sockaddr_path;
+typedef struct nng_sockaddr_path nng_sockaddr_ipc;
+typedef struct nng_sockaddr_path nng_sockaddr_inproc;
+
+struct nng_sockaddr_in6 {
+ uint16_t sa_family;
+ uint16_t sa_port;
+ uint8_t sa_addr[16];
+};
+typedef struct nng_sockaddr_in6 nng_sockaddr_in6;
+typedef struct nng_sockaddr_in6 nng_sockaddr_udp6;
+typedef struct nng_sockaddr_in6 nng_sockaddr_tcp6;
+
+struct nng_sockaddr_in {
+ uint16_t sa_family;
+ uint16_t sa_port;
+ uint32_t sa_addr;
+};
+typedef struct nng_sockaddr_in nng_sockaddr_in;
+typedef struct nng_sockaddr_in nng_sockaddr_udp;
+typedef struct nng_sockaddr_in nng_sockaddr_tcp;
+
+typedef struct nng_sockaddr {
+ union {
+ uint16_t s_family;
+ nng_sockaddr_path s_path;
+ nng_sockaddr_in6 s_in6;
+ nng_sockaddr_in s_in;
+ } s_un;
+} nng_sockaddr;
+
+#define NNG_AF_UNSPEC 0
+#define NNG_AF_INPROC 1
+#define NNG_AF_IPC 2
+#define NNG_AF_INET 3
+#define NNG_AF_INET6 4
+
#ifdef __cplusplus
}
#endif
diff --git a/src/platform/posix/posix_debug.c b/src/platform/posix/posix_debug.c
index 56b443e9..f1c6f9e7 100644
--- a/src/platform/posix/posix_debug.c
+++ b/src/platform/posix/posix_debug.c
@@ -11,8 +11,10 @@
#ifdef PLATFORM_POSIX_DEBUG
+#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
void
nni_plat_abort(void)
@@ -28,4 +30,81 @@ nni_plat_println(const char *message)
}
+const char *
+nni_plat_strerror(int errnum)
+{
+ if (errnum > NNG_ESYSERR) {
+ errnum -= NNG_ESYSERR;
+ }
+ return (strerror(errnum));
+}
+
+
+#define NNI_ERR(x, y) { x, y },
+
+// There are of course other errors than these, but these are the ones
+// that we might reasonably expect and want to handle "cleanly". Most of
+// the others should be handled by the system error code. Note that EFAULT
+// is very special, because if the error code is *that*, then we should panic
+// because an invalid system call has been made. (That would be a sign
+// of a serious software bug, in other words.) POSIX says that all these
+// error codes should exist, and be distinct positive numbers. (EWOULDBLOCK
+// and EAGAIN are permitted to have the same value.)
+static struct {
+ int posix_err;
+ int nng_err;
+}
+nni_plat_errnos[] = {
+ NNI_ERR(EINTR, NNG_EINTR)
+ NNI_ERR(EINVAL, NNG_EINVAL)
+ NNI_ERR(ENOMEM, NNG_ENOMEM)
+ NNI_ERR(EACCES, NNG_EPERM)
+ NNI_ERR(EADDRINUSE, NNG_EADDRINUSE)
+ NNI_ERR(EADDRNOTAVAIL, NNG_EADDRINVAL)
+ NNI_ERR(EAFNOSUPPORT, NNG_ENOTSUP)
+ NNI_ERR(EAGAIN, NNG_EAGAIN)
+ NNI_ERR(EBADF, NNG_ECLOSED)
+ NNI_ERR(EBUSY, NNG_EBUSY)
+ NNI_ERR(ECONNABORTED, NNG_ECLOSED)
+ NNI_ERR(ECONNREFUSED, NNG_ECONNREFUSED)
+ NNI_ERR(ECONNRESET, NNG_ECLOSED)
+ NNI_ERR(EHOSTUNREACH, NNG_EUNREACHABLE)
+ NNI_ERR(ENETUNREACH, NNG_EUNREACHABLE)
+ NNI_ERR(ENAMETOOLONG, NNG_EINVAL)
+ NNI_ERR(ENOENT, NNG_ENOENT)
+ NNI_ERR(ENOBUFS, NNG_ENOMEM)
+ NNI_ERR(ENOPROTOOPT, NNG_ENOTSUP)
+ NNI_ERR(ENOSYS, NNG_ENOTSUP)
+ NNI_ERR(ENOTSUP, NNG_ENOTSUP)
+ NNI_ERR(EPERM, NNG_EPERM)
+ NNI_ERR(EPIPE, NNG_ECLOSED)
+ NNI_ERR(EPROTO, NNG_EPROTO)
+ NNI_ERR(EPROTONOSUPPORT, NNG_ENOTSUP)
+ NNI_ERR(ETIME, NNG_ETIMEDOUT)
+ NNI_ERR(ETIMEDOUT, NNG_ETIMEDOUT)
+ NNI_ERR(EWOULDBLOCK, NNG_EAGAIN)
+ NNI_ERR(0, 0) // must be last
+};
+
+int
+nni_plat_errno(int errnum)
+{
+ int i;
+
+ if (errnum == 0) {
+ return (0);
+ }
+ if (errnum == EFAULT) {
+ nni_panic("System EFAULT encountered!");
+ }
+ for (i = 0; nni_plat_errnos[i].nng_err != 0; i++) {
+ if (errnum == nni_plat_errnos[i].posix_err) {
+ return (nni_plat_errnos[i].nng_err);
+ }
+ }
+ // Other system errno.
+ return (NNG_ESYSERR + errnum);
+}
+
+
#endif // PLATFORM_POSIX_DEBUG
diff --git a/src/platform/posix/posix_impl.h b/src/platform/posix/posix_impl.h
index 5c5c3798..38fe27c9 100644
--- a/src/platform/posix/posix_impl.h
+++ b/src/platform/posix/posix_impl.h
@@ -12,35 +12,34 @@
// Some dependency notes:
//
-// PLATFORM_POSIX_THREAD and PLATFORM_POSIX_SYNCH depend on each other,
-// and they both depend on PLATFORM_POSIX_CLOCK. Furthermore, note that
+// PLATFORM_POSIX_THREAD depends on PLATFORM_POSIX_CLOCK. Furthermore,
// when using PLATFORM_POSIX_CLOCK, your condition variable timeouts need
-// to use the same base clock values. Normally all three should be used
-// together.
+// to use the same base clock values. Normally these should be used
+// together. Almost everything depends on PLATFORM_POSIX_DEBUG.
#ifdef PLATFORM_POSIX
#define PLATFORM_POSIX_ALLOC
#define PLATFORM_POSIX_DEBUG
#define PLATFORM_POSIX_CLOCK
+#define PLATFORM_POSIX_NET
#define PLATFORM_POSIX_RANDOM
-#define PLATFORM_POSIX_SYNCH
#define PLATFORM_POSIX_THREAD
#include "platform/posix/posix_config.h"
#endif
-// Define types that this platform uses.
-#ifdef PLATFORM_POSIX_SYNCH
+#ifdef PLATFORM_POSIX_DEBUG
+extern int nni_plat_errno(int);
-#include <pthread.h>
+#endif
-struct nni_mutex {
- pthread_mutex_t mx;
-};
+#ifdef PLATFORM_POSIX_NET
+typedef int nni_plat_tcpsock;
+#endif
-struct nni_cond {
- pthread_cond_t cv;
- pthread_mutex_t * mx;
-};
+// Define types that this platform uses.
+#ifdef PLATFORM_POSIX_THREAD
+
+#include <pthread.h>
// These types are provided for here, to permit them to be directly inlined
// elsewhere.