Coverage Report

Created: 2025-07-01 06:07

/src/libzmq/src/mechanism.cpp
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: MPL-2.0 */
2
3
#include "precompiled.hpp"
4
#include <string.h>
5
#include <limits.h>
6
7
#include "mechanism.hpp"
8
#include "options.hpp"
9
#include "msg.hpp"
10
#include "err.hpp"
11
#include "wire.hpp"
12
#include "session_base.hpp"
13
14
0
zmq::mechanism_t::mechanism_t (const options_t &options_) : options (options_)
15
0
{
16
0
}
17
18
zmq::mechanism_t::~mechanism_t ()
19
0
{
20
0
}
21
22
void zmq::mechanism_t::set_peer_routing_id (const void *id_ptr_,
23
                                            size_t id_size_)
24
0
{
25
0
    _routing_id.set (static_cast<const unsigned char *> (id_ptr_), id_size_);
26
0
}
27
28
void zmq::mechanism_t::peer_routing_id (msg_t *msg_)
29
0
{
30
0
    const int rc = msg_->init_size (_routing_id.size ());
31
0
    errno_assert (rc == 0);
32
0
    memcpy (msg_->data (), _routing_id.data (), _routing_id.size ());
33
0
    msg_->set_flags (msg_t::routing_id);
34
0
}
35
36
void zmq::mechanism_t::set_user_id (const void *user_id_, size_t size_)
37
0
{
38
0
    _user_id.set (static_cast<const unsigned char *> (user_id_), size_);
39
0
    _zap_properties.ZMQ_MAP_INSERT_OR_EMPLACE (
40
0
      std::string (ZMQ_MSG_PROPERTY_USER_ID),
41
0
      std::string (reinterpret_cast<const char *> (user_id_), size_));
42
0
}
43
44
const zmq::blob_t &zmq::mechanism_t::get_user_id () const
45
0
{
46
0
    return _user_id;
47
0
}
48
49
const char socket_type_pair[] = "PAIR";
50
const char socket_type_pub[] = "PUB";
51
const char socket_type_sub[] = "SUB";
52
const char socket_type_req[] = "REQ";
53
const char socket_type_rep[] = "REP";
54
const char socket_type_dealer[] = "DEALER";
55
const char socket_type_router[] = "ROUTER";
56
const char socket_type_pull[] = "PULL";
57
const char socket_type_push[] = "PUSH";
58
const char socket_type_xpub[] = "XPUB";
59
const char socket_type_xsub[] = "XSUB";
60
const char socket_type_stream[] = "STREAM";
61
#ifdef ZMQ_BUILD_DRAFT_API
62
const char socket_type_server[] = "SERVER";
63
const char socket_type_client[] = "CLIENT";
64
const char socket_type_radio[] = "RADIO";
65
const char socket_type_dish[] = "DISH";
66
const char socket_type_gather[] = "GATHER";
67
const char socket_type_scatter[] = "SCATTER";
68
const char socket_type_dgram[] = "DGRAM";
69
const char socket_type_peer[] = "PEER";
70
const char socket_type_channel[] = "CHANNEL";
71
#endif
72
73
const char *zmq::mechanism_t::socket_type_string (int socket_type_)
74
0
{
75
    // TODO the order must of the names must correspond to the values resp. order of ZMQ_* socket type definitions in zmq.h!
76
0
    static const char *names[] = {socket_type_pair,   socket_type_pub,
77
0
                                  socket_type_sub,    socket_type_req,
78
0
                                  socket_type_rep,    socket_type_dealer,
79
0
                                  socket_type_router, socket_type_pull,
80
0
                                  socket_type_push,   socket_type_xpub,
81
0
                                  socket_type_xsub,   socket_type_stream,
82
0
#ifdef ZMQ_BUILD_DRAFT_API
83
0
                                  socket_type_server, socket_type_client,
84
0
                                  socket_type_radio,  socket_type_dish,
85
0
                                  socket_type_gather, socket_type_scatter,
86
0
                                  socket_type_dgram,  socket_type_peer,
87
0
                                  socket_type_channel
88
0
#endif
89
0
    };
90
0
    static const size_t names_count = sizeof (names) / sizeof (names[0]);
91
0
    zmq_assert (socket_type_ >= 0
92
0
                && socket_type_ < static_cast<int> (names_count));
93
0
    return names[socket_type_];
94
0
}
95
96
const size_t name_len_size = sizeof (unsigned char);
97
const size_t value_len_size = sizeof (uint32_t);
98
99
static size_t property_len (size_t name_len_, size_t value_len_)
100
0
{
101
0
    return name_len_size + name_len_ + value_len_size + value_len_;
102
0
}
103
104
static size_t name_len (const char *name_)
105
0
{
106
0
    const size_t name_len = strlen (name_);
107
0
    zmq_assert (name_len <= UCHAR_MAX);
108
0
    return name_len;
109
0
}
110
111
size_t zmq::mechanism_t::add_property (unsigned char *ptr_,
112
                                       size_t ptr_capacity_,
113
                                       const char *name_,
114
                                       const void *value_,
115
                                       size_t value_len_)
