예제 #1
0
int nn_efd_wait (struct nn_efd *self, int timeout)
{
    int rc;
    struct timeval tv;

    FD_SET (self->r, &self->fds);
    if (timeout >= 0) {
        tv.tv_sec = timeout / 1000;
        tv.tv_usec = timeout % 1000 * 1000;
    }
    rc = select (0, &self->fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
    if (nn_slow (rc == SOCKET_ERROR)) {
        rc = nn_err_wsa_to_posix (WSAGetLastError ());
        errno = rc;
        if (nn_slow (rc == EINTR || rc == ENOTSOCK))
            return -EINTR;
    }

    errno_assert (rc >= 0);
    if (nn_slow (rc == 0))
        return -ETIMEDOUT;
    return 0;
}
예제 #2
0
파일: req.c 프로젝트: Adellica/nanomsg
int nn_req_crecv (struct nn_sockbase *self, struct nn_msg *msg)
{
    struct nn_req *req;

    req = nn_cont (self, struct nn_req, xreq.sockbase);

    /*  No request was sent. Waiting for a reply doesn't make sense. */
    if (nn_slow (!nn_req_inprogress (req)))
        return -EFSM;

    /*  If reply was not yet recieved, wait further. */
    if (nn_slow (req->state != NN_REQ_STATE_DONE))
        return -EAGAIN;

    /*  If the reply was already received, just pass it to the caller. */
    nn_msg_mv (msg, &req->task.reply);
    nn_msg_init (&req->task.reply, 0);

    /*  Notify the state machine. */
    nn_fsm_action (&req->fsm, NN_REQ_ACTION_RECEIVED);

    return 0;
}
예제 #3
0
파일: ctx.c 프로젝트: jjrdn/nanomsg
int nn_recv (int s, void *buf, size_t len, int flags)
{
    int rc;
    struct nn_msg msg;
    size_t sz;
    struct nn_chunk *ch;

    NN_BASIC_CHECKS;

    if (nn_slow (!buf && len)) {
        errno = EFAULT;
        return -1;
    }

    rc = nn_sock_recv (self.socks [s], &msg, flags);
    if (nn_slow (rc < 0)) {
        errno = -rc;
        return -1;
    }

    if (len == NN_MSG) {
        ch = nn_chunkref_getchunk (&msg.body);
        *(void**) buf = nn_chunk_data (ch);
        sz = nn_chunk_size (ch);
    }
    else {
        sz = nn_chunkref_size (&msg.body);
        memcpy (buf, nn_chunkref_data (&msg.body), len < sz ? len : sz);
    }
    nn_msg_term (&msg);

#if defined NN_LATENCY_MONITOR
    nn_latmon_measure (NN_LATMON_RECV);
#endif

    return (int) sz;
}
예제 #4
0
파일: chunk.c 프로젝트: rudyLi/nanomsg
int nn_chunk_alloc (size_t size, int type, void **result)
{
    size_t sz;
    struct nn_chunk *self;
    const size_t hdrsz = sizeof (struct nn_chunk) + 2 * sizeof (uint32_t);

    /*  Compute total size to be allocated. Check for overflow. */
    sz = hdrsz + size;
    if (nn_slow (sz < hdrsz))
        return -ENOMEM;

    /*  Allocate the actual memory depending on the type. */
    switch (type) {
    case 0:
        self = nn_alloc (sz, "message chunk");
        break;
    default:
        return -EINVAL;
    }
    if (nn_slow (!self))
        return -ENOMEM;

    /*  Fill in the chunk header. */
    nn_atomic_init (&self->refcount, 1);
    self->size = size;
    self->ffn = nn_chunk_default_free;

    /*  Fill in the size of the empty space between the chunk header
        and the message. */
    nn_putl ((uint8_t*) ((uint32_t*) (self + 1)), 0);

    /*  Fill in the tag. */
    nn_putl ((uint8_t*) ((((uint32_t*) (self + 1))) + 1), NN_CHUNK_TAG);

    *result = ((uint8_t*) (self + 1)) + 2 * sizeof (uint32_t);
    return 0;
}
예제 #5
0
파일: sock.c 프로젝트: Granoia/cacheBench
int nn_sock_getopt (struct nn_sock *self, int level, int option,
    void *optval, size_t *optvallen)
{
    int rc;

    nn_ctx_enter (&self->ctx);
    if (nn_slow (self->state == NN_SOCK_STATE_ZOMBIE)) {
        nn_ctx_leave (&self->ctx);
        return -ETERM;
    }
    rc = nn_sock_getopt_inner (self, level, option, optval, optvallen);
    nn_ctx_leave (&self->ctx);

    return rc;
}
예제 #6
0
static void nn_timer_shutdown (struct nn_fsm *self, int src, int type,
    void *srcptr)
{
    struct nn_timer *timer;

    timer = nn_cont (self, struct nn_timer, fsm);

    if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) {
        nn_worker_execute (timer->worker, &timer->stop_task);
        timer->state = NN_TIMER_STATE_STOPPING;
        return;
    }
    if (nn_slow (timer->state == NN_TIMER_STATE_STOPPING)) {
        if (src != NN_TIMER_SRC_STOP_TASK)
            return;
        nn_assert (type == NN_WORKER_TASK_EXECUTE);
        nn_worker_rm_timer (timer->worker, &timer->wtimer);
        timer->state = NN_TIMER_STATE_IDLE;
        nn_fsm_stopped (&timer->fsm, NN_TIMER_STOPPED);
        return;
    }

    nn_fsm_bad_state(timer->state, src, type);
}
예제 #7
0
int nn_msgqueue_send (struct nn_msgqueue *self, struct nn_msg *msg)
{
    size_t msgsz;

    /*  By allowing one message of arbitrary size to be written to the queue,
        we allow even messages that exceed max buffer size to pass through.
        Beyond that we'll apply the buffer limit as specified by the user. */
    msgsz = nn_chunkref_size (&msg->hdr) + nn_chunkref_size (&msg->body);
    if (nn_slow (self->count > 0 && self->mem + msgsz >= self->maxmem))
        return -EAGAIN;

    /*  Adjust the statistics. */
    ++self->count;
    self->mem += msgsz;

    /*  Move the content of the message to the pipe. */
    nn_msg_mv (&self->out.chunk->msgs [self->out.pos], msg);
    ++self->out.pos;

    /*  If there's no space for a new message in the pipe, either re-use
        the cache chunk or allocate a new chunk if it does not exist. */
    if (nn_slow (self->out.pos == NN_MSGQUEUE_GRANULARITY)) {
        if (nn_slow (!self->cache)) {
            self->cache = nn_alloc (sizeof (struct nn_msgqueue_chunk),
                "msgqueue chunk");
            alloc_assert (self->cache);
            self->cache->next = NULL;
        }
        self->out.chunk->next = self->cache;
        self->out.chunk = self->cache;
        self->cache = NULL;
        self->out.pos = 0;
    }

    return 0;
}
예제 #8
0
파일: global.c 프로젝트: Amaury/AngstromDB
int nn_shutdown (int s, int how)
{
    int rc;

    NN_BASIC_CHECKS;

    rc = nn_sock_rm_ep (self.socks [s], how);
    if (nn_slow (rc < 0)) {
        errno = -rc;
        return -1;
    }
    nn_assert (rc == 0);

    return 0;
}
예제 #9
0
파일: ctcp.c 프로젝트: Miyurz/SuperNET
static void nn_ctcp_shutdown (struct nn_fsm *self, int src, int type,
    NN_UNUSED void *srcptr)
{
    struct nn_ctcp *ctcp;

    ctcp = nn_cont (self, struct nn_ctcp, fsm);

    if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) {
        if (!nn_stcp_isidle (&ctcp->stcp)) {
            nn_epbase_stat_increment (&ctcp->epbase,
                NN_STAT_DROPPED_CONNECTIONS, 1);
            nn_stcp_stop (&ctcp->stcp);
        }
        ctcp->state = NN_CTCP_STATE_STOPPING_STCP_FINAL;
    }
    if (nn_slow (ctcp->state == NN_CTCP_STATE_STOPPING_STCP_FINAL)) {
        if (!nn_stcp_isidle (&ctcp->stcp))
            return;
        nn_backoff_stop (&ctcp->retry);
        nn_usock_stop (&ctcp->usock);
        nn_dns_stop (&ctcp->dns);
        ctcp->state = NN_CTCP_STATE_STOPPING;
    }
    if (nn_slow (ctcp->state == NN_CTCP_STATE_STOPPING)) {
        if (!nn_backoff_isidle (&ctcp->retry) ||
              !nn_usock_isidle (&ctcp->usock) ||
              !nn_dns_isidle (&ctcp->dns))
            return;
        ctcp->state = NN_CTCP_STATE_IDLE;
        nn_fsm_stopped_noevent (&ctcp->fsm);
        nn_epbase_stopped (&ctcp->epbase);
        return;
    }

    nn_fsm_bad_state (ctcp->state, src, type);
}
예제 #10
0
파일: surveyor.c 프로젝트: tpopen/nanomsg
static int nn_surveyor_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_surveyor *surveyor;
    uint32_t surveyid;

    surveyor = nn_cont (self, struct nn_surveyor, xsurveyor.sockbase);

    /*  If no survey is going on return EFSM error. */
    if (nn_slow (!nn_surveyor_inprogress (surveyor)))
       return -EFSM;

    while (1) {

        /*  Get next response. */
        rc = nn_xsurveyor_recv (&surveyor->xsurveyor.sockbase, msg);
        if (nn_slow (rc == -EAGAIN))
            return -EAGAIN;
        errnum_assert (rc == 0, -rc);

        /*  Get the survey ID. Ignore any stale responses. */
        /*  TODO: This should be done asynchronously! */
        if (nn_slow (nn_chunkref_size (&msg->hdr) != sizeof (uint32_t)))
            continue;
        surveyid = nn_getl (nn_chunkref_data (&msg->hdr));
        if (nn_slow (surveyid != surveyor->surveyid))
            continue;

        /*  Discard the header and return the message to the user. */
        nn_chunkref_term (&msg->hdr);
        nn_chunkref_init (&msg->hdr, 0);
        break;
    }

    return 0;
}
예제 #11
0
파일: sock.c 프로젝트: Granoia/cacheBench
static void nn_sock_onleave (struct nn_ctx *self)
{
    struct nn_sock *sock;
    int events;

    sock = nn_cont (self, struct nn_sock, ctx);

    /*  If nn_close() was already called there's no point in adjusting the
        snd/rcv file descriptors. */
    if (nn_slow (sock->state != NN_SOCK_STATE_ACTIVE))
        return;

    /*  Check whether socket is readable and/or writable at the moment. */
    events = sock->sockbase->vfptr->events (sock->sockbase);
    errnum_assert (events >= 0, -events);

    /*  Signal/unsignal IN as needed. */
    if (!(sock->socktype->flags & NN_SOCKTYPE_FLAG_NORECV)) {
        if (events & NN_SOCKBASE_EVENT_IN) {
            if (!(sock->flags & NN_SOCK_FLAG_IN)) {
                sock->flags |= NN_SOCK_FLAG_IN;
                nn_efd_signal (&sock->rcvfd);
            }
        }
        else {
            if (sock->flags & NN_SOCK_FLAG_IN) {
                sock->flags &= ~NN_SOCK_FLAG_IN;
                nn_efd_unsignal (&sock->rcvfd);
            }
        }
    }

    /*  Signal/unsignal OUT as needed. */
    if (!(sock->socktype->flags & NN_SOCKTYPE_FLAG_NOSEND)) {
        if (events & NN_SOCKBASE_EVENT_OUT) {
            if (!(sock->flags & NN_SOCK_FLAG_OUT)) {
                sock->flags |= NN_SOCK_FLAG_OUT;
                nn_efd_signal (&sock->sndfd);
            }
        }
        else {
            if (sock->flags & NN_SOCK_FLAG_OUT) {
                sock->flags &= ~NN_SOCK_FLAG_OUT;
                nn_efd_unsignal (&sock->sndfd);
            }
        }
    }
}
예제 #12
0
파일: tcp.c 프로젝트: Droppe/nanomsg
static int nn_tcp_bind (const char *addr, void *hint,
    struct nn_epbase **epbase)
{
    int rc;
    struct nn_bstream *bstream;

