コード例 #1
0
ファイル: xsurveyor.c プロジェクト: javarange/nanomsg
int nn_xsurveyor_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_xsurveyor *xsurveyor;

    xsurveyor = nn_cont (self, struct nn_xsurveyor, sockbase);

    rc = nn_fq_recv (&xsurveyor->inpipes, msg, NULL);
    if (nn_slow (rc < 0))
        return rc;

    /*  Split the header from the body, if needed. */
    if (!(rc & NN_PIPE_PARSED)) {
        if (nn_slow (nn_chunkref_size (&msg->body) < sizeof (uint32_t))) {
            nn_msg_term (msg);
            return -EAGAIN;
        }
        nn_assert (nn_chunkref_size (&msg->hdr) == 0);
        nn_chunkref_term (&msg->hdr);
        nn_chunkref_init (&msg->hdr, sizeof (uint32_t));
        memcpy (nn_chunkref_data (&msg->hdr), nn_chunkref_data (&msg->body),
           sizeof (uint32_t));
        nn_chunkref_trim (&msg->body, sizeof (uint32_t));
    }

    return 0;
}
コード例 #2
0
ファイル: sipc.c プロジェクト: JadeHub/nanomsg
static int nn_sipc_send (struct nn_pipebase *self, struct nn_msg *msg)
{
    struct nn_sipc *sipc;
    struct nn_iovec iov [3];

    sipc = nn_cont (self, struct nn_sipc, pipebase);

    nn_assert (sipc->state == NN_SIPC_STATE_ACTIVE);
    nn_assert (sipc->outstate == NN_SIPC_OUTSTATE_IDLE);

    /*  Move the message to the local storage. */
    nn_msg_term (&sipc->outmsg);
    nn_msg_mv (&sipc->outmsg, msg);

    /*  Serialise the message header. */
    sipc->outhdr [0] = NN_SIPC_MSG_NORMAL;
    nn_putll (sipc->outhdr + 1, nn_chunkref_size (&sipc->outmsg.hdr) +
        nn_chunkref_size (&sipc->outmsg.body));

    /*  Start async sending. */
    iov [0].iov_base = sipc->outhdr;
    iov [0].iov_len = sizeof (sipc->outhdr);
    iov [1].iov_base = nn_chunkref_data (&sipc->outmsg.hdr);
    iov [1].iov_len = nn_chunkref_size (&sipc->outmsg.hdr);
    iov [2].iov_base = nn_chunkref_data (&sipc->outmsg.body);
    iov [2].iov_len = nn_chunkref_size (&sipc->outmsg.body);
    nn_usock_send (sipc->usock, iov, 3);

    sipc->outstate = NN_SIPC_OUTSTATE_SENDING;

    return 0;
}
コード例 #3
0
ファイル: xreq.c プロジェクト: ryanbaylorkillea/nanomsg
int nn_xreq_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;

    rc = nn_fq_recv (&nn_cont (self, struct nn_xreq, sockbase)->fq, msg, NULL);
    if (rc == -EAGAIN)
        return -EAGAIN;
    errnum_assert (rc >= 0, -rc);

    if (!(rc & NN_PIPE_PARSED)) {

        /*  Ignore malformed replies. */
        if (nn_slow (nn_chunkref_size (&msg->body) < sizeof (uint32_t))) {
            nn_msg_term (msg);
            return -EAGAIN;
        }

        /*  Split the message into the header and the body. */
        nn_assert (nn_chunkref_size (&msg->sphdr) == 0);
        nn_chunkref_term (&msg->sphdr);
        nn_chunkref_init (&msg->sphdr, sizeof (uint32_t));
        memcpy (nn_chunkref_data (&msg->sphdr), nn_chunkref_data (&msg->body),
            sizeof (uint32_t));
        nn_chunkref_trim (&msg->body, sizeof (uint32_t));
    }

    return 0;
}
コード例 #4
0
ファイル: msgqueue.c プロジェクト: 4Second2None/nanomsg
int nn_msgqueue_recv (struct nn_msgqueue *self, struct nn_msg *msg)
{
    struct nn_msgqueue_chunk *o;

    /*  If there is no message in the queue. */
    if (nn_slow (!self->count))
        return -EAGAIN;

    /*  Move the message from the pipe to the user. */
    nn_msg_mv (msg, &self->in.chunk->msgs [self->in.pos]);

    /*  Move to the next position. */
    ++self->in.pos;
    if (nn_slow (self->in.pos == NN_MSGQUEUE_GRANULARITY)) {
        o = self->in.chunk;
        self->in.chunk = self->in.chunk->next;
        self->in.pos = 0;
        if (nn_fast (!self->cache))
            self->cache = o;
        else
            nn_free (o);
    }

    /*  Adjust the statistics. */
    --self->count;
    self->mem -= (nn_chunkref_size (&msg->hdr) + nn_chunkref_size (&msg->body));

    return 0;
}
コード例 #5
0
ファイル: stcp.c プロジェクト: zakharov/nanomsg
static int nn_stcp_send (struct nn_pipebase *self, struct nn_msg *msg)
{
    struct nn_stcp *stcp;
    struct nn_iovec iov [3];

    stcp = nn_cont (self, struct nn_stcp, pipebase);
    nn_assert (stcp);

    nn_assert_state (stcp, NN_STCP_STATE_ACTIVE);
    nn_assert (stcp->outstate == NN_STCP_OUTSTATE_IDLE);

    /*  Move the message to the local storage. */
    nn_msg_term (&stcp->outmsg);
    nn_msg_mv (&stcp->outmsg, msg);

    /*  Serialise the message header. */
    nn_putll (stcp->outhdr, nn_chunkref_size (&stcp->outmsg.sphdr) +
        nn_chunkref_size (&stcp->outmsg.body));

    /*  Start async sending. */
    iov [0].iov_base = stcp->outhdr;
    iov [0].iov_len = sizeof (stcp->outhdr);
    iov [1].iov_base = nn_chunkref_data (&stcp->outmsg.sphdr);
    iov [1].iov_len = nn_chunkref_size (&stcp->outmsg.sphdr);
    iov [2].iov_base = nn_chunkref_data (&stcp->outmsg.body);
    iov [2].iov_len = nn_chunkref_size (&stcp->outmsg.body);
    nn_usock_send (stcp->usock, iov, 3);

    stcp->outstate = NN_STCP_OUTSTATE_SENDING;

    return 0;
}
コード例 #6
0
ファイル: chunkref.c プロジェクト: Neopallium/nanomsg
void nn_chunkref_cp (struct nn_chunkref *dst, struct nn_chunkref *src)
{
    /*  TODO: At the moment, copy is made. Do it via reference count. */
    nn_chunkref_init (dst, nn_chunkref_size (src));
    memcpy (nn_chunkref_data (dst), nn_chunkref_data (src),
        nn_chunkref_size (src));
}
コード例 #7
0
ファイル: stream.c プロジェクト: Droppe/nanomsg
static int nn_stream_send (struct nn_pipebase *self, struct nn_msg *msg)
{
    struct nn_stream *stream;
    struct nn_iobuf iov [3];

    stream = nn_cont (self, struct nn_stream, pipebase);

    /*  Mave the message to the local storage. */
    nn_msg_term (&stream->outmsg);
    nn_msg_mv (&stream->outmsg, msg);

    /*  Serialise the message header. */
    nn_putll (stream->outhdr, nn_chunkref_size (&stream->outmsg.hdr) +
        nn_chunkref_size (&stream->outmsg.body));

    /*  Start async sending. */
    iov [0].iov_base = stream->outhdr;
    iov [0].iov_len = sizeof (stream->outhdr);
    iov [1].iov_base = nn_chunkref_data (&stream->outmsg.hdr);
    iov [1].iov_len = nn_chunkref_size (&stream->outmsg.hdr);
    iov [2].iov_base = nn_chunkref_data (&stream->outmsg.body);
    iov [2].iov_len = nn_chunkref_size (&stream->outmsg.body);;
    nn_usock_send (stream->usock, iov, 3);

    return 0;
}
コード例 #8
0
ファイル: surveyor.c プロジェクト: Droppe/nanomsg
static int nn_surveyor_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_surveyor *surveyor;

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

    /*  Cancel any ongoing survey. */
    if (nn_slow (surveyor->flags & NN_SURVEYOR_INPROGRESS)) {
        surveyor->flags &= ~NN_SURVEYOR_INPROGRESS;
        nn_timer_stop (&surveyor->deadline_timer);
    }

    /*  Generate new survey ID. */
    ++surveyor->surveyid;

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

    /*  Send the survey. */
    rc = nn_xsurveyor_send (&surveyor->xsurveyor.sockbase, msg);
    errnum_assert (rc == 0, -rc);

    surveyor->flags |= NN_SURVEYOR_INPROGRESS;

    /*  Set up the re-send timer. */
    nn_timer_start (&surveyor->deadline_timer, surveyor->deadline);

    return 0;
}
コード例 #9
0
ファイル: xsub.c プロジェクト: 4ker/nanomsg
static int nn_xsub_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_xsub *xsub;

    xsub = nn_cont (self, struct nn_xsub, sockbase);

    /*  Loop while a matching message is found or when there are no more
        messages to receive. */
    while (1) {
        rc = nn_fq_recv (&xsub->fq, msg, NULL);
        if (nn_slow (rc == -EAGAIN))
            return -EAGAIN;
        errnum_assert (rc >= 0, -rc);
        rc = nn_trie_match (&xsub->trie, nn_chunkref_data (&msg->body),
            nn_chunkref_size (&msg->body));
        if (rc == 0) {
            nn_msg_term (msg);
            continue;
        }
        if (rc == 1)
            return 0;
        errnum_assert (0, -rc);
    }
}
コード例 #10
0
ファイル: xbus.c プロジェクト: WongTai/nanomsg
int nn_xbus_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_xbus *xbus;
    struct nn_pipe *pipe;

    xbus = nn_cont (self, struct nn_xbus, sockbase);

    while (1) {

        /*  Get next message in fair-queued manner. */
        rc = nn_fq_recv (&xbus->inpipes, msg, &pipe);
        if (nn_slow (rc < 0))
            return rc;

        /*  The message should have no header. Drop malformed messages. */
        if (nn_chunkref_size (&msg->hdr) == 0)
            break;
        nn_msg_term (msg);
    }

    /*  Add pipe ID to the message header. */
    nn_chunkref_term (&msg->hdr);
    nn_chunkref_init (&msg->hdr, sizeof (uint64_t));
    memset (nn_chunkref_data (&msg->hdr), 0, sizeof (uint64_t));
    memcpy (nn_chunkref_data (&msg->hdr), &pipe, sizeof (pipe));

    return 0;
}
コード例 #11
0
ファイル: respondent.c プロジェクト: ryanbaylorkillea/nanomsg
static int nn_respondent_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_respondent *respondent;

    respondent = nn_cont (self, struct nn_respondent, xrespondent.sockbase);

    /*  Cancel current survey, if it exists. */
    respondent->flags &= ~NN_RESPONDENT_INPROGRESS;

    /*  Get next survey. */
    rc = nn_xrespondent_recv (&respondent->xrespondent.sockbase, msg);
    if (nn_slow (rc == -EAGAIN))
        return -EAGAIN;
    errnum_assert (rc == 0, -rc);

    /*  Remember the survey ID. */
    nn_assert (nn_chunkref_size (&msg->sphdr) == sizeof (uint32_t));
    respondent->surveyid = nn_getl (nn_chunkref_data (&msg->sphdr));
    nn_chunkref_term (&msg->sphdr);
    nn_chunkref_init (&msg->sphdr, 0);

    /*  Remember that survey is being processed. */
    respondent->flags |= NN_RESPONDENT_INPROGRESS;

    return 0;
}
コード例 #12
0
ファイル: respondent.c プロジェクト: ryanbaylorkillea/nanomsg
static int nn_respondent_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_respondent *respondent;

    respondent = nn_cont (self, struct nn_respondent, xrespondent.sockbase);

    /*  If there's no survey going on, report EFSM error. */
    if (nn_slow (!(respondent->flags & NN_RESPONDENT_INPROGRESS)))
        return -EFSM;

    /*  Tag the message 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), respondent->surveyid);

    /*  Try to send the message. If it cannot be sent due to pushback, drop it
        silently. */
    rc = nn_xrespondent_send (&respondent->xrespondent.sockbase, msg);
    if (nn_slow (rc == -EAGAIN)) {
        nn_msg_term (msg);
        return -EAGAIN;
    }
    errnum_assert (rc == 0, -rc);

    /*  Remember that no survey is being processed. */
    respondent->flags &= ~NN_RESPONDENT_INPROGRESS;

    return 0;
}
コード例 #13
0
ファイル: global.c プロジェクト: Amaury/AngstromDB
int nn_recv (int s, void *buf, size_t len, int flags)
{
    int rc;
    struct nn_msg msg;
    size_t sz;
    void *chunk;

    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) {
        chunk = nn_chunkref_getchunk (&msg.body);
        *(void**) buf = chunk;
        sz = nn_chunk_size (chunk);
    }
    else {
        sz = nn_chunkref_size (&msg.body);
        memcpy (buf, nn_chunkref_data (&msg.body), len < sz ? len : sz);
    }
    nn_msg_term (&msg);

    return (int) sz;
}
コード例 #14
0
ファイル: xrespondent.c プロジェクト: javarange/nanomsg
int nn_xrespondent_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_xrespondent *xrespondent;

    xrespondent = nn_cont (self, struct nn_xrespondent, sockbase);

    /*  Get the survey. */
    rc = nn_excl_recv (&xrespondent->excl, msg);
    if (rc == -EAGAIN)
        return -EAGAIN;
    errnum_assert (rc >= 0, -rc);

    /*  Split the survey ID from the body, if needed. */
    if (!(rc & NN_PIPE_PARSED)) {
        if (nn_slow (nn_chunkref_size (&msg->body) < sizeof (uint32_t))) {
            nn_msg_term (msg);
            return -EAGAIN;
        }
        nn_chunkref_term (&msg->hdr);
        nn_chunkref_init (&msg->hdr, sizeof (uint32_t));
        memcpy (nn_chunkref_data (&msg->hdr), nn_chunkref_data (&msg->body),
            sizeof (uint32_t));
        nn_chunkref_trim (&msg->body, sizeof (uint32_t));
    }

    return 0;
}
コード例 #15
0
ファイル: req.c プロジェクト: ryanbaylorkillea/nanomsg
void nn_req_in (struct nn_sockbase *self, struct nn_pipe *pipe)
{
    int rc;
    struct nn_req *req;
    uint32_t reqid;

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

    /*  Pass the pipe to the raw REQ socket. */
    nn_xreq_in (&req->xreq.sockbase, pipe);

    while (1) {

        /*  Get new reply. */
        rc = nn_xreq_recv (&req->xreq.sockbase, &req->task.reply);
        if (nn_slow (rc == -EAGAIN))
            return;
        errnum_assert (rc == 0, -rc);

        /*  No request was sent. Getting a reply doesn't make sense. */
        if (nn_slow (!nn_req_inprogress (req))) {
            nn_msg_term (&req->task.reply);
            continue;
        }

        /*  Ignore malformed replies. */
        if (nn_slow (nn_chunkref_size (&req->task.reply.sphdr) !=
              sizeof (uint32_t))) {
            nn_msg_term (&req->task.reply);
            continue;
        }

        /*  Ignore replies with incorrect request IDs. */
        reqid = nn_getl (nn_chunkref_data (&req->task.reply.sphdr));
        if (nn_slow (!(reqid & 0x80000000))) {
            nn_msg_term (&req->task.reply);
            continue;
        }
        if (nn_slow (reqid != (req->task.id | 0x80000000))) {
            nn_msg_term (&req->task.reply);
            continue;
        }

        /*  Trim the request ID. */
        nn_chunkref_term (&req->task.reply.sphdr);
        nn_chunkref_init (&req->task.reply.sphdr, 0);

        /*  TODO: Deallocate the request here? */

        /*  Notify the state machine. */
        if (req->state == NN_REQ_STATE_ACTIVE)
            nn_fsm_action (&req->fsm, NN_REQ_ACTION_IN);

        return;
    }
}
コード例 #16
0
ファイル: req.c プロジェクト: Neopallium/nanomsg
static void nn_req_in (struct nn_sockbase *self, struct nn_pipe *pipe)
{
    int rc;
    struct nn_req *req;
    uint32_t reqid;

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

    /*  Pass the pipe to the raw REQ socket. */
    nn_xreq_in (&req->xreq.sockbase, pipe);

    while (1) {

        /*  Get new reply. */
        rc = nn_xreq_recv (&req->xreq.sockbase, &req->reply);
        if (nn_slow (rc == -EAGAIN))
            return;
        errnum_assert (rc == 0, -rc);

        /*  No request was sent. Getting a reply doesn't make sense. */
        if (nn_slow (req->state != NN_REQ_STATE_SENT)) {
            nn_msg_term (&req->reply);
            continue;
        }

        /*  Ignore malformed replies. */
        if (nn_slow (nn_chunkref_size (&req->reply.hdr) != sizeof (uint32_t))) {
            nn_msg_term (&req->reply);
            continue;
        }

        /*  Ignore replies with incorrect request IDs. */
        reqid = nn_getl (nn_chunkref_data (&req->reply.hdr));
        if (nn_slow (!(reqid & 0x80000000))) {
            nn_msg_term (&req->reply);
            continue;
        }
        if (nn_slow (reqid != (req->reqid | 0x80000000))) {
            nn_msg_term (&req->reply);
            continue;
        }

        /*  Trim the request ID. */
        nn_chunkref_term (&req->reply.hdr);
        nn_chunkref_init (&req->reply.hdr, 0);

        /*  Swtich to RECEIVED state. */
        nn_timer_stop (&req->resend_timer);
        nn_msg_term (&req->request);
        req->state = NN_REQ_STATE_RECEIVED;

        return;
    }
}
コード例 #17
0
ファイル: msgqueue.c プロジェクト: 4Second2None/nanomsg
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;
}
コード例 #18
0
ファイル: req.c プロジェクト: Neopallium/nanomsg
static int nn_req_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_req *req;

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

    /*  If there's a request in progress, cancel it. */
    if (nn_slow (req->state != NN_REQ_STATE_IDLE)) {
        if (req->state == NN_REQ_STATE_UNSENT ||
              req->state == NN_REQ_STATE_SENT)
            nn_msg_term (&req->request);
        if (req->state == NN_REQ_STATE_RECEIVED)
            nn_msg_term (&req->reply);
        nn_timer_term (&req->resend_timer);
        req->state = NN_REQ_STATE_IDLE;
    }

    /*  Generate new request ID for the new request and put it into message
        header. The most important bit is set to 1 to indicate that this is
        the bottom of the backtrace stack. */
    ++req->reqid;
    nn_assert (nn_chunkref_size (&msg->hdr) == 0);
    nn_chunkref_term (&msg->hdr);
    nn_chunkref_init (&msg->hdr, 4);
    nn_putl (nn_chunkref_data (&msg->hdr), req->reqid | 0x80000000);

    /*  Store the message so that it can be re-sent if there's no reply. 
        Then make a copy of it and send it. */
    nn_msg_cp (&req->request, msg);
    rc = nn_xreq_send (&req->xreq.sockbase, msg);
    errnum_assert (rc == 0 || rc == -EAGAIN, -rc);

    /*  If the request cannot be sent at the moment switch to UNSENT state.
        It will be sent as soon as a new outbound pipe arrives. */
    if (nn_slow (rc == -EAGAIN)) {
        nn_msg_term (msg);
        req->state = NN_REQ_STATE_UNSENT;
        return 0;
    }

    /*  If the request was successgfully sent set up the re-send timer in case
        it get lost somewhere further out in the topology. */
    nn_timer_start (&req->resend_timer, req->resend_ivl);
    req->state = NN_REQ_STATE_SENT;

    return 0;
}
コード例 #19
0
ファイル: xbus.c プロジェクト: WongTai/nanomsg
int nn_xbus_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    size_t hdrsz;
    struct nn_pipe *exclude;

    hdrsz = nn_chunkref_size (&msg->hdr);
    if (hdrsz == 0)
        exclude = NULL;
    else if (hdrsz == sizeof (uint64_t)) {
        memcpy (&exclude, nn_chunkref_data (&msg->hdr), sizeof (exclude));
        nn_chunkref_term (&msg->hdr);
        nn_chunkref_init (&msg->hdr, 0);
    }
    else
        return -EINVAL;

    return nn_dist_send (&nn_cont (self, struct nn_xbus, sockbase)->outpipes,
        msg, exclude);
}
コード例 #20
0
ファイル: surveyor.c プロジェクト: Granoia/cacheBench
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))) {
        if (surveyor->timedout == NN_SURVEYOR_TIMEDOUT) {
            surveyor->timedout = 0;
            return -ETIMEDOUT;
        } else
            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->sphdr) != sizeof (uint32_t)))
            continue;
        surveyid = nn_getl (nn_chunkref_data (&msg->sphdr));
        if (nn_slow (surveyid != surveyor->surveyid))
            continue;

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

    return 0;
}
コード例 #21
0
ファイル: surveyor.c プロジェクト: Granoia/cacheBench
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;
}
コード例 #22
0
ファイル: surveyor.c プロジェクト: Droppe/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 (!(surveyor->flags & NN_SURVEYOR_INPROGRESS)))
       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. */
        if (nn_slow (nn_chunkref_size (&msg->hdr) != sizeof (uint32_t))) {
            nn_msg_term (msg);
            continue;
        }
        surveyid = nn_getl (nn_chunkref_data (&msg->hdr));
        if (nn_slow (surveyid != surveyor->surveyid)) {
            nn_msg_term (msg);
            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;
}
コード例 #23
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;
}
コード例 #24
0
ファイル: req.c プロジェクト: javarange/nanomsg
static int nn_req_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    struct nn_req *req;

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

    /*  Generate new request ID for the new request and put it into message
        header. The most important bit is set to 1 to indicate that this is
        the bottom of the backtrace stack. */
    ++req->reqid;
    nn_assert (nn_chunkref_size (&msg->hdr) == 0);
    nn_chunkref_term (&msg->hdr);
    nn_chunkref_init (&msg->hdr, 4);
    nn_putl (nn_chunkref_data (&msg->hdr), req->reqid | 0x80000000);

    /*  Store the message so that it can be re-sent if there's no reply. */
    nn_msg_term (&req->request);
    nn_msg_mv (&req->request, msg);

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

    return 0;
}
コード例 #25
0
ファイル: rep.c プロジェクト: huyubing/nanomsg
int nn_rep_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_rep *rep;

    rep = nn_cont (self, struct nn_rep, xrep.sockbase);

    /*  If no request was received, there's nowhere to send the reply to. */
    if (nn_slow (!(rep->flags & NN_REP_INPROGRESS)))
        return -EFSM;

    /*  Move the stored backtrace into the message header. */
    nn_assert (nn_chunkref_size (&msg->sphdr) == 0);
    nn_chunkref_term (&msg->sphdr);
    nn_chunkref_mv (&msg->sphdr, &rep->backtrace);
    rep->flags &= ~NN_REP_INPROGRESS;

    /*  Send the reply. If it cannot be sent because of pushback,
        drop it silently. */
    rc = nn_xrep_send (&rep->xrep.sockbase, msg);
    errnum_assert (rc == 0 || rc == -EAGAIN, -rc);

    return 0;
}
コード例 #26
0
ファイル: cws.c プロジェクト: 4ker/nanomsg
static void nn_cws_start_connecting (struct nn_cws *self,
    struct sockaddr_storage *ss, size_t sslen)
{
    int rc;
    struct sockaddr_storage remote;
    size_t remotelen;
    struct sockaddr_storage local;
    size_t locallen;
    int ipv4only;
    size_t ipv4onlylen;
    int val;
    size_t sz;

