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; }
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; }
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; }
/* 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; }