aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2016-12-10 22:12:08 -0800
committerGarrett D'Amore <garrett@damore.org>2016-12-10 22:12:08 -0800
commite72c61989757d8c0700f8e48ea82a3d99cf327fc (patch)
tree6e03d6a6993d7f85ea62b23ddc0c6491045fbe5f /src/core
downloadnng-e72c61989757d8c0700f8e48ea82a3d99cf327fc.tar.gz
nng-e72c61989757d8c0700f8e48ea82a3d99cf327fc.tar.bz2
nng-e72c61989757d8c0700f8e48ea82a3d99cf327fc.zip
Initial commit. This is not going to be useful to you for anything.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/message.c249
-rw-r--r--src/core/nng_impl.h64
-rw-r--r--src/core/panic.c86
-rw-r--r--src/core/platform.c33
-rw-r--r--src/core/snprintf.c36
5 files changed, 468 insertions, 0 deletions
diff --git a/src/core/message.c b/src/core/message.c
new file mode 100644
index 00000000..20ca6b80
--- /dev/null
+++ b/src/core/message.c
@@ -0,0 +1,249 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../nng.h"
+
+#include "nng_impl.h"
+
+/*
+ * Message API.
+ */
+
+/* Message chunk, internal to the message implementation. */
+typedef struct {
+ size_t ch_cap; /* allocated size */
+ size_t ch_len; /* length in use */
+ char *ch_buf; /* underlying buffer */
+ char *ch_ptr; /* pointer to actual data */
+} chunk_t;
+
+/* Underlying message chunk. */
+struct nng_msg {
+ chunk_t m_header;
+ chunk_t m_body;
+ int64_t m_expire; /* Unix usec */
+ nng_pipe_t m_pipe; /* Pipe message was received on */
+};
+
+/*
+ * chunk_grow increases the underlying space for a chunk. It ensures
+ * that the desired amount of trailing space (including the length)
+ * and headroom (excluding the length) are available. It also copies
+ * any extant referenced data. Note that the capacity will increase,
+ * but not the length. To increase the length of the referenced data,
+ * use either chunk_append or chunk_prepend.
+ *
+ * Note that having some headroom is useful when data must be prepended
+ * to a message - it avoids having to perform extra data copies, so we
+ * encourage initial allocations to start with sufficient room.
+ */
+static int
+chunk_grow(chunk_t *ch, size_t newsz, size_t headwanted)
+{
+ size_t headroom = 0;
+ char *newbuf;
+
+ /*
+ * We assume that if the pointer is a valid pointer, and inside
+ * the backing store, then the entire data length fits. In this
+ * case we perform a logical realloc, except we don't copy any
+ * unreferenced data. We do preserve the headroom of the previous
+ * use, since that may be there for a reason.
+ *
+ * The test below also covers the case where the pointers are both
+ * NULL, or the capacity is zero.
+ */
+
+ if ((ch->ch_ptr >= ch->ch_buf) &&
+ (ch->ch_ptr < (ch->ch_buf + ch->ch_cap))) {
+
+ headroom = (size_t)(ch->ch_ptr - ch->ch_buf);
+ if (((newsz + headwanted) < ch->ch_cap) &&
+ (headwanted <= headroom)) {
+ /* We have enough space at the ends already. */
+ return (0);
+ }
+ if (headwanted < headroom) {
+ /* We never shrink... headroom either. */
+ headwanted = headroom;
+ }
+ if ((newbuf = nni_alloc(newsz + headwanted)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+ /* Copy all the data, but not header or trailer. */
+ memcpy(newbuf + headwanted, ch->ch_buf + headroom, ch->ch_len);
+ nni_free(ch->ch_buf, ch->ch_cap);
+ ch->ch_buf = newbuf;
+ ch->ch_ptr = newbuf + headwanted;
+ ch->ch_cap = newsz + headwanted;
+ return (0);
+ }
+
+ /*
+ * We either don't have a data pointer yet, or it doesn't reference
+ * the backing store. In this case, we just check against the
+ * allocated capacity and grow, or don't grow.
+ */
+ if (newsz > ch->ch_cap) {
+ /* Enough space at end, so just use it. */
+ if (ch->ch_ptr == NULL) {
+ ch->ch_ptr = ch->ch_buf;
+ }
+ return (0);
+
+ } else if ((newbuf = nni_alloc(newsz)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+
+ nni_free(ch->ch_buf, ch->ch_cap);
+ ch->ch_buf = newbuf;
+ ch->ch_cap = newsz;
+ if (ch->ch_ptr == NULL) {
+ ch->ch_ptr = ch->ch_buf;
+ }
+ return (0);
+}
+
+static void
+chunk_free(chunk_t *ch)
+{
+ if ((ch->ch_cap != 0) && (ch->ch_buf != NULL)) {
+ nni_free(ch->ch_buf, ch->ch_cap);
+ }
+ ch->ch_ptr = NULL;
+ ch->ch_buf = NULL;
+ ch->ch_len = 0;
+ ch->ch_cap = 0;
+}
+
+/* chunk_trunc truncates the number of bytes from the end of the chunk. */
+static int
+chunk_trunc(chunk_t *ch, size_t len)
+{
+ if (ch->ch_len < len) {
+ return (NNG_EINVAL);
+ }
+ ch->ch_len -= len;
+ return (0);
+}
+
+/* chunk_trim removes the number of bytes from the beginning of the chunk. */
+static int
+chunk_trim(chunk_t *ch, size_t len)
+{
+ if (ch->ch_len < len) {
+ return (NNG_EINVAL);
+ }
+ ch->ch_ptr += len;
+ ch->ch_len -= len;
+ return (0);
+}
+
+/*
+ * chunk_append appends the data to the chunk, growing the size as necessary.
+ * If the data pointer is NULL, then the chunk data region is allocated, but
+ * uninitialized.
+ */
+static int
+chunk_append(chunk_t *ch, const char *data, size_t len)
+{
+ int rv;
+ if (len == 0) {
+ return (0);
+ }
+ if ((rv = chunk_grow(ch, len + ch->ch_len, 0)) != 0) {
+ return (rv);
+ }
+ if (ch->ch_ptr == NULL) {
+ ch->ch_ptr = ch->ch_buf;
+ }
+ if (data != NULL) {
+ memcpy(ch->ch_ptr + ch->ch_len, data, len);
+ }
+ ch->ch_len += len;
+ return (0);
+}
+
+/*
+ * chunk_prepend prepends data to the chunk, as efficiently as possible.
+ * If the data pointer is NULL, then no data is actually copied, but the
+ * data region will have "grown" in the beginning, with uninitialized data.
+ */
+static int
+chunk_prepend(chunk_t *ch, const char *data, size_t len)
+{
+ int rv;
+ char *newbuf;
+ size_t headroom = 0;
+
+ if (ch->ch_ptr == NULL) {
+ ch->ch_ptr = ch->ch_buf;
+ }
+
+ if ((ch->ch_ptr >= ch->ch_buf) &&
+ (ch->ch_ptr < (ch->ch_buf + ch->ch_cap)) &&
+ (len <= (size_t)(ch->ch_ptr - ch->ch_buf))) {
+ /* There is already enough room at the beginning. */
+ ch->ch_ptr -= len;
+
+ } else if ((ch->ch_len + len) <= ch->ch_cap) {
+ /* We had enough capacity, just shuffle data down. */
+ memmove(ch->ch_ptr + len, ch->ch_ptr, ch->ch_len);
+
+ } else if ((rv = chunk_grow(ch, 0, len)) == 0) {
+ /* We grew the chunk, so adjust. */
+ ch->ch_ptr -= len;
+
+ } else {
+ /* Couldn't grow the chunk either. Error. */
+ return (rv);
+ }
+
+ ch->ch_len += len;
+ if (data) {
+ memcpy(ch->ch_ptr, data, len);
+ }
+
+ return (0);
+}
+
+#if 0
+NNG_DECL int nng_msg_alloc(nng_msg_t *, size_t);
+NNG_DECL void nng_msg_free(nng_msg_t);
+NNG_DECL int nng_msg_realloc(nng_mst_t, size_t);
+NNG_DECL void *nng_msg_header(nng_msg_t, size_t *);
+NNG_DECL void *nng_msg_body(nng_msg_t, size_t *);
+NNG_DECL int nng_msg_port(nng_msg_t, nng_pipe_t *);
+
+NNG_DECL int nng_msg_append(nng_msg_t, const char *, size_t);
+NNG_DECL int nng_msg_prepend(nng_msg_t, const char *, size_t);
+NNG_DECL int nng_msg_trim(nng_msg_t, size_t);
+NNG_DECL int nng_msg_trunc(nng_msg_t, size_t);
+
+NNG_DECL int nng_msg_append_header(nng_msg_t, const char *, size_t);
+NNG_DECL int nng_msg_prepend_header(nng_msg_t, const char *, size_t);
+NNG_DECL int nng_msg_trim_header(nng_msg_t, size_t);
+NNG_DECL int nng_msg_trunc_header(nng_msg_t, size_t);
+#endif
diff --git a/src/core/nng_impl.h b/src/core/nng_impl.h
new file mode 100644
index 00000000..a25b87a4
--- /dev/null
+++ b/src/core/nng_impl.h
@@ -0,0 +1,64 @@
+/*
+ * 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 NNG_IMPL_H
+#define NNG_IMPL_H
+
+#include "nng.h"
+#include "platform/platform.h"
+
+/*
+ * Internal implementation things for NNG, common definitions, etc.
+ *
+ * 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.
+ */
+
+/*
+ * 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 *, ...);
+
+#endif /* NNG_IMPL_H */
diff --git a/src/core/panic.c b/src/core/panic.c
new file mode 100644
index 00000000..47556f70
--- /dev/null
+++ b/src/core/panic.c
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef NNG_HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
+
+#include "nng.h"
+
+#include "nng_impl.h"
+
+/*
+ * Panic handling.
+ */
+
+static void
+show_backtrace(void)
+{
+#if NNG_HAVE_BACKTRACE
+ void *frames[50];
+ int nframes;
+ char *lines;
+ int i;
+
+ nframes = backtrace(frames, sizeof (frames) / sizeof (frames[0]));
+ if (nframes > 1) {
+ lines = backtrace_symbols(frames, nframes -1);
+ if (lines == NULL) {
+ return;
+ }
+ for (i = 0; i < nframes; i++) {
+ nni_debug_out(lines[i]);
+ }
+ }
+#endif
+}
+
+/*
+ * nni_panic shows a panic message, a possible stack bracktrace, then aborts
+ * the process/program. This should only be called when a condition arises
+ * that should not be possible, e.g. a programming assertion failure. It should
+ * not be called in situations such as ENOMEM, as nni_panic is fairly rude
+ * to any application it may be called from within.
+ */
+void
+nni_panic(const char *fmt, ...)
+{
+ char buf[128];
+ char fbuf[128];
+ va_list va;
+
+ va_start(va, fmt);
+ (void) nni_snprintf(fbuf, sizeof (buf), "panic: %s", fmt);
+ (void) nni_vsnprintf(buf, sizeof (buf), fbuf, va);
+ va_end(va);
+
+ nni_debug_out(buf);
+ nni_debug_out("This message is indicative of a BUG.");
+ nni_debug_out("Report this at http://github.com/nanomsg/nanomsg");
+
+ show_backtrace();
+ nni_abort();
+}
diff --git a/src/core/platform.c b/src/core/platform.c
new file mode 100644
index 00000000..d96ebe70
--- /dev/null
+++ b/src/core/platform.c
@@ -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.
+ */
+
+/*
+ * This file pulls in the correct platform implementation.
+ */
+
+#include "core/nng_impl.h"
+
+#if defined(PLATFORM_POSIX)
+#include "platform/posix/posix_impl.h"
+#else
+#error "unknown platform"
+#endif
diff --git a/src/core/snprintf.c b/src/core/snprintf.c
new file mode 100644
index 00000000..3ca73e00
--- /dev/null
+++ b/src/core/snprintf.c
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "nng_impl.h"
+
+void
+nni_snprintf(char *dst, size_t sz, const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ nni_vsnprintf(dst, sz, fmt, va);
+ va_end(va);
+}