aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/pipe.c25
-rw-r--r--src/core/socket.c15
-rw-r--r--src/core/socket.h2
3 files changed, 26 insertions, 16 deletions
diff --git a/src/core/pipe.c b/src/core/pipe.c
index 0633dea9..6cc93d98 100644
--- a/src/core/pipe.c
+++ b/src/core/pipe.c
@@ -121,6 +121,7 @@ nni_pipe_create(nni_pipe **pp, nni_ep *ep)
p->p_tran_data = NULL;
p->p_proto_data = NULL;
p->p_active = 0;
+ p->p_id = 0;
NNI_LIST_NODE_INIT(&p->p_node);
// Make a copy of the transport ops. We can override entry points
@@ -168,7 +169,6 @@ nni_pipe_start(nni_pipe *pipe)
{
int rv;
int i;
- int collide;
nni_sock *sock = pipe->p_sock;
nni_mtx_lock(&sock->s_mx);
@@ -184,23 +184,16 @@ nni_pipe_start(nni_pipe *pipe)
return (NNG_EPROTO);
}
- do {
- // We generate a new pipe ID, but we make sure it does not
- // collide with any we already have. This can only normally
- // happen if we wrap -- i.e. we've had 4 billion or so pipes.
- // XXX: consider making this a hash table!!
- nni_pipe *check;
- pipe->p_id = nni_random() & 0x7FFFFFFF;
- collide = 0;
- NNI_LIST_FOREACH (&sock->s_pipes, check) {
- if ((pipe != check) && (check->p_id == pipe->p_id)) {
- collide = 1;
- break;
- }
- }
- } while (collide);
+ rv = nni_idhash_alloc(sock->s_pipes_by_id, &pipe->p_id, pipe);
+ if (rv != 0) {
+ nni_pipe_bail(pipe);
+ nni_mtx_unlock(&sock->s_mx);
+ return (rv);
+ }
if ((rv = sock->s_pipe_ops.pipe_add(pipe->p_proto_data)) != 0) {
+ nni_idhash_remove(sock->s_pipes_by_id, pipe->p_id);
+ pipe->p_id = 0;
nni_pipe_bail(pipe);
nni_mtx_unlock(&sock->s_mx);
return (rv);
diff --git a/src/core/socket.c b/src/core/socket.c
index 1e9fe11f..e19485a5 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -47,6 +47,10 @@ nni_reaper(void *arg)
nni_mtx_lock(&sock->s_mx);
if ((pipe = nni_list_first(&sock->s_reaps)) != NULL) {
nni_list_remove(&sock->s_reaps, pipe);
+ if (pipe->p_id != 0) {
+ nni_idhash_remove(sock->s_pipes_by_id,
+ pipe->p_id);
+ }
if (((ep = pipe->p_ep) != NULL) &&
((ep->ep_pipe == pipe))) {
@@ -232,6 +236,15 @@ nni_sock_open(nni_sock **sockp, uint16_t pnum)
goto fail;
}
+ if ((rv = nni_idhash_create(&sock->s_pipes_by_id)) != 0) {
+ goto fail;
+ }
+ // Pipe IDs are always positive values with the upper bit clear.
+ // Start the IDs at a random place to minimize chances of PIPE ID
+ // reuse improperly.
+ nni_idhash_set_limits(sock->s_pipes_by_id, 1, 0x7FFFFFFF,
+ nni_random() & 0x7FFFFFFF);
+
rv = nni_ev_init(&sock->s_recv_ev, NNG_EV_CAN_RECV, sock);
if (rv != 0) {
goto fail;
@@ -290,6 +303,7 @@ fail:
nni_ev_fini(&sock->s_recv_ev);
nni_msgq_fini(sock->s_urq);
nni_msgq_fini(sock->s_uwq);
+ nni_idhash_destroy(sock->s_pipes_by_id);
nni_cv_fini(&sock->s_notify_cv);
nni_cv_fini(&sock->s_cv);
nni_mtx_fini(&sock->s_notify_mx);
@@ -428,6 +442,7 @@ nni_sock_close(nni_sock *sock)
nni_msgq_fini(sock->s_uwq);
nni_ev_fini(&sock->s_send_ev);
nni_ev_fini(&sock->s_recv_ev);
+ nni_idhash_destroy(sock->s_pipes_by_id);
nni_cv_fini(&sock->s_notify_cv);
nni_cv_fini(&sock->s_cv);
nni_mtx_fini(&sock->s_notify_mx);
diff --git a/src/core/socket.h b/src/core/socket.h
index 424b1321..2860ad46 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -42,6 +42,8 @@ struct nng_socket {
nni_cv s_notify_cv; // wakes notify thread
nni_mtx s_notify_mx; // protects s_notify list
+ nni_idhash * s_pipes_by_id; // pipes by id
+
nni_list s_reaps; // pipes to reap
nni_thr s_reaper;
nni_thr s_notifier;