static int s_agent_handle_dealer (agent_t *self) { if (self->state == connecting) { zframe_t *input = zframe_recv (self->dealer); zframe_t *output = curve_codec_execute (self->codec, &input); if (output) zframe_send (&output, self->dealer, 0); else if (curve_codec_connected (self->codec)) self->state = connected; else if (curve_codec_exception (self->codec)) self->state = exception; } else if (self->state == connected) { zframe_t *encrypted = zframe_recv (self->dealer); zframe_t *cleartext = curve_codec_decode (self->codec, &encrypted); if (cleartext) { int flags = zframe_more (cleartext)? ZFRAME_MORE: 0; zframe_send (&cleartext, self->data, flags); } else self->state = exception; } return 0; }
static int s_agent_handle_router (agent_t *self) { zframe_t *address = zframe_recv (self->router); char *hashkey = zframe_strhex (address); client_t *client = (client_t *) zhash_lookup (self->clients, hashkey); if (client == NULL && self->nbr_pending < self->max_pending) { client = client_new (self, address); client_set_pending (client); curve_codec_set_verbose (client->codec, self->verbose); zhash_foreach (self->metadata, client_set_metadata, client); zhash_insert (self->clients, hashkey, client); zhash_freefn (self->clients, hashkey, client_free); } free (hashkey); zframe_destroy (&address); // If we're overloaded, discard client request without any further // ado. The client will have to detect this and retry later. // TODO: retry in client side to handle overloaded servers. if (client == NULL) return 0; // If not yet connected, process one command frame // We always read one request, and send one reply if (client->state == pending) { zframe_t *input = zframe_recv (self->router); zframe_t *output = curve_codec_execute (client->codec, &input); if (output) { zframe_send (&client->address, self->router, ZFRAME_MORE + ZFRAME_REUSE); zframe_send (&output, self->router, 0); if (curve_codec_connected (client->codec)) client_set_connected (client); } else client_set_exception (client); } else // If connected, process one message frame // We will queue message frames in the client until we get a // whole message ready to deliver up the data socket -- frames // from different clients will be randomly intermixed. if (client->state == connected) { zframe_t *encrypted = zframe_recv (self->router); zframe_t *cleartext = curve_codec_decode (client->codec, &encrypted); if (cleartext) { if (client->incoming == NULL) client->incoming = zmsg_new (); zmsg_add (client->incoming, cleartext); if (!zframe_more (cleartext)) { zmsg_pushstr (client->incoming, client->hashkey); zmsg_send (&client->incoming, self->data); } } else client_set_exception (client); } // If client is misbehaving, remove it if (client->state == exception) zhash_delete (self->clients, client->hashkey); return 0; }
static void * server_task (void *args) { bool verbose = *((bool *) args); // Install the authenticator zctx_t *ctx = zctx_new (); zauth_t *auth = zauth_new (ctx); assert (auth); zauth_set_verbose (auth, verbose); zauth_configure_curve (auth, "*", TESTDIR); void *router = zsocket_new (ctx, ZMQ_ROUTER); int rc = zsocket_bind (router, "tcp://127.0.0.1:9005"); assert (rc != -1); zcert_t *server_cert = zcert_load (TESTDIR "/server.cert"); assert (server_cert); curve_codec_t *server = curve_codec_new_server (server_cert, ctx); assert (server); zcert_destroy (&server_cert); curve_codec_set_verbose (server, verbose); // Set some metadata properties curve_codec_set_metadata (server, "Server", "CURVEZMQ/curve_codec"); // Execute incoming frames until ready or exception // In practice we'd want a server instance per unique client while (!curve_codec_connected (server)) { zframe_t *sender = zframe_recv (router); zframe_t *input = zframe_recv (router); assert (input); zframe_t *output = curve_codec_execute (server, &input); assert (output); zframe_send (&sender, router, ZFRAME_MORE); zframe_send (&output, router, 0); } // Check client metadata char *client_name = (char *) zhash_lookup (curve_codec_metadata (server), "client"); assert (client_name); assert (streq (client_name, "CURVEZMQ/curve_client")); bool finished = false; while (!finished) { // Now act as echo service doing a full decode and encode zframe_t *sender = zframe_recv (router); zframe_t *encrypted = zframe_recv (router); assert (encrypted); zframe_t *cleartext = curve_codec_decode (server, &encrypted); assert (cleartext); if (memcmp (cleartext, "END", 3) == 0) finished = true; // Echo message back encrypted = curve_codec_encode (server, &cleartext); assert (encrypted); zframe_send (&sender, router, ZFRAME_MORE); zframe_send (&encrypted, router, 0); } curve_codec_destroy (&server); zauth_destroy (&auth); zctx_destroy (&ctx); return NULL; }