Reputation: 106
With zmq and zmqpp, I am looking for a way to forward meta-data along with the message it belong. The goal is to get the 'User-Id' in a worker behind a load balancer which own the secure socket.
Here is a simple example, you can see the metadata disappear after being forwarded. I am not sure: is this metadata 'vanishment' a bug or a feature? Is there any workaround?
#include "zmqpp/zmqpp.hpp"
#include "zmqpp/curve.hpp"
int main()
{
zmqpp::curve::keypair client_keypair = zmqpp::curve::generate_keypair();
zmqpp::curve::keypair server_keypair = zmqpp::curve::generate_keypair();
std::cout << "Client Public Key: " << client_keypair.public_key << std::endl;
std::cout << "Server Public Key: " << server_keypair.public_key << std::endl;
zmqpp::context context;
zmqpp::auth authenticator(context);
authenticator.set_verbose(false);
authenticator.configure_curve(client_keypair.public_key);
zmqpp::socket curve_rep(context, zmqpp::socket_type::rep);
curve_rep.set(zmqpp::socket_option::curve_server, true);
curve_rep.set(zmqpp::socket_option::curve_secret_key, server_keypair.secret_key);
curve_rep.bind("tcp://127.0.0.1:4242");
zmqpp::socket curve_req(context, zmqpp::socket_type::req);
curve_req.set(zmqpp::socket_option::curve_server_key, server_keypair.public_key);
curve_req.set(zmqpp::socket_option::curve_public_key, client_keypair.public_key);
curve_req.set(zmqpp::socket_option::curve_secret_key, client_keypair.secret_key);
curve_req.connect("tcp://127.0.0.1:4242");
zmqpp::socket internal_rep(context, zmqpp::socket_type::rep);
internal_rep.bind("inproc://clear");
zmqpp::socket internal_req(context, zmqpp::socket_type::req);
internal_req.connect("inproc://clear");
{
zmqpp::message msg;
msg << "Hello";
curve_req.send(msg);
}
{
zmqpp::message msg;
curve_rep.receive(msg);
// read User-Id
std::string user_id;
std::cout << "- Before forward: ";
if (msg.get_property("User-Id", user_id))
std::cout << user_id << std::endl;
else
std::cout << "No user id" << std::endl;
// Forward message
internal_req.send(msg);
}
{
zmqpp::message msg;
internal_rep.receive(msg);
// read User-Id
std::string user_id;
std::cout << "- After forward: ";
if (msg.get_property("User-Id", user_id))
std::cout << user_id << std::endl;
else
std::cout << "No user id" << std::endl;
std::string content;
msg >> content;
std::cout << "- Message: " << content << std::endl;
}
{
zmqpp::message msg;
msg << "world !";
internal_rep.send(msg);
}
{
zmqpp::message msg;
internal_req.receive(msg);
// Forward message
curve_rep.send(msg);
}
{
zmqpp::message msg;
curve_req.receive(msg);
std::cout << "- Message: " << msg.get<std::string>(0) << std::endl;
}
return 0;
}
Output:
Client Public Key: }-}3(fH/r!I/9*tJX0bN/TT]Y2Qd#{IqszYzBX.g
Server Public Key: !@kpBlDrmW@e3jW)q6FumkKGjv@7lU?y9mD(QWd8
auth: Starting ZAP Authentication Server
- Before forward: }-}3(fH/r!I/9*tJX0bN/TT]Y2Qd#{IqszYzBX.g
- After forward: No user id
- Message: Hello
- Message: world !
auth: Shutdown ZAP Authentication Server
Upvotes: 2
Views: 1474
Reputation: 13766
This can be a confusing element of ZMQ. The meta-data to which you are referring is not a part of the ZMQ message itself, it's part of the connection over which you received that message. The fact that you can access it as a property of that message is an artifact of the ZMQ wireline protocol, how data is transferred from one socket to another with all of the information that the receiving socket needs to appropriately process that message. A ZMQ message has no "headers" per se, it just has "frames", and the ZMQ sockets know how to handle those frames when they include metadata.
So, the short answer is that the sockets, being given details to negotiate the Curve crypto, send crypto metadata along with the message and the receiving socket, being set up with crypto details, knows what to do with that meta data. When you send it over "normal" sockets with no crypto, that metadata is stripped. If the backend pair of sockets used crypto, it would no longer have the metadata that applied to the frontend, it would have a User-Id that applied to the broker backend socket.
If you want to add the metadata to the message so it gets sent back to the backend, you'll have to append it to the message data, either directly or in a new message frame (multi-part message) and handle it yourself, it won't be metadata anymore it'll be first-class data.
Upvotes: 4