    bstream = nn_alloc (sizeof (struct nn_bstream), "bstream (tcp)");
    alloc_assert (bstream);
    rc = nn_bstream_init (bstream, addr, hint, nn_tcp_binit, NN_TCP_BACKLOG);
    if (nn_slow (rc != 0)) {
        nn_free (bstream);
        return rc;
    }
    *epbase = &bstream->epbase;

    return 0;
}
예제 #13
0
파일: pipe.c 프로젝트: javarange/nanomsg
int nn_pipebase_start (struct nn_pipebase *self)
{
    int rc;

    nn_assert (self->state == NN_PIPEBASE_STATE_IDLE);

    self->state = NN_PIPEBASE_STATE_ACTIVE;
    self->instate = NN_PIPEBASE_INSTATE_ASYNC;
    self->outstate = NN_PIPEBASE_OUTSTATE_IDLE;
    rc = nn_sock_add (self->sock, (struct nn_pipe*) self);
    if (nn_slow (rc < 0))
        return rc;
    if (self->sock)
        nn_fsm_raise (&self->fsm, &self->out, NN_PIPE_OUT);

    return 0;
}
예제 #14
0
파일: cipc.c 프로젝트: tpoonach/SuperNET
static void nn_cipc_start_connecting (struct nn_cipc *self)
{
    int rc;
    struct sockaddr_storage ss;
    struct sockaddr_un *un;
    const char *addr;
    int val;
    size_t sz;

    /*  Try to start the underlying socket. */
    rc = nn_usock_start (&self->usock, AF_UNIX, SOCK_STREAM, 0);
    if (nn_slow (rc < 0)) {
        nn_backoff_start (&self->retry);
        self->state = NN_CIPC_STATE_WAITING;
        return;
    }

    /*  Set the relevant socket options. */
    sz = sizeof (val);
    nn_epbase_getopt (&self->epbase, NN_SOL_SOCKET, NN_SNDBUF, &val, &sz);
    nn_assert (sz == sizeof (val));
    nn_usock_setsockopt (&self->usock, SOL_SOCKET, SO_SNDBUF,
        &val, sizeof (val));
    sz = sizeof (val);
    nn_epbase_getopt (&self->epbase, NN_SOL_SOCKET, NN_RCVBUF, &val, &sz);
    nn_assert (sz == sizeof (val));
    nn_usock_setsockopt (&self->usock, SOL_SOCKET, SO_RCVBUF,
        &val, sizeof (val));

    /*  Create the IPC address from the address string. */
    addr = nn_epbase_getaddr (&self->epbase);
    memset (&ss, 0, sizeof (ss));
    un = (struct sockaddr_un*) &ss;
    nn_assert (strlen (addr) < sizeof (un->sun_path));
    ss.ss_family = AF_UNIX;
    strncpy (un->sun_path, addr, sizeof (un->sun_path));

    /*  Start connecting. */
    nn_usock_connect (&self->usock, (struct sockaddr*) &ss,
        sizeof (struct sockaddr_un));
    self->state  = NN_CIPC_STATE_CONNECTING;

    nn_epbase_stat_increment (&self->epbase,
        NN_STAT_INPROGRESS_CONNECTIONS, 1);
}
예제 #15
0
파일: pipe.c 프로젝트: tpoonach/SuperNET
int nn_pipebase_start (struct nn_pipebase *self)
{
    int rc;
    nn_assert_state (self,NN_PIPEBASE_STATE_IDLE);
    self->state = NN_PIPEBASE_STATE_ACTIVE;
    self->instate = NN_PIPEBASE_INSTATE_ASYNC;
    self->outstate = NN_PIPEBASE_OUTSTATE_IDLE;
    rc = nn_sock_add(self->sock,(struct nn_pipe *)self);
    PNACL_msg("nn_pipebase_start self.%p rc.%d\n",self,rc);
    if ( nn_slow(rc < 0) )
    {
        self->state = NN_PIPEBASE_STATE_FAILED;
        return rc;
    }
    if ( self->sock )
        nn_fsm_raise(&self->fsm,&self->out,NN_PIPE_OUT);
    return 0;
}
예제 #16
0
int nn_usock_listen (struct nn_usock *self, int backlog)
{
    int rc;

    /*  You can start listening only before the socket is connected. */
    nn_assert_state (self, NN_USOCK_STATE_STARTING);

    /*  Start listening for incoming connections. */
    rc = listen (self->s, backlog);
    //printf("usock.%d -> listen rc.%d errno.%d %s\n",self->s,rc,errno,nn_strerror(errno));
    if (nn_slow (rc != 0))
        return -errno;

    /*  Notify the state machine. */
    nn_fsm_action (&self->fsm, NN_USOCK_ACTION_LISTEN);

    return 0;
}
예제 #17
0
void nn_usock_send (struct nn_usock *self, const struct nn_iovec *iov,
    int iovcnt)
{
    int rc;
    int i;
    int out;

    /*  Make sure that the socket is actually alive. */
    nn_assert_state (self, NN_USOCK_STATE_ACTIVE);

    /*  Copy the iovecs to the socket. */
    nn_assert (iovcnt <= NN_USOCK_MAX_IOVCNT);
    self->out.hdr.msg_iov = self->out.iov;
    out = 0;
    for (i = 0; i != iovcnt; ++i) {
        if (iov [i].iov_len == 0)
            continue;
        self->out.iov [out].iov_base = iov [i].iov_base;
        self->out.iov [out].iov_len = iov [i].iov_len;
        out++;
        //PNACL_message("{%d} ",(int)iov [i].iov_len);
    }
    //PNACL_message("iov[%d]\n",out);
    self->out.hdr.msg_iovlen = out;

    /*  Try to send the data immediately. */
    rc = nn_usock_send_raw (self, &self->out.hdr);

    /*  Success. */
    if (nn_fast (rc == 0)) {
        nn_fsm_raise (&self->fsm, &self->event_sent, NN_USOCK_SENT);
        return;
    }

    /*  Errors. */
    if (nn_slow (rc != -EAGAIN)) {
        errnum_assert (rc == -ECONNRESET, -rc);
        nn_fsm_action (&self->fsm, NN_USOCK_ACTION_ERROR);
        return;
    }

    /*  Ask the worker thread to send the remaining data. */
    nn_worker_execute (self->worker, &self->task_send);
}
예제 #18
0
static int nn_inproc_ctx_bind (const char *addr, void *hint,
    struct nn_epbase **epbase)
{
    int rc;
    struct nn_list_item *it;
    struct nn_inprocb *inprocb;
    struct nn_inprocc *inprocc;
    struct nn_msgpipe *pipe;