    memset (&remote, 0, sizeof (remote));
    memset (&local, 0, sizeof (local));

    /*  Check whether IPv6 is to be used. */
    ipv4onlylen = sizeof (ipv4only);
    nn_epbase_getopt (&self->epbase, NN_SOL_SOCKET, NN_IPV4ONLY,
        &ipv4only, &ipv4onlylen);
    nn_assert (ipv4onlylen == sizeof (ipv4only));

    rc = nn_iface_resolve (nn_chunkref_data (&self->nic),
    nn_chunkref_size (&self->nic), ipv4only, &local, &locallen);

    if (nn_slow (rc < 0)) {
        nn_backoff_start (&self->retry);
        self->state = NN_CWS_STATE_WAITING;
        return;
    }

    /*  Combine the remote address and the port. */
    remote = *ss;
    remotelen = sslen;
    if (remote.ss_family == AF_INET)
        ((struct sockaddr_in*) &remote)->sin_port = htons (self->remote_port);
    else if (remote.ss_family == AF_INET6)
        ((struct sockaddr_in6*) &remote)->sin6_port = htons (self->remote_port);
    else
        nn_assert (0);

    /*  Try to start the underlying socket. */
    rc = nn_usock_start (&self->usock, remote.ss_family, SOCK_STREAM, 0);
    if (nn_slow (rc < 0)) {
        nn_backoff_start (&self->retry);
        self->state = NN_CWS_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));

    /*  Bind the socket to the local network interface. */
    rc = nn_usock_bind (&self->usock, (struct sockaddr*) &local, locallen);
    if (nn_slow (rc != 0)) {
        nn_backoff_start (&self->retry);
        self->state = NN_CWS_STATE_WAITING;
        return;
    }

    /*  Start connecting. */
    nn_usock_connect (&self->usock, (struct sockaddr*) &remote, remotelen);
    self->state = NN_CWS_STATE_CONNECTING;
    nn_epbase_stat_increment (&self->epbase,
        NN_STAT_INPROGRESS_CONNECTIONS, 1);
}
コード例 #27
0
ファイル: sws.c プロジェクト: threatstack/nanomsg
/*  Start sending a message. */
static int nn_sws_send (struct nn_pipebase *self, struct nn_msg *msg)
{
    struct nn_sws *sws;
    struct nn_iovec iov [3];
    int mask_pos;
    size_t sz;
    size_t hdrsz;
    uint8_t mask [4];

    sws = nn_cont (self, struct nn_sws, pipebase);

    nn_assert_state (sws, NN_SWS_STATE_ACTIVE);
    nn_assert (sws->outstate == NN_SWS_OUTSTATE_IDLE);

    /*  Move the message to the local storage. */
    nn_msg_term (&sws->outmsg);
    nn_msg_mv (&sws->outmsg, msg);

    /*  Compose the message header. See RFC 6455, section 5.2. */

    /*  Messages are always sent in a single fragment.
        They may be split up on the way to the peer though. */
    sws->outhdr [0] = NN_WS_OPCODE_BINARY | NN_SWS_FRAME_BITMASK_FIN;
    hdrsz = 1;
    
    /*  Frame the payload size. Don't set the mask bit yet. */
    sz = nn_chunkref_size (&sws->outmsg.sphdr) +
        nn_chunkref_size (&sws->outmsg.body);
    if (sz <= 0x7d) {
        sws->outhdr [1] = (uint8_t) sz;
        hdrsz += 1;
    }
    else if (sz <= 0xffff) {
        sws->outhdr [1] = 0x7e;
        nn_puts (&sws->outhdr [2], (uint16_t) sz);
        hdrsz += 3;
    }
    else {
        sws->outhdr [1] = 0x7f;
        nn_putll (&sws->outhdr [2], (uint64_t) sz);
        hdrsz += 9;
    }

    /*  Client-to-server communication has to be masked. See RFC 6455 5.3. */
    if (sws->mode == NN_WS_CLIENT) {

        /*  Generate 32-bit mask and store it in the frame. */
        /*  TODO: This is not a strong source of entropy. However, can we
            afford one wihout exhausting all the available entropy in the
            system at the high message rates? */
        nn_random_generate (mask, 4);
        sws->outhdr [1] |= NN_SWS_FRAME_BITMASK_MASKED;
        memcpy (&sws->outhdr [hdrsz], mask, 4);
        hdrsz += 4;

        /*  Mask payload, beginning with header and moving to body. */
        /*  TODO: This won't work if the message is shared among muliple
                   transports. We probably want to send the message in multiple
                   operations, masking only as much data at a time. */
        mask_pos = 0;
        nn_sws_mask_payload (nn_chunkref_data (&sws->outmsg.sphdr),
            nn_chunkref_size (&sws->outmsg.sphdr), mask, &mask_pos);
        nn_sws_mask_payload (nn_chunkref_data (&sws->outmsg.body),
            nn_chunkref_size (&sws->outmsg.body), mask, &mask_pos);
    }

    /*  Start async sending. */
    iov [0].iov_base = sws->outhdr;
    iov [0].iov_len = hdrsz;
    iov [1].iov_base = nn_chunkref_data (&sws->outmsg.sphdr);
    iov [1].iov_len = nn_chunkref_size (&sws->outmsg.sphdr);
    iov [2].iov_base = nn_chunkref_data (&sws->outmsg.body);
    iov [2].iov_len = nn_chunkref_size (&sws->outmsg.body);
    nn_usock_send (sws->usock, iov, 3);

    sws->outstate = NN_SWS_OUTSTATE_SENDING;

    /*  If a Close handshake was just sent, it's time to shut down. */
    if ((sws->outhdr [0] & NN_SWS_FRAME_BITMASK_OPCODE) ==
        NN_WS_OPCODE_CLOSE) {
        nn_pipebase_stop (&sws->pipebase);
        sws->state = NN_SWS_STATE_CLOSING_CONNECTION;
    }

    return 0;
}
コード例 #28
0
ファイル: sws.c プロジェクト: threatstack/nanomsg
static int nn_sws_recv (struct nn_pipebase *self, struct nn_msg *msg)
{
    struct nn_sws *sws;
    struct nn_iovec iov [1];
    struct nn_list_item *it;
    struct msg_chunk *ch;
    int pos;
    size_t len;

    sws = nn_cont (self, struct nn_sws, pipebase);

    nn_assert_state (sws, NN_SWS_STATE_ACTIVE);

    switch (sws->instate) {
    case NN_SWS_INSTATE_FAILING:

        /*  Prevent further send/recv operations on this connection. */
        nn_pipebase_stop (self);
        sws->instate = NN_SWS_INSTATE_CLOSED;

        /*  Inform user this connection has been failed. */
        nn_msg_init (msg, 1);
        *(uint8_t *) nn_chunkref_data (&msg->body) = 0x7f |
            NN_SWS_FRAME_BITMASK_FIN;

        iov [0].iov_base = sws->fail_msg;
        iov [0].iov_len = sws->fail_msg_len;

        /*  TODO: Consider queueing and unconditionally sending close
            handshake rather than skipping it. */
        /*  RFC 6455 7.1.7 - try to send helpful Closing Handshake only if
            the socket is not currently sending. If it's still busy sending,
            forcibly close this connection, since it's not readily deterministic
            how much time that action could take to complete, or if the peer is
            even healthy enough to receive. Rationale: try to be nice, but be
            mindful of self-preservation! */
        if (sws->outstate == NN_SWS_OUTSTATE_IDLE) {
            nn_usock_send (sws->usock, iov, 1);
            sws->outstate = NN_SWS_OUTSTATE_SENDING;
            sws->state = NN_SWS_STATE_CLOSING_CONNECTION;
        }
        else {
            sws->state = NN_SWS_STATE_DONE;
            nn_fsm_raise (&sws->fsm, &sws->done,
                NN_SWS_RETURN_CLOSE_HANDSHAKE);
        }
        return 0;
    
    case NN_SWS_INSTATE_RECVD_CHUNKED:

        /*  This library should not deliver fragmented messages to the
            application, so it's expected that this is the final frame. */
        nn_assert (sws->is_final_frame);

        len = sws->inmsg_total_size;

        nn_msg_init (msg, len);

        /*  Reassemble incoming message scatter array. */
        while (!nn_list_empty (&sws->inmsg_array)) {
            it = nn_list_begin (&sws->inmsg_array);
            ch = nn_cont (it, struct msg_chunk, item);
            memcpy (((uint8_t*) nn_chunkref_data (&msg->body)) + pos,
                nn_chunkref_data (&ch->chunk),
                nn_chunkref_size (&ch->chunk));
            pos += nn_chunkref_size (&ch->chunk);
            nn_msg_chunk_term (ch, &sws->inmsg_array);
        }

        nn_assert (pos == len);
        nn_assert (nn_list_empty (&sws->inmsg_array));

        /*  No longer collecting scatter array of incoming msg chunks. */
        sws->continuing = 0;

        nn_sws_recv_hdr (sws);

        return 0;

    case NN_SWS_INSTATE_RECVD_CONTROL:

        /*  This library should not deliver fragmented messages to the user, so
        it's expected that this is the final frame. */
        nn_assert (sws->is_final_frame);

        len = sws->inmsg_current_chunk_len + sizeof (sws->inmsg_hdr);

        nn_msg_init (msg, len);

        /*  Relay opcode, RSV and FIN bits to the user in order to
            interpret payload. */
        memcpy (nn_chunkref_data (&msg->body),
            &sws->inhdr, sizeof (sws->inmsg_hdr));
        pos = sizeof (sws->inmsg_hdr);

        memcpy (((uint8_t*) nn_chunkref_data (&msg->body)) + pos,
            sws->inmsg_control, sws->inmsg_current_chunk_len);

        /*  If a closing handshake was just transferred to the application,
            discontinue continual, async receives. */
        if (sws->opcode == NN_WS_OPCODE_CLOSE) {
            sws->instate = NN_SWS_INSTATE_CLOSED;
        }
        else {
            nn_sws_recv_hdr (sws);
        }

        return 0;

    default:
        /*  Unexpected state. */
        nn_assert (0);
        return 0;
    }
}
コード例 #29
0
ファイル: global.c プロジェクト: Amaury/AngstromDB
int nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags)
{
    int rc;
    struct nn_msg msg;
    uint8_t *data;
    size_t sz;
    int i;
    struct nn_iovec *iov;
    void *chunk;

    NN_BASIC_CHECKS;

    if (nn_slow (!msghdr)) {
        errno = EINVAL;
        return -1;
    }

    if (nn_slow (msghdr->msg_iovlen < 0)) {
        errno = EMSGSIZE;
        return -1;
    }

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

    if (msghdr->msg_iovlen == 1 && msghdr->msg_iov [0].iov_len == NN_MSG) {
        chunk = nn_chunkref_getchunk (&msg.body);
        *(void**) (msghdr->msg_iov [0].iov_base) = chunk;
        sz = nn_chunk_size (chunk);
    }
    else {

        /*  Copy the message content into the supplied gather array. */
        data = nn_chunkref_data (&msg.body);
        sz = nn_chunkref_size (&msg.body);
        for (i = 0; i != msghdr->msg_iovlen; ++i) {
            iov = &msghdr->msg_iov [i];
            if (nn_slow (iov->iov_len == NN_MSG)) {
                nn_msg_term (&msg);
                errno = EINVAL;
                return -1;
            }
            if (iov->iov_len > sz) {
                memcpy (iov->iov_base, data, sz);
                break;
            }
            memcpy (iov->iov_base, data, iov->iov_len);
            data += iov->iov_len;
            sz -= iov->iov_len;
        }
        sz = nn_chunkref_size (&msg.body);
    }

    /*  Retrieve the ancillary data from the message. */
    if (msghdr->msg_control) {
        if (msghdr->msg_controllen == NN_MSG) {
            chunk = nn_chunkref_getchunk (&msg.hdr);
            *((void**) msghdr->msg_control) = chunk;
        }
        else {

            /*  TODO: Copy the data to the supplied buffer, prefix them
                with size. */
            nn_assert (0);
        }   
    }

    nn_msg_term (&msg);

    return (int) sz;
}
コード例 #30
0
ファイル: global.c プロジェクト: TTimo/nanomsg
int nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags)
{
    int rc;
    struct nn_msg msg;
    uint8_t *data;
    size_t sz;
    int i;
    struct nn_iovec *iov;
    void *chunk;
    size_t hdrssz;
    void *ctrl;
    size_t ctrlsz;
    size_t spsz;
    size_t sptotalsz;
    struct nn_cmsghdr *chdr;

    NN_BASIC_CHECKS;

    if (nn_slow (!msghdr)) {
        errno = EINVAL;
        return -1;
    }

    if (nn_slow (msghdr->msg_iovlen < 0)) {
        errno = EMSGSIZE;
        return -1;
    }

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

    if (msghdr->msg_iovlen == 1 && msghdr->msg_iov [0].iov_len == NN_MSG) {
        chunk = nn_chunkref_getchunk (&msg.body);
        *(void**) (msghdr->msg_iov [0].iov_base) = chunk;
        sz = nn_chunk_size (chunk);
    }
    else {

        /*  Copy the message content into the supplied gather array. */
        data = nn_chunkref_data (&msg.body);
        sz = nn_chunkref_size (&msg.body);
        for (i = 0; i != msghdr->msg_iovlen; ++i) {
            iov = &msghdr->msg_iov [i];
            if (nn_slow (iov->iov_len == NN_MSG)) {
                nn_msg_term (&msg);
                errno = EINVAL;
                return -1;
            }
            if (iov->iov_len > sz) {
                memcpy (iov->iov_base, data, sz);
                break;
            }
            memcpy (iov->iov_base, data, iov->iov_len);
            data += iov->iov_len;
            sz -= iov->iov_len;
        }
        sz = nn_chunkref_size (&msg.body);
    }

    /*  Retrieve the ancillary data from the message. */
    if (msghdr->msg_control) {

        spsz = nn_chunkref_size (&msg.sphdr);
        sptotalsz = NN_CMSG_SPACE (spsz);
        ctrlsz = sptotalsz + nn_chunkref_size (&msg.hdrs);

        if (msghdr->msg_controllen == NN_MSG) {

            /* Allocate the buffer. */
            rc = nn_chunk_alloc (ctrlsz, 0, &ctrl);
            errnum_assert (rc == 0, -rc);

            /* Set output parameters. */
            *((void**) msghdr->msg_control) = ctrl;
        }
        else {

            /* Just use the buffer supplied by the user. */
            ctrl = msghdr->msg_control;
            ctrlsz = msghdr->msg_controllen;
        }

        /* If SP header alone won't fit into the buffer, return no ancillary
           properties. */
        if (ctrlsz >= sptotalsz) {

            /*  Fill in SP_HDR ancillary property. */
            chdr = (struct nn_cmsghdr*) ctrl;
            chdr->cmsg_len = sptotalsz;
            chdr->cmsg_level = PROTO_SP;
            chdr->cmsg_type = SP_HDR;
            memcpy (chdr + 1, nn_chunkref_data (&msg.sphdr), spsz);

            /*  Fill in as many remaining properties as possible.
                Truncate the trailing properties if necessary. */
            hdrssz = nn_chunkref_size (&msg.hdrs);
            if (hdrssz > ctrlsz - sptotalsz)
                hdrssz = ctrlsz - sptotalsz;
            memcpy (((char*) ctrl) + sptotalsz,
                nn_chunkref_data (&msg.hdrs), hdrssz);
        }
    }

    nn_msg_term (&msg);

    return (int) sz;
}