diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-08-23 11:23:22 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-08-23 21:14:12 -0700 |
| commit | 8ad296769192cf4628710ac0b228be2aca6d8dad (patch) | |
| tree | edd6240a63cc3b2a7e6206e1cc07b5c5edb9f1bf /src/core/options.c | |
| parent | 7074c5c50936308d1ef58be4ce1ca5e776e4c8cb (diff) | |
| download | nng-8ad296769192cf4628710ac0b228be2aca6d8dad.tar.gz nng-8ad296769192cf4628710ac0b228be2aca6d8dad.tar.bz2 nng-8ad296769192cf4628710ac0b228be2aca6d8dad.zip | |
Implement dynamic option numbering.
This permits option numbers to be allocated based on string name.
Eventually all the option values will be replaced with option
names. This will facilitate transports (ZeroTier) that may need
further options.
Diffstat (limited to 'src/core/options.c')
| -rw-r--r-- | src/core/options.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/core/options.c b/src/core/options.c index ecfa437e..55797218 100644 --- a/src/core/options.c +++ b/src/core/options.c @@ -10,8 +10,22 @@ #include "core/nng_impl.h" +#include <stdio.h> #include <string.h> +// Dynamic options. + +typedef struct nni_option nni_option; +struct nni_option { + nni_list_node o_link; + char * o_name; + int o_id; +}; + +static nni_mtx nni_option_lk; +static nni_list nni_options; +static int nni_option_nextid; + int nni_chkopt_usec(const void *v, size_t sz) { @@ -241,3 +255,146 @@ nni_getopt_fd(nni_sock *s, nni_notifyfd *fd, int mask, void *val, size_t *szp) memcpy(val, &fd->sn_rfd, sizeof(int)); return (0); } + +// nni_option_set_id sets the id for an option, if not already done so. +// (Some options have hard coded values that end-user may depend upon.) +// If the ID passed in is negative, then a new ID is allocated dynamically. +static int +nni_option_set_id(const char *name, int id) +{ + nni_option *opt; + int len; + nni_mtx_lock(&nni_option_lk); + NNI_LIST_FOREACH (&nni_options, opt) { + if (strcmp(name, opt->o_name) == 0) { + nni_mtx_unlock(&nni_option_lk); + return (0); + } + } + if ((opt = NNI_ALLOC_STRUCT(opt)) == NULL) { + nni_mtx_unlock(&nni_option_lk); + return (NNG_ENOMEM); + } + len = strlen(name) + 1; + if ((opt->o_name = nni_alloc(len)) == NULL) { + nni_mtx_unlock(&nni_option_lk); + NNI_FREE_STRUCT(opt); + return (NNG_ENOMEM); + } + (void) snprintf(opt->o_name, len, "%s", name); + if (id < 0) { + id = nni_option_nextid++; + } + opt->o_id = id; + nni_list_append(&nni_options, opt); + nni_mtx_unlock(&nni_option_lk); + return (0); +} + +int +nni_option_lookup(const char *name) +{ + nni_option *opt; + int id = -1; + + nni_mtx_lock(&nni_option_lk); + NNI_LIST_FOREACH (&nni_options, opt) { + if (strcmp(name, opt->o_name) == 0) { + id = opt->o_id; + break; + } + } + nni_mtx_unlock(&nni_option_lk); + return (id); +} + +const char * +nni_option_name(int id) +{ + nni_option *opt; + const char *name = NULL; + + nni_mtx_lock(&nni_option_lk); + NNI_LIST_FOREACH (&nni_options, opt) { + if (id == opt->o_id) { + name = opt->o_name; + break; + } + } + nni_mtx_unlock(&nni_option_lk); + return (name); +} + +int +nni_option_register(const char *name, int *idp) +{ + int id; + int rv; + + // Note that if the id was already in use, we will + // wind up leaving a gap in the ID space. That should + // be inconsequential. + if ((rv = nni_option_set_id(name, -1)) != 0) { + return (rv); + } + *idp = nni_option_lookup(name); + return (0); +} + +int +nni_option_sys_init(void) +{ + nni_mtx_init(&nni_option_lk); + NNI_LIST_INIT(&nni_options, nni_option, o_link); + nni_option_nextid = 0x10000; + int rv; + + // Register our well-known options. + if (((rv = nni_option_set_id("raw", NNG_OPT_RAW)) != 0) || + ((rv = nni_option_set_id("linger", NNG_OPT_LINGER)) != 0) || + ((rv = nni_option_set_id("recv-buf", NNG_OPT_RCVBUF)) != 0) || + ((rv = nni_option_set_id("send-buf", NNG_OPT_SNDBUF)) != 0) || + ((rv = nni_option_set_id("recv-timeout", NNG_OPT_RCVTIMEO)) != + 0) || + ((rv = nni_option_set_id("send-timeout", NNG_OPT_SNDTIMEO)) != + 0) || + ((rv = nni_option_set_id("reconnect-time", NNG_OPT_RECONN_TIME)) != + 0) || + ((rv = nni_option_set_id( + "reconnect-max-time", NNG_OPT_RECONN_MAXTIME)) != 0) || + ((rv = nni_option_set_id("recv-max-size", NNG_OPT_RCVMAXSZ)) != + 0) || + ((rv = nni_option_set_id("max-ttl", NNG_OPT_MAXTTL)) != 0) || + ((rv = nni_option_set_id("protocol", NNG_OPT_PROTOCOL)) != 0) || + ((rv = nni_option_set_id("subscribe", NNG_OPT_SUBSCRIBE)) != 0) || + ((rv = nni_option_set_id("unsubscribe", NNG_OPT_UNSUBSCRIBE)) != + 0) || + ((rv = nni_option_set_id("survey-time", NNG_OPT_SURVEYTIME)) != + 0) || + ((rv = nni_option_set_id("resend-time", NNG_OPT_RESENDTIME)) != + 0) || + ((rv = nni_option_set_id("transport", NNG_OPT_TRANSPORT)) != 0) || + ((rv = nni_option_set_id("local-addr", NNG_OPT_LOCALADDR)) != 0) || + ((rv = nni_option_set_id("remote-addr", NNG_OPT_REMOTEADDR)) != + 0) || + ((rv = nni_option_set_id("recv-fd", NNG_OPT_RCVFD)) != 0) || + ((rv = nni_option_set_id("send-fd", NNG_OPT_SNDFD)) != 0)) { + nni_option_sys_fini(); + return (rv); + } + return (0); +} + +void +nni_option_sys_fini(void) +{ + if (nni_option_nextid != 0) { + nni_option *opt; + while ((opt = nni_list_first(&nni_options)) != NULL) { + nni_list_remove(&nni_options, opt); + nni_free(opt->o_name, strlen(opt->o_name) + 1); + NNI_FREE_STRUCT(opt); + } + } + nni_option_nextid = 0; +}
\ No newline at end of file |
