diff --git a/src/curve_client.cpp b/src/curve_client.cpp index e0641990..c811d3c3 100644 --- a/src/curve_client.cpp +++ b/src/curve_client.cpp @@ -399,47 +399,16 @@ int zmq::curve_client_t::process_ready (msg_t *msg_) return -1; } - rc = parse_property_list (ready_plaintext + crypto_box_ZEROBYTES, - clen - crypto_box_ZEROBYTES); + rc = parse_properties (ready_plaintext + crypto_box_ZEROBYTES, + clen - crypto_box_ZEROBYTES); return rc; } -int zmq::curve_client_t::parse_property_list (const uint8_t *ptr, - size_t bytes_left) +int zmq::curve_client_t::property (const std::string name, + const void *value, size_t length) { - while (bytes_left > 1) { - const size_t name_length = static_cast (*ptr); - ptr += 1; - bytes_left -= 1; - if (bytes_left < name_length) - break; - - const std::string name = std::string ((const char *) ptr, name_length); - ptr += name_length; - bytes_left -= name_length; - if (bytes_left < 4) - break; - - const size_t value_length = static_cast (get_uint32 (ptr)); - ptr += 4; - bytes_left -= 4; - if (bytes_left < value_length) - break; - - const uint8_t * const value = ptr; - ptr += value_length; - bytes_left -= value_length; - - if (name == "Socket-Type") { - // TODO: Implement socket type checking - } - else - if (name == "Identity" && options.recv_identity) - set_peer_identity (value, value_length); - } - if (bytes_left > 0) { - errno = EPROTO; - return -1; + if (name == "Socket-Type") { + // TODO: Implement socket type checking } return 0; } diff --git a/src/curve_client.hpp b/src/curve_client.hpp index 66a071ff..f825ef3a 100644 --- a/src/curve_client.hpp +++ b/src/curve_client.hpp @@ -101,7 +101,8 @@ namespace zmq int initiate_msg (msg_t *msg_); int process_ready (msg_t *msg_); - int parse_property_list (const uint8_t *ptr, size_t length); + virtual int property (const std::string name, + const void *value, size_t length); }; } diff --git a/src/curve_server.cpp b/src/curve_server.cpp index 10d592a2..16c7d1e4 100644 --- a/src/curve_server.cpp +++ b/src/curve_server.cpp @@ -441,8 +441,8 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) } } - return parse_property_list (initiate_plaintext + crypto_box_ZEROBYTES + 96, - clen - crypto_box_ZEROBYTES - 96); + return parse_properties (initiate_plaintext + crypto_box_ZEROBYTES + 96, + clen - crypto_box_ZEROBYTES - 96); } int zmq::curve_server_t::ready_msg (msg_t *msg_) @@ -543,42 +543,11 @@ void zmq::curve_server_t::send_zap_request (const uint8_t *key) errno_assert (rc == 0); } -int zmq::curve_server_t::parse_property_list (const uint8_t *ptr, - size_t bytes_left) +int zmq::curve_server_t::property (const std::string name, + const void *value, size_t length) { - while (bytes_left > 1) { - const size_t name_length = static_cast (*ptr); - ptr += 1; - bytes_left -= 1; - if (bytes_left < name_length) - break; - - const std::string name = std::string ((const char *) ptr, name_length); - ptr += name_length; - bytes_left -= name_length; - if (bytes_left < 4) - break; - - const size_t value_length = static_cast (get_uint32 (ptr)); - ptr += 4; - bytes_left -= 4; - if (bytes_left < value_length) - break; - - const uint8_t * const value = ptr; - ptr += value_length; - bytes_left -= value_length; - - if (name == "Socket-Type") { - // TODO: Implement socket type checking - } - else - if (name == "Identity" && options.recv_identity) - set_peer_identity (value, value_length); - } - if (bytes_left > 0) { - errno = EPROTO; - return -1; + if (name == "Socket-Type") { + // TODO: Implement socket type checking } return 0; } diff --git a/src/curve_server.hpp b/src/curve_server.hpp index 2aeb6b6f..ba5fc4f2 100644 --- a/src/curve_server.hpp +++ b/src/curve_server.hpp @@ -107,7 +107,9 @@ namespace zmq void send_zap_request (const uint8_t *key); int receive_and_process_zap_reply (); - int parse_property_list (const uint8_t *ptr, size_t length); + + virtual int property (const std::string name, + const void *value, size_t length); }; } diff --git a/src/mechanism.cpp b/src/mechanism.cpp index 1ad0bb32..bee0a00c 100644 --- a/src/mechanism.cpp +++ b/src/mechanism.cpp @@ -71,3 +71,53 @@ size_t zmq::mechanism_t::add_property (unsigned char *ptr, const char *name, return 1 + name_len + 4 + value_len; } + +int zmq::mechanism_t::parse_properties (const unsigned char *ptr_, + size_t length_) +{ + size_t bytes_left = length_; + + while (bytes_left > 1) { + const size_t name_length = static_cast (*ptr_); + 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; + + const size_t value_length = static_cast (get_uint32 (ptr_)); + ptr_ += 4; + bytes_left -= 4; + if (bytes_left < value_length) + break; + + const uint8_t *value = ptr_; + ptr_ += value_length; + bytes_left -= value_length; + + const int rc = property (name, value, value_length); + if (rc == -1) + return -1; + + if (name == "Identity" && options.recv_identity) + set_peer_identity (value, value_length); + } + if (bytes_left > 0) { + errno = EPROTO; + return -1; + } + return 0; +} + +int zmq::mechanism_t::property (const std::string name_, + const void *value_, size_t length_) +{ + // Default implementation does not check + // property values and returns 0 to signal success. + return 0; +} diff --git a/src/mechanism.hpp b/src/mechanism.hpp index a1127f30..a5d94986 100644 --- a/src/mechanism.hpp +++ b/src/mechanism.hpp @@ -69,6 +69,20 @@ namespace zmq size_t add_property (unsigned char *ptr, const char *name, const void *value, size_t value_len) const; + // Parse a list of properties. Returns 0 on success + // and -1 on error, in which case errno is set. + int parse_properties (const unsigned char *ptr_, size_t length); + + // This is called by parse_property method whenever it + // parses a new property. The function should return 0 + // on success and -1 on error, in which case it should + // set errno. Signaling error prevetns parser from + // parsing remaining data. + // Derived classes are supposed to override this + // method to handle custom processing. + virtual int property (const std::string name_, + const void *value_, size_t length_); + options_t options; private: diff --git a/src/null_mechanism.cpp b/src/null_mechanism.cpp index e0f7ef52..ea1c5eca 100644 --- a/src/null_mechanism.cpp +++ b/src/null_mechanism.cpp @@ -99,54 +99,29 @@ int zmq::null_mechanism_t::process_handshake_message (msg_t *msg_) ptr += 8; bytes_left -= 8; - // Parse the property list - while (bytes_left > 1) { - const size_t name_length = static_cast (*ptr); - ptr += 1; - bytes_left -= 1; - - if (bytes_left < name_length) - break; - const std::string name = std::string((const char *) ptr, name_length); - ptr += name_length; - bytes_left -= name_length; - - if (bytes_left < 4) - break; - const size_t value_length = static_cast (get_uint32 (ptr)); - ptr += 4; - bytes_left -= 4; - - if (bytes_left < value_length) - break; - const unsigned char * const value = ptr; - ptr += value_length; - bytes_left -= value_length; - - if (name == "Socket-Type") { - // TODO: Implement socket type checking - } - else - if (name == "Identity" && options.recv_identity) - set_peer_identity (value, value_length); + int rc = parse_properties (ptr, bytes_left); + if (rc == 0) { + int rc = msg_->close (); + errno_assert (rc == 0); + rc = msg_->init (); + errno_assert (rc == 0); } - if (bytes_left > 0) { - errno = EPROTO; - return -1; - } - - int rc = msg_->close (); - errno_assert (rc == 0); - rc = msg_->init (); - errno_assert (rc == 0); - ready_command_received = true; - return 0; + return rc; } bool zmq::null_mechanism_t::is_handshake_complete () const { return ready_command_received && ready_command_sent; } + +int zmq::null_mechanism_t::property (const std::string name, + const void *value, size_t length) +{ + if (name == "Socket-Type") { + // TODO: Implement socket type checking + } + return 0; +} diff --git a/src/null_mechanism.hpp b/src/null_mechanism.hpp index 2c5d9c27..4947d1f2 100644 --- a/src/null_mechanism.hpp +++ b/src/null_mechanism.hpp @@ -40,6 +40,10 @@ namespace zmq virtual int process_handshake_message (msg_t *msg_); virtual bool is_handshake_complete () const; + protected: + + virtual int property (const std::string name, + const void *value, size_t length); private: bool ready_command_sent; diff --git a/src/plain_mechanism.cpp b/src/plain_mechanism.cpp index d28eae96..0cba5e4c 100644 --- a/src/plain_mechanism.cpp +++ b/src/plain_mechanism.cpp @@ -285,7 +285,7 @@ int zmq::plain_mechanism_t::process_initiate_command (msg_t *msg_) errno = EPROTO; return -1; } - return parse_property_list (ptr + 8, bytes_left - 8); + return parse_properties (ptr + 8, bytes_left - 8); } int zmq::plain_mechanism_t::ready_command (msg_t *msg_) const @@ -329,7 +329,7 @@ int zmq::plain_mechanism_t::process_ready_command (msg_t *msg_) errno = EPROTO; return -1; } - return parse_property_list (ptr + 8, bytes_left - 8); + return parse_properties (ptr + 8, bytes_left - 8); } void zmq::plain_mechanism_t::send_zap_request (const std::string &username, @@ -451,42 +451,11 @@ error: return rc; } -int zmq::plain_mechanism_t::parse_property_list (const unsigned char *ptr, - size_t bytes_left) +int zmq::plain_mechanism_t::property (const std::string name, + const void *value, size_t length) { - while (bytes_left > 1) { - const size_t name_length = static_cast (*ptr); - ptr += 1; - bytes_left -= 1; - if (bytes_left < name_length) - break; - - const std::string name = std::string ((const char *) ptr, name_length); - ptr += name_length; - bytes_left -= name_length; - if (bytes_left < 4) - break; - - const size_t value_length = static_cast (get_uint32 (ptr)); - ptr += 4; - bytes_left -= 4; - if (bytes_left < value_length) - break; - - const unsigned char * const value = ptr; - ptr += value_length; - bytes_left -= value_length; - - if (name == "Socket-Type") { - // TODO: Implement socket type checking - } - else - if (name == "Identity" && options.recv_identity) - set_peer_identity (value, value_length); - } - if (bytes_left > 0) { - errno = EPROTO; - return -1; + if (name == "Socket-Type") { + // TODO: Implement socket type checking } return 0; } diff --git a/src/plain_mechanism.hpp b/src/plain_mechanism.hpp index 6dfcc51a..3457aebe 100644 --- a/src/plain_mechanism.hpp +++ b/src/plain_mechanism.hpp @@ -43,6 +43,11 @@ namespace zmq virtual int zap_msg_available (); virtual bool is_handshake_complete () const; + protected: + + virtual int property (const std::string name, + const void *value, size_t length); + private: enum state_t { @@ -78,8 +83,6 @@ namespace zmq void send_zap_request (const std::string &username, const std::string &password); int receive_and_process_zap_reply (); - - int parse_property_list (const unsigned char *ptr, size_t length); }; }