116
0
{
117
0
    const size_t name_len = ::name_len (name_);
118
0
    const size_t total_len = ::property_len (name_len, value_len_);
119
0
    zmq_assert (total_len <= ptr_capacity_);
120
121
0
    *ptr_ = static_cast<unsigned char> (name_len);
122
0
    ptr_ += name_len_size;
123
0
    memcpy (ptr_, name_, name_len);
124
0
    ptr_ += name_len;
125
0
    zmq_assert (value_len_ <= 0x7FFFFFFF);
126
0
    put_uint32 (ptr_, static_cast<uint32_t> (value_len_));
127
0
    ptr_ += value_len_size;
128
0
    memcpy (ptr_, value_, value_len_);
129
130
0
    return total_len;
131
0
}
132
133
size_t zmq::mechanism_t::property_len (const char *name_, size_t value_len_)
134
0
{
135
0
    return ::property_len (name_len (name_), value_len_);
136
0
}
137
138
0
#define ZMTP_PROPERTY_SOCKET_TYPE "Socket-Type"
139
0
#define ZMTP_PROPERTY_IDENTITY "Identity"
140
141
size_t zmq::mechanism_t::add_basic_properties (unsigned char *ptr_,
142
                                               size_t ptr_capacity_) const
143
0
{
144
0
    unsigned char *ptr = ptr_;
145
146
    //  Add socket type property
147
0
    const char *socket_type = socket_type_string (options.type);
148
0
    ptr += add_property (ptr, ptr_capacity_, ZMTP_PROPERTY_SOCKET_TYPE,
149
0
                         socket_type, strlen (socket_type));
150
151
    //  Add identity (aka routing id) property
152
0
    if (options.type == ZMQ_REQ || options.type == ZMQ_DEALER
153
0
        || options.type == ZMQ_ROUTER) {
154
0
        ptr += add_property (ptr, ptr_capacity_ - (ptr - ptr_),
155
0
                             ZMTP_PROPERTY_IDENTITY, options.routing_id,
156
0
                             options.routing_id_size);
157
0
    }
158
159
160
0
    for (std::map<std::string, std::string>::const_iterator
161
0
           it = options.app_metadata.begin (),
162
0
           end = options.app_metadata.end ();
163
0
         it != end; ++it) {
164
0
        ptr +=
165
0
          add_property (ptr, ptr_capacity_ - (ptr - ptr_), it->first.c_str (),
166
0
                        it->second.c_str (), strlen (it->second.c_str ()));
167
0
    }
168
169
0
    return ptr - ptr_;
170
0
}
171
172
size_t zmq::mechanism_t::basic_properties_len () const
173
0
{
174
0
    const char *socket_type = socket_type_string (options.type);
175
0
    size_t meta_len = 0;
176
177
0
    for (std::map<std::string, std::string>::const_iterator
178
0
           it = options.app_metadata.begin (),
179
0
           end = options.app_metadata.end ();
180
0
         it != end; ++it) {
181
0
        meta_len +=
182
0
          property_len (it->first.c_str (), strlen (it->second.c_str ()));
183
0
    }
184
185
0
    return property_len (ZMTP_PROPERTY_SOCKET_TYPE, strlen (socket_type))
186
0
           + meta_len
187
0
           + ((options.type == ZMQ_REQ || options.type == ZMQ_DEALER
188
0
               || options.type == ZMQ_ROUTER)
189
0
                ? property_len (ZMTP_PROPERTY_IDENTITY, options.routing_id_size)
190
0
                : 0);
191
0
}
192
193
void zmq::mechanism_t::make_command_with_basic_properties (
194
  msg_t *msg_, const char *prefix_, size_t prefix_len_) const