    /*  Check whether the endpoint isn't already bound. */
    /*  TODO:  This is an O(n) algorithm! */
    for (it = nn_list_begin (&self.bound); it != nn_list_end (&self.bound);
          it = nn_list_next (&self.bound, it)) {
        inprocb = nn_cont (it, struct nn_inprocb, list);
        if (strncmp (addr, nn_inprocb_getaddr (inprocb), NN_SOCKADDR_MAX) == 0)
            return -EADDRINUSE;
    }

    /*  Insert the entry into the endpoint repository. */
    inprocb = nn_alloc (sizeof (struct nn_inprocb), "inprocb");
    alloc_assert (inprocb);
    rc = nn_inprocb_init (inprocb, addr, hint);
    if (nn_slow (rc != 0))
        return rc;
    nn_list_insert (&self.bound, &inprocb->list, nn_list_end (&self.bound));

    /*  During this process new pipes may be created. */
    for (it = nn_list_begin (&self.connected);
          it != nn_list_end (&self.connected);
          it = nn_list_next (&self.connected, it)) {
        inprocc = nn_cont (it, struct nn_inprocc, list);
        if (strncmp (addr, nn_inprocc_getaddr (inprocc),
              NN_SOCKADDR_MAX) == 0) {
            pipe = nn_alloc (sizeof (struct nn_msgpipe), "msgpipe");
            alloc_assert (pipe);
            nn_msgpipe_init (pipe, inprocb, inprocc);
        }
    }

