From 68ff9c823d3cead2b11a003c40c8f5affc11dc71 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Wed, 23 Aug 2017 18:30:51 -0700 Subject: Add init/fini to protocols to allow them to register options. --- src/core/init.c | 2 ++ src/core/protocol.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ src/core/protocol.h | 15 +++++++++- src/protocol/pair/pair_v1.c | 40 ++++++++++++++++++++++---- 4 files changed, 119 insertions(+), 7 deletions(-) diff --git a/src/core/init.c b/src/core/init.c index 54c72c5e..36f96d61 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -25,6 +25,7 @@ nni_init_helper(void) ((rv = nni_sock_sys_init()) != 0) || ((rv = nni_ep_sys_init()) != 0) || ((rv = nni_pipe_sys_init()) != 0) || + ((rv = nni_proto_sys_init()) != 0) || ((rv = nni_tran_sys_init()) != 0)) { nni_fini(); } @@ -41,6 +42,7 @@ void nni_fini(void) { nni_tran_sys_fini(); + nni_proto_sys_fini(); nni_pipe_sys_fini(); nni_ep_sys_fini(); nni_sock_sys_fini(); diff --git a/src/core/protocol.c b/src/core/protocol.c index 7faf9068..e36bc31f 100644 --- a/src/core/protocol.c +++ b/src/core/protocol.c @@ -13,6 +13,44 @@ #include "core/nng_impl.h" // Protocol related stuff - generically. +typedef struct nni_protocol nni_protocol; +struct nni_protocol { + const nni_proto *p_proto; + nni_list_node p_link; +}; + +static nni_mtx nni_proto_lk; +static nni_list nni_proto_list; +static int nni_proto_inited = 0; + +static int +nni_proto_init(const nni_proto *proto) +{ + nni_protocol *p; + int rv; + + nni_mtx_lock(&nni_proto_lk); + NNI_LIST_FOREACH (&nni_proto_list, p) { + if (p->p_proto == proto) { + nni_mtx_unlock(&nni_proto_lk); + return (0); + } + } + if ((p = NNI_ALLOC_STRUCT(p)) == NULL) { + nni_mtx_unlock(&nni_proto_lk); + return (NNG_ENOMEM); + } + NNI_LIST_NODE_INIT(&p->p_link); + p->p_proto = proto; + if ((proto->proto_init != NULL) && ((rv = proto->proto_init()) != 0)) { + NNI_FREE_STRUCT(p); + nni_mtx_unlock(&nni_proto_lk); + return (rv); + } + nni_list_append(&nni_proto_list, p); + nni_mtx_unlock(&nni_proto_lk); + return (0); +} int nni_proto_open(nng_socket *sockidp, const nni_proto *proto) @@ -20,8 +58,39 @@ nni_proto_open(nng_socket *sockidp, const nni_proto *proto) int rv; nni_sock *sock; + if (((rv = nni_init()) != 0) || ((rv = nni_proto_init(proto)) != 0)) { + return (rv); + } if ((rv = nni_sock_open(&sock, proto)) == 0) { *sockidp = nni_sock_id(sock); // Keep socket held open. } return (rv); } + +int +nni_proto_sys_init(void) +{ + NNI_LIST_INIT(&nni_proto_list, nni_protocol, p_link); + nni_mtx_init(&nni_proto_lk); + nni_proto_inited = 1; + return (0); +} + +void +nni_proto_sys_fini(void) +{ + if (nni_proto_inited) { + nni_protocol *p; + nni_mtx_lock(&nni_proto_lk); + while ((p = nni_list_first(&nni_proto_list)) != NULL) { + nni_list_remove(&nni_proto_list, p); + if (p->p_proto->proto_fini != NULL) { + p->p_proto->proto_fini(); + } + NNI_FREE_STRUCT(p); + } + nni_mtx_unlock(&nni_proto_lk); + } + nni_proto_inited = 0; + nni_mtx_fini(&nni_proto_lk); +} \ No newline at end of file diff --git a/src/core/protocol.h b/src/core/protocol.h index 14954b49..9416b2bf 100644 --- a/src/core/protocol.h +++ b/src/core/protocol.h @@ -95,6 +95,15 @@ struct nni_proto { uint32_t proto_flags; // Protocol flags const nni_proto_sock_ops *proto_sock_ops; // Per-socket opeations const nni_proto_pipe_ops *proto_pipe_ops; // Per-pipe operations. + + // proto_init, if not NULL, provides a function that initializes + // global values. The main purpose of this may be to initialize + // protocol option values. + int (*proto_init)(void); + + // proto_fini, if not NULL, is called at shutdown, to release + // any resources allocated at proto_init time. + void (*proto_fini)(void); }; // We quite intentionally use a signature where the upper word is nonzero, @@ -118,7 +127,11 @@ struct nni_proto { // nni_proto_open is called by the protocol to create a socket instance // with its ops vector. The intent is that applications will only see // the single protocol-specific constructure, like nng_pair_v0_open(), -// which should just be a thin wrapper around this. +// which should just be a thin wrapper around this. If the protocol has +// not been initialized yet, this routine will do so. extern int nni_proto_open(nng_socket *, const nni_proto *); +extern int nni_proto_sys_init(void); +extern void nni_proto_sys_fini(void); + #endif // CORE_PROTOCOL_H diff --git a/src/protocol/pair/pair_v1.c b/src/protocol/pair/pair_v1.c index 09543830..3b6770ba 100644 --- a/src/protocol/pair/pair_v1.c +++ b/src/protocol/pair/pair_v1.c @@ -25,6 +25,10 @@ static void pair1_pipe_getq_cb(void *); static void pair1_pipe_putq_cb(void *); static void pair1_pipe_fini(void *); +static int pair1_opt_poly = -1; +static int pair1_opt_maxttl = -1; +static int pair1_opt_raw = -1; + // pair1_sock is our per-socket protocol private structure. struct pair1_sock { nni_sock * nsock; @@ -399,7 +403,7 @@ pair1_sock_setopt(void *arg, int opt, const void *buf, size_t sz) pair1_sock *s = arg; int rv; - if (opt == nni_option_lookup("raw")) { + if (opt == pair1_opt_raw) { nni_mtx_lock(&s->mtx); if (s->started) { rv = NNG_ESTATE; @@ -407,7 +411,7 @@ pair1_sock_setopt(void *arg, int opt, const void *buf, size_t sz) rv = nni_setopt_int(&s->raw, buf, sz, 0, 1); } nni_mtx_unlock(&s->mtx); - } else if (opt == nni_option_lookup("polyamorous")) { + } else if (opt == pair1_opt_poly) { nni_mtx_lock(&s->mtx); if (s->started) { rv = NNG_ESTATE; @@ -415,7 +419,7 @@ pair1_sock_setopt(void *arg, int opt, const void *buf, size_t sz) rv = nni_setopt_int(&s->poly, buf, sz, 0, 1); } nni_mtx_unlock(&s->mtx); - } else if (opt == nni_option_lookup("max-ttl")) { + } else if (opt == pair1_opt_maxttl) { nni_mtx_lock(&s->mtx); rv = nni_setopt_int(&s->ttl, buf, sz, 1, 255); nni_mtx_unlock(&s->mtx); @@ -432,15 +436,15 @@ pair1_sock_getopt(void *arg, int opt, void *buf, size_t *szp) pair1_sock *s = arg; int rv; - if (opt == nni_option_lookup("raw")) { + if (opt == pair1_opt_raw) { nni_mtx_lock(&s->mtx); rv = nni_getopt_int(&s->raw, buf, szp); nni_mtx_unlock(&s->mtx); - } else if (opt == nni_option_lookup("max-ttl")) { + } else if (opt == pair1_opt_maxttl) { nni_mtx_lock(&s->mtx); rv = nni_getopt_int(&s->ttl, buf, szp); nni_mtx_unlock(&s->mtx); - } else if (opt == nni_option_lookup("polyamorous")) { + } else if (opt == pair1_opt_poly) { nni_mtx_lock(&s->mtx); rv = nni_getopt_int(&s->poly, buf, szp); nni_mtx_unlock(&s->mtx); @@ -450,6 +454,28 @@ pair1_sock_getopt(void *arg, int opt, void *buf, size_t *szp) return (rv); } +static void +pair1_fini(void) +{ + pair1_opt_poly = -1; + pair1_opt_raw = -1; + pair1_opt_maxttl = -1; +} + +static int +pair1_init(void) +{ + int rv; + if (((rv = nni_option_register("polyamorous", &pair1_opt_poly)) != + 0) || + ((rv = nni_option_register("raw", &pair1_opt_raw)) != 0) || + ((rv = nni_option_register("max-ttl", &pair1_opt_maxttl)) != 0)) { + pair1_fini(); + return (rv); + } + return (0); +} + static nni_proto_pipe_ops pair1_pipe_ops = { .pipe_init = pair1_pipe_init, .pipe_fini = pair1_pipe_fini, @@ -473,6 +499,8 @@ static nni_proto pair1_proto = { .proto_flags = NNI_PROTO_FLAG_SNDRCV, .proto_sock_ops = &pair1_sock_ops, .proto_pipe_ops = &pair1_pipe_ops, + .proto_init = &pair1_init, + .proto_fini = &pair1_fini, }; int -- cgit v1.2.3-70-g09d2