195
0
{
196
0
    const size_t command_size = prefix_len_ + basic_properties_len ();
197
0
    const int rc = msg_->init_size (command_size);
198
0
    errno_assert (rc == 0);
199
200
0
    unsigned char *ptr = static_cast<unsigned char *> (msg_->data ());
201
202
    //  Add prefix
203
0
    memcpy (ptr, prefix_, prefix_len_);
204
0
    ptr += prefix_len_;
205
206
0
    add_basic_properties (
207
0
      ptr, command_size - (ptr - static_cast<unsigned char *> (msg_->data ())));
208
0
}
209
210
int zmq::mechanism_t::parse_metadata (const unsigned char *ptr_,
211
                                      size_t length_,
212
                                      bool zap_flag_)
213
0
{
214
0
    size_t bytes_left = length_;
215
216
0
    while (bytes_left > 1) {
217
0
        const size_t name_length = static_cast<size_t> (*ptr_);
218
0
        ptr_ += name_len_size;
219
0
        bytes_left -= name_len_size;
220
0
        if (bytes_left < name_length)
221
0
            break;
222
223
0
        const std::string name =
224
0
          std::string (reinterpret_cast<const char *> (ptr_), name_length);
225
0
        ptr_ += name_length;
226
0
        bytes_left -= name_length;
227
0
        if (bytes_left < value_len_size)
228
0
            break;
229
230
0
        const size_t value_length = static_cast<size_t> (get_uint32 (ptr_));
231
0
        ptr_ += value_len_size;
232
0
        bytes_left -= value_len_size;
233
0
        if (bytes_left < value_length)
234
0
            break;
235
236
0
        const uint8_t *value = ptr_;
237
0
        ptr_ += value_length;
238
0
        bytes_left -= value_length;
239
240
0
        if (name == ZMTP_PROPERTY_IDENTITY && options.recv_routing_id)
241
0
            set_peer_routing_id (value, value_length);
242
0
        else if (name == ZMTP_PROPERTY_SOCKET_TYPE) {
243
0
            if (!check_socket_type (reinterpret_cast<const char *> (value),
244
0
                                    value_length)) {
245
0
                errno = EINVAL;
246
0
                return -1;
247
0
            }
248
0
        } else {
249
0
            const int rc = property (name, value, value_length);
250
0
            if (rc == -1)
251
0
                return -1;
252
0
        }
253
0
        (zap_flag_ ? _zap_properties : _zmtp_properties)
254
0
          .ZMQ_MAP_INSERT_OR_EMPLACE (
255
0
            name,
256
0
            std::string (reinterpret_cast<const char *> (value), value_length));
257
0
    }
258
0
    if (bytes_left > 0) {
259
0
        errno = EPROTO;
260
0
        return -1;
261
0
    }
262
0
    return 0;
263
0
}
264
265
int zmq::mechanism_t::property (const std::string & /* name_ */,
266
                                const void * /* value_ */,
267
                                size_t /* length_ */)
268
0
{
269
    //  Default implementation does not check
270
    //  property values and returns 0 to signal success.
271
0
    return 0;
272
0
}
273
274
template <size_t N>
275
static bool strequals (const char *actual_type_,
276
                       const size_t actual_len_,
277
                       const char (&expected_type_)[N])