    nn_assert (epbase);
    *epbase = &inprocb->epbase;
    return 0;
}
예제 #19
0
static int nn_surveyor_setopt (struct nn_sockbase *self, int level, int option,
    const void *optval, size_t optvallen)
{
    struct nn_surveyor *surveyor;

    surveyor = nn_cont (self, struct nn_surveyor, xsurveyor.sockbase);

    if (level != NN_SURVEYOR)
        return -ENOPROTOOPT;

    if (option == NN_SURVEYOR_DEADLINE) {
        if (nn_slow (optvallen != sizeof (int)))
            return -EINVAL;
        surveyor->deadline = *(int*) optval;
        return 0;
    }

    return -ENOPROTOOPT;
}
예제 #20
0
파일: req.c 프로젝트: javarange/nanomsg
static int nn_req_setopt (struct nn_sockbase *self, int level, int option,
        const void *optval, size_t optvallen)
{
    struct nn_req *req;

    req = nn_cont (self, struct nn_req, xreq.sockbase);

    if (level != NN_REQ)
        return -ENOPROTOOPT;

    if (option == NN_REQ_RESEND_IVL) {
        if (nn_slow (optvallen != sizeof (int)))
            return -EINVAL;
        req->resend_ivl = *(int*) optval;
        return 0;
    }

    return -ENOPROTOOPT;
}
예제 #21
0
파일: dist.c 프로젝트: Droppe/nanomsg
int nn_dist_send (struct nn_dist *self, struct nn_msg *msg,
    struct nn_pipe *exclude)
{
    int rc;
    struct nn_list_item *it;
    struct nn_dist_data *data;
    struct nn_msg copy;

