zap_client.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 
5 #include "zap_client.hpp"
6 #include "msg.hpp"
7 #include "session_base.hpp"
8 
9 namespace zmq
10 {
11 const char zap_version[] = "1.0";
12 const size_t zap_version_len = sizeof (zap_version) - 1;
13 
14 const char id[] = "1";
15 const size_t id_len = sizeof (id) - 1;
16 
18  const std::string &peer_address_,
19  const options_t &options_) :
20  mechanism_base_t (session_, options_), peer_address (peer_address_)
21 {
22 }
23 
24 void zap_client_t::send_zap_request (const char *mechanism_,
25  size_t mechanism_length_,
26  const uint8_t *credentials_,
27  size_t credentials_size_)
28 {
29  send_zap_request (mechanism_, mechanism_length_, &credentials_,
30  &credentials_size_, 1);
31 }
32 
33 void zap_client_t::send_zap_request (const char *mechanism_,
34  size_t mechanism_length_,
35  const uint8_t **credentials_,
36  size_t *credentials_sizes_,
37  size_t credentials_count_)
38 {
39  // write_zap_msg cannot fail. It could only fail if the HWM was exceeded,
40  // but on the ZAP socket, the HWM is disabled.
41 
42  int rc;
43  msg_t msg;
44 
45  // Address delimiter frame
46  rc = msg.init ();
47  errno_assert (rc == 0);
48  msg.set_flags (msg_t::more);
49  rc = session->write_zap_msg (&msg);
50  errno_assert (rc == 0);
51 
52  // Version frame
53  rc = msg.init_size (zap_version_len);
54  errno_assert (rc == 0);
55  memcpy (msg.data (), zap_version, zap_version_len);
56  msg.set_flags (msg_t::more);
57  rc = session->write_zap_msg (&msg);
58  errno_assert (rc == 0);
59 
60  // Request ID frame
61  rc = msg.init_size (id_len);
62  errno_assert (rc == 0);
63  memcpy (msg.data (), id, id_len);
64  msg.set_flags (msg_t::more);
65  rc = session->write_zap_msg (&msg);
66  errno_assert (rc == 0);
67 
68  // Domain frame
69  rc = msg.init_size (options.zap_domain.length ());
70  errno_assert (rc == 0);
71  memcpy (msg.data (), options.zap_domain.c_str (),
72  options.zap_domain.length ());
73  msg.set_flags (msg_t::more);
74  rc = session->write_zap_msg (&msg);
75  errno_assert (rc == 0);
76 
77  // Address frame
78  rc = msg.init_size (peer_address.length ());
79  errno_assert (rc == 0);
80  memcpy (msg.data (), peer_address.c_str (), peer_address.length ());
81  msg.set_flags (msg_t::more);
82  rc = session->write_zap_msg (&msg);
83  errno_assert (rc == 0);
84 
85  // Routing id frame
87  errno_assert (rc == 0);
88  memcpy (msg.data (), options.routing_id, options.routing_id_size);
89  msg.set_flags (msg_t::more);
90  rc = session->write_zap_msg (&msg);
91  errno_assert (rc == 0);
92 
93  // Mechanism frame
94  rc = msg.init_size (mechanism_length_);
95  errno_assert (rc == 0);
96  memcpy (msg.data (), mechanism_, mechanism_length_);
97  if (credentials_count_)
98  msg.set_flags (msg_t::more);
99  rc = session->write_zap_msg (&msg);
100  errno_assert (rc == 0);
101 
102  // Credentials frames
103  for (size_t i = 0; i < credentials_count_; ++i) {
104  rc = msg.init_size (credentials_sizes_[i]);
105  errno_assert (rc == 0);
106  if (i < credentials_count_ - 1)
107  msg.set_flags (msg_t::more);
108  memcpy (msg.data (), credentials_[i], credentials_sizes_[i]);
109  rc = session->write_zap_msg (&msg);
110  errno_assert (rc == 0);
111  }
112 }
113 
115 {
116  int rc = 0;
117  const size_t zap_reply_frame_count = 7;
118  msg_t msg[zap_reply_frame_count];
119 
120  // Initialize all reply frames
121  for (size_t i = 0; i < zap_reply_frame_count; i++) {
122  rc = msg[i].init ();
123  errno_assert (rc == 0);
124  }
125 
126  for (size_t i = 0; i < zap_reply_frame_count; i++) {
127  rc = session->read_zap_msg (&msg[i]);
128  if (rc == -1) {
129  if (errno == EAGAIN) {
130  return 1;
131  }
132  return close_and_return (msg, -1);
133  }
134  if ((msg[i].flags () & msg_t::more)
135  == (i < zap_reply_frame_count - 1 ? 0 : msg_t::more)) {
138  errno = EPROTO;
139  return close_and_return (msg, -1);
140  }
141  }
142 
143  // Address delimiter frame
144  if (msg[0].size () > 0) {
145  // TODO can a ZAP handler produce such a message at all?
148  errno = EPROTO;
149  return close_and_return (msg, -1);
150  }
151 
152  // Version frame
153  if (msg[1].size () != zap_version_len
154  || memcmp (msg[1].data (), zap_version, zap_version_len)) {
157  errno = EPROTO;
158  return close_and_return (msg, -1);
159  }
160 
161  // Request id frame
162  if (msg[2].size () != id_len || memcmp (msg[2].data (), id, id_len)) {
165  errno = EPROTO;
166  return close_and_return (msg, -1);
167  }
168 
169  // Status code frame, only 200, 300, 400 and 500 are valid status codes
170  const char *status_code_data = static_cast<const char *> (msg[3].data ());
171  if (msg[3].size () != 3 || status_code_data[0] < '2'
172  || status_code_data[0] > '5' || status_code_data[1] != '0'
173  || status_code_data[2] != '0') {
176  errno = EPROTO;
177  return close_and_return (msg, -1);
178  }
179 
180  // Save status code
181  status_code.assign (static_cast<char *> (msg[3].data ()), 3);
182 
183  // Save user id
184  set_user_id (msg[5].data (), msg[5].size ());
185 
186  // Process metadata frame
187  rc = parse_metadata (static_cast<const unsigned char *> (msg[6].data ()),
188  msg[6].size (), true);
189 
190  if (rc != 0) {
193  errno = EPROTO;
194  return close_and_return (msg, -1);
195  }
196 
197  // Close all reply frames
198  for (size_t i = 0; i < zap_reply_frame_count; i++) {
199  const int rc2 = msg[i].close ();
200  errno_assert (rc2 == 0);
201  }
202 
204 
205  return 0;
206 }
207 
209 {
210  // we can assume here that status_code is a valid ZAP status code,
211  // i.e. 200, 300, 400 or 500
212  int status_code_numeric = 0;
213  switch (status_code[0]) {
214  case '2':
215  return;
216  case '3':
217  status_code_numeric = 300;
218  break;
219  case '4':
220  status_code_numeric = 400;
221  break;
222  case '5':
223  status_code_numeric = 500;
224  break;
225  }
226 
228  session->get_endpoint (), status_code_numeric);
229 }
230 
232  session_base_t *const session_,
233  const std::string &peer_address_,
234  const options_t &options_,
235  state_t zap_reply_ok_state_) :
236  mechanism_base_t (session_, options_),
237  zap_client_t (session_, peer_address_, options_),
238  state (waiting_for_hello),
239  _zap_reply_ok_state (zap_reply_ok_state_)
240 {
241 }
242 
244 {
245  if (state == ready)
246  return mechanism_t::ready;
247  if (state == error_sent)
248  return mechanism_t::error;
249 
251 }
252 
254 {
256  return receive_and_process_zap_reply () == -1 ? -1 : 0;
257 }
258 
260 {
262 
263  // we can assume here that status_code is a valid ZAP status code,
264  // i.e. 200, 300, 400 or 500
265  switch (status_code[0]) {
266  case '2':
268  break;
269  case '3':
270  // a 300 error code (temporary failure)
271  // should NOT result in an ERROR message, but instead the
272  // client should be silently disconnected (see CURVEZMQ RFC)
273  // therefore, go immediately to state error_sent
274  state = error_sent;
275  break;
276  default:
278  }
279 }
280 
282 {
285 }
286 }
zmq::zap_version_len
const size_t zap_version_len
Definition: zap_client.cpp:12
zmq::session_base_t
Definition: session_base.hpp:21
zmq::zap_client_common_handshake_t::_zap_reply_ok_state
const state_t _zap_reply_ok_state
Definition: zap_client.hpp:70
zmq::zap_version
const char zap_version[]
Definition: zap_client.cpp:11
zmq::options_t
Definition: options.hpp:34
zmq::id_len
const size_t id_len
Definition: zap_client.cpp:15
zmq::zap_client_common_handshake_t::handle_zap_status_code
void handle_zap_status_code() ZMQ_FINAL
Definition: zap_client.cpp:259
zmq::mechanism_t::ready
@ ready
Definition: mechanism.hpp:25
zmq::mechanism_t::error
@ error
Definition: mechanism.hpp:26
EAGAIN
#define EAGAIN
Definition: errno.hpp:14
zmq::session_base_t::get_endpoint
const endpoint_uri_pair_t & get_endpoint() const
Definition: session_base.cpp:112
precompiled.hpp
zmq_assert
#define zmq_assert(x)
Definition: err.hpp:102
zmq::zap_client_common_handshake_t::ready
@ ready
Definition: zap_client.hpp:50
zmq::session_base_t::write_zap_msg
int write_zap_msg(msg_t *msg_)
Definition: session_base.cpp:187
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
errno
int errno
zmq::zap_client_t::zap_client_t
zap_client_t(session_base_t *session_, const std::string &peer_address_, const options_t &options_)
Definition: zap_client.cpp:17
zmq::zap_client_common_handshake_t::state_t
state_t
Definition: zap_client.hpp:41
zmq::zap_client_common_handshake_t::state
state_t state
Definition: zap_client.hpp:67
zmq::zap_client_common_handshake_t::receive_and_process_zap_reply
int receive_and_process_zap_reply() ZMQ_FINAL
Definition: zap_client.cpp:281
flags
GLbitfield flags
Definition: glcorearb.h:3585
zmq::options_t::zap_domain
std::string zap_domain
Definition: options.hpp:178
zmq::mechanism_base_t::session
session_base_t *const session
Definition: mechanism_base.hpp:17
zmq::msg_t::init_size
int init_size(size_t size_)
Definition: msg.cpp:62
zmq::mechanism_t::parse_metadata
int parse_metadata(const unsigned char *ptr_, size_t length_, bool zap_flag_=false)
Definition: mechanism.cpp:210
zmq::zap_client_t::status_code
std::string status_code
Definition: zap_client.hpp:35
zmq
Definition: zmq.hpp:229
EPROTO
#define EPROTO
Definition: err.hpp:26
zmq::socket_base_t::event_handshake_failed_auth
void event_handshake_failed_auth(const endpoint_uri_pair_t &endpoint_uri_pair_, int err_)
Definition: socket_base.cpp:1925
zmq::socket_base_t::event_handshake_failed_protocol
void event_handshake_failed_protocol(const endpoint_uri_pair_t &endpoint_uri_pair_, int err_)
Definition: socket_base.cpp:1918
errno_assert
#define errno_assert(x)
Definition: err.hpp:113
zmq::session_base_t::get_socket
socket_base_t * get_socket() const
Definition: session_base.cpp:316
zap_client.hpp
zmq::mechanism_t::handshaking
@ handshaking
Definition: mechanism.hpp:24
zmq::msg_t::close
int close()
Definition: msg.cpp:242
zmq::options_t::routing_id_size
unsigned char routing_id_size
Definition: options.hpp:53
zmq::zap_client_t::receive_and_process_zap_reply
virtual int receive_and_process_zap_reply()
Definition: zap_client.cpp:114
zmq::zap_client_t::send_zap_request
void send_zap_request(const char *mechanism_, size_t mechanism_length_, const uint8_t *credentials_, size_t credentials_size_)
Definition: zap_client.cpp:24
zmq::close_and_return
int close_and_return(zmq::msg_t *msg_, int echo_)
Definition: msg.hpp:300
zmq::mechanism_t::status_t
status_t
Definition: mechanism.hpp:22
zmq::zap_client_common_handshake_t::sending_error
@ sending_error
Definition: zap_client.hpp:48
zmq::msg_t::init
int init()
Definition: msg.cpp:50
ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID
#define ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID
Definition: zmq.h:441
i
int i
Definition: gmock-matchers_test.cc:764
msg.hpp
zmq::id
const char id[]
Definition: zap_client.cpp:14
zmq::session_base_t::read_zap_msg
int read_zap_msg(msg_t *msg_)
Definition: session_base.cpp:172
zmq::msg_t::more
@ more
Definition: msg.hpp:55
zmq::zap_client_common_handshake_t::waiting_for_zap_reply
@ waiting_for_zap_reply
Definition: zap_client.hpp:46
zmq::zap_client_common_handshake_t::zap_msg_available
int zap_msg_available() ZMQ_FINAL
Definition: zap_client.cpp:253
zmq::zap_client_common_handshake_t::zap_client_common_handshake_t
zap_client_common_handshake_t(session_base_t *session_, const std::string &peer_address_, const options_t &options_, state_t zap_reply_ok_state_)
Definition: zap_client.cpp:231
ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY
#define ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY
Definition: zmq.h:440
size
GLsizeiptr size
Definition: glcorearb.h:2943
zmq::zap_client_t::handle_zap_status_code
virtual void handle_zap_status_code()
Definition: zap_client.cpp:208
zmq::zap_client_common_handshake_t::error_sent
@ error_sent
Definition: zap_client.hpp:49
zmq::mechanism_base_t
Definition: mechanism_base.hpp:12
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: glcorearb.h:2879
zmq::mechanism_t::options
const options_t options
Definition: mechanism.hpp:105
zmq::zap_client_common_handshake_t::status
status_t status() const ZMQ_FINAL
Definition: zap_client.cpp:243
zmq::zap_client_t
Definition: zap_client.hpp:10
ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE
#define ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE
Definition: zmq.h:443
session_base.hpp
zmq::msg_t::data
unsigned char data[max_vsm_size]
Definition: msg.hpp:239
zmq::options_t::routing_id
unsigned char routing_id[256]
Definition: options.hpp:54
ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION
#define ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION
Definition: zmq.h:442
zmq::msg_t::set_flags
void set_flags(unsigned char flags_)
Definition: msg.cpp:433
zmq::mechanism_t::set_user_id
void set_user_id(const void *user_id_, size_t size_)
Definition: mechanism.cpp:36
zmq::msg_t
Definition: msg.hpp:33
zmq::zap_client_t::peer_address
const std::string peer_address
Definition: zap_client.hpp:32
ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED
#define ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED
Definition: zmq.h:439
ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA
#define ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA
Definition: zmq.h:444
options_
DebugStringOptions options_
Definition: src/google/protobuf/descriptor.cc:2410


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