278
0
{
279
0
    return actual_len_ == N - 1
280
0
           && memcmp (actual_type_, expected_type_, N - 1) == 0;
281
0
}
Unexecuted instantiation: mechanism.cpp:bool strequals<4ul>(char const*, unsigned long, char const (&) [4ul])
Unexecuted instantiation: mechanism.cpp:bool strequals<7ul>(char const*, unsigned long, char const (&) [7ul])
Unexecuted instantiation: mechanism.cpp:bool strequals<5ul>(char const*, unsigned long, char const (&) [5ul])
Unexecuted instantiation: mechanism.cpp:bool strequals<6ul>(char const*, unsigned long, char const (&) [6ul])
Unexecuted instantiation: mechanism.cpp:bool strequals<8ul>(char const*, unsigned long, char const (&) [8ul])
282
283
bool zmq::mechanism_t::check_socket_type (const char *type_,
284
                                          const size_t len_) const
285
0
{
286
0
    switch (options.type) {
287
0
        case ZMQ_REQ:
288
0
            return strequals (type_, len_, socket_type_rep)
289
0
                   || strequals (type_, len_, socket_type_router);
290
0
        case ZMQ_REP:
291
0
            return strequals (type_, len_, socket_type_req)
292
0
                   || strequals (type_, len_, socket_type_dealer);
293
0
        case ZMQ_DEALER:
294
0
            return strequals (type_, len_, socket_type_rep)
295
0
                   || strequals (type_, len_, socket_type_dealer)
296
0
                   || strequals (type_, len_, socket_type_router);
297
0
        case ZMQ_ROUTER:
298
0
            return strequals (type_, len_, socket_type_req)
299
0
                   || strequals (type_, len_, socket_type_dealer)
300
0
                   || strequals (type_, len_, socket_type_router);
301
0
        case ZMQ_PUSH:
302
0
            return strequals (type_, len_, socket_type_pull);
303
0
        case ZMQ_PULL:
304
0
            return strequals (type_, len_, socket_type_push);
305
0
        case ZMQ_PUB:
306
0
            return strequals (type_, len_, socket_type_sub)
307
0
                   || strequals (type_, len_, socket_type_xsub);
308
0
        case ZMQ_SUB:
309
0
            return strequals (type_, len_, socket_type_pub)
310
0
                   || strequals (type_, len_, socket_type_xpub);
311
0
        case ZMQ_XPUB:
312
0
            return strequals (type_, len_, socket_type_sub)
313
0
                   || strequals (type_, len_, socket_type_xsub);
314
0
        case ZMQ_XSUB:
315
0
            return strequals (type_, len_, socket_type_pub)
316
0
                   || strequals (type_, len_, socket_type_xpub);
317
0
        case ZMQ_PAIR:
318
0
            return strequals (type_, len_, socket_type_pair);
319
0
#ifdef ZMQ_BUILD_DRAFT_API
320
0
        case ZMQ_SERVER:
321
0
            return strequals (type_, len_, socket_type_client);
322
0
        case ZMQ_CLIENT:
323
0
            return strequals (type_, len_, socket_type_server);
324
0
        case ZMQ_RADIO:
325
0
            return strequals (type_, len_, socket_type_dish);
326
0
        case ZMQ_DISH:
327
0
            return strequals (type_, len_, socket_type_radio);
328
0
        case ZMQ_GATHER:
329
0
            return strequals (type_, len_, socket_type_scatter);
330
0
        case ZMQ_SCATTER:
331
0
            return strequals (type_, len_, socket_type_gather);
332
0
        case ZMQ_DGRAM:
333
0
            return strequals (type_, len_, socket_type_dgram);
334
0
        case ZMQ_PEER:
335
0
            return strequals (type_, len_, socket_type_peer);
336
0
        case ZMQ_CHANNEL:
337
0
            return strequals (type_, len_, socket_type_channel);
338
0
#endif
339
0
        default:
340
0
            break;
341
0
    }
342
0
    return false;
343
0
}