plain_client.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 #include "macros.hpp"
5 
6 #include <string>
7 #include <limits.h>
8 
9 #include "msg.hpp"
10 #include "err.hpp"
11 #include "plain_client.hpp"
12 #include "session_base.hpp"
13 #include "plain_common.hpp"
14 
15 zmq::plain_client_t::plain_client_t (session_base_t *const session_,
16  const options_t &options_) :
17  mechanism_base_t (session_, options_), _state (sending_hello)
18 {
19 }
20 
21 zmq::plain_client_t::~plain_client_t ()
22 {
23 }
24 
25 int zmq::plain_client_t::next_handshake_command (msg_t *msg_)
26 {
27  int rc = 0;
28 
29  switch (_state) {
30  case sending_hello:
31  produce_hello (msg_);
32  _state = waiting_for_welcome;
33  break;
34  case sending_initiate:
35  produce_initiate (msg_);
36  _state = waiting_for_ready;
37  break;
38  default:
39  errno = EAGAIN;
40  rc = -1;
41  }
42  return rc;
43 }
44 
45 int zmq::plain_client_t::process_handshake_command (msg_t *msg_)
46 {
47  const unsigned char *cmd_data =
48  static_cast<unsigned char *> (msg_->data ());
49  const size_t data_size = msg_->size ();
50 
51  int rc = 0;
52  if (data_size >= welcome_prefix_len
53  && !memcmp (cmd_data, welcome_prefix, welcome_prefix_len))
54  rc = process_welcome (cmd_data, data_size);
55  else if (data_size >= ready_prefix_len
56  && !memcmp (cmd_data, ready_prefix, ready_prefix_len))
57  rc = process_ready (cmd_data, data_size);
58  else if (data_size >= error_prefix_len
59  && !memcmp (cmd_data, error_prefix, error_prefix_len))
60  rc = process_error (cmd_data, data_size);
61  else {
62  session->get_socket ()->event_handshake_failed_protocol (
63  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
64  errno = EPROTO;
65  rc = -1;
66  }
67 
68  if (rc == 0) {
69  rc = msg_->close ();
70  errno_assert (rc == 0);
71  rc = msg_->init ();
72  errno_assert (rc == 0);
73  }
74 
75  return rc;
76 }
77 
78 zmq::mechanism_t::status_t zmq::plain_client_t::status () const
79 {
80  switch (_state) {
81  case ready:
82  return mechanism_t::ready;
83  case error_command_received:
84  return mechanism_t::error;
85  default:
87  }
88 }
89 
90 void zmq::plain_client_t::produce_hello (msg_t *msg_) const
91 {
92  const std::string username = options.plain_username;
93  zmq_assert (username.length () <= UCHAR_MAX);
94 
95  const std::string password = options.plain_password;
96  zmq_assert (password.length () <= UCHAR_MAX);
97 
98  const size_t command_size = hello_prefix_len + brief_len_size
99  + username.length () + brief_len_size
100  + password.length ();
101 
102  const int rc = msg_->init_size (command_size);
103  errno_assert (rc == 0);
104 
105  unsigned char *ptr = static_cast<unsigned char *> (msg_->data ());
106  memcpy (ptr, hello_prefix, hello_prefix_len);
107  ptr += hello_prefix_len;
108 
109  *ptr++ = static_cast<unsigned char> (username.length ());
110  memcpy (ptr, username.c_str (), username.length ());
111  ptr += username.length ();
112 
113  *ptr++ = static_cast<unsigned char> (password.length ());
114  memcpy (ptr, password.c_str (), password.length ());
115 }
116 
117 int zmq::plain_client_t::process_welcome (const unsigned char *cmd_data_,
118  size_t data_size_)
119 {
120  LIBZMQ_UNUSED (cmd_data_);
121 
122  if (_state != waiting_for_welcome) {
123  session->get_socket ()->event_handshake_failed_protocol (
124  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
125  errno = EPROTO;
126  return -1;
127  }
128  if (data_size_ != welcome_prefix_len) {
129  session->get_socket ()->event_handshake_failed_protocol (
130  session->get_endpoint (),
132  errno = EPROTO;
133  return -1;
134  }
135  _state = sending_initiate;
136  return 0;
137 }
138 
139 void zmq::plain_client_t::produce_initiate (msg_t *msg_) const
140 {
141  make_command_with_basic_properties (msg_, initiate_prefix,
143 }
144 
145 int zmq::plain_client_t::process_ready (const unsigned char *cmd_data_,
146  size_t data_size_)
147 {
148  if (_state != waiting_for_ready) {
149  session->get_socket ()->event_handshake_failed_protocol (
150  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
151  errno = EPROTO;
152  return -1;
153  }
154  const int rc = parse_metadata (cmd_data_ + ready_prefix_len,
155  data_size_ - ready_prefix_len);
156  if (rc == 0)
157  _state = ready;
158  else
159  session->get_socket ()->event_handshake_failed_protocol (
160  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA);
161 
162  return rc;
163 }
164 
165 int zmq::plain_client_t::process_error (const unsigned char *cmd_data_,
166  size_t data_size_)
167 {
168  if (_state != waiting_for_welcome && _state != waiting_for_ready) {
169  session->get_socket ()->event_handshake_failed_protocol (
170  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
171  errno = EPROTO;
172  return -1;
173  }
174  const size_t start_of_error_reason = error_prefix_len + brief_len_size;
175  if (data_size_ < start_of_error_reason) {
176  session->get_socket ()->event_handshake_failed_protocol (
177  session->get_endpoint (),
179  errno = EPROTO;
180  return -1;
181  }
182  const size_t error_reason_len =
183  static_cast<size_t> (cmd_data_[error_prefix_len]);
184  if (error_reason_len > data_size_ - start_of_error_reason) {
185  session->get_socket ()->event_handshake_failed_protocol (
186  session->get_endpoint (),
188  errno = EPROTO;
189  return -1;
190  }
191  const char *error_reason =
192  reinterpret_cast<const char *> (cmd_data_) + start_of_error_reason;
193  handle_error_reason (error_reason, error_reason_len);
194  _state = error_command_received;
195  return 0;
196 }
ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND
#define ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND
Definition: zmq.h:425
zmq::initiate_prefix
const char initiate_prefix[]
Definition: plain_common.hpp:14
zmq::mechanism_t::ready
@ ready
Definition: mechanism.hpp:25
zmq::mechanism_t::error
@ error
Definition: mechanism.hpp:26
options
Message * options
Definition: src/google/protobuf/descriptor.cc:3119
zmq::ready_prefix
const char ready_prefix[]
Definition: plain_common.hpp:17
EAGAIN
#define EAGAIN
Definition: errno.hpp:14
precompiled.hpp
zmq_assert
#define zmq_assert(x)
Definition: err.hpp:102
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
errno
int errno
zmq::ready_prefix_len
const size_t ready_prefix_len
Definition: plain_common.hpp:18
plain_common.hpp
zmq::hello_prefix_len
const size_t hello_prefix_len
Definition: plain_common.hpp:9
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR
Definition: zmq.h:432
EPROTO
#define EPROTO
Definition: err.hpp:26
zmq::hello_prefix
const char hello_prefix[]
Definition: plain_common.hpp:8
ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA
#define ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA
Definition: zmq.h:435
errno_assert
#define errno_assert(x)
Definition: err.hpp:113
macros.hpp
zmq::brief_len_size
const size_t brief_len_size
Definition: plain_common.hpp:23
LIBZMQ_UNUSED
#define LIBZMQ_UNUSED(object)
Definition: macros.hpp:6
zmq::mechanism_t::handshaking
@ handshaking
Definition: mechanism.hpp:24
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_WELCOME
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_WELCOME
Definition: zmq.h:434
zmq::error_prefix_len
const size_t error_prefix_len
Definition: plain_common.hpp:21
zmq::mechanism_t::status_t
status_t
Definition: mechanism.hpp:22
zmq::welcome_prefix_len
const size_t welcome_prefix_len
Definition: plain_common.hpp:12
msg.hpp
plain_client.hpp
zmq::welcome_prefix
const char welcome_prefix[]
Definition: plain_common.hpp:11
err.hpp
zmq::initiate_prefix_len
const size_t initiate_prefix_len
Definition: plain_common.hpp:15
session_base.hpp
options_
DebugStringOptions options_
Definition: src/google/protobuf/descriptor.cc:2410
zmq::error_prefix
const char error_prefix[]
Definition: plain_common.hpp:20


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:57