    /*  TODO: We can optimise for the case when there's only one outbound
        pipe here. No message copying is needed in such case. */

    /*  In the specific case when there are no outbound pipes. There's nowhere
        to send the message to. Deallocate it. */
    if (nn_slow (self->count) == 0) {
        nn_msg_term (msg);
        return 0;
    }

    /*  Send the message to all the subscribers. */
    nn_msg_bulkcopy_start (msg, self->count);
    it = nn_list_begin (&self->pipes);
    while (it != nn_list_end (&self->pipes)) {
       data = nn_cont (it, struct nn_dist_data, item);
       nn_msg_bulkcopy_cp (&copy, msg);
       if (nn_fast (data->pipe == exclude)) {
           nn_msg_term (&copy);
       }
       else {
           rc = nn_pipe_send (data->pipe, &copy);
           errnum_assert (rc >= 0, -rc);
           if (rc & NN_PIPE_RELEASE) {
               --self->count;
               it = nn_list_erase (&self->pipes, it);
               continue;
           }
       }
       it = nn_list_next (&self->pipes, it);
    }
    nn_msg_term (msg);

    return 0;
}
예제 #22
0
파일: ipc.c 프로젝트: Droppe/nanomsg
static int nn_ipc_connect (const char *addr, void *hint,
    struct nn_epbase **epbase)
{
    int rc;
    struct nn_cstream *cstream;

