From 3b73756a5e5d075adfd03f5c49014094428d818f Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sat, 24 Dec 2016 15:54:44 -0800 Subject: Change in handling of extended info for messages. Instead of supplying a pipe, and expecting that the info there would be included we use nng_msg_getopt(). This will be enabled by the app asking for extended information by setting an option, we don't copy the data for every app (most won't care). This means we don't have to worry about reference counting the pipe for the life of associated messages. --- src/core/message.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 9 deletions(-) (limited to 'src/core/message.c') diff --git a/src/core/message.c b/src/core/message.c index f1e1fc99..6976f4da 100644 --- a/src/core/message.c +++ b/src/core/message.c @@ -27,9 +27,17 @@ struct nng_msg { nni_chunk m_header; nni_chunk m_body; nni_time m_expire; // usec - nni_pipe * m_pipe; // Pipe message was received on + nni_list m_options; }; +typedef struct { + int mo_num; + size_t mo_sz; + void * mo_val; + nni_list_node mo_node; +} nni_msgopt; + + // nni_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 @@ -238,6 +246,7 @@ nni_msg_alloc(nni_msg **mp, size_t sz) nni_panic("chunk_append failed"); } + NNI_LIST_INIT(&m->m_options, nni_msgopt, mo_node); *mp = m; return (0); } @@ -246,12 +255,71 @@ nni_msg_alloc(nni_msg **mp, size_t sz) void nni_msg_free(nni_msg *m) { + nni_msgopt *mo; + nni_chunk_free(&m->m_header); nni_chunk_free(&m->m_body); + while ((mo = nni_list_first(&m->m_options)) != NULL) { + nni_list_remove(&m->m_options, mo); + nni_free(mo, sizeof (*mo) + mo->mo_sz); + } nni_free(m, sizeof (*m)); } +int +nni_msg_setopt(nni_msg *m, int opt, const void *val, size_t sz) +{ + // Find the existing option if present. Note that if we alter + // a value, we can wind up trashing old data due to ENOMEM. + nni_msgopt *oldmo, *newmo; + + NNI_LIST_FOREACH (&m->m_options, oldmo) { + if (oldmo->mo_num == opt) { + if (sz == oldmo->mo_sz) { + // nice! we can just overwrite old value + memcpy(oldmo->mo_val, val, sz); + return (0); + } + break; + } + } + if ((newmo = nni_alloc(sizeof (*newmo) + sz)) == NULL) { + return (NNG_ENOMEM); + } + newmo->mo_val = ((char *) newmo + sizeof (*newmo)); + newmo->mo_sz = sz; + newmo->mo_num = opt; + memcpy(newmo->mo_val, val, sz); + if (oldmo != NULL) { + nni_list_remove(&m->m_options, oldmo); + nni_free(oldmo, sizeof (*oldmo) + oldmo->mo_sz); + } + nni_list_append(&m->m_options, newmo); + return (0); +} + + +int +nni_msg_getopt(nni_msg *m, int opt, void *val, size_t *szp) +{ + nni_msgopt *mo; + + NNI_LIST_FOREACH (&m->m_options, mo) { + if (mo->mo_num == opt) { + int sz = *szp; + if (sz > mo->mo_sz) { + sz = mo->mo_sz; + memcpy(val, mo->mo_val, sz); + *szp = mo->mo_sz; + return (0); + } + } + } + return (NNG_ENOTSUP); +} + + int nni_msg_realloc(nni_msg *m, size_t sz) { @@ -344,11 +412,3 @@ nni_msg_trunc_header(nni_msg *m, size_t len) { return (nni_chunk_trunc(&m->m_header, len)); } - - -int -nni_msg_pipe(nni_msg *m, nni_pipe **pp) -{ - *pp = m->m_pipe; - return (0); -} -- cgit v1.2.3-70-g09d2