aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/defs.h16
-rw-r--r--src/core/endpt.c37
-rw-r--r--src/core/endpt.h7
-rw-r--r--src/core/pipe.c8
-rw-r--r--src/core/pipe.h5
-rw-r--r--src/core/protocol.h1
-rw-r--r--src/core/socket.c99
-rw-r--r--src/core/socket.h6
-rw-r--r--src/core/transport.h9
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 *);
};