diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/init.c | 2 | ||||
| -rw-r--r-- | src/core/options.c | 157 | ||||
| -rw-r--r-- | src/core/options.h | 7 | ||||
| -rw-r--r-- | src/nng.c | 12 | ||||
| -rw-r--r-- | src/nng.h | 8 | ||||
| -rw-r--r-- | src/protocol/pair/pair_v1.c | 46 |
6 files changed, 211 insertions, 21 deletions
diff --git a/src/core/init.c b/src/core/init.c index 4025c0f4..54c72c5e 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -21,6 +21,7 @@ nni_init_helper(void) ((rv = nni_timer_sys_init()) != 0) || ((rv = nni_aio_sys_init()) != 0) || ((rv = nni_random_sys_init()) != 0) || + ((rv = nni_option_sys_init()) != 0) || ((rv = nni_sock_sys_init()) != 0) || ((rv = nni_ep_sys_init()) != 0) || ((rv = nni_pipe_sys_init()) != 0) || @@ -43,6 +44,7 @@ nni_fini(void) nni_pipe_sys_fini(); nni_ep_sys_fini(); nni_sock_sys_fini(); + nni_option_sys_fini(); nni_random_sys_fini(); nni_aio_sys_fini(); nni_timer_sys_fini(); 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 diff --git a/src/core/options.h b/src/core/options.h index 4b29c4b6..03a6e37e 100644 --- a/src/core/options.h +++ b/src/core/options.h @@ -56,4 +56,11 @@ extern int nni_chkopt_usec(const void *, size_t); extern int nni_chkopt_int(const void *, size_t, int, int); extern int nni_chkopt_size(const void *, size_t, size_t, size_t); +extern int nni_option_register(const char *, int *); +extern int nni_option_lookup(const char *); +extern const char *nni_option_name(int); + +extern int nni_option_sys_init(void); +extern void nni_option_sys_fini(void); + #endif // CORE_OPTIONS_H @@ -878,6 +878,18 @@ nng_msg_getopt(nng_msg *msg, int opt, void *ptr, size_t *szp) return (nni_msg_getopt(msg, opt, ptr, szp)); } +int +nng_option_lookup(const char *name) +{ + return (nni_option_lookup(name)); +} + +const char * +nng_option_name(int id) +{ + return (nni_option_name(id)); +} + #if 0 int nng_snapshot_create(nng_socket sock, nng_snapshot **snapp) @@ -309,6 +309,13 @@ NNG_DECL void nng_msg_set_pipe(nng_msg *, nng_pipe); NNG_DECL nng_pipe nng_msg_get_pipe(const nng_msg *); NNG_DECL int nng_msg_getopt(nng_msg *, int, void *, size_t *); +// Lookup an option by name. This returns either the option value, +// or -1 if the option name is unknown. +NNG_DECL int nng_option_lookup(const char *); + +// Lookup an option name by id. Returns NULL if not known. +NNG_DECL const char *nng_option_name(int); + // Pipe API. Generally pipes are only "observable" to applications, but // we do permit an application to close a pipe. This can be useful, for // example during a connection notification, to disconnect a pipe that @@ -417,7 +424,6 @@ enum nng_opt_enum { NNG_OPT_REMOTEADDR = NNG_OPT_SOCKET(17), NNG_OPT_RCVFD = NNG_OPT_SOCKET(18), NNG_OPT_SNDFD = NNG_OPT_SOCKET(19), - NNG_OPT_POLYAMOROUS = NNG_OPT_SOCKET(20), }; // XXX: TBD: priorities, socket names, ipv4only diff --git a/src/protocol/pair/pair_v1.c b/src/protocol/pair/pair_v1.c index 2b8a9120..09543830 100644 --- a/src/protocol/pair/pair_v1.c +++ b/src/protocol/pair/pair_v1.c @@ -69,6 +69,7 @@ pair1_sock_init(void **sp, nni_sock *nsock) { pair1_sock *s; int rv; + int poly; if ((s = NNI_ALLOC_STRUCT(s)) == NULL) { return (NNG_ENOMEM); @@ -83,6 +84,11 @@ pair1_sock_init(void **sp, nni_sock *nsock) nni_aio_init(&s->aio_getq, pair1_sock_getq_cb, s); nni_mtx_init(&s->mtx); + if ((rv = nni_option_register("polyamorous", &poly)) != 0) { + pair1_sock_fini(s); + return (rv); + } + s->nsock = nsock; s->raw = 0; s->poly = 0; @@ -393,30 +399,30 @@ pair1_sock_setopt(void *arg, int opt, const void *buf, size_t sz) pair1_sock *s = arg; int rv; - nni_mtx_lock(&s->mtx); - switch (opt) { - case NNG_OPT_RAW: + if (opt == nni_option_lookup("raw")) { + nni_mtx_lock(&s->mtx); if (s->started) { rv = NNG_ESTATE; } else { rv = nni_setopt_int(&s->raw, buf, sz, 0, 1); } - break; - case NNG_OPT_POLYAMOROUS: + nni_mtx_unlock(&s->mtx); + } else if (opt == nni_option_lookup("polyamorous")) { + nni_mtx_lock(&s->mtx); if (s->started) { rv = NNG_ESTATE; } else { rv = nni_setopt_int(&s->poly, buf, sz, 0, 1); } - break; - case NNG_OPT_MAXTTL: + nni_mtx_unlock(&s->mtx); + } else if (opt == nni_option_lookup("max-ttl")) { + nni_mtx_lock(&s->mtx); rv = nni_setopt_int(&s->ttl, buf, sz, 1, 255); - break; - default: + nni_mtx_unlock(&s->mtx); + } else { rv = NNG_ENOTSUP; } - nni_mtx_unlock(&s->mtx); return (rv); } @@ -426,21 +432,21 @@ pair1_sock_getopt(void *arg, int opt, void *buf, size_t *szp) pair1_sock *s = arg; int rv; - nni_mtx_lock(&s->mtx); - switch (opt) { - case NNG_OPT_RAW: + if (opt == nni_option_lookup("raw")) { + nni_mtx_lock(&s->mtx); rv = nni_getopt_int(&s->raw, buf, szp); - break; - case NNG_OPT_MAXTTL: + nni_mtx_unlock(&s->mtx); + } else if (opt == nni_option_lookup("max-ttl")) { + nni_mtx_lock(&s->mtx); rv = nni_getopt_int(&s->ttl, buf, szp); - break; - case NNG_OPT_POLYAMOROUS: + nni_mtx_unlock(&s->mtx); + } else if (opt == nni_option_lookup("polyamorous")) { + nni_mtx_lock(&s->mtx); rv = nni_getopt_int(&s->poly, buf, szp); - break; - default: + nni_mtx_unlock(&s->mtx); + } else { rv = NNG_ENOTSUP; } - nni_mtx_unlock(&s->mtx); return (rv); } |
