2013-05-13 22:34:27 +02:00
|
|
|
/*
|
2016-01-28 15:07:31 +01:00
|
|
|
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
2013-05-13 22:34:27 +02:00
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
This file is part of libzmq, the ZeroMQ core engine in C++.
|
2013-05-13 22:34:27 +02:00
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
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
|
2013-05-13 22:34:27 +02:00
|
|
|
(at your option) any later version.
|
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
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.
|
2013-05-13 22:34:27 +02:00
|
|
|
|
|
|
|
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/>.
|
|
|
|
*/
|
|
|
|
|
2016-02-18 17:56:52 +01:00
|
|
|
#include "precompiled.hpp"
|
2013-05-13 22:34:27 +02:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "mechanism.hpp"
|
|
|
|
#include "options.hpp"
|
|
|
|
#include "msg.hpp"
|
|
|
|
#include "err.hpp"
|
|
|
|
#include "wire.hpp"
|
2017-08-18 10:04:58 +02:00
|
|
|
#include "session_base.hpp"
|
2013-05-13 22:34:27 +02:00
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
zmq::mechanism_t::mechanism_t (const options_t &options_) : options (options_)
|
2013-05-13 22:34:27 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
zmq::mechanism_t::~mechanism_t ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-09-06 17:45:56 +02:00
|
|
|
void zmq::mechanism_t::set_peer_routing_id (const void *id_ptr, size_t id_size)
|
2013-05-13 22:34:27 +02:00
|
|
|
{
|
2018-02-01 11:46:09 +01:00
|
|
|
routing_id.set (static_cast<const unsigned char *> (id_ptr), id_size);
|
2013-05-13 22:34:27 +02:00
|
|
|
}
|
|
|
|
|
2017-09-06 17:45:56 +02:00
|
|
|
void zmq::mechanism_t::peer_routing_id (msg_t *msg_)
|
2013-05-13 22:34:27 +02:00
|
|
|
{
|
2017-09-06 17:45:56 +02:00
|
|
|
const int rc = msg_->init_size (routing_id.size ());
|
2013-05-13 22:34:27 +02:00
|
|
|
errno_assert (rc == 0);
|
2017-09-06 17:45:56 +02:00
|
|
|
memcpy (msg_->data (), routing_id.data (), routing_id.size ());
|
|
|
|
msg_->set_flags (msg_t::routing_id);
|
2013-05-13 22:34:27 +02:00
|
|
|
}
|
|
|
|
|
2014-01-12 21:58:36 +01:00
|
|
|
void zmq::mechanism_t::set_user_id (const void *data_, size_t size_)
|
|
|
|
{
|
2018-02-01 11:46:09 +01:00
|
|
|
user_id.set (static_cast<const unsigned char *> (data_), size_);
|
2017-10-22 17:05:41 +02:00
|
|
|
zap_properties.ZMQ_MAP_INSERT_OR_EMPLACE (
|
2018-05-13 14:16:37 +02:00
|
|
|
std::string (ZMQ_MSG_PROPERTY_USER_ID),
|
|
|
|
std::string ((char *) data_, size_));
|
2014-01-12 21:58:36 +01:00
|
|
|
}
|
|
|
|
|
2017-10-21 13:19:51 +02:00
|
|
|
const zmq::blob_t &zmq::mechanism_t::get_user_id () const
|
2014-01-12 21:58:36 +01:00
|
|
|
{
|
|
|
|
return user_id;
|
|
|
|
}
|
|
|
|
|
2018-02-03 16:12:49 +01:00
|
|
|
const char socket_type_pair[] = "PAIR";
|
|
|
|
const char socket_type_pub[] = "PUB";
|
|
|
|
const char socket_type_sub[] = "SUB";
|
|
|
|
const char socket_type_req[] = "REQ";
|
|
|
|
const char socket_type_rep[] = "REP";
|
|
|
|
const char socket_type_dealer[] = "DEALER";
|
|
|
|
const char socket_type_router[] = "ROUTER";
|
|
|
|
const char socket_type_pull[] = "PULL";
|
|
|
|
const char socket_type_push[] = "PUSH";
|
|
|
|
const char socket_type_xpub[] = "XPUB";
|
|
|
|
const char socket_type_xsub[] = "XSUB";
|
|
|
|
const char socket_type_stream[] = "STREAM";
|
|
|
|
#ifdef ZMQ_BUILD_DRAFT_API
|
|
|
|
const char socket_type_server[] = "SERVER";
|
|
|
|
const char socket_type_client[] = "CLIENT";
|
|
|
|
const char socket_type_radio[] = "RADIO";
|
|
|
|
const char socket_type_dish[] = "DISH";
|
|
|
|
const char socket_type_gather[] = "GATHER";
|
|
|
|
const char socket_type_scatter[] = "SCATTER";
|
|
|
|
const char socket_type_dgram[] = "DGRAM";
|
|
|
|
#endif
|
|
|
|
|
2013-05-13 22:34:27 +02:00
|
|
|
const char *zmq::mechanism_t::socket_type_string (int socket_type) const
|
|
|
|
{
|
2018-02-03 16:12:49 +01:00
|
|
|
// TODO the order must of the names must correspond to the values resp. order of ZMQ_* socket type definitions in zmq.h!
|
2018-02-01 11:46:09 +01:00
|
|
|
static const char *names[] = {
|
2018-02-03 16:12:49 +01:00
|
|
|
socket_type_pair, socket_type_pub, socket_type_sub,
|
|
|
|
socket_type_req, socket_type_rep, socket_type_dealer,
|
|
|
|
socket_type_router, socket_type_pull, socket_type_push,
|
|
|
|
socket_type_xpub, socket_type_xsub, socket_type_stream,
|
|
|
|
#ifdef ZMQ_BUILD_DRAFT_API
|
|
|
|
socket_type_server, socket_type_client, socket_type_radio,
|
|
|
|
socket_type_dish, socket_type_gather, socket_type_scatter,
|
|
|
|
socket_type_dgram
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
static const size_t names_count = sizeof (names) / sizeof (names[0]);
|
|
|
|
zmq_assert (socket_type >= 0 && socket_type < (int) names_count);
|
2018-02-01 11:46:09 +01:00
|
|
|
return names[socket_type];
|
2013-05-13 22:34:27 +02:00
|
|
|
}
|
|
|
|
|
2017-08-15 19:42:31 +02:00
|
|
|
static size_t property_len (size_t name_len, size_t value_len)
|
|
|
|
{
|
|
|
|
return 1 + name_len + 4 + value_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t name_len (const char *name)
|
2013-05-13 22:34:27 +02:00
|
|
|
{
|
|
|
|
const size_t name_len = strlen (name);
|
|
|
|
zmq_assert (name_len <= 255);
|
2017-08-15 19:42:31 +02:00
|
|
|
return name_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t zmq::mechanism_t::add_property (unsigned char *ptr,
|
|
|
|
size_t ptr_capacity,
|
|
|
|
const char *name,
|
|
|
|
const void *value,
|
|
|
|
size_t value_len)
|
|
|
|
{
|
|
|
|
const size_t name_len = ::name_len (name);
|
|
|
|
const size_t total_len = ::property_len (name_len, value_len);
|
|
|
|
zmq_assert (total_len <= ptr_capacity);
|
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
*ptr++ = static_cast<unsigned char> (name_len);
|
2013-05-13 22:34:27 +02:00
|
|
|
memcpy (ptr, name, name_len);
|
|
|
|
ptr += name_len;
|
2013-05-31 22:22:51 +02:00
|
|
|
zmq_assert (value_len <= 0x7FFFFFFF);
|
2018-02-01 11:46:09 +01:00
|
|
|
put_uint32 (ptr, static_cast<uint32_t> (value_len));
|
2013-05-13 22:34:27 +02:00
|
|
|
ptr += 4;
|
|
|
|
memcpy (ptr, value, value_len);
|
|
|
|
|
2017-08-15 19:42:31 +02:00
|
|
|
return total_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t zmq::mechanism_t::property_len (const char *name, size_t value_len)
|
|
|
|
{
|
|
|
|
return ::property_len (name_len (name), value_len);
|
|
|
|
}
|
|
|
|
|
2017-09-07 12:41:58 +02:00
|
|
|
#define ZMTP_PROPERTY_SOCKET_TYPE "Socket-Type"
|
|
|
|
#define ZMTP_PROPERTY_IDENTITY "Identity"
|
|
|
|
|
2017-08-15 19:42:31 +02:00
|
|
|
size_t zmq::mechanism_t::add_basic_properties (unsigned char *buf,
|
|
|
|
size_t buf_capacity) const
|
|
|
|
{
|
|
|
|
unsigned char *ptr = buf;
|
|
|
|
|
|
|
|
// Add socket type property
|
|
|
|
const char *socket_type = socket_type_string (options.type);
|
2018-02-01 11:46:09 +01:00
|
|
|
ptr += add_property (ptr, buf_capacity, ZMTP_PROPERTY_SOCKET_TYPE,
|
|
|
|
socket_type, strlen (socket_type));
|
2017-08-15 19:42:31 +02:00
|
|
|
|
2017-09-07 12:41:58 +02:00
|
|
|
// Add identity (aka routing id) property
|
2017-08-15 19:42:31 +02:00
|
|
|
if (options.type == ZMQ_REQ || options.type == ZMQ_DEALER
|
2018-02-03 16:12:49 +01:00
|
|
|
|| options.type == ZMQ_ROUTER) {
|
2018-02-01 11:46:09 +01:00
|
|
|
ptr +=
|
|
|
|
add_property (ptr, buf_capacity - (ptr - buf), ZMTP_PROPERTY_IDENTITY,
|
|
|
|
options.routing_id, options.routing_id_size);
|
2018-02-03 16:12:49 +01:00
|
|
|
}
|
2017-08-15 19:42:31 +02:00
|
|
|
|
2018-03-12 01:41:33 +01:00
|
|
|
|
|
|
|
for (std::map<std::string, std::string>::const_iterator it =
|
|
|
|
options.app_metadata.begin ();
|
|
|
|
it != options.app_metadata.end (); ++it)
|
|
|
|
ptr +=
|
|
|
|
add_property (ptr, buf_capacity - (ptr - buf), it->first.c_str (),
|
|
|
|
it->second.c_str (), strlen (it->second.c_str ()));
|
|
|
|
|
2017-08-15 19:42:31 +02:00
|
|
|
return ptr - buf;
|
|
|
|
}
|
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
size_t zmq::mechanism_t::basic_properties_len () const
|
2017-08-15 19:42:31 +02:00
|
|
|
{
|
|
|
|
const char *socket_type = socket_type_string (options.type);
|
2018-05-13 11:11:19 +02:00
|
|
|
size_t meta_len = 0;
|
2018-03-12 01:41:33 +01:00
|
|
|
|
|
|
|
for (std::map<std::string, std::string>::const_iterator it =
|
|
|
|
options.app_metadata.begin ();
|
2018-05-13 11:11:19 +02:00
|
|
|
it != options.app_metadata.end (); ++it) {
|
2018-03-12 01:41:33 +01:00
|
|
|
meta_len +=
|
|
|
|
property_len (it->first.c_str (), strlen (it->second.c_str ()));
|
2018-05-13 11:11:19 +02:00
|
|
|
}
|
2018-03-12 01:41:33 +01:00
|
|
|
|
2017-09-07 12:41:58 +02:00
|
|
|
return property_len (ZMTP_PROPERTY_SOCKET_TYPE, strlen (socket_type))
|
2018-03-12 01:41:33 +01:00
|
|
|
+ meta_len
|
2017-08-15 19:42:31 +02:00
|
|
|
+ ((options.type == ZMQ_REQ || options.type == ZMQ_DEALER
|
|
|
|
|| options.type == ZMQ_ROUTER)
|
2018-02-01 11:46:09 +01:00
|
|
|
? property_len (ZMTP_PROPERTY_IDENTITY, options.routing_id_size)
|
2017-08-15 19:42:31 +02:00
|
|
|
: 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zmq::mechanism_t::make_command_with_basic_properties (
|
2018-02-03 16:12:49 +01:00
|
|
|
msg_t *msg_, const char *prefix_, size_t prefix_len_) const
|
2017-08-15 19:42:31 +02:00
|
|
|
{
|
2018-02-03 16:12:49 +01:00
|
|
|
const size_t command_size = prefix_len_ + basic_properties_len ();
|
2017-08-15 19:42:31 +02:00
|
|
|
const int rc = msg_->init_size (command_size);
|
|
|
|
errno_assert (rc == 0);
|
|
|
|
|
|
|
|
unsigned char *ptr = (unsigned char *) msg_->data ();
|
|
|
|
|
|
|
|
// Add prefix
|
2018-02-03 16:12:49 +01:00
|
|
|
memcpy (ptr, prefix_, prefix_len_);
|
|
|
|
ptr += prefix_len_;
|
2017-08-15 19:42:31 +02:00
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
add_basic_properties (ptr, command_size
|
|
|
|
- (ptr - (unsigned char *) msg_->data ()));
|
2013-05-13 22:34:27 +02:00
|
|
|
}
|
2013-06-22 19:02:08 +02:00
|
|
|
|
2013-06-23 08:52:27 +02:00
|
|
|
int zmq::mechanism_t::parse_metadata (const unsigned char *ptr_,
|
2017-08-15 19:42:31 +02:00
|
|
|
size_t length_,
|
2018-02-03 16:12:49 +01:00
|
|
|
bool zap_flag_)
|
2013-06-22 19:02:08 +02:00
|
|
|
{
|
|
|
|
size_t bytes_left = length_;
|
|
|
|
|
|
|
|
while (bytes_left > 1) {
|
2018-02-01 11:46:09 +01:00
|
|
|
const size_t name_length = static_cast<size_t> (*ptr_);
|
2013-06-22 19:02:08 +02:00
|
|
|
ptr_ += 1;
|
|
|
|
bytes_left -= 1;
|
|
|
|
if (bytes_left < name_length)
|
|
|
|
break;
|
|
|
|
|
|
|
|
const std::string name = std::string ((char *) ptr_, name_length);
|
|
|
|
ptr_ += name_length;
|
|
|
|
bytes_left -= name_length;
|
|
|
|
if (bytes_left < 4)
|
|
|
|
break;
|
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
const size_t value_length = static_cast<size_t> (get_uint32 (ptr_));
|
2013-06-22 19:02:08 +02:00
|
|
|
ptr_ += 4;
|
|
|
|
bytes_left -= 4;
|
|
|
|
if (bytes_left < value_length)
|
|
|
|
break;
|
|
|
|
|
|
|
|
const uint8_t *value = ptr_;
|
|
|
|
ptr_ += value_length;
|
|
|
|
bytes_left -= value_length;
|
|
|
|
|
2017-09-07 12:41:58 +02:00
|
|
|
if (name == ZMTP_PROPERTY_IDENTITY && options.recv_routing_id)
|
2017-09-06 17:45:56 +02:00
|
|
|
set_peer_routing_id (value, value_length);
|
2018-02-01 11:46:09 +01:00
|
|
|
else if (name == ZMTP_PROPERTY_SOCKET_TYPE) {
|
2018-02-03 16:12:49 +01:00
|
|
|
if (!check_socket_type ((const char *) value, value_length)) {
|
2013-07-01 10:04:54 +02:00
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
2018-02-01 11:46:09 +01:00
|
|
|
} else {
|
2013-07-01 10:04:54 +02:00
|
|
|
const int rc = property (name, value, value_length);
|
|
|
|
if (rc == -1)
|
|
|
|
return -1;
|
|
|
|
}
|
2018-02-03 16:12:49 +01:00
|
|
|
(zap_flag_ ? zap_properties : zmtp_properties)
|
|
|
|
.ZMQ_MAP_INSERT_OR_EMPLACE (
|
|
|
|
name, std::string ((char *) value, value_length));
|
2013-06-22 19:02:08 +02:00
|
|
|
}
|
|
|
|
if (bytes_left > 0) {
|
|
|
|
errno = EPROTO;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-02-01 11:46:09 +01:00
|
|
|
int zmq::mechanism_t::property (const std::string & /* name_ */,
|
|
|
|
const void * /* value_ */,
|
|
|
|
size_t /* length_ */)
|
2013-06-22 19:02:08 +02:00
|
|
|
{
|
|
|
|
// Default implementation does not check
|
|
|
|
// property values and returns 0 to signal success.
|
|
|
|
return 0;
|
|
|
|
}
|
2013-07-01 10:04:54 +02:00
|
|
|
|
2018-02-03 16:12:49 +01:00
|
|
|
template <size_t N>
|
|
|
|
static bool strequals (const char *actual_type_,
|
|
|
|
const size_t actual_len_,
|
|
|
|
const char (&expected_type_)[N])
|
|
|
|
{
|
|
|
|
return actual_len_ == N - 1
|
|
|
|
&& memcmp (actual_type_, expected_type_, N - 1) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool zmq::mechanism_t::check_socket_type (const char *type_,
|
|
|
|
const size_t len_) const
|
2013-07-01 10:04:54 +02:00
|
|
|
{
|
|
|
|
switch (options.type) {
|
|
|
|
case ZMQ_REQ:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_rep)
|
|
|
|
|| strequals (type_, len_, socket_type_router);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_REP:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_req)
|
|
|
|
|| strequals (type_, len_, socket_type_dealer);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_DEALER:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_rep)
|
|
|
|
|| strequals (type_, len_, socket_type_dealer)
|
|
|
|
|| strequals (type_, len_, socket_type_router);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_ROUTER:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_req)
|
|
|
|
|| strequals (type_, len_, socket_type_dealer)
|
|
|
|
|| strequals (type_, len_, socket_type_router);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_PUSH:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_pull);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_PULL:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_push);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_PUB:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_sub)
|
|
|
|
|| strequals (type_, len_, socket_type_xsub);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_SUB:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_pub)
|
|
|
|
|| strequals (type_, len_, socket_type_xpub);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_XPUB:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_sub)
|
|
|
|
|| strequals (type_, len_, socket_type_xsub);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_XSUB:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_pub)
|
|
|
|
|| strequals (type_, len_, socket_type_xpub);
|
2013-07-01 10:04:54 +02:00
|
|
|
case ZMQ_PAIR:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_pair);
|
|
|
|
#ifdef ZMQ_BUILD_DRAFT_API
|
2015-02-02 00:17:37 +01:00
|
|
|
case ZMQ_SERVER:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_client);
|
2015-02-02 10:59:13 +01:00
|
|
|
case ZMQ_CLIENT:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_server);
|
2016-01-27 17:19:14 +01:00
|
|
|
case ZMQ_RADIO:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_dish);
|
2016-01-27 17:19:14 +01:00
|
|
|
case ZMQ_DISH:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_radio);
|
2016-04-21 12:23:44 +02:00
|
|
|
case ZMQ_GATHER:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_scatter);
|
2016-04-21 12:23:44 +02:00
|
|
|
case ZMQ_SCATTER:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_gather);
|
2016-05-13 03:20:31 +02:00
|
|
|
case ZMQ_DGRAM:
|
2018-02-03 16:12:49 +01:00
|
|
|
return strequals (type_, len_, socket_type_dgram);
|
|
|
|
#endif
|
2013-07-01 10:04:54 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|