static void pipe_drop_local_writer (pipe_t **self_p) { assert (self_p); if (*self_p) { pipe_t *self = *self_p; // TODO: what if self->writer is REMOTE_NODE? self->writer = NULL; if (self->reader) { if (self->reader == REMOTE_NODE) { // Tell remote node we're dropping off zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "DROP WRITER"); zmsg_addstr (msg, self->name); zyre_whisper (self->server->zyre, self->remote, &msg); zsys_info ("%s: tell peer we stopped being writer", self->name); } else { engine_send_event (self->reader, writer_dropped_event); // Don't destroy pipe yet - reader is still using it *self_p = NULL; } } pipe_destroy (self_p); } }
static void write_message_to_mailbox (client_t *self) { mlm_msg_t *msg = mlm_msg_new ( self->address, mlm_proto_address (self->message), mlm_proto_subject (self->message), mlm_proto_tracker (self->message), mlm_proto_timeout (self->message), mlm_proto_get_content (self->message)); // Try to dispatch to client immediately, if it's connected client_t *target = (client_t *) zhashx_lookup ( self->server->clients, mlm_proto_address (self->message)); if (target) { assert (!target->msg); target->msg = msg; engine_send_event (target, mailbox_message_event); } else // Else store in the eponymous mailbox zsock_send (self->server->mailbox, "ssp", "STORE", mlm_proto_address (self->message), msg); }
void s_service_dispatch (service_t *self) { // for each message, check regexp and dispatch if possible if (zlistx_size (self->offers)) { mlm_msg_t *message = (mlm_msg_t *) zlistx_first (self->queue); while (message) { offer_t *offer = (offer_t *) zlistx_first (self->offers); while (offer) { if (zrex_matches (offer->rex, mlm_msg_subject (message))) { client_t *target = offer->client; assert (target); assert (!target->msg); target->msg = (mlm_msg_t *) zlistx_detach ( self->queue, zlistx_cursor (self->queue)); engine_send_event (target, service_message_event); zlistx_move_end (self->offers, zlistx_cursor (self->offers)); break; } offer = (offer_t *) zlistx_next (self->offers); } message = (mlm_msg_t *) zlistx_next (self->queue); } } }
static int pipe_attach_remote_reader (pipe_t *self, const char *remote, bool unicast) { assert (self); if (self->writer == REMOTE_NODE) { // We're witnessing two nodes chatting, so we can drop the pipe // and forget all about it pipe_destroy (&self); return 0; } else if (self->reader == NULL) { // This is how we indicate a remote reader self->reader = REMOTE_NODE; self->remote = strdup (remote); zsys_info ("%s: attach remote reader", self->name); if (self->writer && !unicast) { // Tell remote node we're acting as writer, if we got a // broadcast message. If we got a unicast message, the peer // already knows about us, so don't re-echo the message zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "HAVE WRITER"); zmsg_addstr (msg, self->name); zyre_whisper (self->server->zyre, self->remote, &msg); zsys_info ("%s: tell peer we are now writer", self->name); } // Writer must be local at this stage; wake it up so it can // ship off its waiting data engine_send_event (self->writer, have_reader_event); return 0; } zsys_info ("%s: pipe already has reader: ignored", self->name); return -1; // Pipe already has reader }
static void write_message_to_xrap_handler (client_t *self) { service_t *service = self->server->xrap; assert (service); ztrie_t *routes = NULL; zmsg_t *content = zmsg_dup (xrap_traffic_content (self->message)); xrap_msg_t *msg = xrap_msg_decode (&content); char *route; int method = xrap_msg_id (msg); if (method == XRAP_MSG_GET) { route = (char *) xrap_msg_resource (msg); routes = service->get_routes; } else if (method == XRAP_MSG_POST) { route = (char *) xrap_msg_parent (msg); routes = service->post_routes; } else if (method == XRAP_MSG_PUT) { route = (char *) xrap_msg_resource (msg); routes = service->put_routes; } else if (method == XRAP_MSG_DELETE) { route = (char *) xrap_msg_resource (msg); routes = service->delete_routes; } else { xrap_traffic_set_status_code (self->message, XRAP_TRAFFIC_BAD_REQUEST); engine_set_exception (self, fail_event); } client_t *target; if (routes && ztrie_matches (routes, route)) { target = (client_t *) ztrie_hit_data (routes); // Save message for broker target->msg = zmsg_dup (xrap_traffic_content (self->message)); // Trigger dispatch event target->callee = self; engine_send_event (target, xrap_message_event); } else { xrap_traffic_set_status_code (self->message, XRAP_TRAFFIC_NOT_FOUND); self->rc = -1; } // Clean up xrap_msg_destroy (&msg); }
static int s_forward_stream_traffic (zloop_t *loop, zsock_t *reader, void *argument) { client_t *client; mlm_msg_t *msg; zsock_brecv (reader, "pp", &client, &msg); assert (client); assert (!client->msg); client->msg = msg; engine_send_event (client, stream_message_event); assert (!client->msg); return 0; }
static void write_message_to_xrap_client (client_t *self) { zuuid_t *client_id = xrap_traffic_sender (self->message); assert (client_id); client_t *client = (client_t *) zhashx_lookup (self->server->clients, zuuid_str (client_id)); if (client) { // Save message for broker client->msg = zmsg_dup (xrap_traffic_content (self->message)); client->callee = NULL; engine_send_event (client, xrap_message_event); } }
static void pipe_drop_remote_writer (pipe_t **self_p, const char *remote) { assert (self_p); if (*self_p) { pipe_t *self = *self_p; if (self->writer == REMOTE_NODE && streq (self->remote, remote)) { self->writer = NULL; if (self->reader) { assert (self->reader != REMOTE_NODE); engine_send_event (self->reader, writer_dropped_event); // Don't destroy pipe yet - reader is still using it *self_p = NULL; } } pipe_destroy (self_p); } }
static bool s_service_dispatch_message (service_t *self, mlm_msg_t *message) { offer_t *offer = (offer_t *) zlistx_first (self->offers); while (offer) { if (zrex_matches (offer->rex, mlm_msg_subject (message))) { client_t *target = offer->client; assert (target); assert (!target->msg); target->msg = message; engine_send_event (target, service_message_event); zlistx_move_end (self->offers, zlistx_cursor (self->offers)); return true; } offer = (offer_t *) zlistx_next (self->offers); } return false; }
static void register_new_client (client_t *self) { self->address = strdup (mlm_proto_address (self->message)); // We ignore anonymous clients, which have empty addresses if (*self->address) { // If there's an existing client with this address, expire it // The alternative would be to reject new clients with the same address client_t *existing = (client_t *) zhashx_lookup ( self->server->clients, self->address); if (existing) engine_send_event (existing, expired_event); // In any case, we now own this address zhashx_update (self->server->clients, self->address, self); } if (*self->address) zsys_info ("client %u address='%s' - registering", self->unique_id, self->address); mlm_proto_set_status_code (self->message, MLM_PROTO_SUCCESS); }
static int s_forward_stream_traffic (zloop_t *loop, zsock_t *reader, void *argument) { client_t *client; mlm_msg_t *msg; zsock_brecv (reader, "pp", &client, &msg); assert (client); if (msg == MLM_STREAM_ACK_CANCEL) { // This is an ACK for a previously sent CANCEL command engine_client_put (client); return 0; } // We may be receiving messages for an already dropped client if (!engine_client_is_valid (client)) { mlm_msg_unlink (&msg); return 0; } assert (!client->msg); client->msg = msg; engine_send_event (client, stream_message_event); assert (!client->msg); return 0; }
static void pipe_send_data (pipe_t *self, zchunk_t **chunk_p) { assert (self); assert (self->reader); zchunk_t *chunk = *chunk_p; assert (chunk); if (self->reader == REMOTE_NODE) { // Send chunk to remote node reader zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "DATA"); zmsg_addstr (msg, self->name); zmsg_addmem (msg, zchunk_data (chunk), zchunk_size (chunk)); zyre_whisper (self->server->zyre, self->remote, &msg); zchunk_destroy (chunk_p); } else { client_store_chunk (self->reader, chunk_p); engine_send_event (self->reader, have_data_event); } }
static int pipe_attach_local_writer (pipe_t *self, client_t *writer) { assert (self); if (self->writer == NULL) { zsys_info ("%s: attach local writer", self->name); self->writer = writer; if (self->reader == NULL) { if (self->server->zyre) { // Announce that we have a new pipe writer so that readers // in the cluster may discover us zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "HAVE WRITER"); zmsg_addstr (msg, self->name); zyre_shout (self->server->zyre, "ZPIPES", &msg); zsys_info ("%s: broadcast we are now writer", self->name); } } else if (self->reader == REMOTE_NODE) { assert (self->server->zyre); // Tell remote node we would like to be writer zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "HAVE WRITER"); zmsg_addstr (msg, self->name); zyre_whisper (self->server->zyre, self->remote, &msg); zsys_info ("%s: tell peer we are now writer", self->name); } else engine_send_event (self->reader, have_writer_event); return 0; } zsys_info ("%s: pipe already has writer: ignored", self->name); return -1; }