summaryrefslogtreecommitdiffstats
path: root/external_libs/python/pyzmq-14.7.0/bundled/zeromq/src/stream_engine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'external_libs/python/pyzmq-14.7.0/bundled/zeromq/src/stream_engine.cpp')
-rw-r--r--external_libs/python/pyzmq-14.7.0/bundled/zeromq/src/stream_engine.cpp960
1 files changed, 0 insertions, 960 deletions
diff --git a/external_libs/python/pyzmq-14.7.0/bundled/zeromq/src/stream_engine.cpp b/external_libs/python/pyzmq-14.7.0/bundled/zeromq/src/stream_engine.cpp
deleted file mode 100644
index 87186cc0..00000000
--- a/external_libs/python/pyzmq-14.7.0/bundled/zeromq/src/stream_engine.cpp
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- Copyright (c) 2007-2015 Contributors as noted in the AUTHORS file
-
- This file is part of libzmq, the ZeroMQ core engine in C++.
-
- libzmq is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License (LGPL) as published
- by the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- As a special exception, the Contributors give you permission to link
- this library with independent modules to produce an executable,
- regardless of the license terms of these independent modules, and to
- copy and distribute the resulting executable under terms of your choice,
- provided that you also meet, for each linked independent module, the
- terms and conditions of the license of that module. An independent
- module is a module which is not derived from or based on this library.
- If you modify this library, you must extend this exception to your
- version of the library.
-
- libzmq is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "platform.hpp"
-#if defined ZMQ_HAVE_WINDOWS
-#include "windows.hpp"
-#else
-#include <unistd.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/tcp.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <fcntl.h>
-#if defined ZMQ_HAVE_OPENBSD
-#define ucred sockpeercred
-#endif
-#endif
-
-#include <string.h>
-#include <new>
-#include <sstream>
-#include <iostream>
-
-#include "stream_engine.hpp"
-#include "io_thread.hpp"
-#include "session_base.hpp"
-#include "v1_encoder.hpp"
-#include "v1_decoder.hpp"
-#include "v2_encoder.hpp"
-#include "v2_decoder.hpp"
-#include "null_mechanism.hpp"
-#include "plain_client.hpp"
-#include "plain_server.hpp"
-#include "gssapi_client.hpp"
-#include "gssapi_server.hpp"
-#include "curve_client.hpp"
-#include "curve_server.hpp"
-#include "raw_decoder.hpp"
-#include "raw_encoder.hpp"
-#include "config.hpp"
-#include "err.hpp"
-#include "ip.hpp"
-#include "tcp.hpp"
-#include "likely.hpp"
-#include "wire.hpp"
-
-zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_,
- const std::string &endpoint_) :
- s (fd_),
- inpos (NULL),
- insize (0),
- decoder (NULL),
- outpos (NULL),
- outsize (0),
- encoder (NULL),
- metadata (NULL),
- handshaking (true),
- greeting_size (v2_greeting_size),
- greeting_bytes_read (0),
- session (NULL),
- options (options_),
- endpoint (endpoint_),
- plugged (false),
- next_msg (&stream_engine_t::identity_msg),
- process_msg (&stream_engine_t::process_identity_msg),
- io_error (false),
- subscription_required (false),
- mechanism (NULL),
- input_stopped (false),
- output_stopped (false),
- has_handshake_timer (false),
- socket (NULL)
-{
- int rc = tx_msg.init ();
- errno_assert (rc == 0);
-
- // Put the socket into non-blocking mode.
- unblock_socket (s);
-
- int family = get_peer_ip_address (s, peer_address);
- if (family == 0)
- peer_address.clear();
-#if defined ZMQ_HAVE_SO_PEERCRED
- else
- if (family == PF_UNIX) {
- struct ucred cred;
- socklen_t size = sizeof (cred);
- if (!getsockopt (s, SOL_SOCKET, SO_PEERCRED, &cred, &size)) {
- std::ostringstream buf;
- buf << ":" << cred.uid << ":" << cred.gid << ":" << cred.pid;
- peer_address += buf.str ();
- }
- }
-#elif defined ZMQ_HAVE_LOCAL_PEERCRED
- else
- if (family == PF_UNIX) {
- struct xucred cred;
- socklen_t size = sizeof (cred);
- if (!getsockopt (s, 0, LOCAL_PEERCRED, &cred, &size)
- && cred.cr_version == XUCRED_VERSION) {
- std::ostringstream buf;
- buf << ":" << cred.cr_uid << ":";
- if (cred.cr_ngroups > 0)
- buf << cred.cr_groups[0];
- buf << ":";
- peer_address += buf.str ();
- }
- }
-#endif
-
-#ifdef SO_NOSIGPIPE
- // Make sure that SIGPIPE signal is not generated when writing to a
- // connection that was already closed by the peer.
- int set = 1;
- rc = setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int));
- errno_assert (rc == 0);
-#endif
-}
-
-zmq::stream_engine_t::~stream_engine_t ()
-{
- zmq_assert (!plugged);
-
- if (s != retired_fd) {
-#ifdef ZMQ_HAVE_WINDOWS
- int rc = closesocket (s);
- wsa_assert (rc != SOCKET_ERROR);
-#else
- int rc = close (s);
- errno_assert (rc == 0);
-#endif
- s = retired_fd;
- }
-
- int rc = tx_msg.close ();
- errno_assert (rc == 0);
-
- // Drop reference to metadata and destroy it if we are
- // the only user.
- if (metadata != NULL)
- if (metadata->drop_ref ())
- delete metadata;
-
- delete encoder;
- delete decoder;
- delete mechanism;
-}
-
-void zmq::stream_engine_t::plug (io_thread_t *io_thread_,
- session_base_t *session_)
-{
- zmq_assert (!plugged);
- plugged = true;
-
- // Connect to session object.
- zmq_assert (!session);
- zmq_assert (session_);
- session = session_;
- socket = session-> get_socket ();
-
- // Connect to I/O threads poller object.
- io_object_t::plug (io_thread_);
- handle = add_fd (s);
- io_error = false;
-
- if (options.raw_sock) {
- // no handshaking for raw sock, instantiate raw encoder and decoders
- encoder = new (std::nothrow) raw_encoder_t (out_batch_size);
- alloc_assert (encoder);
-
- decoder = new (std::nothrow) raw_decoder_t (in_batch_size);
- alloc_assert (decoder);
-
- // disable handshaking for raw socket
- handshaking = false;
-
- next_msg = &stream_engine_t::pull_msg_from_session;
- process_msg = &stream_engine_t::push_raw_msg_to_session;
-
- if (!peer_address.empty()) {
- // Compile metadata.
- typedef metadata_t::dict_t properties_t;
- properties_t properties;
- properties.insert(std::make_pair("Peer-Address", peer_address));
- zmq_assert (metadata == NULL);
- metadata = new (std::nothrow) metadata_t (properties);
- }
-
- // For raw sockets, send an initial 0-length message to the
- // application so that it knows a peer has connected.
- msg_t connector;
- connector.init();
- push_raw_msg_to_session (&connector);
- connector.close();
- session->flush ();
- }
- else {
- // start optional timer, to prevent handshake hanging on no input
- set_handshake_timer ();
-
- // Send the 'length' and 'flags' fields of the identity message.
- // The 'length' field is encoded in the long format.
- outpos = greeting_send;
- outpos [outsize++] = 0xff;
- put_uint64 (&outpos [outsize], options.identity_size + 1);
- outsize += 8;
- outpos [outsize++] = 0x7f;
- }
-
- set_pollin (handle);
- set_pollout (handle);
- // Flush all the data that may have been already received downstream.
- in_event ();
-}
-
-void zmq::stream_engine_t::unplug ()
-{
- zmq_assert (plugged);
- plugged = false;
-
- // Cancel all timers.
- if (has_handshake_timer) {
- cancel_timer (handshake_timer_id);
- has_handshake_timer = false;
- }
-
- // Cancel all fd subscriptions.
- if (!io_error)
- rm_fd (handle);
-
- // Disconnect from I/O threads poller object.
- io_object_t::unplug ();
-
- session = NULL;
-}
-
-void zmq::stream_engine_t::terminate ()
-{
- unplug ();
- delete this;
-}
-
-void zmq::stream_engine_t::in_event ()
-{
- zmq_assert (!io_error);
-
- // If still handshaking, receive and process the greeting message.
- if (unlikely (handshaking))
- if (!handshake ())
- return;
-
- zmq_assert (decoder);
-
- // If there has been an I/O error, stop polling.
- if (input_stopped) {
- rm_fd (handle);
- io_error = true;
- return;
- }
-
- // If there's no data to process in the buffer...
- if (!insize) {
-
- // Retrieve the buffer and read as much data as possible.
- // Note that buffer can be arbitrarily large. However, we assume
- // the underlying TCP layer has fixed buffer size and thus the
- // number of bytes read will be always limited.
- size_t bufsize = 0;
- decoder->get_buffer (&inpos, &bufsize);
-
- const int rc = tcp_read (s, inpos, bufsize);
- if (rc == 0) {
- error (connection_error);
- return;
- }
- if (rc == -1) {
- if (errno != EAGAIN)
- error (connection_error);
- return;
- }
-
- // Adjust input size
- insize = static_cast <size_t> (rc);
- }
-
- int rc = 0;
- size_t processed = 0;
-
- while (insize > 0) {
- rc = decoder->decode (inpos, insize, processed);
- zmq_assert (processed <= insize);
- inpos += processed;
- insize -= processed;
- if (rc == 0 || rc == -1)
- break;
- rc = (this->*process_msg) (decoder->msg ());
- if (rc == -1)
- break;
- }
-
- // Tear down the connection if we have failed to decode input data
- // or the session has rejected the message.
- if (rc == -1) {
- if (errno != EAGAIN) {
- error (protocol_error);
- return;
- }
- input_stopped = true;
- reset_pollin (handle);
- }
-
- session->flush ();
-}
-
-void zmq::stream_engine_t::out_event ()
-{
- zmq_assert (!io_error);
-
- // If write buffer is empty, try to read new data from the encoder.
- if (!outsize) {
-
- // Even when we stop polling as soon as there is no
- // data to send, the poller may invoke out_event one
- // more time due to 'speculative write' optimisation.
- if (unlikely (encoder == NULL)) {
- zmq_assert (handshaking);
- return;
- }
-
- outpos = NULL;
- outsize = encoder->encode (&outpos, 0);
-
- while (outsize < out_batch_size) {
- if ((this->*next_msg) (&tx_msg) == -1)
- break;
- encoder->load_msg (&tx_msg);
- unsigned char *bufptr = outpos + outsize;
- size_t n = encoder->encode (&bufptr, out_batch_size - outsize);
- zmq_assert (n > 0);
- if (outpos == NULL)
- outpos = bufptr;
- outsize += n;
- }
-
- // If there is no data to send, stop polling for output.
- if (outsize == 0) {
- output_stopped = true;
- reset_pollout (handle);
- return;
- }
- }
-
- // If there are any data to write in write buffer, write as much as
- // possible to the socket. Note that amount of data to write can be
- // arbitrarily large. However, we assume that underlying TCP layer has
- // limited transmission buffer and thus the actual number of bytes
- // written should be reasonably modest.
- const int nbytes = tcp_write (s, outpos, outsize);
-
- // IO error has occurred. We stop waiting for output events.
- // The engine is not terminated until we detect input error;
- // this is necessary to prevent losing incoming messages.
- if (nbytes == -1) {
- reset_pollout (handle);
- return;
- }
-
- outpos += nbytes;
- outsize -= nbytes;
-
- // If we are still handshaking and there are no data
- // to send, stop polling for output.
- if (unlikely (handshaking))
- if (outsize == 0)
- reset_pollout (handle);
-}
-
-void zmq::stream_engine_t::restart_output ()
-{
- if (unlikely (io_error))
- return;
-
- if (likely (output_stopped)) {
- set_pollout (handle);
- output_stopped = false;
- }
-
- // Speculative write: The assumption is that at the moment new message
- // was sent by the user the socket is probably available for writing.
- // Thus we try to write the data to socket avoiding polling for POLLOUT.
- // Consequently, the latency should be better in request/reply scenarios.
- out_event ();
-}
-
-void zmq::stream_engine_t::restart_input ()
-{
- zmq_assert (input_stopped);
- zmq_assert (session != NULL);
- zmq_assert (decoder != NULL);
-
- int rc = (this->*process_msg) (decoder->msg ());
- if (rc == -1) {
- if (errno == EAGAIN)
- session->flush ();
- else
- error (protocol_error);
- return;
- }
-
- while (insize > 0) {
- size_t processed = 0;
- rc = decoder->decode (inpos, insize, processed);
- zmq_assert (processed <= insize);
- inpos += processed;
- insize -= processed;
- if (rc == 0 || rc == -1)
- break;
- rc = (this->*process_msg) (decoder->msg ());
- if (rc == -1)
- break;
- }
-
- if (rc == -1 && errno == EAGAIN)
- session->flush ();
- else
- if (io_error)
- error (connection_error);
- else
- if (rc == -1)
- error (protocol_error);
- else {
- input_stopped = false;
- set_pollin (handle);
- session->flush ();
-
- // Speculative read.
- in_event ();
- }
-}
-
-bool zmq::stream_engine_t::handshake ()
-{
- zmq_assert (handshaking);
- zmq_assert (greeting_bytes_read < greeting_size);
- // Receive the greeting.
- while (greeting_bytes_read < greeting_size) {
- const int n = tcp_read (s, greeting_recv + greeting_bytes_read,
- greeting_size - greeting_bytes_read);
- if (n == 0) {
- error (connection_error);
- return false;
- }
- if (n == -1) {
- if (errno != EAGAIN)
- error (connection_error);
- return false;
- }
-
- greeting_bytes_read += n;
-
- // We have received at least one byte from the peer.
- // If the first byte is not 0xff, we know that the
- // peer is using unversioned protocol.
- if (greeting_recv [0] != 0xff)
- break;
-
- if (greeting_bytes_read < signature_size)
- continue;
-
- // Inspect the right-most bit of the 10th byte (which coincides
- // with the 'flags' field if a regular message was sent).
- // Zero indicates this is a header of identity message
- // (i.e. the peer is using the unversioned protocol).
- if (!(greeting_recv [9] & 0x01))
- break;
-
- // The peer is using versioned protocol.
- // Send the major version number.
- if (outpos + outsize == greeting_send + signature_size) {
- if (outsize == 0)
- set_pollout (handle);
- outpos [outsize++] = 3; // Major version number
- }
-
- if (greeting_bytes_read > signature_size) {
- if (outpos + outsize == greeting_send + signature_size + 1) {
- if (outsize == 0)
- set_pollout (handle);
-
- // Use ZMTP/2.0 to talk to older peers.
- if (greeting_recv [10] == ZMTP_1_0
- || greeting_recv [10] == ZMTP_2_0)
- outpos [outsize++] = options.type;
- else {
- outpos [outsize++] = 0; // Minor version number
- memset (outpos + outsize, 0, 20);
-
- zmq_assert (options.mechanism == ZMQ_NULL
- || options.mechanism == ZMQ_PLAIN
- || options.mechanism == ZMQ_CURVE
- || options.mechanism == ZMQ_GSSAPI);
-
- if (options.mechanism == ZMQ_NULL)
- memcpy (outpos + outsize, "NULL", 4);
- else
- if (options.mechanism == ZMQ_PLAIN)
- memcpy (outpos + outsize, "PLAIN", 5);
- else
- if (options.mechanism == ZMQ_GSSAPI)
- memcpy (outpos + outsize, "GSSAPI", 6);
- else
- if (options.mechanism == ZMQ_CURVE)
- memcpy (outpos + outsize, "CURVE", 5);
- outsize += 20;
- memset (outpos + outsize, 0, 32);
- outsize += 32;
- greeting_size = v3_greeting_size;
- }
- }
- }
- }
-
- // Position of the revision field in the greeting.
- const size_t revision_pos = 10;
-
- // Is the peer using ZMTP/1.0 with no revision number?
- // If so, we send and receive rest of identity message
- if (greeting_recv [0] != 0xff || !(greeting_recv [9] & 0x01)) {
- if (session->zap_enabled ()) {
- // reject ZMTP 1.0 connections if ZAP is enabled
- error (protocol_error);
- return false;
- }
-
- encoder = new (std::nothrow) v1_encoder_t (out_batch_size);
- alloc_assert (encoder);
-
- decoder = new (std::nothrow) v1_decoder_t (in_batch_size, options.maxmsgsize);
- alloc_assert (decoder);
-
- // We have already sent the message header.
- // Since there is no way to tell the encoder to
- // skip the message header, we simply throw that
- // header data away.
- const size_t header_size = options.identity_size + 1 >= 255 ? 10 : 2;
- unsigned char tmp [10], *bufferp = tmp;
-
- // Prepare the identity message and load it into encoder.
- // Then consume bytes we have already sent to the peer.
- const int rc = tx_msg.init_size (options.identity_size);
- zmq_assert (rc == 0);
- memcpy (tx_msg.data (), options.identity, options.identity_size);
- encoder->load_msg (&tx_msg);
- size_t buffer_size = encoder->encode (&bufferp, header_size);
- zmq_assert (buffer_size == header_size);
-
- // Make sure the decoder sees the data we have already received.
- inpos = greeting_recv;
- insize = greeting_bytes_read;
-
- // To allow for interoperability with peers that do not forward
- // their subscriptions, we inject a phantom subscription message
- // message into the incoming message stream.
- if (options.type == ZMQ_PUB || options.type == ZMQ_XPUB)
- subscription_required = true;
-
- // We are sending our identity now and the next message
- // will come from the socket.
- next_msg = &stream_engine_t::pull_msg_from_session;
-
- // We are expecting identity message.
- process_msg = &stream_engine_t::process_identity_msg;
- }
- else
- if (greeting_recv [revision_pos] == ZMTP_1_0) {
- if (session->zap_enabled ()) {
- // reject ZMTP 1.0 connections if ZAP is enabled
- error (protocol_error);
- return false;
- }
-
- encoder = new (std::nothrow) v1_encoder_t (
- out_batch_size);
- alloc_assert (encoder);
-
- decoder = new (std::nothrow) v1_decoder_t (
- in_batch_size, options.maxmsgsize);
- alloc_assert (decoder);
- }
- else
- if (greeting_recv [revision_pos] == ZMTP_2_0) {
- if (session->zap_enabled ()) {
- // reject ZMTP 2.0 connections if ZAP is enabled
- error (protocol_error);
- return false;
- }
-
- encoder = new (std::nothrow) v2_encoder_t (out_batch_size);
- alloc_assert (encoder);
-
- decoder = new (std::nothrow) v2_decoder_t (
- in_batch_size, options.maxmsgsize);
- alloc_assert (decoder);
- }
- else {
- encoder = new (std::nothrow) v2_encoder_t (out_batch_size);
- alloc_assert (encoder);
-
- decoder = new (std::nothrow) v2_decoder_t (
- in_batch_size, options.maxmsgsize);
- alloc_assert (decoder);
-
- if (options.mechanism == ZMQ_NULL
- && memcmp (greeting_recv + 12, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
- mechanism = new (std::nothrow)
- null_mechanism_t (session, peer_address, options);
- alloc_assert (mechanism);
- }
- else
- if (options.mechanism == ZMQ_PLAIN
- && memcmp (greeting_recv + 12, "PLAIN\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
- if (options.as_server)
- mechanism = new (std::nothrow)
- plain_server_t (session, peer_address, options);
- else
- mechanism = new (std::nothrow)
- plain_client_t (options);
- alloc_assert (mechanism);
- }
-#ifdef HAVE_LIBSODIUM
- else
- if (options.mechanism == ZMQ_CURVE
- && memcmp (greeting_recv + 12, "CURVE\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
- if (options.as_server)
- mechanism = new (std::nothrow)
- curve_server_t (session, peer_address, options);
- else
- mechanism = new (std::nothrow) curve_client_t (options);
- alloc_assert (mechanism);
- }
-#endif
-#ifdef HAVE_LIBGSSAPI_KRB5
- else
- if (options.mechanism == ZMQ_GSSAPI
- && memcmp (greeting_recv + 12, "GSSAPI\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) {
- if (options.as_server)
- mechanism = new (std::nothrow)
- gssapi_server_t (session, peer_address, options);
- else
- mechanism = new (std::nothrow) gssapi_client_t (options);
- alloc_assert (mechanism);
- }
-#endif
- else {
- error (protocol_error);
- return false;
- }
- next_msg = &stream_engine_t::next_handshake_command;
- process_msg = &stream_engine_t::process_handshake_command;
- }
-
- // Start polling for output if necessary.
- if (outsize == 0)
- set_pollout (handle);
-
- // Handshaking was successful.
- // Switch into the normal message flow.
- handshaking = false;
-
- if (has_handshake_timer) {
- cancel_timer (handshake_timer_id);
- has_handshake_timer = false;
- }
-
- return true;
-}
-
-int zmq::stream_engine_t::identity_msg (msg_t *msg_)
-{
- int rc = msg_->init_size (options.identity_size);
- errno_assert (rc == 0);
- if (options.identity_size > 0)
- memcpy (msg_->data (), options.identity, options.identity_size);
- next_msg = &stream_engine_t::pull_msg_from_session;
- return 0;
-}
-
-int zmq::stream_engine_t::process_identity_msg (msg_t *msg_)
-{
- if (options.recv_identity) {
- msg_->set_flags (msg_t::identity);
- int rc = session->push_msg (msg_);
- errno_assert (rc == 0);
- }
- else {
- int rc = msg_->close ();
- errno_assert (rc == 0);
- rc = msg_->init ();
- errno_assert (rc == 0);
- }
-
- if (subscription_required)
- process_msg = &stream_engine_t::write_subscription_msg;
- else
- process_msg = &stream_engine_t::push_msg_to_session;
-
- return 0;
-}
-
-int zmq::stream_engine_t::next_handshake_command (msg_t *msg_)
-{
- zmq_assert (mechanism != NULL);
-
- if (mechanism->status () == mechanism_t::ready) {
- mechanism_ready ();
- return pull_and_encode (msg_);
- }
- else
- if (mechanism->status () == mechanism_t::error) {
- errno = EPROTO;
- return -1;
- }
- else {
- const int rc = mechanism->next_handshake_command (msg_);
- if (rc == 0)
- msg_->set_flags (msg_t::command);
- return rc;
- }
-}
-
-int zmq::stream_engine_t::process_handshake_command (msg_t *msg_)
-{
- zmq_assert (mechanism != NULL);
- const int rc = mechanism->process_handshake_command (msg_);
- if (rc == 0) {
- if (mechanism->status () == mechanism_t::ready)
- mechanism_ready ();
- else
- if (mechanism->status () == mechanism_t::error) {
- errno = EPROTO;
- return -1;
- }
- if (output_stopped)
- restart_output ();
- }
-
- return rc;
-}
-
-void zmq::stream_engine_t::zap_msg_available ()
-{
- zmq_assert (mechanism != NULL);
-
- const int rc = mechanism->zap_msg_available ();
- if (rc == -1) {
- error (protocol_error);
- return;
- }
- if (input_stopped)
- restart_input ();
- if (output_stopped)
- restart_output ();
-}
-
-void zmq::stream_engine_t::mechanism_ready ()
-{
- if (options.recv_identity) {
- msg_t identity;
- mechanism->peer_identity (&identity);
- const int rc = session->push_msg (&identity);
- if (rc == -1 && errno == EAGAIN) {
- // If the write is failing at this stage with
- // an EAGAIN the pipe must be being shut down,
- // so we can just bail out of the identity set.
- return;
- }
- errno_assert (rc == 0);
- session->flush ();
- }
-
- next_msg = &stream_engine_t::pull_and_encode;
- process_msg = &stream_engine_t::write_credential;
-
- // Compile metadata.
- typedef metadata_t::dict_t properties_t;
- properties_t properties;
- properties_t::const_iterator it;
-
- // If we have a peer_address, add it to metadata
- if (!peer_address.empty()) {
- properties.insert(std::make_pair("Peer-Address", peer_address));
- }
-
- // Add ZAP properties.
- const properties_t& zap_properties = mechanism->get_zap_properties ();
- properties.insert(zap_properties.begin (), zap_properties.end ());
-
- // Add ZMTP properties.
- const properties_t& zmtp_properties = mechanism->get_zmtp_properties ();
- properties.insert(zmtp_properties.begin (), zmtp_properties.end ());
-
- zmq_assert (metadata == NULL);
- if (!properties.empty ())
- metadata = new (std::nothrow) metadata_t (properties);
-}
-
-int zmq::stream_engine_t::pull_msg_from_session (msg_t *msg_)
-{
- return session->pull_msg (msg_);
-}
-
-int zmq::stream_engine_t::push_msg_to_session (msg_t *msg_)
-{
- return session->push_msg (msg_);
-}
-
-int zmq::stream_engine_t::push_raw_msg_to_session (msg_t *msg_) {
- if (metadata)
- msg_->set_metadata(metadata);
- return push_msg_to_session(msg_);
-}
-
-int zmq::stream_engine_t::write_credential (msg_t *msg_)
-{
- zmq_assert (mechanism != NULL);
- zmq_assert (session != NULL);
-
- const blob_t credential = mechanism->get_user_id ();
- if (credential.size () > 0) {
- msg_t msg;
- int rc = msg.init_size (credential.size ());
- zmq_assert (rc == 0);
- memcpy (msg.data (), credential.data (), credential.size ());
- msg.set_flags (msg_t::credential);
- rc = session->push_msg (&msg);
- if (rc == -1) {
- rc = msg.close ();
- errno_assert (rc == 0);
- return -1;
- }
- }
- process_msg = &stream_engine_t::decode_and_push;
- return decode_and_push (msg_);
-}
-
-int zmq::stream_engine_t::pull_and_encode (msg_t *msg_)
-{
- zmq_assert (mechanism != NULL);
-
- if (session->pull_msg (msg_) == -1)
- return -1;
- if (mechanism->encode (msg_) == -1)
- return -1;
- return 0;
-}
-
-int zmq::stream_engine_t::decode_and_push (msg_t *msg_)
-{
- zmq_assert (mechanism != NULL);
-
- if (mechanism->decode (msg_) == -1)
- return -1;
- if (metadata)
- msg_->set_metadata (metadata);
- if (session->push_msg (msg_) == -1) {
- if (errno == EAGAIN)
- process_msg = &stream_engine_t::push_one_then_decode_and_push;
- return -1;
- }
- return 0;
-}
-
-int zmq::stream_engine_t::push_one_then_decode_and_push (msg_t *msg_)
-{
- const int rc = session->push_msg (msg_);
- if (rc == 0)
- process_msg = &stream_engine_t::decode_and_push;
- return rc;
-}
-
-int zmq::stream_engine_t::write_subscription_msg (msg_t *msg_)
-{
- msg_t subscription;
-
- // Inject the subscription message, so that also
- // ZMQ 2.x peers receive published messages.
- int rc = subscription.init_size (1);
- errno_assert (rc == 0);
- *(unsigned char*) subscription.data () = 1;
- rc = session->push_msg (&subscription);
- if (rc == -1)
- return -1;
-
- process_msg = &stream_engine_t::push_msg_to_session;
- return push_msg_to_session (msg_);
-}
-
-void zmq::stream_engine_t::error (error_reason_t reason)
-{
- if (options.raw_sock) {
- // For raw sockets, send a final 0-length message to the application
- // so that it knows the peer has been disconnected.
- msg_t terminator;
- terminator.init();
- (this->*process_msg) (&terminator);
- terminator.close();
- }
- zmq_assert (session);
- socket->event_disconnected (endpoint, s);
- session->flush ();
- session->engine_error (reason);
- unplug ();
- delete this;
-}
-
-void zmq::stream_engine_t::set_handshake_timer ()
-{
- zmq_assert (!has_handshake_timer);
-
- if (!options.raw_sock && options.handshake_ivl > 0) {
- add_timer (options.handshake_ivl, handshake_timer_id);
- has_handshake_timer = true;
- }
-}
-
-void zmq::stream_engine_t::timer_event (int id_)
-{
- zmq_assert (id_ == handshake_timer_id);
- has_handshake_timer = false;
-
- // handshake timer expired before handshake completed, so engine fails
- error (timeout_error);
-}