diff options
| author | Garrett D'Amore <garrett@damore.org> | 2021-06-19 07:59:48 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2021-06-19 07:59:48 -0700 |
| commit | e2204832ee7647ae4f1dade458535b76a0ea88ae (patch) | |
| tree | 47f750578d60d9cb198f7ec0ef340cae425c7c14 | |
| parent | a61c9f101bcb90381e4fe1fb1ee9c9164ea2b777 (diff) | |
| download | nng-e2204832ee7647ae4f1dade458535b76a0ea88ae.tar.gz nng-e2204832ee7647ae4f1dade458535b76a0ea88ae.tar.bz2 nng-e2204832ee7647ae4f1dade458535b76a0ea88ae.zip | |
Use protocol private data instead of options for messages.mqtt
This is simpler and faster.
| -rw-r--r-- | src/core/message.c | 168 | ||||
| -rw-r--r-- | src/core/message.h | 63 |
2 files changed, 48 insertions, 183 deletions
diff --git a/src/core/message.c b/src/core/message.c index 49b6c453..a39ef4bb 100644 --- a/src/core/message.c +++ b/src/core/message.c @@ -24,22 +24,13 @@ typedef struct { // Underlying message structure. struct nng_msg { - uint32_t m_header_buf[(NNI_MAX_MAX_TTL + 1)]; - size_t m_header_len; - nni_chunk m_body; - uint32_t m_pipe; // set on receive - nni_atomic_int m_refcnt; - struct nni_msg_opt *m_opts; -}; - -// Message options. For protocol use only. -struct nni_msg_opt { - struct nni_msg_opt *mo_next; - const char * mo_name; - void * mo_value; - size_t mo_size; - void (*mo_free)(void *, size_t); // called by nni_msg_free - int (*mo_dup)(void **, void *, size_t); // called by nni_msg_dup + uint32_t m_header_buf[(NNI_MAX_MAX_TTL + 1)]; + size_t m_header_len; + nni_chunk m_body; + nni_proto_msg_ops *m_proto_ops; + void * m_proto_data; + nni_atomic_int m_refcnt; + uint32_t m_pipe; // set on receive }; #if 0 @@ -441,30 +432,15 @@ nni_msg_dup(nni_msg **dup, const nni_msg *src) nni_atomic_init(&m->m_refcnt); nni_atomic_set(&m->m_refcnt, 1); - // clone message options -- we use the supplied cloner function - // if one was provided. - opp = &m->m_opts; - for (os = src->m_opts; os != NULL; os = os->mo_next) { - if ((od = NNI_ALLOC_STRUCT(od)) != NULL) { + // clone protocol data if a method was supplied. + if (src->m_proto_ops != NULL && src->m_proto_ops->msg_free != NULL) { + rv = src->m_proto_ops->msg_dup( + &m->m_proto_data, src->m_proto_data); + if (rv != 0) { nni_msg_free(m); return (NNG_ENOMEM); } - if ((os->mo_dup) != NULL) { - rv = os->mo_dup( - &od->mo_value, os->mo_value, os->mo_size); - if (rv != 0) { - nni_msg_free(m); - return (rv); - } - od->mo_size = os->mo_size; - od->mo_free = os->mo_free; - od->mo_dup = os->mo_dup; - } else { - od->mo_value = os->mo_value; - od->mo_size = os->mo_size; - } - *opp = od; - opp = &od->mo_next; + m->m_proto_ops = src->m_proto_ops; } *dup = m; @@ -478,12 +454,9 @@ nni_msg_free(nni_msg *m) struct nni_msg_opt *mo; nni_chunk_free(&m->m_body); - while ((mo = m->m_opts) != NULL) { - m->m_opts = mo->mo_next; - if (mo->mo_free != NULL) { - mo->mo_free(mo->mo_value, mo->mo_size); - } - NNI_FREE_STRUCT(mo); + if (m->m_proto_ops != NULL && + m->m_proto_ops->msg_free != NULL) { + m->m_proto_ops->msg_free(m->m_proto_data); } NNI_FREE_STRUCT(m); } @@ -672,111 +645,18 @@ nni_msg_get_pipe(const nni_msg *m) return (m->m_pipe); } -int -nni_msg_set_opt(nng_msg *m, const char *name, void *val, size_t size, - void (*free_func)(void *, size_t), - int (*dup_func)(void **, void *, size_t)) -{ - struct nni_msg_opt **opp; - struct nni_msg_opt * op; - - for (opp = &m->m_opts; (op = *opp) != NULL; opp = &op->mo_next) { - if (strcmp(op->mo_name, name) == 0) { - break; - } - } - if (op == NULL) { - if ((op = NNI_ALLOC_STRUCT(op)) == NULL) { - return (NNG_ENOMEM); - } - if ((op->mo_name = nni_strdup(name)) == NULL) { - NNI_FREE_STRUCT(op); - return (NNG_ENOMEM); - } - *opp = op; - } - op->mo_value = val; - op->mo_size = size; - op->mo_free = free_func; - op->mo_dup = dup_func; - return (0); -} - -int -nni_msg_add_opt(nng_msg *m, const char *name, void *val, size_t size, - void (*free_func)(void *, size_t), - int (*dup_func)(void **, void *, size_t)) -{ - struct nni_msg_opt **opp; - struct nni_msg_opt * op; - - opp = &m->m_opts; - while ((op = *opp) != NULL) { - opp = &op->mo_next; - } - if ((op = NNI_ALLOC_STRUCT(op)) == NULL) { - return (NNG_ENOMEM); - } - if ((op->mo_name = nni_strdup(name)) == NULL) { - NNI_FREE_STRUCT(op); - return (NNG_ENOMEM); - } - *opp = op; - op->mo_value = val; - op->mo_size = size; - op->mo_free = free_func; - op->mo_dup = dup_func; - return (0); -} - -// nni_msg_rem_opt removes *all* options with the given name. -int -nni_msg_rem_opt(nng_msg *m, const char *name) -{ - struct nni_msg_opt **opp; - struct nni_msg_opt * op; - int rv = NNG_ENOENT; - - opp = &m->m_opts; - while ((op = *opp) != NULL) { - if (strcmp(name, op->mo_name) == 0) { - if (op->mo_free != NULL) { - op->mo_free(op->mo_value, op->mo_size); - } - *opp = op->mo_next; - NNI_FREE_STRUCT(op); - rv = 0; - } else { - *opp = op->mo_next; - } - } - return (rv); -} - void -nni_msg_walk_opt( - nng_msg *m, void *arg, bool (*fn)(void *, const char *, void *, size_t)) +nni_msg_set_proto_data(nng_msg *m, nni_proto_msg_ops *ops, void *data) { - struct nni_msg_opt *op; - - for (op = m->m_opts; op != NULL; op = op->mo_next) { - if (!fn(arg, op->mo_name, op->mo_value, op->mo_size)) { - break; - } + if (m->m_proto_ops != NULL && m->m_proto_ops->msg_free != NULL) { + m->m_proto_ops->msg_free(m->m_proto_data); } + m->m_proto_ops = ops; + m->m_proto_data = data; } -int -nni_msg_get_opt(nng_msg *m, const char *name, void **vp, size_t *szp) +void * +nni_msg_get_proto_data(nng_msg *m) { - struct nni_msg_opt *op; - - for (op = m->m_opts; op != NULL; op = op->mo_next) { - if (strcmp(op->mo_name, name) == 0) { - *vp = op->mo_value; - *szp = op->mo_size; - return 0; - } - } - return (NNG_ENOENT); + return (m->m_proto_data); } diff --git a/src/core/message.h b/src/core/message.h index fb03ca6b..95152853 100644 --- a/src/core/message.h +++ b/src/core/message.h @@ -60,48 +60,33 @@ extern bool nni_msg_shared(nni_msg *); // original message in that case (same semantics as realloc). extern nni_msg *nni_msg_pull_up(nni_msg *); -// Message option handling. Message options are intended for protocol -// specific use. For this reason, their API is not made public -- instead -// protocols should provide protocol specific functions for accessing them. -// Note that manipulation of message options must not be performed while the -// message is shared. If a copy is made with nni_msg_unique(), then the -// options will be cloned appropriately. +// Message protocol private data. This is specific for protocol use, +// and not exposed to library users. -// nni_msg_set_opt sets a given option. This will replace another option -// on the message set using the same name. The supplied functions are -// used when freeing the message, or when duplicating the message. -// If the value was created using nni_alloc, then nni_free and nni_mem_dup -// can be supplied. Note that the message must not be shared when this -// is called. -// -// NB: It is possible to use a non-NULL dup function, but have a NULL -// free function. This is appropriate if the content of the buffer is -// located in the message header, for example. -extern int nni_msg_set_opt(nng_msg *, const char *, void *, size_t, - void (*)(void *, size_t), int (*)(void **, void *, size_t)); - -// nni_msg_add_opt adds a given option, regardless of whether another -// instance of the option with the same name exists. In all other respects -// it behaves like nng_msg_set_opt. -extern int nni_msg_add_opt(nng_msg *, const char *, void *, size_t, - void (*)(void *, size_t), int (*)(void **, void *, size_t)); +// nni_proto_msg_ops is used to handle the protocol private data +// associated with a message. +typedef struct nni_proto_msg_ops { + // This is used to free protocol specific data previously + // attached to the message, and is called when the message + // itself is freed, or when protocol private is replaced. + int (*msg_free)(void *); -// nni_msg_rem_opt removes any (and all) instances of the named option -// from the message. It returns zero if any instances are removed, or -// NNG_ENOENT if no instance of the option was found on the message. -// The message must not be shared. -extern int nni_msg_rem_opt(nng_msg *, const char *); + // Duplicate protocol private data when duplicating a message, + // such as by nni_msg_dup() or calling nni_msg_unique() on a + // shared message. + int (*msg_dup)(void **, const void *); +} nni_proto_msg_ops; -// nni_msg_get_opt is used to get the first instance of a message option. -// If the option cannot be found, then NNG_ENOENT is returned. -extern int nni_msg_get_opt(nng_msg *, const char *, void **, size_t *); +// nni_msg_set_proto_data is used to set protocol private data, and +// callbacks for freeing and duplicating said data, on the message. +// If other protocol private data exists on the message, it will be freed. +// NULL can be used for the ops and the pointer to clear any previously +// set data. The message must not be shared when this is called. +extern void nni_msg_set_proto_data(nng_msg *, nni_proto_msg_ops *, void *); -// nni_msg_walk_opt is used to iterate over all options with a function. -// The called function should return true to keep iterating, or false -// to stop the iteration. The argument is supplied as the first parameter -// to the function. -extern void -nni_msg_walk_opt( - nng_msg *, void *, bool (*)(void *, const char *, void *, size_t)) +// nni_msg_get_proto_data returns the data previously set on the message. +// Note that the protocol is responsible for ensuring that the data on +// the message is set by it alone. +extern void *nni_msg_get_proto_data(nng_msg *); #endif // CORE_SOCKET_H |
