Ejemplo n.º 1
0
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);
    }
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
        }
    }
}
Ejemplo n.º 4
0
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
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
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);
    }
}
Ejemplo n.º 8
0
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);
    }
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
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);
    }
}
Ejemplo n.º 13
0
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;
}