aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/init.c2
-rw-r--r--src/core/options.c157
-rw-r--r--src/core/options.h7
-rw-r--r--src/nng.c12
-rw-r--r--src/nng.h8
-rw-r--r--src/protocol/pair/pair_v1.c46
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
diff --git a/src/nng.c b/src/nng.c
index 2cd1b3a5..191c83fb 100644
--- a/src/nng.c
+++ b/src/nng.c
@@ -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)
diff --git a/src/nng.h b/src/nng.h
index 568347b3..e7d7fe2f 100644
--- a/src/nng.h
+++ b/src/nng.h
@@ -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);
}