    /*  TODO: Check the syntax of the address here! */

    cstream = nn_alloc (sizeof (struct nn_cstream), "cstream (ipc)");
    alloc_assert (cstream);
    rc = nn_cstream_init (cstream, addr, hint, nn_ipc_csockinit,
        nn_ipc_cresolve);
    if (nn_slow (rc != 0)) {
        nn_free (cstream);
        return rc;
    }
    *epbase = &cstream->epbase;

    return 0;
}
예제 #23
0
파일: req.c 프로젝트: Neopallium/nanomsg
static void nn_req_timeout (const struct nn_cp_sink **self,
    struct nn_timer *timer)
{
    int rc;
    struct nn_req *req;
    struct nn_msg msg;

    req = nn_cont (self, struct nn_req, sink);
    nn_assert (req->state == NN_REQ_STATE_SENT);

    /*  Re-send the request. If it cannot be sent, just drop it. */
    nn_msg_cp (&msg, &req->request);
    rc = nn_xreq_send (&req->xreq.sockbase, &msg);
    errnum_assert (rc == 0 || rc == -EAGAIN, -rc);
    if (nn_slow (rc == -EAGAIN))
        nn_msg_term (&msg);

    /*  Set up the next re-send timer. */
    nn_timer_start (&req->resend_timer, req->resend_ivl);
}
예제 #24
0
int nn_req_getopt (struct nn_sockbase *self, int level, int option,
        void *optval, size_t *optvallen)
{
    struct nn_req *req;

    req = nn_cont (self, struct nn_req, xreq.sockbase);

    if (level != NN_REQ)
        return -ENOPROTOOPT;

    if (option == NN_REQ_RESEND_IVL) {
        if (nn_slow (*optvallen < sizeof (int)))
            return -EINVAL;
        *(int*) optval = req->resend_ivl;
        *optvallen = sizeof (int);
        return 0;
    }

    return -ENOPROTOOPT;
}
예제 #25
0
파일: tcp.c 프로젝트: Droppe/nanomsg
static int nn_tcp_connect (const char *addr, void *hint,
    struct nn_epbase **epbase)
{
    int rc;
    const char *end;
    const char *pos;
    struct nn_cstream *cstream;

