aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2016-12-12 03:42:26 -0800
committerGarrett D'Amore <garrett@damore.org>2016-12-12 03:42:26 -0800
commit1adefe3879b211a47a784f477d56a9416ae72254 (patch)
treecf017599969fb109d62981cbef56eeeef4d2b108 /src/core
parent091043a0df9568b18e9bb49b07762b95e3508108 (diff)
downloadnng-1adefe3879b211a47a784f477d56a9416ae72254.tar.gz
nng-1adefe3879b211a47a784f477d56a9416ae72254.tar.bz2
nng-1adefe3879b211a47a784f477d56a9416ae72254.zip
New inproc transport.
Lots of supporting changes.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/defs.h33
-rw-r--r--src/core/list.c36
-rw-r--r--src/core/list.h28
-rw-r--r--src/core/message.c4
-rw-r--r--src/core/msgqueue.c (renamed from src/core/msqueue.c)2
-rw-r--r--src/core/msgqueue.h73
-rw-r--r--src/core/nng_impl.h88
-rw-r--r--src/core/panic.c2
-rw-r--r--src/core/panic.h37
-rw-r--r--src/core/platform.h142
-rw-r--r--src/core/snprintf.c2
-rw-r--r--src/core/snprintf.h35
-rw-r--r--src/core/socket.c4
-rw-r--r--src/core/transport.h117
14 files changed, 488 insertions, 115 deletions
diff --git a/src/core/defs.h b/src/core/defs.h
new file mode 100644
index 00000000..f747f901
--- /dev/null
+++ b/src/core/defs.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Garrett D'Amore <garrett@damore.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef CORE_DEFS_H
+#define CORE_DEFS_H
+
+/*
+ * C compilers may get unhappy when named arguments are not used. While
+ * there are things like __attribute__((unused)) which are arguably
+ * superior, support for such are not universal.
+ */
+#define NNI_ARG_UNUSED(x) ((void)x);
+
+#endif /* NNG_IMPL_H */
diff --git a/src/core/list.c b/src/core/list.c
index f59c75e0..d81c6379 100644
--- a/src/core/list.c
+++ b/src/core/list.c
@@ -31,12 +31,12 @@
*/
#define NODE(list, item) \
- (nni_list_node_t)(void *)(((char *)item) + list->ll_offset)
+ (nni_list_node_t *)(void *)(((char *)item) + list->ll_offset)
#define ITEM(list, node) \
(void *)(((char *)node) - list->ll_offset)
void
-nni_list_init_offset(nni_list_t list, size_t offset)
+nni_list_init_offset(nni_list_t *list, size_t offset)
{
list->ll_offset = offset;
list->ll_head.ln_next = &list->ll_head;
@@ -44,9 +44,9 @@ nni_list_init_offset(nni_list_t list, size_t offset)
}
void *
-nni_list_first(nni_list_t list)
+nni_list_first(nni_list_t *list)
{
- nni_list_node_t node = list->ll_head.ln_next;
+ nni_list_node_t *node = list->ll_head.ln_next;
if (node == &list->ll_head) {
return (NULL);
}
@@ -54,9 +54,9 @@ nni_list_first(nni_list_t list)
}
void *
-nni_list_last(nni_list_t list)
+nni_list_last(nni_list_t *list)
{
- nni_list_node_t node = list->ll_head.ln_prev;
+ nni_list_node_t *node = list->ll_head.ln_prev;
if (node == &list->ll_head) {
return (NULL);
}
@@ -64,9 +64,9 @@ nni_list_last(nni_list_t list)
}
void
-nni_list_append(nni_list_t list, void *item)
+nni_list_append(nni_list_t *list, void *item)
{
- nni_list_node_t node = NODE(list, item);
+ nni_list_node_t *node = NODE(list, item);
node->ln_prev = list->ll_head.ln_prev;
node->ln_next = &list->ll_head;
@@ -74,9 +74,9 @@ nni_list_append(nni_list_t list, void *item)
node->ln_prev->ln_next = node;
}
void
-nni_list_prepend(nni_list_t list, void *item)
+nni_list_prepend(nni_list_t *list, void *item)
{
- nni_list_node_t node = NODE(list, item);
+ nni_list_node_t *node = NODE(list, item);
node->ln_next = list->ll_head.ln_next;
node->ln_prev = &list->ll_head;
@@ -85,9 +85,9 @@ nni_list_prepend(nni_list_t list, void *item)
}
void *
-nni_list_next(nni_list_t list, void *item)
+nni_list_next(nni_list_t *list, void *item)
{
- nni_list_node_t node = NODE(list, item);
+ nni_list_node_t *node = NODE(list, item);
if ((node = node->ln_next) == &list->ll_head) {
return (NULL);
@@ -96,9 +96,9 @@ nni_list_next(nni_list_t list, void *item)
}
void *
-nni_list_prev(nni_list_t list, void *item)
+nni_list_prev(nni_list_t *list, void *item)
{
- nni_list_node_t node = NODE(list, item);
+ nni_list_node_t *node = NODE(list, item);
if ((node = node->ln_prev) == &list->ll_head) {
return (NULL);
@@ -107,16 +107,16 @@ nni_list_prev(nni_list_t list, void *item)
}
void
-nni_list_remove(nni_list_t list, void *item)
+nni_list_remove(nni_list_t *list, void *item)
{
- nni_list_node_t node = NODE(list, item);
+ nni_list_node_t *node = NODE(list, item);
node->ln_prev->ln_next = node->ln_next;
node->ln_next->ln_prev = node->ln_prev;
}
void
-nni_list_node_init(nni_list_t list, void *item)
+nni_list_node_init(nni_list_t *list, void *item)
{
- nni_list_node_t node = NODE(list, item);
+ nni_list_node_t *node = NODE(list, item);
node->ln_prev = node->ln_next = NULL;
}
diff --git a/src/core/list.h b/src/core/list.h
index c55870cb..f12087a2 100644
--- a/src/core/list.h
+++ b/src/core/list.h
@@ -32,23 +32,25 @@
typedef struct nni_list_node {
struct nni_list_node *ln_next;
struct nni_list_node *ln_prev;
-} *nni_list_node_t;
+} nni_list_node_t;
typedef struct nni_list {
struct nni_list_node ll_head;
size_t ll_offset;
-} *nni_list_t;
+} nni_list_t;
-extern void nni_list_init_offset(nni_list_t list, size_t offset);
+extern void nni_list_init_offset(nni_list_t *list, size_t offset);
#define NNI_LIST_INIT(list, type, field) \
- nni_list_init_offset(list, type, (size_t)&((type *)0)->field)
-extern void *nni_list_first(nni_list_t list);
-extern void *nni_list_last(nni_list_t list);
-extern void nni_list_append(nni_list_t list, void *item);
-extern void nni_list_prepend(nni_list_t list, void *item);
-extern void *nni_list_next(nni_list_t list, void *item);
-extern void *nni_list_prev(nni_list_t list, void *item);
-extern void nni_list_remove(nni_list_t list, void *item);
-extern void nni_list_node_init(nni_list_t, void *);
+ nni_list_init_offset(list, offsetof (type, field))
+extern void *nni_list_first(nni_list_t *);
+extern void *nni_list_last(nni_list_t *);
+extern void nni_list_append(nni_list_t *, void *);
+extern void nni_list_prepend(nni_list_t *, void *);
+extern void *nni_list_next(nni_list_t *, void *);
+extern void *nni_list_prev(nni_list_t *, void *);
+extern void nni_list_remove(nni_list_t *, void *);
+extern void nni_list_node_init(nni_list_t *, void *);
+#define NNI_LIST_FOREACH(l, it) \
+ for (it = nni_list_first(l); it != NULL; it = nni_list_next(l, it))
-#endif /* CORE_MSQUEUE_H */
+#endif /* CORE_LIST_H */
diff --git a/src/core/message.c b/src/core/message.c
index 82f58dc5..581f7683 100644
--- a/src/core/message.c
+++ b/src/core/message.c
@@ -23,9 +23,7 @@
#include <stdlib.h>
#include <string.h>
-#include "../nng.h"
-
-#include "nng_impl.h"
+#include "core/nng_impl.h"
/*
* Message API.
diff --git a/src/core/msqueue.c b/src/core/msgqueue.c
index 7becabfb..9f168878 100644
--- a/src/core/msqueue.c
+++ b/src/core/msgqueue.c
@@ -20,8 +20,6 @@
* IN THE SOFTWARE.
*/
-#include "../nng.h"
-
#include "nng_impl.h"
/*
diff --git a/src/core/msgqueue.h b/src/core/msgqueue.h
new file mode 100644
index 00000000..9d856edd
--- /dev/null
+++ b/src/core/msgqueue.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 Garrett D'Amore <garrett@damore.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef CORE_MSGQUEUE_H
+#define CORE_MSGQUEUE_H
+
+#include "nng.h"
+
+/*
+ * Message queues. Message queues work in some ways like Go channels;
+ * they are a thread-safe way to pass messages between subsystems.
+ */
+typedef struct nni_msgqueue *nni_msgqueue_t;
+
+/*
+ * nni_msgqueue_create creates a message queue with the given capacity,
+ * which must be a positive number. It returns NNG_EINVAL if the capacity
+ * is invalid, or NNG_ENOMEM if resources cannot be allocated.
+ */
+extern int nni_msgqueue_create(nni_msgqueue_t *, int);
+
+/*
+ * nni_msgqueue_destroy destroys a message queue. It will also free any
+ * messages that may be in the queue.
+ */
+extern void nni_msgqueue_destroy(nni_msgqueue_t);
+
+/*
+ * nni_msgqueue_put attempts to put a message to the queue. It will wait
+ * for the timeout (us), if the value is positive. If the value is negative
+ * then it will wait forever. If the value is zero, it will just check, and
+ * return immediately whether a message can be put or not. Valid returns are
+ * NNG_ECLOSED if the queue is closed or NNG_ETIMEDOUT if the message cannot
+ * be placed after a time, or NNG_EAGAIN if the operation cannot succeed
+ * immediately and a zero timeout is specified. Note that timeout granularity
+ * may be limited -- for example Windows systems have a millisecond resolution
+ * timeout capability.
+ */
+extern int nni_msgqueue_put(nni_msgqueue_t, nng_msg_t, int);
+
+/*
+ * nni_msgqueue_get gets the message from the queue, using a timeout just
+ * like nni_msgqueue_put.
+ */
+extern int nni_msgqueue_get(nni_msgqueue_t, nng_msg_t *, int);
+
+/*
+ * nni_msgqueue_close closes the queue. After this all operates on the
+ * message queue will return NNG_ECLOSED. Messages inside the queue
+ * are freed. Unlike closing a go channel, this operation is idempotent.
+ */
+extern void nni_msgqueue_close(nni_msgqueue_t);
+
+#endif /* CORE_MSQUEUE_H */
diff --git a/src/core/nng_impl.h b/src/core/nng_impl.h
index 683e0df1..d728c652 100644
--- a/src/core/nng_impl.h
+++ b/src/core/nng_impl.h
@@ -20,90 +20,30 @@
* IN THE SOFTWARE.
*/
-#ifndef NNG_IMPL_H
-#define NNG_IMPL_H
+#ifndef CORE_NNG_IMPL_H
+#define CORE_NNG_IMPL_H
#include "nng.h"
-#include "platform/platform.h"
/*
* Internal implementation things for NNG, common definitions, etc.
+ * All internal modules wind up including this file to avoid having
+ * to figure out which header(s) to include.
*
* Hopefully it should be clear by the name that this file and its contents
* are *NOT* for use outside of this library.
*
* Symbols that are private to the library begin with the nni_ prefix, whereas
- * those starting with nng_ are intended for external consumption.
+ * those starting with nng_ are intended for external consumption. The latter
+ * symbols should be found in the toplevel nng.h header.
*/
-/*
- * C compilers may get unhappy when named arguments are not used. While
- * there are things like __attribute__((unused)) which are arguably
- * superior, support for such are not universal.
- */
-#define NNI_ARG_UNUSED(x) ((void)x);
-
-/*
- * We have our own snprintf, because some platforms lack this, while
- * others need special handling. Ours just calls the vsnprintf version
- * from the platform.
- */
-extern void nni_snprintf(char *, size_t, const char *, ...);
-
-/*
- * nni_panic is used to terminate the process with prejudice, and
- * should only be called in the face of a critical programming error,
- * or other situation where it would be unsafe to attempt to continue.
- * As this crashes the program, it should never be used when factors outside
- * the program can cause it, such as receiving protocol errors, or running
- * out of memory. Its better in those cases to return an error to the
- * program and let the caller handle the error situation.
- */
-extern void nni_panic(const char *, ...);
-
-/*
- * Message queues. Message queues work in some ways like Go channels;
- * they are a thread-safe way to pass messages between subsystems.
- */
-typedef struct nni_msgqueue *nni_msgqueue_t;
-
-/*
- * nni_msgqueue_create creates a message queue with the given capacity,
- * which must be a positive number. It returns NNG_EINVAL if the capacity
- * is invalid, or NNG_ENOMEM if resources cannot be allocated.
- */
-extern int nni_msgqueue_create(nni_msgqueue_t *, int);
-
-/*
- * nni_msgqueue_destroy destroys a message queue. It will also free any
- * messages that may be in the queue.
- */
-extern void nni_msgqueue_destroy(nni_msgqueue_t);
-
-/*
- * nni_msgqueue_put attempts to put a message to the queue. It will wait
- * for the timeout (us), if the value is positive. If the value is negative
- * then it will wait forever. If the value is zero, it will just check, and
- * return immediately whether a message can be put or not. Valid returns are
- * NNG_ECLOSED if the queue is closed or NNG_ETIMEDOUT if the message cannot
- * be placed after a time, or NNG_EAGAIN if the operation cannot succeed
- * immediately and a zero timeout is specified. Note that timeout granularity
- * may be limited -- for example Windows systems have a millisecond resolution
- * timeout capability.
- */
-extern int nni_msgqueue_put(nni_msgqueue_t, nng_msg_t, int);
-
-/*
- * nni_msgqueue_get gets the message from the queue, using a timeout just
- * like nni_msgqueue_put.
- */
-extern int nni_msgqueue_get(nni_msgqueue_t, nng_msg_t *, int);
-
-/*
- * nni_msgqueue_close closes the queue. After this all operates on the
- * message queue will return NNG_ECLOSED. Messages inside the queue
- * are freed. Unlike closing a go channel, this operation is idempotent.
- */
-extern void nni_msgqueue_close(nni_msgqueue_t);
+#include "core/defs.h"
+#include "core/list.h"
+#include "core/msgqueue.h"
+#include "core/panic.h"
+#include "core/snprintf.h"
+#include "core/platform.h"
+#include "core/transport.h"
-#endif /* NNG_IMPL_H */
+#endif /* CORE_NNG_IMPL_H */
diff --git a/src/core/panic.c b/src/core/panic.c
index 60c790ac..52dcb8c8 100644
--- a/src/core/panic.c
+++ b/src/core/panic.c
@@ -28,7 +28,7 @@
#include <execinfo.h>
#endif
-#include "nng_impl.h"
+#include "core/nng_impl.h"
/*
* Panic handling.
diff --git a/src/core/panic.h b/src/core/panic.h
new file mode 100644
index 00000000..6deef964
--- /dev/null
+++ b/src/core/panic.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Garrett D'Amore <garrett@damore.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef CORE_PANIC_H
+#define CORE_PANIC_H
+
+/*
+ * nni_panic is used to terminate the process with prejudice, and
+ * should only be called in the face of a critical programming error,
+ * or other situation where it would be unsafe to attempt to continue.
+ * As this crashes the program, it should never be used when factors outside
+ * the program can cause it, such as receiving protocol errors, or running
+ * out of memory. Its better in those cases to return an error to the
+ * program and let the caller handle the error situation.
+ */
+extern void nni_panic(const char *, ...);
+
+#endif /* CORE_PANIC_H */
diff --git a/src/core/platform.h b/src/core/platform.h
new file mode 100644
index 00000000..ea8f1378
--- /dev/null
+++ b/src/core/platform.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2016 Garrett D'Amore <garrett@damore.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef CORE_PLATFORM_H
+#define CORE_PLATFORM_H
+
+/*
+ * We require some standard C header files. The only one of these that might
+ * be problematic is <stdint.h>, which is required for C99. Older versions
+ * of the Windows compilers might not have this. However, latest versions of
+ * MS Studio have a functional <stdint.h>. If this impacts you, just upgrade
+ * your tool chain.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * These are the APIs that a platform must implement to support nng.
+ */
+
+/*
+ * nni_abort crashes the system; it should do whatever is appropriate
+ * for abnormal programs on the platform, such as calling abort().
+ */
+void nni_abort(void);
+
+/*
+ * nni_vnsprintf is exactly like its POSIX counterpart.
+ * Some platforms (Windows!) need a special version of this.
+ */
+void nni_vsnprintf(char *, size_t, const char *, va_list);
+
+/*
+ * nni_debug_output is used to emit debug messages. Typically this is used
+ * during core debugging, or to emit panic messages. Message content will
+ * not contain newlines, but the output will add them.
+ */
+void nni_debug_out(const char *);
+
+/*
+ * nni_set_debug_output is used to redirect debug output; for example an
+ * application could replace the default output routine with one that sends
+ * it's output to syslog. If NULL is specified, then a default handler
+ * used instead. The handler should add any newlines to the output as
+ * required. The default handler writes to standard error.
+ */
+void nni_set_debug_out(void (*)(const char *));
+
+/*
+ * nni_alloc allocates memory. In most cases this can just be malloc().
+ * However, you may provide a different allocator, for example it is
+ * possible to use a slab allocator or somesuch. It is permissible for this
+ * to return NULL if memory cannot be allocated.
+ */
+void *nni_alloc(size_t);
+
+/*
+ * nni_free frees memory allocated with nni_alloc. It takes a size because
+ * some allocators do not track size, or can operate more efficiently if
+ * the size is provided with the free call. Examples of this are slab
+ * allocators like this found in Solaris/illumos (see libumem or kmem).
+ * This routine does nothing if supplied with a NULL pointer and zero size.
+ * Most implementations can just call free() here.
+ */
+void nni_free(void *, size_t);
+
+typedef struct nni_mutex *nni_mutex_t;
+typedef struct nni_cond *nni_cond_t;
+
+/*
+ * Mutex handling.
+ */
+int nni_mutex_create(nni_mutex_t *);
+void nni_mutex_destroy(nni_mutex_t);
+void nni_mutex_enter(nni_mutex_t);
+void nni_mutex_exit(nni_mutex_t);
+int nni_mutex_tryenter(nni_mutex_t);
+int nni_cond_create(nni_cond_t *, nni_mutex_t);
+void nni_cond_destroy(nni_cond_t);
+
+/*
+ * nni_cond_broadcast wakes all waiters on the condition. This should be
+ * called with the lock held.
+ */
+void nni_cond_broadcast(nni_cond_t);
+
+/*
+ * nni_cond_signal wakes a signal waiter.
+ */
+void nni_cond_signal(nni_cond_t);
+
+/*
+ * nni_condwait waits for a wake up on the condition variable. The
+ * associated lock is atomically released and reacquired upon wake up.
+ * Callers can be spuriously woken. The associated lock must be held.
+ */
+void nni_cond_wait(nni_cond_t);
+
+/*
+ * nni_cond_timedwait waits for a wakeup on the condition variable, just
+ * as with nni_condwait, but it will also wake after the given number of
+ * microseconds has passed. (This is a relative timed wait.) Early
+ * wakeups are permitted, and the caller must take care to double check any
+ * conditions. The return value is 0 on success, or an error code, which
+ * can be NNG_ETIMEDOUT. Note that it is permissible to wait for longer
+ * than the timeout based on the resolution of your system clock.
+ */
+int nni_cond_timedwait(nni_cond_t, uint64_t);
+
+/*
+ * nn_clock returns a number of microseconds since some arbitrary time
+ * in the past. The values returned by nni_clock may be used with
+ * nni_cond_timedwait.
+ */
+uint64_t nni_clock(void);
+
+/*
+ * nni_usleep sleeps for the specified number of microseconds (at least).
+ */
+void nni_usleep(uint64_t);
+
+#endif /* CORE_PLATFORM_H */
diff --git a/src/core/snprintf.c b/src/core/snprintf.c
index 3ca73e00..574d537a 100644
--- a/src/core/snprintf.c
+++ b/src/core/snprintf.c
@@ -24,7 +24,7 @@
#include <stdint.h>
#include <stdlib.h>
-#include "nng_impl.h"
+#include "core/nng_impl.h"
void
nni_snprintf(char *dst, size_t sz, const char *fmt, ...)
diff --git a/src/core/snprintf.h b/src/core/snprintf.h
new file mode 100644
index 00000000..b98b6ee7
--- /dev/null
+++ b/src/core/snprintf.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 Garrett D'Amore <garrett@damore.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef CORE_SNPRINTF_H
+#define CORE_SNPRINTF_H
+
+#include <stddef.h>
+
+/*
+ * We have our own snprintf, because some platforms lack this, while
+ * others need special handling. Ours just calls the vsnprintf version
+ * from the platform.
+ */
+extern void nni_snprintf(char *, size_t, const char *, ...);
+
+#endif /* CORE_SNPRINTF_H */
diff --git a/src/core/socket.c b/src/core/socket.c
index e9963b74..6bb1d5d5 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -20,9 +20,7 @@
* IN THE SOFTWARE.
*/
-#include "../nng.h"
-
-#include "nng_impl.h"
+#include "core/nng_impl.h"
/*
* Socket implementation.
diff --git a/src/core/transport.h b/src/core/transport.h
new file mode 100644
index 00000000..567cc0c5
--- /dev/null
+++ b/src/core/transport.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2016 Garrett D'Amore <garrett@damore.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef CORE_TRANSPORT_H
+#define CORE_TRANSPORT_H
+
+/*
+ * Transport implementation details. Transports must implement the
+ * interfaces in this file.
+ */
+
+struct nni_transport_ops {
+ /*
+ * tran_scheme is the transport scheme, such as "tcp" or "inproc".
+ */
+ const char *tran_scheme;
+
+ /*
+ * tran_ep_ops links our endpoint operations.
+ */
+ const struct nni_endpt_ops *tran_ep_ops;
+
+ /*
+ * tran_pipe_ops links our pipe operations.
+ */
+ const struct nni_pipe_ops *tran_pipe_ops;
+};
+
+struct nni_endpt_ops {
+ /*
+ * ep_create creates a vanilla endpoint. The value created is
+ * used for the first argument for all other endpoint functions.
+ */
+ int (*ep_create)(void **, const char *, uint16_t);
+
+ /*
+ * ep_destroy frees the resources associated with the endpoint.
+ * The endpoint will already have been closed.
+ */
+ void (*ep_destroy)(void *);
+
+ /*
+ * ep_dial starts dialing, and creates a new pipe,
+ * which is returned in the final argument. It can return errors
+ * NNG_EACCESS, NNG_ECONNREFUSED, NNG_EBADADDR, NNG_ECONNFAILED,
+ * NNG_ETIMEDOUT, and NNG_EPROTO.
+ */
+ int (*ep_dial)(void *, void **);
+
+ /*
+ * ep_listen just does the bind() and listen() work,
+ * reserving the address but not creating any connections.
+ * It should return NNG_EADDRINUSE if the address is already
+ * taken. It can also return NNG_EBADADDR for an unsuitable
+ * address, or NNG_EACCESS for permission problems.
+ */
+ int (*ep_listen)(void *);
+
+ /*
+ * ep_accept accepts an inbound connection, and creates
+ * a transport pipe, which is returned in the final argument.
+ */
+ int (*ep_accept)(void *, void **);
+
+ /*
+ * ep_close stops the endpoint from operating altogether. It does
+ * not affect pipes that have already been created.
+ */
+ void (*ep_close)(void *);
+
+ /* ep_setopt sets an endpoint (transport-specific) option */
+ int (*ep_setopt)(void *, int, const void *, size_t);
+
+ /* ep_getopt gets an endpoint (transport-specific) option */
+ int (*ep_getopt)(void *, int, void *, size_t *);
+};
+
+struct nni_pipe_ops {
+ /* p_destroy destroys the pipe */
+ void (*p_destroy)(void *);
+
+ /* p_send sends the message */
+ int (*p_send)(void *, nng_msg_t);
+
+ /* p_recv recvs the message */
+ int (*p_recv)(void *, nng_msg_t *);
+
+ /* p_close closes the pipe */
+ void (*p_close)(void *);
+
+ /* p_proto returns the peer protocol */
+ uint16_t (*p_proto)(void *);
+
+ /* p_getopt gets an pipe (transport-specific) property */
+ int (*p_getopt)(void *, int, void *, size_t *);
+};
+
+#endif /* CORE_TRANSPORT_H */