diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/defs.h | 16 | ||||
| -rw-r--r-- | src/core/endpt.c | 37 | ||||
| -rw-r--r-- | src/core/endpt.h | 7 | ||||
| -rw-r--r-- | src/core/pipe.c | 8 | ||||
| -rw-r--r-- | src/core/pipe.h | 5 | ||||
| -rw-r--r-- | src/core/protocol.h | 1 | ||||
| -rw-r--r-- | src/core/socket.c | 99 | ||||
| -rw-r--r-- | src/core/socket.h | 6 | ||||
| -rw-r--r-- | src/core/transport.h | 9 |
9 files changed, 152 insertions, 36 deletions
diff --git a/src/core/defs.h b/src/core/defs.h index 0f38b9cf..f64d3df7 100644 --- a/src/core/defs.h +++ b/src/core/defs.h @@ -136,4 +136,20 @@ typedef struct { // A few assorted other items. #define NNI_FLAG_IPV4ONLY 1 +// Types. These are used to provide more structured access to options +// (and maybe later statistics). For now these are internal only. +enum nni_type { + NNI_TYPE_OPAQUE, + NNI_TYPE_BOOL, + NNI_TYPE_INT32, + NNI_TYPE_UINT32, + NNI_TYPE_INT64, + NNI_TYPE_UINT64, + NNI_TYPE_SIZE, + NNI_TYPE_DURATION, + NNI_TYPE_STRING, + NNI_TYPE_SOCKADDR, + NNI_TYPE_POINTER, +}; + #endif // CORE_DEFS_H diff --git a/src/core/endpt.c b/src/core/endpt.c index 4d3d9031..131ee1db 100644 --- a/src/core/endpt.c +++ b/src/core/endpt.c @@ -581,7 +581,7 @@ nni_ep_pipe_remove(nni_ep *ep, nni_pipe *pipe) } int -nni_ep_setopt(nni_ep *ep, const char *name, const void *val, size_t sz) +nni_ep_setopt(nni_ep *ep, const char *name, const void *val, size_t sz, int t) { nni_tran_ep_option *eo; @@ -598,6 +598,11 @@ nni_ep_setopt(nni_ep *ep, const char *name, const void *val, size_t sz) if (eo->eo_setopt == NULL) { return (NNG_EREADONLY); } + if ((t != NNI_TYPE_OPAQUE) && + (eo->eo_type != NNI_TYPE_OPAQUE) && (t != eo->eo_type)) { + return (NNG_EBADTYPE); + } + nni_mtx_lock(&ep->ep_mtx); rv = eo->eo_setopt(ep->ep_data, val, sz); nni_mtx_unlock(&ep->ep_mtx); @@ -614,7 +619,25 @@ nni_ep_mode(nni_ep *ep) } int -nni_ep_getopt(nni_ep *ep, const char *name, void *valp, size_t *szp) +nni_ep_opttype(nni_ep *ep, const char *name, int *tp) +{ + nni_tran_ep_option *eo; + + for (eo = ep->ep_ops.ep_options; eo && eo->eo_name; eo++) { + if (strcmp(eo->eo_name, name) == 0) { + *tp = eo->eo_type; + return (0); + } + } + if (strcmp(name, NNG_OPT_URL) == 0) { + *tp = NNI_TYPE_STRING; + return (0); + } + return (NNG_ENOTSUP); +} + +int +nni_ep_getopt(nni_ep *ep, const char *name, void *valp, size_t *szp, int t) { nni_tran_ep_option *eo; @@ -626,6 +649,10 @@ nni_ep_getopt(nni_ep *ep, const char *name, void *valp, size_t *szp) if (eo->eo_getopt == NULL) { return (NNG_EWRITEONLY); } + if ((t != NNI_TYPE_OPAQUE) && + (eo->eo_type != NNI_TYPE_OPAQUE) && (t != eo->eo_type)) { + return (NNG_EBADTYPE); + } nni_mtx_lock(&ep->ep_mtx); rv = eo->eo_getopt(ep->ep_data, valp, szp); nni_mtx_unlock(&ep->ep_mtx); @@ -636,10 +663,14 @@ nni_ep_getopt(nni_ep *ep, const char *name, void *valp, size_t *szp) // override. This allows the URL to be created with wildcards, // that are resolved later. if (strcmp(name, NNG_OPT_URL) == 0) { + if (t != NNI_TYPE_OPAQUE) { + // XXX: Add NNI_TYPE_STRING. + return (NNG_EBADTYPE); + } return (nni_getopt_str(ep->ep_url->u_rawurl, valp, szp)); } - return (nni_sock_getopt(ep->ep_sock, name, valp, szp)); + return (nni_sock_getopt(ep->ep_sock, name, valp, szp, t)); } void diff --git a/src/core/endpt.h b/src/core/endpt.h index df4f345b..f08c7bf2 100644 --- a/src/core/endpt.h +++ b/src/core/endpt.h @@ -27,9 +27,10 @@ extern void nni_ep_close(nni_ep *); extern int nni_ep_dial(nni_ep *, int); extern int nni_ep_listen(nni_ep *, int); extern void nni_ep_list_init(nni_list *); -extern int nni_ep_setopt(nni_ep *, const char *, const void *, size_t); -extern int nni_ep_getopt(nni_ep *, const char *, void *, size_t *); -extern int nni_ep_pipe_add(nni_ep *ep, nni_pipe *); +extern int nni_ep_setopt(nni_ep *, const char *, const void *, size_t, int); +extern int nni_ep_getopt(nni_ep *, const char *, void *, size_t *, int); +extern int nni_ep_opttype(nni_ep *, const char *, int *); +extern int nni_ep_pipe_add(nni_ep *ep, nni_pipe *); extern void nni_ep_pipe_remove(nni_ep *, nni_pipe *); extern int nni_ep_mode(nni_ep *); diff --git a/src/core/pipe.c b/src/core/pipe.c index daee3834..40720906 100644 --- a/src/core/pipe.c +++ b/src/core/pipe.c @@ -289,7 +289,7 @@ nni_pipe_create(nni_ep *ep, void *tdata) } int -nni_pipe_getopt(nni_pipe *p, const char *name, void *val, size_t *szp) +nni_pipe_getopt(nni_pipe *p, const char *name, void *val, size_t *szp, int typ) { nni_tran_pipe_option *po; @@ -297,10 +297,14 @@ nni_pipe_getopt(nni_pipe *p, const char *name, void *val, size_t *szp) if (strcmp(po->po_name, name) != 0) { continue; } + if ((typ != NNI_TYPE_OPAQUE) && + (po->po_type != NNI_TYPE_OPAQUE) && (typ != po->po_type)) { + return (NNG_EBADTYPE); + } return (po->po_getopt(p->p_tran_data, val, szp)); } // Maybe the endpoint knows? - return (nni_ep_getopt(p->p_ep, name, val, szp)); + return (nni_ep_getopt(p->p_ep, name, val, szp, typ)); } void diff --git a/src/core/pipe.h b/src/core/pipe.h index 32871335..ea0c16db 100644 --- a/src/core/pipe.h +++ b/src/core/pipe.h @@ -57,7 +57,10 @@ extern void nni_pipe_start(nni_pipe *); extern uint16_t nni_pipe_proto(nni_pipe *); extern uint16_t nni_pipe_peer(nni_pipe *); -extern int nni_pipe_getopt(nni_pipe *, const char *, void *, size_t *); + +// nni_pipe_getopt looks up the option. The last argument is the type, +// which. If the type is NNI_TYPE_OPAQUE, then no format check is performed. +extern int nni_pipe_getopt(nni_pipe *, const char *, void *, size_t *, int); // nni_pipe_get_proto_data gets the protocol private data set with the // nni_pipe_set_proto_data function. No locking is performed. diff --git a/src/core/protocol.h b/src/core/protocol.h index 47ddfd3f..e0e0e0d7 100644 --- a/src/core/protocol.h +++ b/src/core/protocol.h @@ -49,6 +49,7 @@ struct nni_proto_pipe_ops { struct nni_proto_sock_option { const char *pso_name; + int pso_type; int (*pso_getopt)(void *, void *, size_t *); int (*pso_setopt)(void *, const void *, size_t); }; diff --git a/src/core/socket.c b/src/core/socket.c index 440f1bbf..40fdc9c8 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -21,6 +21,7 @@ static nni_mtx nni_sock_lk; typedef struct nni_socket_option { const char *so_name; + int so_type; int (*so_getopt)(nni_sock *, void *, size_t *); int (*so_setopt)(nni_sock *, const void *, size_t); } nni_socket_option; @@ -28,6 +29,7 @@ typedef struct nni_socket_option { typedef struct nni_sockopt { nni_list_node node; char * name; + int typ; size_t sz; void * data; } nni_sockopt; @@ -251,51 +253,62 @@ nni_sock_setopt_sockname(nni_sock *s, const void *buf, size_t sz) static const nni_socket_option nni_sock_options[] = { { .so_name = NNG_OPT_RECVTIMEO, + .so_type = NNI_TYPE_DURATION, .so_getopt = nni_sock_getopt_recvtimeo, .so_setopt = nni_sock_setopt_recvtimeo, }, { .so_name = NNG_OPT_SENDTIMEO, + .so_type = NNI_TYPE_DURATION, .so_getopt = nni_sock_getopt_sendtimeo, .so_setopt = nni_sock_setopt_sendtimeo, }, { .so_name = NNG_OPT_RECVFD, + .so_type = NNI_TYPE_INT32, .so_getopt = nni_sock_getopt_recvfd, .so_setopt = NULL, }, { .so_name = NNG_OPT_SENDFD, + .so_type = NNI_TYPE_INT32, .so_getopt = nni_sock_getopt_sendfd, .so_setopt = NULL, }, { .so_name = NNG_OPT_RECVBUF, + .so_type = NNI_TYPE_INT32, .so_getopt = nni_sock_getopt_recvbuf, .so_setopt = nni_sock_setopt_recvbuf, }, { .so_name = NNG_OPT_SENDBUF, + .so_type = NNI_TYPE_INT32, .so_getopt = nni_sock_getopt_sendbuf, .so_setopt = nni_sock_setopt_sendbuf, }, { .so_name = NNG_OPT_RECONNMINT, + .so_type = NNI_TYPE_DURATION, .so_getopt = nni_sock_getopt_reconnmint, .so_setopt = nni_sock_setopt_reconnmint, }, { .so_name = NNG_OPT_RECONNMAXT, + .so_type = NNI_TYPE_DURATION, .so_getopt = nni_sock_getopt_reconnmaxt, .so_setopt = nni_sock_setopt_reconnmaxt, }, { .so_name = NNG_OPT_SOCKNAME, + .so_type = NNI_TYPE_STRING, .so_getopt = nni_sock_getopt_sockname, .so_setopt = nni_sock_setopt_sockname, }, // terminate list - { NULL, NULL, NULL }, + { + .so_name = NULL, + }, }; static void @@ -513,17 +526,17 @@ nni_sock_create(nni_sock **sp, const nni_proto *proto) ((rv = nni_msgq_init(&s->s_urq, 0)) != 0) || ((rv = s->s_sock_ops.sock_init(&s->s_data, s)) != 0) || ((rv = nni_sock_setopt(s, NNG_OPT_LINGER, &s->s_linger, - sizeof(nni_duration))) != 0) || + sizeof(nni_duration), NNI_TYPE_DURATION)) != 0) || ((rv = nni_sock_setopt(s, NNG_OPT_SENDTIMEO, &s->s_sndtimeo, - sizeof(nni_duration))) != 0) || + sizeof(nni_duration), NNI_TYPE_DURATION)) != 0) || ((rv = nni_sock_setopt(s, NNG_OPT_RECVTIMEO, &s->s_rcvtimeo, - sizeof(nni_duration))) != 0) || + sizeof(nni_duration), NNI_TYPE_DURATION)) != 0) || ((rv = nni_sock_setopt(s, NNG_OPT_RECONNMINT, &s->s_reconn, - sizeof(nni_duration))) != 0) || + sizeof(nni_duration), NNI_TYPE_DURATION)) != 0) || ((rv = nni_sock_setopt(s, NNG_OPT_RECONNMAXT, &s->s_reconnmax, - sizeof(nni_duration))) != 0) || + sizeof(nni_duration), NNI_TYPE_DURATION)) != 0) || ((rv = nni_sock_setopt(s, NNG_OPT_RECVMAXSZ, &s->s_rcvmaxsz, - sizeof(size_t))) != 0)) { + sizeof(size_t), NNI_TYPE_SIZE)) != 0)) { nni_sock_destroy(s); return (rv); } @@ -823,7 +836,8 @@ nni_sock_ep_add(nni_sock *s, nni_ep *ep) NNI_LIST_FOREACH (&s->s_options, sopt) { int rv; - rv = nni_ep_setopt(ep, sopt->name, sopt->data, sopt->sz); + rv = nni_ep_setopt( + ep, sopt->name, sopt->data, sopt->sz, NNI_TYPE_OPAQUE); if ((rv != 0) && (rv != NNG_ENOTSUP)) { nni_mtx_unlock(&s->s_mx); return (rv); @@ -849,7 +863,7 @@ nni_sock_ep_remove(nni_sock *sock, nni_ep *ep) } int -nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) +nni_sock_setopt(nni_sock *s, const char *name, const void *v, size_t sz, int t) { int rv = NNG_ENOTSUP; nni_ep * ep; @@ -873,7 +887,12 @@ nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) nni_mtx_unlock(&s->s_mx); return (NNG_EREADONLY); } - rv = pso->pso_setopt(s->s_data, val, size); + if ((pso->pso_type != NNI_TYPE_OPAQUE) && + (t != NNI_TYPE_OPAQUE) && (t != pso->pso_type)) { + nni_mtx_unlock(&s->s_mx); + return (NNG_EBADTYPE); + } + rv = pso->pso_setopt(s->s_data, v, sz); nni_mtx_unlock(&s->s_mx); return (rv); } @@ -887,7 +906,12 @@ nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) nni_mtx_unlock(&s->s_mx); return (NNG_EREADONLY); } - rv = sso->so_setopt(s, val, size); + if ((sso->so_type != NNI_TYPE_OPAQUE) && + (t != NNI_TYPE_OPAQUE) && (t != sso->so_type)) { + nni_mtx_unlock(&s->s_mx); + return (NNG_EBADTYPE); + } + rv = sso->so_setopt(s, v, sz); nni_mtx_unlock(&s->s_mx); return (rv); } @@ -901,17 +925,17 @@ nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) // Validation of transport options. This is stateless, so transports // should not fail to set an option later if they passed it here. - rv = nni_tran_chkopt(name, val, size); + rv = nni_tran_chkopt(name, v, sz); // Also check a few generic things. We do this if no transport // was found, or even if a transport rejected one of the settings. if ((rv == NNG_ENOTSUP) || (rv == 0)) { if ((strcmp(name, NNG_OPT_LINGER) == 0)) { - rv = nni_chkopt_ms(val, size); + rv = nni_chkopt_ms(v, sz); } else if (strcmp(name, NNG_OPT_RECVMAXSZ) == 0) { // just a sanity test on the size; it also ensures that // a size can be set even with no transport configured. - rv = nni_chkopt_size(val, size, 0, NNI_MAXSZ); + rv = nni_chkopt_size(v, sz, 0, NNI_MAXSZ); } } @@ -923,24 +947,25 @@ nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) if ((optv = NNI_ALLOC_STRUCT(optv)) == NULL) { return (NNG_ENOMEM); } - if ((optv->data = nni_alloc(size)) == NULL) { + if ((optv->data = nni_alloc(sz)) == NULL) { NNI_FREE_STRUCT(optv); return (NNG_ENOMEM); } if ((optv->name = nni_strdup(name)) == NULL) { - nni_free(optv->data, size); + nni_free(optv->data, sz); NNI_FREE_STRUCT(optv); return (NNG_ENOMEM); } - memcpy(optv->data, val, size); - optv->sz = size; + memcpy(optv->data, v, sz); + optv->sz = sz; + optv->typ = t; NNI_LIST_NODE_INIT(&optv->node); nni_mtx_lock(&s->s_mx); NNI_LIST_FOREACH (&s->s_options, oldv) { if (strcmp(oldv->name, name) == 0) { - if ((oldv->sz != size) || - (memcmp(oldv->data, val, size) != 0)) { + if ((oldv->sz != sz) || + (memcmp(oldv->data, v, sz) != 0)) { break; } @@ -956,7 +981,17 @@ nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) // important that transport wide checks properly pre-validate. NNI_LIST_FOREACH (&s->s_eps, ep) { int x; - x = nni_ep_setopt(ep, optv->name, optv->data, size); + if (optv->typ == NNI_TYPE_OPAQUE) { + int t2; + if (nni_ep_opttype(ep, optv->name, &t2) == + NNG_ENOTSUP) { + continue; + } + // This allows us to determine what the type + // *should* be. + optv->typ = t2; + } + x = nni_ep_setopt(ep, optv->name, optv->data, sz, t); if (x != NNG_ENOTSUP) { if ((rv = x) != 0) { nni_mtx_unlock(&s->s_mx); @@ -971,7 +1006,7 @@ nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) // will already have had a chance to veto this. if (strcmp(name, NNG_OPT_LINGER) == 0) { - rv = nni_setopt_ms(&s->s_linger, val, size); + rv = nni_setopt_ms(&s->s_linger, v, sz); } if (rv == 0) { @@ -994,7 +1029,7 @@ nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) } int -nni_sock_getopt(nni_sock *s, const char *name, void *val, size_t *szp) +nni_sock_getopt(nni_sock *s, const char *name, void *val, size_t *szp, int t) { int rv = NNG_ENOTSUP; nni_sockopt * sopt; @@ -1016,12 +1051,17 @@ nni_sock_getopt(nni_sock *s, const char *name, void *val, size_t *szp) nni_mtx_unlock(&s->s_mx); return (NNG_EWRITEONLY); } + if ((pso->pso_type != NNI_TYPE_OPAQUE) && + (t != NNI_TYPE_OPAQUE) && (t != pso->pso_type)) { + nni_mtx_unlock(&s->s_mx); + return (NNG_EBADTYPE); + } rv = pso->pso_getopt(s->s_data, val, szp); nni_mtx_unlock(&s->s_mx); return (rv); } - // Options that are handled by socket core, and never passed down. + // Socket generic options. for (sso = nni_sock_options; sso->so_name != NULL; sso++) { if (strcmp(name, sso->so_name) != 0) { continue; @@ -1030,6 +1070,11 @@ nni_sock_getopt(nni_sock *s, const char *name, void *val, size_t *szp) nni_mtx_unlock(&s->s_mx); return (NNG_EWRITEONLY); } + if ((sso->so_type != NNI_TYPE_OPAQUE) && + (t != NNI_TYPE_OPAQUE) && (t != sso->so_type)) { + nni_mtx_unlock(&s->s_mx); + return (NNG_EBADTYPE); + } rv = sso->so_getopt(s, val, szp); nni_mtx_unlock(&s->s_mx); return (rv); @@ -1038,6 +1083,12 @@ nni_sock_getopt(nni_sock *s, const char *name, void *val, size_t *szp) NNI_LIST_FOREACH (&s->s_options, sopt) { if (strcmp(sopt->name, name) == 0) { size_t sz = sopt->sz; + + if ((sopt->typ != NNI_TYPE_OPAQUE) && + (t != NNI_TYPE_OPAQUE) && (t != sopt->typ)) { + nni_mtx_unlock(&s->s_mx); + return (NNG_EBADTYPE); + } if (sopt->sz > *szp) { sz = *szp; } diff --git a/src/core/socket.h b/src/core/socket.h index 30561d49..3af6bb9e 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -24,8 +24,10 @@ extern uint16_t nni_sock_proto(nni_sock *); extern uint16_t nni_sock_peer(nni_sock *); extern const char *nni_sock_proto_name(nni_sock *); extern const char *nni_sock_peer_name(nni_sock *); -extern int nni_sock_setopt(nni_sock *, const char *, const void *, size_t); -extern int nni_sock_getopt(nni_sock *, const char *, void *, size_t *); + +extern int nni_sock_setopt( + nni_sock *, const char *, const void *, size_t, int); +extern int nni_sock_getopt(nni_sock *, const char *, void *, size_t *, int); extern int nni_sock_recvmsg(nni_sock *, nni_msg **, int); extern int nni_sock_sendmsg(nni_sock *, nni_msg *, int); extern void nni_sock_send(nni_sock *, nni_aio *); diff --git a/src/core/transport.h b/src/core/transport.h index 0ca9c409..ebc14e83 100644 --- a/src/core/transport.h +++ b/src/core/transport.h @@ -46,13 +46,17 @@ struct nni_tran { // the old version around -- it may be possible to automatically convert // older versions in the future. #define NNI_TRANSPORT_V0 0x54520000 -#define NNI_TRANSPORT_VERSION NNI_TRANSPORT_V0 +#define NNI_TRANSPORT_V1 0x54520001 +#define NNI_TRANSPORT_VERSION NNI_TRANSPORT_V1 // Endpoint option handlers. struct nni_tran_ep_option { // eo_name is the name of the option. const char *eo_name; + // eo_type is the type of the option. + int eo_type; + // eo_getopt retrieves the value of the option. int (*eo_getopt)(void *, void *, size_t *); @@ -113,6 +117,9 @@ struct nni_tran_pipe_option { // po_name is the name of the option. const char *po_name; + // po_type is the type of the option. + int po_type; + // po_getopt retrieves the value of the option. int (*po_getopt)(void *, void *, size_t *); }; |