    /*  Check the syntax of the address here. First, check whether port number
        is OK.  */
    end = addr + strlen (addr);
    pos = strrchr (addr, ':');
    if (!pos)
        return -EINVAL;
    ++pos;
    rc = nn_addr_parse_port (pos, end - pos);
    if (rc < 0)
        return rc;

    /*  Now check whether local address, in any, is valid. */
    pos = strchr (addr, ';');
    if (pos) {
        rc = nn_addr_parse_local (addr, pos - addr, NN_ADDR_IPV4ONLY,
            NULL, NULL);
        if (rc < 0)
            return rc;
    }

    /*  Create the async object to handle the connection. */
    cstream = nn_alloc (sizeof (struct nn_cstream), "cstream (tcp)");
    alloc_assert (cstream);
    rc = nn_cstream_init (cstream, addr, hint, nn_tcp_csockinit,
        nn_tcp_cresolve);
    if (nn_slow (rc != 0)) {
        nn_free (cstream);
        return rc;
    }
    *epbase = &cstream->epbase;

    return 0;
}
예제 #26
0
파일: global.c 프로젝트: DCEngines/nanomsg
int nn_connect (int s, const char *addr)
{
    int rc;
    struct nn_sock *sock;

    rc = nn_global_hold_socket (&sock, s);
    if (nn_slow (rc < 0)) {
        errno = -rc;
        return -1;
    }

    rc = nn_global_create_ep (sock, addr, 0);
    if (rc < 0) {
        nn_global_rele_socket (sock);
        errno = -rc;
        return -1;
    }

    nn_global_rele_socket (sock);
    return rc;
}
예제 #27
0
int nn_usock_bind (struct nn_usock *self, const struct sockaddr *addr,
    size_t addrlen)
{
    int rc;
    int opt;

    /*  The socket can be bound only before it's connected. */
    nn_assert_state (self, NN_USOCK_STATE_STARTING);

    /*  Allow re-using the address. */
    opt = 1;
    rc = setsockopt (self->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
    errno_assert (rc == 0);

    rc = bind (self->s, addr, (socklen_t) addrlen);
    //printf("usock.%d -> bind rc.%d errno.%d %s\n",self->s,rc,errno,nn_strerror(errno));
    if (nn_slow (rc != 0))
        return -errno;

    return 0;
}
예제 #28
0
파일: sock.c 프로젝트: SamuelRamond/nanomsg
int nn_sock_term (struct nn_sock *self)
{
    int rc;
    int i;

    /*  Ask the state machine to start closing the socket. */
    nn_ctx_enter (&self->ctx);
    nn_fsm_stop (&self->fsm);
    nn_ctx_leave (&self->ctx);

    /*  Shutdown process was already started but some endpoints may still
        alive. Here we are going to wait till they are all closed. */
    rc = nn_sem_wait (&self->termsem);
    if (nn_slow (rc == -EINTR))
        return -EINTR;
    errnum_assert (rc == 0, -rc);

    /*  The thread that posted the semaphore can still have the ctx locked
        for a short while. By simply entering the context and exiting it
        immediately we can be sure that the thread in question have already
        exited the context. */
    nn_ctx_enter (&self->ctx);
    nn_ctx_leave (&self->ctx);

    /*  Deallocate the resources. */
    nn_fsm_stopped_noevent (&self->fsm);
    nn_fsm_term (&self->fsm);
    nn_sem_term (&self->termsem);
    nn_list_term (&self->sdeps);
    nn_list_term (&self->eps);
    nn_clock_term (&self->clock);
    nn_ctx_term (&self->ctx);

    /*  Destroy any optsets associated with the socket. */
    for (i = 0; i != NN_MAX_TRANSPORT; ++i)
        if (self->optsets [i])
            self->optsets [i]->vfptr->destroy (self->optsets [i]);

    return 0;
}
예제 #29
0
/*  添加一项到hash 返回值 0 插入成功 非0 表示数据已经被更新*/
hash_item *nn_hash_set (hash *self, void *key, hash_item *item)
{
    hash_item *prev = NULL;
    hash_item *it;
    uint32_t i;

    nn_assert (item->next == NN_HASH_NOTINHASH);
    i = hash_key(self, key) % self->slots;

    item->key = key;
    for (it = self->array[i]; it != NULL; it = it->next) 
    {
        if(hash_compare_keys(self, key, it->key))
        {
            if(prev == NULL)
            {
                item->next = it->next;
                self->array[i] = item;
            }
            else
            {
                item->next = it->next;
                prev->next = item;
            }
            return it;
        }  
        prev = it;
    }

    item->next = self->array[i];
    self->array[i] = item;

    ++self->items;

    /*  If the hash is getting full, double the amount of slots and
        re-hash all the items. */
    if (nn_slow (self->items > self->slots * 2 && self->slots < 0x80000000))
        nn_hash_rehash(self);
    return 0;
}
예제 #30
0
static int nn_surveyor_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    struct nn_surveyor *surveyor;

    surveyor = nn_cont (self, struct nn_surveyor, xsurveyor.sockbase);

    /*  Generate new survey ID. */
    ++surveyor->surveyid;
    surveyor->surveyid |= 0x80000000;

    /*  Tag the survey body with survey ID. */
    nn_assert (nn_chunkref_size (&msg->sphdr) == 0);
    nn_chunkref_term (&msg->sphdr);
    nn_chunkref_init (&msg->sphdr, 4);
    nn_putl (nn_chunkref_data (&msg->sphdr), surveyor->surveyid);

    /*  Store the survey, so that it can be sent later on. */
    nn_msg_term (&surveyor->tosend);
    nn_msg_mv (&surveyor->tosend, msg);
    nn_msg_init (msg, 0);

    /*  Cancel any ongoing survey, if any. */
    if (nn_slow (nn_surveyor_inprogress (surveyor))) {

        /*  First check whether the survey can be sent at all. */
        if (!(nn_xsurveyor_events (&surveyor->xsurveyor.sockbase) &
              NN_SOCKBASE_EVENT_OUT))
            return -EAGAIN;

        /*  Cancel the current survey. */
        nn_fsm_action (&surveyor->fsm, NN_SURVEYOR_ACTION_CANCEL);

        return 0;
    }

    /*  Notify the state machine that the survey was started. */
    nn_fsm_action (&surveyor->fsm, NN_SURVEYOR_ACTION_START);

    return 0;
}