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_); encoder.set_session (session_); decoder.set_session (session_); session = session_; // Connect to I/O threads poller object. io_object_t::plug (io_thread_); handle = add_fd (s); set_pollin (handle); set_pollout (handle); // Flush all the data that may have been already received downstream. in_event (); }
void zmq::zmq_engine_t::plug (io_thread_t *io_thread_, i_inout *inout_) { zmq_assert (!plugged); plugged = true; ephemeral_inout = NULL; // Connect to session/init object. zmq_assert (!inout); zmq_assert (inout_); encoder.set_inout (inout_); decoder.set_inout (inout_); inout = inout_; // Connect to I/O threads poller object. io_object_t::plug (io_thread_); handle = add_fd (tcp_socket.get_fd ()); set_pollin (handle); set_pollout (handle); // Flush all the data that may have been already received downstream. in_event (); }
void xs::stream_engine_t::plug (io_thread_t *io_thread_, session_base_t *session_) { xs_assert (!plugged); plugged = true; leftover_session = NULL; // Connect to session object. xs_assert (!session); xs_assert (session_); encoder.set_session (session_); decoder.set_session (session_); session = session_; // Connect to the io_thread object. io_object_t::plug (io_thread_); handle = add_fd (s); set_pollin (handle); set_pollout (handle); // Flush all the data that may have been already received downstream. in_event (s); }
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 { // Temporary support for security debugging char mechanism [21]; memcpy (mechanism, greeting_recv + 12, 20); mechanism [20] = 0; printf ("LIBZMQ I: security failure, self=%s peer=%s\n", options.mechanism == ZMQ_NULL? "NULL": options.mechanism == ZMQ_PLAIN? "PLAIN": options.mechanism == ZMQ_CURVE? "CURVE": options.mechanism == ZMQ_GSSAPI? "GSSAPI": "OTHER", mechanism); 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; }
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_socket) { // 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; properties_t properties; if (init_properties(properties)) { // Compile metadata. zmq_assert (metadata == NULL); metadata = new (std::nothrow) metadata_t (properties); } if (options.raw_notify) { // 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::pgm_sender_t::revive () { set_pollout (handle); out_event (); }
void zmq::pgm_sender_t::activate_out () { set_pollout (handle); out_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 = read (greeting_recv + greeting_bytes_read, greeting_size - greeting_bytes_read); if (n == -1) { error (); return false; } if (n == 0) 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); if (options.mechanism == ZMQ_NULL) memcpy (outpos + outsize, "NULL", 4); else if (options.mechanism == ZMQ_PLAIN) memcpy (outpos + outsize, "PLAIN", 5); else 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)) { 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; 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; } else if (greeting_recv [revision_pos] == ZMTP_1_0) { 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) { 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 (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 (memcmp (greeting_recv + 12, "PLAIN\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0) { mechanism = new (std::nothrow) plain_mechanism_t (session, peer_address, options); alloc_assert (mechanism); } #ifdef HAVE_LIBSODIUM else if (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 else { error (); return false; } read_msg = &stream_engine_t::next_handshake_command; write_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; return true; }
void zmq::socks_connecter_t::in_event () { zmq_assert (status != unplugged && status != waiting_for_reconnect_time); if (status == waiting_for_choice) { int rc = choice_decoder.input (s); if (rc == 0 || rc == -1) error (); else if (choice_decoder.message_ready ()) { const socks_choice_t choice = choice_decoder.decode (); rc = process_server_response (choice); if (rc == -1) error (); else { std::string hostname = ""; uint16_t port = 0; if (parse_address (addr->address, hostname, port) == -1) error (); else { request_encoder.encode ( socks_request_t (1, hostname, port)); reset_pollin (handle); set_pollout (handle); status = sending_request; } } } } else if (status == waiting_for_response) { int rc = response_decoder.input (s); if (rc == 0 || rc == -1) error (); else if (response_decoder.message_ready ()) { const socks_response_t response = response_decoder.decode (); rc = process_server_response (response); if (rc == -1) error (); else { // Create the engine object for this connection. stream_engine_t *engine = new (std::nothrow) stream_engine_t (s, options, endpoint); alloc_assert (engine); // Attach the engine to the corresponding session object. send_attach (session, engine); socket->event_connected (endpoint, (int) s); rm_fd (handle); s = -1; status = unplugged; // Shut the connecter down. terminate (); } } } else error (); }
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 = read (greeting + greeting_bytes_read, greeting_size - greeting_bytes_read); if (n == -1) { error (); return false; } if (n == 0) 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 [0] != 0xff) break; if (greeting_bytes_read < 10) 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 [9] & 0x01)) break; // The peer is using versioned protocol. // Send the rest of the greeting, if necessary. if (outpos + outsize != greeting_output_buffer + greeting_size) { if (outsize == 0) set_pollout (handle); outpos [outsize++] = 1; // Protocol version outpos [outsize++] = options.type; // Socket type } } // Position of the version field in the greeting. const size_t version_pos = 10; // Is the peer using the unversioned protocol? // If so, we send and receive rests of identity // messages. if (greeting [0] != 0xff || !(greeting [9] & 0x01)) { encoder = new (std::nothrow) encoder_t (out_batch_size); alloc_assert (encoder); encoder->set_msg_source (session); decoder = new (std::nothrow) decoder_t (in_batch_size, options.maxmsgsize); alloc_assert (decoder); decoder->set_msg_sink (session); // 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; size_t buffer_size = header_size; encoder->get_data (&bufferp, &buffer_size); zmq_assert (buffer_size == header_size); // Make sure the decoder sees the data we have already received. inpos = greeting; insize = greeting_bytes_read; // To allow for interoperability with peers that do not forward // their subscriptions, we inject a phony subsription // message into the incomming message stream. To put this // message right after the identity message, we temporarily // divert the message stream from session to ourselves. if (options.type == ZMQ_PUB || options.type == ZMQ_XPUB) decoder->set_msg_sink (this); } else if (greeting [version_pos] == 0) { // ZMTP/1.0 framing. encoder = new (std::nothrow) encoder_t (out_batch_size); alloc_assert (encoder); encoder->set_msg_source (session); decoder = new (std::nothrow) decoder_t (in_batch_size, options.maxmsgsize); alloc_assert (decoder); decoder->set_msg_sink (session); } else { // v1 framing protocol. encoder = new (std::nothrow) v1_encoder_t (out_batch_size, session); alloc_assert (encoder); decoder = new (std::nothrow) v1_decoder_t (in_batch_size, options.maxmsgsize, session); alloc_assert (decoder); } // Start polling for output if necessary. if (outsize == 0) set_pollout (handle); // Handshaking was successful. // Switch into the normal message flow. handshaking = false; return true; }
void zmq::pgm_sender_t::out_event () { // POLLOUT event from send socket. If write buffer is empty, // try to read new data from the encoder. if (write_size == 0) { // First two bytes (sizeof uint16_t) are used to store message // offset in following steps. Note that by passing our buffer to // the get data function we prevent it from returning its own buffer. unsigned char *bf = out_buffer + sizeof (uint16_t); size_t bfsz = out_buffer_size - sizeof (uint16_t); uint16_t offset = 0xffff; size_t bytes = encoder.encode (&bf, bfsz); while (bytes < bfsz) { if (!more_flag && offset == 0xffff) offset = static_cast <uint16_t> (bytes); int rc = session->pull_msg (&msg); if (rc == -1) break; more_flag = msg.flags () & msg_t::more; encoder.load_msg (&msg); bf = out_buffer + sizeof (uint16_t) + bytes; bytes += encoder.encode (&bf, bfsz - bytes); } // If there are no data to write stop polling for output. if (bytes == 0) { reset_pollout (handle); return; } write_size = sizeof (uint16_t) + bytes; // Put offset information in the buffer. put_uint16 (out_buffer, offset); } if (has_tx_timer) { cancel_timer (tx_timer_id); set_pollout (handle); has_tx_timer = false; } // Send the data. size_t nbytes = pgm_socket.send (out_buffer, write_size); // We can write either all data or 0 which means rate limit reached. if (nbytes == write_size) write_size = 0; else { zmq_assert (nbytes == 0); if (errno == ENOMEM) { // Stop polling handle and wait for tx timeout const long timeout = pgm_socket.get_tx_timeout (); add_timer (timeout, tx_timer_id); reset_pollout (handle); has_tx_timer = true; } else errno_assert (errno == EBUSY); } }
void zmq::pgm_sender_t::restart_output () { set_pollout (handle); out_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) { errno = EPIPE; 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 a routing id 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 routing id 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.routing_id_size + 1 >= UCHAR_MAX ? 10 : 2; unsigned char tmp[10], *bufferp = tmp; // Prepare the routing id message and load it into encoder. // Then consume bytes we have already sent to the peer. const int rc = _tx_msg.init_size (_options.routing_id_size); zmq_assert (rc == 0); memcpy (_tx_msg.data (), _options.routing_id, _options.routing_id_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 routing id now and the next message // will come from the socket. _next_msg = &stream_engine_t::pull_msg_from_session; // We are expecting routing id message. _process_msg = &stream_engine_t::process_routing_id_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, _options.zero_copy); 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, _options.zero_copy); 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 (_session, _options); alloc_assert (_mechanism); } #ifdef ZMQ_HAVE_CURVE 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 (_session, _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 (_session, _options); alloc_assert (_mechanism); } #endif else { _session->get_socket ()->event_handshake_failed_protocol ( _session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH); 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; }
void xs::pgm_sender_t::activate_out () { set_pollout (handle); out_event (retired_fd); }
void zmq::udp_engine_t::plug (io_thread_t *io_thread_, session_base_t *session_) { zmq_assert (!plugged); plugged = true; zmq_assert (!session); zmq_assert (session_); session = session_; // Connect to I/O threads poller object. io_object_t::plug (io_thread_); handle = add_fd (fd); // Bind the socket to a device if applicable if (!options.bound_device.empty ()) bind_to_device (fd, options.bound_device); if (send_enabled) { if (!options.raw_socket) { out_address = address->resolved.udp_addr->dest_addr (); out_addrlen = address->resolved.udp_addr->dest_addrlen (); } else { out_address = (sockaddr *) &raw_address; out_addrlen = sizeof (sockaddr_in); } set_pollout (handle); } if (recv_enabled) { int on = 1; int rc = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)); #ifdef ZMQ_HAVE_WINDOWS wsa_assert (rc != SOCKET_ERROR); #else errno_assert (rc == 0); #endif #ifdef ZMQ_HAVE_VXWORKS rc = bind (fd, (sockaddr *) address->resolved.udp_addr->bind_addr (), address->resolved.udp_addr->bind_addrlen ()); #else rc = bind (fd, address->resolved.udp_addr->bind_addr (), address->resolved.udp_addr->bind_addrlen ()); #endif #ifdef ZMQ_HAVE_WINDOWS wsa_assert (rc != SOCKET_ERROR); #else errno_assert (rc == 0); #endif if (address->resolved.udp_addr->is_mcast ()) { struct ip_mreq mreq; mreq.imr_multiaddr = address->resolved.udp_addr->multicast_ip (); mreq.imr_interface = address->resolved.udp_addr->interface_ip (); rc = setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof (mreq)); #ifdef ZMQ_HAVE_WINDOWS wsa_assert (rc != SOCKET_ERROR); #else errno_assert (rc == 0); #endif } set_pollin (handle); // Call restart output to drop all join/leave commands restart_output (); } }