Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
/*  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;
}