Ejemplo n.º 1
0
//  .split main task
//  We have a single task that implements the worker side of the
//  Paranoid Pirate Protocol (PPP). The interesting parts here are
//  the heartbeating, which lets the worker detect if the queue has
//  died, and vice versa:
static void ppworker_actor(zsock_t *pipe, void *args)
{
	ubx_block_t *b = (ubx_block_t *) args;
	struct czmq_ppworker_info *inf = (struct czmq_ppworker_info*) b->private_data;
    zsock_t *worker = s_worker_socket ();

    //  If liveness hits zero, queue is considered disconnected
    size_t liveness = HEARTBEAT_LIVENESS;
    size_t interval = INTERVAL_INIT;

    //  Send out heartbeats at regular intervals
    uint64_t heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL;

    srandom ((unsigned) time (NULL));

    printf("ppworker: actor started.\n");
    // send signal on pipe socket to acknowledge initialisation
    zsock_signal (pipe, 0);

    while (true) {
        zmq_pollitem_t items [] = { { zsock_resolve(worker),  0, ZMQ_POLLIN, 0 } };
        int rc = zmq_poll (items, 1, HEARTBEAT_INTERVAL * ZMQ_POLL_MSEC);
        if (rc == -1)
            break;              //  Interrupted

        if (items [0].revents & ZMQ_POLLIN) {
            //  Get message
            //  - 3-part envelope + content -> request
            //  - 1-part HEARTBEAT -> heartbeat
            zmsg_t *msg = zmsg_recv (worker);
            if (!msg)
                break;          //  Interrupted

            if (zmsg_size (msg) == 3) {
                printf ("I: normal reply\n");
                byte *buffer;
                size_t buffer_size = zmsg_encode (msg, &buffer);
                ubx_type_t* type =  ubx_type_get(b->ni, "unsigned char");
                ubx_data_t umsg;
                umsg.data = (void *)buffer;
                umsg.len = buffer_size;
                umsg.type = type;
                __port_write(inf->ports.zmq_in, &umsg);
                zmsg_send (&msg, worker);
                liveness = HEARTBEAT_LIVENESS;
                sleep (1);              //  Do some heavy work
                if (zsys_interrupted)
                    break;
            }
            else
            //  .split handle heartbeats
            //  When we get a heartbeat message from the queue, it means the
            //  queue was (recently) alive, so we must reset our liveness
            //  indicator:
            if (zmsg_size (msg) == 1) {
                zframe_t *frame = zmsg_first (msg);
                if (memcmp (zframe_data (frame), PPP_HEARTBEAT, 1) == 0)
                    liveness = HEARTBEAT_LIVENESS;
                else {
                    printf ("E: invalid message\n");
                    zmsg_dump (msg);
                }
                zmsg_destroy (&msg);
            }
            else {
                printf ("E: invalid message\n");
                zmsg_dump (msg);
            }
            interval = INTERVAL_INIT;
        }
        else
        //  .split detecting a dead queue
        //  If the queue hasn't sent us heartbeats in a while, destroy the
        //  socket and reconnect. This is the simplest most brutal way of
        //  discarding any messages we might have sent in the meantime:
        if (--liveness == 0) {
            printf ("W: heartbeat failure, can't reach queue\n");
            printf ("W: reconnecting in %zd msec...\n", interval);
            zclock_sleep (interval);

            if (interval < INTERVAL_MAX)
                interval *= 2;
            zsock_destroy(&worker);
            worker = s_worker_socket ();
            liveness = HEARTBEAT_LIVENESS;
        }
        //  Send heartbeat to queue if it's time
        if (zclock_time () > heartbeat_at) {
            heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL;
            printf ("I: worker heartbeat\n");
            zframe_t *frame = zframe_new (PPP_HEARTBEAT, 1);
            zframe_send (&frame, worker, 0);
        }
    }
}
Ejemplo n.º 2
0
zmsg_t *
zgossip_msg_encode (zgossip_msg_t **self_p)
{
    assert (self_p);
    assert (*self_p);
    
    zgossip_msg_t *self = *self_p;
    zmsg_t *msg = zmsg_new ();

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case ZGOSSIP_MSG_HELLO:
            //  version is a 1-byte integer
            frame_size += 1;
            break;
            
        case ZGOSSIP_MSG_PUBLISH:
            //  version is a 1-byte integer
            frame_size += 1;
            //  key is a string with 1-byte length
            frame_size++;       //  Size is one octet
            if (self->key)
                frame_size += strlen (self->key);
            //  value is a string with 4-byte length
            frame_size += 4;
            if (self->value)
                frame_size += strlen (self->value);
            //  ttl is a 4-byte integer
            frame_size += 4;
            break;
            
        case ZGOSSIP_MSG_PING:
            //  version is a 1-byte integer
            frame_size += 1;
            break;
            
        case ZGOSSIP_MSG_PONG:
            //  version is a 1-byte integer
            frame_size += 1;
            break;
            
        case ZGOSSIP_MSG_INVALID:
            //  version is a 1-byte integer
            frame_size += 1;
            break;
            
        default:
            zsys_error ("bad message type '%d', not sent\n", self->id);
            //  No recovery, this is a fatal application error
            assert (false);
    }
    //  Now serialize message into the frame
    zframe_t *frame = zframe_new (NULL, frame_size);
    self->needle = zframe_data (frame);
    PUT_NUMBER2 (0xAAA0 | 0);
    PUT_NUMBER1 (self->id);

    switch (self->id) {
        case ZGOSSIP_MSG_HELLO:
            PUT_NUMBER1 (1);
            break;

        case ZGOSSIP_MSG_PUBLISH:
            PUT_NUMBER1 (1);
            if (self->key) {
                PUT_STRING (self->key);
            }
            else
                PUT_NUMBER1 (0);    //  Empty string
            if (self->value) {
                PUT_LONGSTR (self->value);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            PUT_NUMBER4 (self->ttl);
            break;

        case ZGOSSIP_MSG_PING:
            PUT_NUMBER1 (1);
            break;

        case ZGOSSIP_MSG_PONG:
            PUT_NUMBER1 (1);
            break;

        case ZGOSSIP_MSG_INVALID:
            PUT_NUMBER1 (1);
            break;

    }
    //  Now send the data frame
    if (zmsg_append (msg, &frame)) {
        zmsg_destroy (&msg);
        zgossip_msg_destroy (self_p);
        return NULL;
    }
    //  Destroy zgossip_msg object
    zgossip_msg_destroy (self_p);
    return msg;
}
Ejemplo n.º 3
0
///
//  Return address of frame data
byte *QmlZframe::data () {
    return zframe_data (self);
};
Ejemplo n.º 4
0
void zwsdecoder_process_buffer(zwsdecoder_t *self, zframe_t* data)
{
	int i = 0;

	byte* buffer = zframe_data(data);
	int buffer_length = zframe_size(data);

	int bytes_to_read;

	while (i < buffer_length)
	{
		switch (self->state)
		{
		case error:
			return;
		case begin_payload:

			self->payload_index = 0;
			self->payload = zmalloc(sizeof(byte) * (self->payload_length + 4)); // +4 extra bytes in case we have to inflate it

			// continue to payload
		case payload:
			bytes_to_read = self->payload_length - self->payload_index;

			if (bytes_to_read > (buffer_length - i))
			{
				bytes_to_read = buffer_length - i;
			}

			memcpy(self->payload + self->payload_index, buffer + i, bytes_to_read);

			if (self->is_masked)
			{
				for (int j = self->payload_index; j < self->payload_index + bytes_to_read; j++)
				{
					self->payload[j] = self->payload[j] ^ self->mask[(j) % 4];
				}
			}

			self->payload_index += bytes_to_read;
			i += bytes_to_read;

			if (self->payload_index < self->payload_length)
			{
				self->state = payload;
			}
			else
			{
				// temp(this, new MessageEventArgs(m_opcode, m_payload, m_more));

				self->state = new_message;
				invoke_new_message(self);
			}

			break;
		default:
			zwsdecoder_process_byte(self, buffer[i]);
			i++;
			break;
		}
	}
}
Ejemplo n.º 5
0
static int
zyre_node_recv_peer (zyre_node_t *self)
{
    //  Router socket tells us the identity of this peer
    zre_msg_t *msg = zre_msg_recv (self->inbox);
    if (msg == NULL)
        return 0;               //  Interrupted

    //  First frame is sender identity, holding binary UUID
    zuuid_t *uuid = zuuid_new ();
    zuuid_set (uuid, zframe_data (zre_msg_address (msg)));

    //  On HELLO we may create the peer if it's unknown
    //  On other commands the peer must already exist
    zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, zuuid_str (uuid));
    if (zre_msg_id (msg) == ZRE_MSG_HELLO) {
        peer = zyre_node_require_peer (self, uuid, zre_msg_ipaddress (msg), zre_msg_mailbox (msg));
        assert (peer);
        zyre_peer_set_ready (peer, true);
    }
    //  Ignore command if peer isn't ready
    if (peer == NULL || !zyre_peer_ready (peer)) {
        zre_msg_destroy (&msg);
        zuuid_destroy (&uuid);
        return 0;
    }
    if (!zyre_peer_check_message (peer, msg)) {
        zclock_log ("W: [%s] lost messages from %s", zuuid_str (self->uuid), zuuid_str (uuid));
        assert (false);
    }

    //  Now process each command
    if (zre_msg_id (msg) == ZRE_MSG_HELLO) {
        //  Tell the caller about the peer
        zstr_sendm (self->pipe, "ENTER");
        zstr_sendm (self->pipe, zuuid_str (uuid));
        zframe_t *headers = zhash_pack (zre_msg_headers (msg));
        zframe_send (&headers, self->pipe, ZFRAME_MORE);
        zstr_send (self->pipe, zre_msg_ipaddress (msg));
        
        //  Join peer to listed groups
        char *name = zre_msg_groups_first (msg);
        while (name) {
            zyre_node_join_peer_group (self, peer, name);
            name = zre_msg_groups_next (msg);
        }
        //  Hello command holds latest status of peer
        zyre_peer_set_status (peer, zre_msg_status (msg));
        
        //  Store peer headers for future reference
        zyre_peer_set_headers (peer, zre_msg_headers (msg));

        //  If peer is a ZRE/LOG collector, connect to it
        char *collector = zre_msg_headers_string (msg, "X-ZRELOG", NULL);
        if (collector)
            zyre_log_connect (self->log, collector);
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_WHISPER) {
        //  Pass up to caller API as WHISPER event
        zstr_sendm (self->pipe, "WHISPER");
        zstr_sendm (self->pipe, zuuid_str (uuid));
        zmsg_t *content = zmsg_dup (zre_msg_content (msg));
        zmsg_send (&content, self->pipe);
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_SHOUT) {
        //  Pass up to caller as SHOUT event
        zstr_sendm (self->pipe, "SHOUT");
        zstr_sendm (self->pipe, zuuid_str (uuid));
        zstr_sendm (self->pipe, zre_msg_group (msg));
        zmsg_t *content = zmsg_dup (zre_msg_content (msg));
        zmsg_send (&content, self->pipe);
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_PING) {
        zre_msg_t *msg = zre_msg_new (ZRE_MSG_PING_OK);
        zyre_peer_send (peer, &msg);
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_JOIN) {
        zyre_node_join_peer_group (self, peer, zre_msg_group (msg));
        assert (zre_msg_status (msg) == zyre_peer_status (peer));
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_LEAVE) {
        zyre_node_leave_peer_group (self, peer, zre_msg_group (msg));
        assert (zre_msg_status (msg) == zyre_peer_status (peer));
    }
    zuuid_destroy (&uuid);
    zre_msg_destroy (&msg);
    
    //  Activity from peer resets peer timers
    zyre_peer_refresh (peer);
    return 0;
}
Ejemplo n.º 6
0
int main (void)
{
    zctx_t *ctx = zctx_new ();
    void *frontend = zsocket_new (ctx, ZMQ_ROUTER);
    void *backend = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (frontend, "tcp://*:5555");    //  For clients
    zsocket_bind (backend,  "tcp://*:5556");    //  For workers

    //  List of available workers
    zlist_t *workers = zlist_new ();

    //  Send out heartbeats at regular intervals
    uint64_t heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL;

    while (true) {
        zmq_pollitem_t items [] = {
            { backend,  0, ZMQ_POLLIN, 0 },
            { frontend, 0, ZMQ_POLLIN, 0 }
        };
        //  Poll frontend only if we have available workers
        int rc = zmq_poll (items, zlist_size (workers)? 2: 1,
            HEARTBEAT_INTERVAL * ZMQ_POLL_MSEC);
        if (rc == -1)
            break;              //  Interrupted

        //  Handle worker activity on backend
        if (items [0].revents & ZMQ_POLLIN) {
            //  Use worker identity for load-balancing
            zmsg_t *msg = zmsg_recv (backend);
            if (!msg)
                break;          //  Interrupted

            //  Any sign of life from worker means it's ready
            zframe_t *identity = zmsg_unwrap (msg);
            worker_t *worker = s_worker_new (identity);
            s_worker_ready (worker, workers);

            //  Validate control message, or return reply to client
            if (zmsg_size (msg) == 1) {
                zframe_t *frame = zmsg_first (msg);
                if (memcmp (zframe_data (frame), PPP_READY, 1)
                &&  memcmp (zframe_data (frame), PPP_HEARTBEAT, 1)) {
                    printf ("E: invalid message from worker");
                    zmsg_dump (msg);
                }
                zmsg_destroy (&msg);
            }
            else
                zmsg_send (&msg, frontend);
        }
        if (items [1].revents & ZMQ_POLLIN) {
            //  Now get next client request, route to next worker
            zmsg_t *msg = zmsg_recv (frontend);
            if (!msg)
                break;          //  Interrupted
            zmsg_push (msg, s_workers_next (workers));
            zmsg_send (&msg, backend);
        }
        //  .split handle heartbeating
        //  We handle heartbeating after any socket activity. First we send
        //  heartbeats to any idle workers if it's time. Then we purge any
        //  dead workers:
        if (zclock_time () >= heartbeat_at) {
            worker_t *worker = (worker_t *) zlist_first (workers);
            while (worker) {
                zframe_send (&worker->identity, backend,
                             ZFRAME_REUSE + ZFRAME_MORE);
                zframe_t *frame = zframe_new (PPP_HEARTBEAT, 1);
                zframe_send (&frame, backend, 0);
                worker = (worker_t *) zlist_next (workers);
            }
            heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL;
        }
        s_workers_purge (workers);
    }
    //  When we're done, clean up properly
    while (zlist_size (workers)) {
        worker_t *worker = (worker_t *) zlist_pop (workers);
        s_worker_destroy (&worker);
    }
    zlist_destroy (&workers);
    zctx_destroy (&ctx);
    return 0;
}
Ejemplo n.º 7
0
zre_msg_t *
zre_msg_decode (zmsg_t **msg_p, int socket_type)
{
    assert (msg_p);
    zmsg_t *msg = *msg_p;
    if (msg == NULL)
        return NULL;
        
    zre_msg_t *self = zre_msg_new (0);
    //  If message came from a router socket, first frame is routing_id
    if (socket_type == ZMQ_ROUTER) {
        self->routing_id = zmsg_pop (msg);
        //  If message was not valid, forget about it
        if (!self->routing_id || !zmsg_next (msg)) {
            zre_msg_destroy (&self);
            return (NULL);      //  Malformed or empty
        }
    }
    //  Read and parse command in frame
    zframe_t *frame = zmsg_pop (msg);
    if (!frame) 
        goto empty;             //  Malformed or empty

    //  Get and check protocol signature
    self->needle = zframe_data (frame);
    self->ceiling = self->needle + zframe_size (frame);
    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 1))
        goto empty;             //  Invalid signature

    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case ZRE_MSG_HELLO:
            GET_NUMBER2 (self->sequence);
            GET_STRING (self->ipaddress);
            GET_NUMBER2 (self->mailbox);
            {
                size_t list_size;
                GET_NUMBER4 (list_size);
                self->groups = zlist_new ();
                zlist_autofree (self->groups);
                while (list_size--) {
                    char *string;
                    GET_LONGSTR (string);
                    zlist_append (self->groups, string);
                    free (string);
                }
            }
            GET_NUMBER1 (self->status);
            {
                size_t hash_size;
                GET_NUMBER4 (hash_size);
                self->headers = zhash_new ();
                zhash_autofree (self->headers);
                while (hash_size--) {
                    char *key, *value;
                    GET_STRING (key);
                    GET_LONGSTR (value);
                    zhash_insert (self->headers, key, value);
                    free (key);
                    free (value);
                }
            }
            break;

        case ZRE_MSG_WHISPER:
            GET_NUMBER2 (self->sequence);
            //  Get zero or more remaining frames, leaving current
            //  frame untouched
            self->content = zmsg_new ();
            while (zmsg_size (msg))
                zmsg_add (self->content, zmsg_pop (msg));
            break;

        case ZRE_MSG_SHOUT:
            GET_NUMBER2 (self->sequence);
            GET_STRING (self->group);
            //  Get zero or more remaining frames, leaving current
            //  frame untouched
            self->content = zmsg_new ();
            while (zmsg_size (msg))
                zmsg_add (self->content, zmsg_pop (msg));
            break;

        case ZRE_MSG_JOIN:
            GET_NUMBER2 (self->sequence);
            GET_STRING (self->group);
            GET_NUMBER1 (self->status);
            break;

        case ZRE_MSG_LEAVE:
            GET_NUMBER2 (self->sequence);
            GET_STRING (self->group);
            GET_NUMBER1 (self->status);
            break;

        case ZRE_MSG_PING:
            GET_NUMBER2 (self->sequence);
            break;

        case ZRE_MSG_PING_OK:
            GET_NUMBER2 (self->sequence);
            break;

        default:
            goto malformed;
    }
    //  Successful return
    zframe_destroy (&frame);
    zmsg_destroy (msg_p);
    return self;

    //  Error returns
    malformed:
        printf ("E: malformed message '%d'\n", self->id);
    empty:
        zframe_destroy (&frame);
        zmsg_destroy (msg_p);
        zre_msg_destroy (&self);
        return (NULL);
}
Ejemplo n.º 8
0
static void
s_broker_worker_msg (broker_t *self, zframe_t *sender, zmsg_t *msg)
{
    assert (zmsg_size (msg) >= 1);     //  At least, command

    zframe_t *command = zmsg_pop (msg);
    char *identity = zframe_strhex (sender);
    int worker_ready = (zhash_lookup (self->workers, identity) != NULL);
    free (identity);
    worker_t *worker = s_worker_require (self, sender);

    if (zframe_streq (command, MDPW_READY)) {
        if (worker_ready)               //  Not first command in session
            s_worker_delete (worker, 1);
        else
        if (zframe_size (sender) >= 4  //  Reserved service name
        &&  memcmp (zframe_data (sender), "mmi.", 4) == 0)
            s_worker_delete (worker, 1);
        else {
            //  Attach worker to service and mark as idle
            zframe_t *service_frame = zmsg_pop (msg);
            worker->service = s_service_require (self, service_frame);
            zlist_append (self->waiting, worker);
            zlist_append (worker->service->waiting, worker);
            worker->service->workers++;
            worker->expiry = zclock_time () + HEARTBEAT_EXPIRY;
            s_service_dispatch (worker->service);
            zframe_destroy (&service_frame);
            zclock_log ("worker created");
        }
    }
    else
    if (zframe_streq (command, MDPW_REPORT)) {
        if (worker_ready) {
            //  Remove & save client return envelope and insert the
            //  protocol header and service name, then rewrap envelope.
            zframe_t *client = zmsg_unwrap (msg);
            zmsg_pushstr (msg, worker->service->name);
            zmsg_pushstr (msg, MDPC_REPORT);
            zmsg_pushstr (msg, MDPC_CLIENT);
            zmsg_wrap (msg, client);
            zmsg_send (&msg, self->socket);
        }
        else
            s_worker_delete (worker, 1);
    }
    else
    if (zframe_streq (command, MDPW_HEARTBEAT)) {
        if (worker_ready) {
            if (zlist_size (self->waiting) > 1) {
                // Move worker to the end of the waiting queue,
                // so s_broker_purge will only check old worker(s)
                zlist_remove (self->waiting, worker);
                zlist_append (self->waiting, worker);
            }
            worker->expiry = zclock_time () + HEARTBEAT_EXPIRY;
        }
        else
            s_worker_delete (worker, 1);
    }
    else
    if (zframe_streq (command, MDPW_DISCONNECT))
        s_worker_delete (worker, 0);
    else {
        zclock_log ("E: invalid input message");
        zmsg_dump (msg);
    }
    zframe_destroy (&command);
    zmsg_destroy (&msg);
}
Ejemplo n.º 9
0
static void
s_broker_client_msg (broker_t *self, zframe_t *sender, zmsg_t *msg)
{
    assert (zmsg_size (msg) >= 2);     //  Service name + body

    zframe_t *service_frame = zmsg_pop (msg);
    service_t *service = s_service_require (self, service_frame);

    //  If we got a MMI service request, process that internally
    if (zframe_size (service_frame) >= 4
    &&  memcmp (zframe_data (service_frame), "mmi.", 4) == 0) {
        char *return_code;
        if (zframe_streq (service_frame, "mmi.service")) {
            char *name = zframe_strdup (zmsg_last (msg));
            service_t *service =
                (service_t *) zhash_lookup (self->services, name);
            return_code = service && service->workers? "200": "404";
            free (name);
        }
        else
        // The filter service that can be used to manipulate
        // the command filter table.
        if (zframe_streq (service_frame, "mmi.filter")
        && zmsg_size (msg) == 3) {
            zframe_t *operation = zmsg_pop (msg);
            zframe_t *service_frame = zmsg_pop (msg);
            zframe_t *command_frame = zmsg_pop (msg);
            char *command_str = zframe_strdup (command_frame);

            if (zframe_streq (operation, "enable")) {
                service_t *service = s_service_require (self, service_frame);
                s_service_enable_command (service, command_str);
                return_code = "200";
            }
            else
            if (zframe_streq (operation, "disable")) {
                service_t *service = s_service_require (self, service_frame);
                s_service_disable_command (service, command_str);
                return_code = "200";
            }
            else
                return_code = "400";

            zframe_destroy (&operation);
            zframe_destroy (&service_frame);
            zframe_destroy (&command_frame);
            free (command_str);
            //  Add an empty frame; it will be replaced by the return code.
            zmsg_pushstr (msg, "");
        }
        else
            return_code = "501";

        zframe_reset (zmsg_last (msg), return_code, strlen (return_code));

        //  Insert the protocol header and service name, then rewrap envelope.
        zmsg_push (msg, zframe_dup (service_frame));
        zmsg_pushstr (msg, MDPC_REPORT);
        zmsg_pushstr (msg, MDPC_CLIENT);
        zmsg_wrap (msg, zframe_dup (sender));
        zmsg_send (&msg, self->socket);
    }
    else {
        int enabled = 1;
        if (zmsg_size (msg) >= 1) {
            zframe_t *cmd_frame = zmsg_first (msg);
            char *cmd = zframe_strdup (cmd_frame);
            enabled = s_service_is_command_enabled (service, cmd);
            free (cmd);
        }

        //  Forward the message to the worker.
        if (enabled) {
            zmsg_wrap (msg, zframe_dup (sender));
            zlist_append (service->requests, msg);
            s_service_dispatch (service);
        }
        //  Send a NAK message back to the client.
        else {
            zmsg_push (msg, zframe_dup (service_frame));
            zmsg_pushstr (msg, MDPC_NAK);
            zmsg_pushstr (msg, MDPC_CLIENT);
            zmsg_wrap (msg, zframe_dup (sender));
            zmsg_send (&msg, self->socket);
        }
    }

    zframe_destroy (&service_frame);
}
Ejemplo n.º 10
0
void trigger(void *cvoid, 
             zctx_t * context, 
             void * control) {
  triggerconfig_t * c = (triggerconfig_t*) cvoid;
  //set up msgpack stuff
  zclock_log("watch_port started!");
  msgpack_zone mempool;
  msgpack_zone_init(&mempool, 2048);

  // TODO
  char * user_id = "17"; 
  // TODO get broker in somehow
  char * broker = "tcp://au.ninjablocks.com:5773";

  mdcli_t * client = mdcli_new(broker, 1); //VERBOSE

  triggermemory_t trigger_memory;
  msgpack_object * addins_obj = parse_msgpack(&mempool, c->addins);

  if(!parse_addins(addins_obj, &trigger_memory)) {
    //bad message
    zclock_log("bad trigger definition");
    msgpack_object_print(stdout, *addins_obj);
    send_sync("bad trigger", control);
    return;
  }
  zclock_log("Creating trigger: target %s, rule_id %s, name %s", 
             c->target_worker, c->rule_id, c->trigger_name);
  dump_trigger(&trigger_memory);
  triggerfunction trigger_func;
  if(!(trigger_func = find_trigger(c->channel, c->trigger_name))) {

    zclock_log("no trigger found for channel %s, trigger %s",
               c->channel, c->trigger_name);
    send_sync("no such trigger", control);
    return;
  }

  void * line = zsocket_new(context, ZMQ_SUB);


  // what line are we on?
  // this comes in the addins. 
  char * linesocket = to_linesocket(trigger_memory.line_id);
  zclock_log("trigger is connecting to listen on %s", linesocket);
  zsocket_connect(line, linesocket);

  zsockopt_set_unsubscribe(line, "");
  zsockopt_set_subscribe(line, "VALUE");
  recv_sync("ping", control);
  send_sync("pong", control);
  
  zmq_pollitem_t items [] = {
    { line, 0, ZMQ_POLLIN, 0 },
    { control, 0, ZMQ_POLLIN, 0 }
  };
  while(1) {
    // listen on control and line
    zmq_poll (items, 2, -1);
    if (items[1].revents & ZMQ_POLLIN) {
      zclock_log("rule %s received message on control pipe", c->rule_id);
      // control message
      // really only expecting DESTROY
      zmsg_t * msg = zmsg_recv(control);
      char * str = zmsg_popstr(msg);
      zmsg_destroy(&msg);
      
      if (strcmp("Destroy", str) == 0) {
        zclock_log("rule %s will quit on request", c->rule_id);
        free(str);
        send_sync("ok", control);
        zclock_log("rule %s quitting on request", c->rule_id);
        break;
      } else  {
        zclock_log("unexpected command %s for rule %s", str, c->rule_id);
        free(str);
        send_sync("ok", control);
      }
    }

    if (items[0].revents & ZMQ_POLLIN) {
      // serial update
      zmsg_t * msg = zmsg_recv(line);
      zframe_t * cmd = zmsg_pop(msg);
      if(zframe_streq(cmd, "CHANNEL_CHANGE")) {
        // TODO
        // must have been dormant to have gotten this
        char * new_channel = zmsg_popstr(msg);

        if(strcmp(c->channel, new_channel) == 0) {
        // oh, happy day! We're relevant again.
        // reactivate and start looking at reset levels.
          zclock_log("line %d: changed channel from %s to %s: trigger coming back to life", trigger_memory.line_id, c->channel, new_channel);
          zsockopt_set_subscribe(line, "VALUE");
          zsockopt_set_unsubscribe(line, "CHANNEL_CHANGE");
        }
        free(new_channel);
      } else if (zframe_streq(cmd, "VALUE")) {
        zframe_t * vframe = zmsg_pop(msg);
        int value;
        memcpy(&value, zframe_data(vframe), sizeof(int));
        char * update_channel = zmsg_popstr(msg);

        if(strcmp(c->channel, update_channel) != 0) {
          // channel changed,  go dormant
          // this is legit according to my tests at
          // https://gist.github.com/2042350

          zclock_log("line %d: changed channel from %s to %s: trigger going dormant", trigger_memory.line_id, c->channel, update_channel);
          zsockopt_set_subscribe(line, "CHANNEL_CHANGE");
          zsockopt_set_unsubscribe(line, "VALUE");
        } 
        
        else if(trigger_func(&trigger_memory, value)) {
          send_trigger(client, c->target_worker, c->rule_id, value, user_id);
        }           

        free(update_channel);
      } else {
        // shouldn't ever happen.
        zclock_log("shouldn't have received command %s\n", zframe_strdup(cmd));
      }
      zmsg_destroy(&msg);
      zframe_destroy(&cmd);
    }
    
  }

  msgpack_zone_destroy(&mempool);
}
int _thsafe_zmq_client_open_release (smio_t *self, llio_endpoint_t *endpoint, uint32_t opcode)
{
    assert (self);
    int ret = -1;
    zmsg_t *send_msg = zmsg_new ();
    ASSERT_ALLOC(send_msg, err_msg_alloc);

    DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Calling thsafe_release\n");
    /* Message is:
     * frame 0: RELEASE opcode
     * frame 1: endpopint struct (FIXME?) */
    int zerr = zmsg_addmem (send_msg, &opcode, sizeof (opcode));
    ASSERT_TEST(zerr == 0, "Could not add OPEN opcode in message",
            err_add_opcode);
    zerr = zmsg_addmem (send_msg, endpoint, sizeof (*endpoint));
    ASSERT_TEST(zerr == 0, "Could not add endpoint in message",
            err_add_endpoint);

    DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Sending message:\n");
#ifdef LOCAL_MSG_DBG
    zmsg_print (send_msg);
#endif
    zerr = zmsg_send (&send_msg, self->pipe);
    ASSERT_TEST(zerr == 0, "Could not send message", err_send_msg);

    /* Message is:
     * frame 0: reply code
     * frame 1: return code */
    /* Returns NULL if confirmation was not OK or in case of error.
     * Returns the original message if the confirmation was OK */
    zmsg_t *recv_msg = _thsafe_zmq_client_recv_confirmation (self);
    ASSERT_TEST(recv_msg != NULL, "Could not receive confirmation code", err_null_raw_data);

    /* If we are here the message got a OK reply code.
     * Just return the return code */
    zframe_t *reply_frame = zmsg_pop (recv_msg);
    zframe_destroy (&reply_frame); /* Don't do anything with the reply code */
    zframe_t *ret_code_frame = zmsg_pop (recv_msg);

    if (ret_code_frame == NULL) {
        DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Interrupted or malformed message\n");
        /* Interrupted or malformed message */
        goto err_recv_data;
    }

    /* Check if the frame has the number of bytes requested.
     * For now, we consider a success only when the number of
     * bytes requested is the same as the actually read*/
    if (zframe_size (ret_code_frame) != THSAFE_REPLY_SIZE) {
        DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Frame size is wrong\n");
        goto err_recv_data_size;
    }

    ret = *(THSAFE_REPLY_TYPE *) zframe_data (ret_code_frame);

    DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Received return code: %08X\n", ret);

err_recv_data_size:
    zframe_destroy (&ret_code_frame);
err_recv_data:
err_null_raw_data:
    zmsg_destroy (&recv_msg);
err_send_msg:
err_add_endpoint:
err_add_opcode:
    zmsg_destroy (&send_msg);
err_msg_alloc:
    return ret;
}
Ejemplo n.º 12
0
int main (void)
{
    zctx_t *context = zctx_new ();
    void *frontend = zsocket_new (context, ZMQ_SUB);
    zsocket_bind (frontend, "ipc://frontend");
    void *backend = zsocket_new (context, ZMQ_XPUB);
    zsocket_bind (backend, "ipc://backend");

    //  .split main poll loop
    //  We route topic updates from frontend to backend, and
    //  we handle subscriptions by sending whatever we cached,
    //  if anything:
    while (true) {
	printf("Polling...\r\n");
        zmq_pollitem_t items [] = {
            { frontend, 0, ZMQ_POLLIN, 0 },
            { backend,  0, ZMQ_POLLIN, 0 }
        };
        if (zmq_poll (items, 2, -1) <= 0)
            break;              //  Interrupted(-1) or no event signaled (0)

	printf("Something read...\r\n");

        //  Any new topic data we cache and then forward
        if (items [0].revents & ZMQ_POLLIN) {
	    printf("Received... ");
            char *topic = zstr_recv (frontend);
            char *current = zstr_recv (frontend);
            if (!topic)
                break;
	    printf("%s : %s \r\n", topic, current);

	    zstr_sendm (backend, topic);
            zstr_send (backend, current);
            free (topic);
        }
        //  .split handle subscriptions
        //  When we get a new subscription, we pull data from the cache:
        if (items [1].revents & ZMQ_POLLIN) {
	    printf("Received new subscription...\r\n");
            zframe_t *frame = zframe_recv (backend);
            if (!frame)
                break;
            //  Event is one byte 0=unsub or 1=sub, followed by topic
            byte *event = zframe_data (frame);
            char *topic = zmalloc (zframe_size (frame));
            memcpy (topic, event + 1, zframe_size (frame) - 1);
            printf ("Topic is %s\n", topic);
	    if (event [0] == 0) {
                printf ("Unsubscribing topic %s\r\n", topic);
		zsocket_set_unsubscribe (frontend, topic);
	    }
	    if (event [0] == 1) {
                printf ("Subscribing topic %s\r\n", topic);
		zsocket_set_subscribe (frontend, topic);
            }
	    free(topic);
            zframe_destroy (&frame);
        }
    } 
    zctx_destroy (&context);
    return 0;
}
Ejemplo n.º 13
0
// This function is used by endpoint to receive message from zloop.
int maltcp_ctx_recv_message(void *self, mal_endpoint_t *mal_endpoint, mal_message_t **message) {
  maltcp_ctx_t *maltcp_ctx = (maltcp_ctx_t *) self;
  maltcp_endpoint_data_t *endpoint_data = (maltcp_endpoint_data_t *) mal_endpoint_get_endpoint_data(mal_endpoint);

  int rc = 0;

  clog_debug(maltcp_logger, "maltcp_ctx_recv_message()\n");

  zmsg_t *zmsg = zmsg_recv(endpoint_data->socket);
  if (zmsg) {
    size_t frames_count = zmsg_size(zmsg);

    clog_debug(maltcp_logger, "maltcp_ctx_recv_message: received zmsg (%d frames)\n", frames_count);

    // The first frame contains the peer URI.
    zframe_t *from = zmsg_pop(zmsg);
    char *peer_uri = NULL;
    if (from != NULL) {
      int len = zframe_size(from);
      peer_uri = (char *) malloc(len +1);
      strncpy(peer_uri, (char *)zframe_data(from), len);
      peer_uri[len] = '\0';
      zframe_destroy(&from);
    }
    clog_debug(maltcp_logger, "maltcp_ctx_recv_message: peer_uri = %s\n", peer_uri);

    // The MAL message is in the second frame.
    // Now the frame is owned by us.
    zframe_t *frame = zmsg_pop(zmsg);

    size_t mal_msg_bytes_length = zframe_size(frame);
    clog_debug(maltcp_logger, "maltcp_ctx_recv_message: mal_msg_bytes_length=%d\n", mal_msg_bytes_length);

    // Does not copy the frame bytes in another array.
    byte *mal_msg_bytes = zframe_data(frame);

    *message = mal_message_new_void();

    // MALTCP always uses the 'malbinary' encoding format for the messages header encoding (another
    // format may be used at the application layer for the message body).

    // Note: We could use virtual allocation and initialization functions from encoder
    // rather than malbinary interface.
    malbinary_cursor_t cursor;
    malbinary_cursor_init(&cursor, (char *) mal_msg_bytes, mal_msg_bytes_length, 0);

    mal_uinteger_t variable_length;

    // 'maltcp' encoding format of the MAL header
    if (maltcp_decode_message(maltcp_ctx->maltcp_header, *message, maltcp_ctx->decoder, &cursor, &variable_length) != 0) {
      clog_error(maltcp_logger, "maltcp_ctx_recv_message, cannot decode message\n");
      return -1;
    }
    // Note: Currently the message length is always equal to the frame size.
    assert(mal_msg_bytes_length == (variable_length + FIXED_HEADER_LENGTH));

    // TODO (AF) : Normally the frame should be kept to avoid copying the body of the message.
    // currently the body is always copied in a newly allocated memory.
    // Destroy must free the tcp frame
//    mal_message_set_body_owner(*message, frame);

    // If the From URI field is not completely filled, we have to complete it with
    // the information from TCP/IP protocol.
    mal_uri_t *uri_from = mal_message_get_uri_from(*message);
    if (uri_from == NULL) {
      mal_message_set_uri_from(*message, peer_uri);
      mal_message_set_free_uri_from(*message, (1==1));
    } else if (strncmp(uri_from, MALTCP_URI, sizeof MALTCP_URI -1) != 0) {
      if (uri_from[0] == '/')
        uri_from += 1;
      mal_uri_t *uri = (mal_uri_t *) malloc(strlen(peer_uri) + strlen(uri_from) +2);
      strcpy(uri, peer_uri);
      // Ensures presence of path separator (not added in maltcp_ctx_socket_receive).
      strcat(uri, "/");
      strcat(uri, uri_from);
      mal_message_set_uri_from(*message, uri);
      mal_message_set_free_uri_from(*message, (1==1));
      free(peer_uri);
    } else {
      // The complete URI is registered in the message header, use it.
      free(peer_uri);
    }

    // If the To URI field is not completely filled, we have to complete it.
    // TODO (AF): The To URI should never be completely filled!!
    mal_uri_t *uri_to = mal_message_get_uri_to(*message);
    if ((uri_to == NULL) || (strncmp(uri_to, MALTCP_URI, sizeof MALTCP_URI -1) != 0)) {
      mal_message_set_uri_to(*message, mal_endpoint_get_uri(endpoint_data->mal_endpoint));
      mal_message_set_free_uri_to(*message, (1!=1));
    }

    clog_debug(maltcp_logger, "maltcp_ctx_recv_message: ");
    if (clog_is_loggable(maltcp_logger, CLOG_DEBUG_LEVEL))
      mal_message_print(*message);
    clog_debug(maltcp_logger, "\n");

    // Verify if the message could be delivered and destroy it otherwise.
    if (endpoint_data->mal_endpoint) {
      bool message_delivered = false;
      mal_uri_t *endpoint_uri = mal_endpoint_get_uri(endpoint_data->mal_endpoint);
      if (strcmp(maltcp_get_service_from_uri(endpoint_uri), maltcp_get_service_from_uri(uri_to)) == 0)
        message_delivered = true;

      clog_debug(maltcp_logger, "maltcp_ctx_recv_message: message_delivered=%d\n", message_delivered);

      if (!message_delivered) {
        clog_debug(maltcp_logger, "maltcp_ctx_recv_message: destroy MAL message\n", uri_to);

        mal_message_destroy(message, maltcp_ctx->mal_ctx);
      }
    }

    // TODO (AF) : Normally the frame should be kept to avoid copying the body of the message.
    // currently the body is always copied in a newly allocated memory.
    zframe_destroy(&frame);
  } else {
    clog_debug(maltcp_logger, "maltcp_ctx_recv_message(): NULL\n");
  }

  return rc;
}
Ejemplo n.º 14
0
///
//  Return address of frame data
byte * QZframe::data ()
{
    byte * rv = zframe_data (self);
    return rv;
}
Ejemplo n.º 15
0
static void
s_socket_event (agent_t *self)
{
    zframe_t *frame;
    zmq_event_t event;
    char *description = "Unknown";
    char address [1025];

    //  Copy event data into event struct
    frame = zframe_recv (self->socket);

    //  Extract id of the event as bitfield
    memcpy (&(event.event), zframe_data (frame), sizeof (event.event));

    //  Extract value which is either error code, fd, or reconnect interval
    memcpy (&(event.value), zframe_data (frame) + sizeof (event.event),
           sizeof (event.value));
    zframe_destroy (&frame);

    //  Copy address part
    frame = zframe_recv (self->socket);
    memcpy (address, zframe_data (frame), zframe_size (frame));
    address [zframe_size (frame)] = 0;  // Terminate address string
    zframe_destroy (&frame);

    switch (event.event) {
        case ZMQ_EVENT_ACCEPTED:
            description = "Accepted";
            break;
        case ZMQ_EVENT_ACCEPT_FAILED:
            description = "Accept failed";
            break;
        case ZMQ_EVENT_BIND_FAILED:
            description = "Bind failed";
            break;
        case ZMQ_EVENT_CLOSED:
            description = "Closed";
            break;
        case ZMQ_EVENT_CLOSE_FAILED:
            description = "Close failed";
            break;
        case ZMQ_EVENT_DISCONNECTED:
            description = "Disconnected";
            break;
        case ZMQ_EVENT_CONNECTED:
            description = "Connected";
            break;
        case ZMQ_EVENT_CONNECT_DELAYED:
            description = "Connect delayed";
            break;
        case ZMQ_EVENT_CONNECT_RETRIED:
            description = "Connect retried";
            break;
        case ZMQ_EVENT_LISTENING:
            description = "Listening";
            break;
        case ZMQ_EVENT_MONITOR_STOPPED:
            description = "Monitor stopped";
            break;
        default:
            if (self->verbose)
                printf ("Unknown socket monitor event: %d", event.event);
            break;
    }
    if (self->verbose)
        printf ("I: zmonitor: %s - %s\n", description, address);

    zmsg_t *msg = zmsg_new();
    zmsg_addstrf (msg, "%d", (int) event.event);
    zmsg_addstrf (msg, "%d", (int) event.value);
    zmsg_addstrf (msg, "%s", address);
    zmsg_addstrf (msg, "%s", description);
    zmsg_send (&msg, self->pipe);
}
Ejemplo n.º 16
0
int 
main(int argc, char* argv[])
{
  zctx_t* ctx;
  void* cloudfe;
  void* cloudbe;
  int i;
  void* localfe;
  void* localbe;
  int capacity = 0;
  zlist_t* workers;

  if (argc < 2) {
    fprintf(stderr, "syntax: peering me {you} ...\n");
    return 1;
  }
  self = argv[1];
  fprintf(stdout, "I: preparing broker at %s ...\n", self);
  srand((unsigned int)time(NULL));

  ctx = zctx_new();

  cloudfe = zsocket_new(ctx, ZMQ_ROUTER);
  zsockopt_set_identity(cloudfe, self);
  zsocket_bind(cloudfe, "ipc://%s-cloud.ipc", self);

  cloudbe = zsocket_new(ctx, ZMQ_ROUTER);
  zsockopt_set_identity(cloudbe, self);
  for (i = 2; i < argc; ++i) {
    char* peer = argv[i];
    fprintf(stdout, "I: connecting to cloud frontend at '%s'\n", peer);
    zsocket_connect(cloudbe, "ipc://%s-cloud.ipc", peer);
  }

  localfe = zsocket_new(ctx, ZMQ_ROUTER);
  zsocket_bind(localfe, "ipc://%s-localfe.ipc", self);
  localbe = zsocket_new(ctx, ZMQ_ROUTER);
  zsocket_bind(localbe, "ipc://%s-localbe.ipc", self);

  fprintf(stdout, "Press Enter when all brokers are started: ");
  getchar();

  for (i = 0; i < NUM_WORKERS; ++i)
    zthread_new(worker_routine, NULL);
  for (i = 0; i < NUM_CLIENTS; ++i)
    zthread_new(client_routine, NULL);

  workers = zlist_new();
  while (1) {
    zmsg_t* msg;
    zmq_pollitem_t backends[] = {
      {localbe, 0, ZMQ_POLLIN, 0}, 
      {cloudbe, 0, ZMQ_POLLIN, 0}, 
    };
    int r = zmq_poll(backends, 2, capacity ? 1000 * ZMQ_POLL_MSEC : -1);
    if (-1 == r)
      break;

    msg = NULL;
    if (backends[0].revents & ZMQ_POLLIN) {
      zframe_t* identity;
      zframe_t* frame;
      msg = zmsg_recv(localbe);
      if (!msg)
        break;

      identity = zmsg_unwrap(msg);
      zlist_append(workers, identity);
      ++capacity;

      frame = zmsg_first(msg);
      if (0 == memcmp(zframe_data(frame), WORKER_READY, 1))
        zmsg_destroy(&msg);
    }
    else if (backends[1].revents & ZMQ_POLLIN) {
      zframe_t* identity;
      msg = zmsg_recv(cloudbe);
      if (!msg)
        break;

      identity = zmsg_unwrap(msg);
      zframe_destroy(&identity);
    }
    for (i = 2; msg && i < argc; ++i) {
      char* data = (char*)zframe_data(zmsg_first(msg));
      size_t size = zframe_size(zmsg_first(msg));
      if (size == strlen(argv[i]) && 0 == memcmp(data, argv[i], size))
        zmsg_send(&msg, cloudfe);
    }
    if (msg) 
      zmsg_send(&msg, localfe);


    while (capacity) {
      int reroutable = 0;
      zmq_pollitem_t frontends[] = {
        {localfe, 0, ZMQ_POLLIN, 0}, 
        {cloudfe, 0, ZMQ_POLLIN, 0},
      };
      r = zmq_poll(frontends, 2, 0);
      assert(r >= 0);

      if (frontends[1].revents & ZMQ_POLLIN) {
        msg = zmsg_recv(cloudfe);
        reroutable = 0;
      }
      else if (frontends[0].revents & ZMQ_POLLIN) {
        msg = zmsg_recv(localfe);
        reroutable = 1;
      }
      else 
        break;


      if (0 != reroutable && argc > 2 && 0 == rand() % 5) {
        int random_peer = rand() % (argc - 2) + 2;
        zmsg_pushmem(msg, argv[random_peer], strlen(argv[random_peer]));
        zmsg_send(&msg, cloudbe);
      }
      else {
        zframe_t* frame = (zframe_t*)zlist_pop(workers);
        zmsg_wrap(msg, frame);
        zmsg_send(&msg, localbe);
        --capacity;
      }
    }
  }

  while (zlist_size(workers)) {
    zframe_t* frame = (zframe_t*)zlist_pop(workers);
    zframe_destroy(&frame);
  }
  zlist_destroy(&workers);

  zctx_destroy(&ctx);
  return 0;
}
Ejemplo n.º 17
0
int main (void)
{
    zctx_t *ctx = zctx_new ();
    void *frontend = zsocket_new (ctx, ZMQ_ROUTER);
    void *backend = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (frontend, "ipc://frontend.ipc");
    zsocket_bind (backend, "ipc://backend.ipc");

    int client_nbr;
    for (client_nbr = 0; client_nbr < NBR_CLIENTS; client_nbr++)
        zthread_new (client_task, NULL);
    int worker_nbr;
    for (worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++)
        zthread_new (worker_task, NULL);

    //  Queue of available workers
    zlist_t *workers = zlist_new ();

    //  Here is the main loop for the load-balancer. It works the same way
    //  as the previous example, but is a lot shorter because CZMQ gives
    //  us an API that does more with fewer calls:
    while (true) {
        zmq_pollitem_t items [] = {
            { backend,  0, ZMQ_POLLIN, 0 },
            { frontend, 0, ZMQ_POLLIN, 0 }
        };
        //  Poll frontend only if we have available workers
        int rc = zmq_poll (items, zlist_size (workers)? 2: 1, -1);
        if (rc == -1)
            break;              //  Interrupted

        //  Handle worker activity on backend
        if (items [0].revents & ZMQ_POLLIN) {
            //  Use worker identity for load-balancing
            zmsg_t *msg = zmsg_recv (backend);
            if (!msg)
                break;          //  Interrupted
            zframe_t *identity = zmsg_unwrap (msg);
            zlist_append (workers, identity);

            //  Forward message to client if it's not a READY
            zframe_t *frame = zmsg_first (msg);
            if (memcmp (zframe_data (frame), WORKER_READY, 1) == 0)
                zmsg_destroy (&msg);
            else
                zmsg_send (&msg, frontend);
        }
        if (items [1].revents & ZMQ_POLLIN) {
            //  Get client request, route to first available worker
            zmsg_t *msg = zmsg_recv (frontend);
            if (msg) {
                zmsg_wrap (msg, (zframe_t *) zlist_pop (workers));
                zmsg_send (&msg, backend);
            }
        }
    }
    //  When we're done, clean up properly
    while (zlist_size (workers)) {
        zframe_t *frame = (zframe_t *) zlist_pop (workers);
        zframe_destroy (&frame);
    }
    zlist_destroy (&workers);
    zctx_destroy (&ctx);
    return 0;
}
Ejemplo n.º 18
0
zre_log_msg_t *
zre_log_msg_recv (void *input)
{
    assert (input);
    zre_log_msg_t *self = zre_log_msg_new (0);
    zframe_t *frame = NULL;
    size_t string_size;
    size_t list_size;
    size_t hash_size;

    //  Read valid message frame from socket; we loop over any
    //  garbage data we might receive from badly-connected peers
    while (true) {
        //  If we're reading from a ROUTER socket, get address
        if (zsocket_type (input) == ZMQ_ROUTER) {
            zframe_destroy (&self->address);
            self->address = zframe_recv (input);
            if (!self->address)
                goto empty;         //  Interrupted
            if (!zsocket_rcvmore (input))
                goto malformed;
        }
        //  Read and parse command in frame
        frame = zframe_recv (input);
        if (!frame)
            goto empty;             //  Interrupted

        //  Get and check protocol signature
        self->needle = zframe_data (frame);
        self->ceiling = self->needle + zframe_size (frame);
        uint16_t signature;
        GET_NUMBER2 (signature);
        if (signature == (0xAAA0 | 2))
            break;                  //  Valid signature

        //  Protocol assertion, drop message
        while (zsocket_rcvmore (input)) {
            zframe_destroy (&frame);
            frame = zframe_recv (input);
        }
        zframe_destroy (&frame);
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case ZRE_LOG_MSG_LOG:
            GET_NUMBER1 (self->level);
            GET_NUMBER1 (self->event);
            GET_NUMBER2 (self->node);
            GET_NUMBER2 (self->peer);
            GET_NUMBER8 (self->time);
            free (self->data);
            GET_STRING (self->data);
            break;

        default:
            goto malformed;
    }
    //  Successful return
    zframe_destroy (&frame);
    return self;

    //  Error returns
    malformed:
        printf ("E: malformed message '%d'\n", self->id);
    empty:
        zframe_destroy (&frame);
        zre_log_msg_destroy (&self);
        return (NULL);
}
Ejemplo n.º 19
0
int main (void)
{
    zctx_t *context = zctx_new ();
    void *frontend = zsocket_new (context, ZMQ_SUB);
    zsocket_bind (frontend, "tcp://*:5557");
    void *backend = zsocket_new (context, ZMQ_XPUB);
    zsocket_bind (backend, "tcp://*:5558");

    //  Subscribe to every single topic from publisher
    zsocket_set_subscribe (frontend, "");

    //  Store last instance of each topic in a cache
    zhash_t *cache = zhash_new ();

    //  .split main poll loop
    //  We route topic updates from frontend to backend, and
    //  we handle subscriptions by sending whatever we cached,
    //  if anything:
    while (true) {
        zmq_pollitem_t items [] = {
            { frontend, 0, ZMQ_POLLIN, 0 },
            { backend,  0, ZMQ_POLLIN, 0 }
        };
        if (zmq_poll (items, 2, 1000 * ZMQ_POLL_MSEC) == -1)
            break;              //  Interrupted

        //  Any new topic data we cache and then forward
        if (items [0].revents & ZMQ_POLLIN) {
            char *topic = zstr_recv (frontend);
            char *current = zstr_recv (frontend);
            if (!topic)
                break;
            char *previous = zhash_lookup (cache, topic);
            if (previous) {
                zhash_delete (cache, topic);
                free (previous);
            }
            zhash_insert (cache, topic, current);
            zstr_sendm (backend, topic);
            zstr_send (backend, current);
            free (topic);
        }
        //  .split handle subscriptions
        //  When we get a new subscription we pull data from the cache:
        if (items [1].revents & ZMQ_POLLIN) {
            zframe_t *frame = zframe_recv (backend);
            if (!frame)
                break;
            //  Event is one byte 0=unsub or 1=sub, followed by topic
            byte *event = zframe_data (frame);
            if (event [0] == 1) {
                char *topic = zmalloc (zframe_size (frame));
                memcpy (topic, event + 1, zframe_size (frame) - 1);
                printf ("Sending cached topic %s\n", topic);
                char *previous = zhash_lookup (cache, topic);
                if (previous) {
                    zstr_sendm (backend, topic);
                    zstr_send (backend, previous);
                }
                free (topic);
            }
            zframe_destroy (&frame);
        }
    }
    zctx_destroy (&context);
    zhash_destroy (&cache);
    return 0;
}
Ejemplo n.º 20
0
int
zre_log_msg_send (zre_log_msg_t **self_p, void *output)
{
    assert (output);
    assert (self_p);
    assert (*self_p);

    //  Calculate size of serialized data
    zre_log_msg_t *self = *self_p;
    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case ZRE_LOG_MSG_LOG:
            //  level is a 1-byte integer
            frame_size += 1;
            //  event is a 1-byte integer
            frame_size += 1;
            //  node is a 2-byte integer
            frame_size += 2;
            //  peer is a 2-byte integer
            frame_size += 2;
            //  time is a 8-byte integer
            frame_size += 8;
            //  data is a string with 1-byte length
            frame_size++;       //  Size is one octet
            if (self->data)
                frame_size += strlen (self->data);
            break;
            
        default:
            printf ("E: bad message type '%d', not sent\n", self->id);
            //  No recovery, this is a fatal application error
            assert (false);
    }
    //  Now serialize message into the frame
    zframe_t *frame = zframe_new (NULL, frame_size);
    self->needle = zframe_data (frame);
    size_t string_size;
    int frame_flags = 0;
    PUT_NUMBER2 (0xAAA0 | 2);
    PUT_NUMBER1 (self->id);

    switch (self->id) {
        case ZRE_LOG_MSG_LOG:
            PUT_NUMBER1 (self->level);
            PUT_NUMBER1 (self->event);
            PUT_NUMBER2 (self->node);
            PUT_NUMBER2 (self->peer);
            PUT_NUMBER8 (self->time);
            if (self->data) {
                PUT_STRING (self->data);
            }
            else
                PUT_NUMBER1 (0);    //  Empty string
            break;
            
    }
    //  If we're sending to a ROUTER, we send the address first
    if (zsocket_type (output) == ZMQ_ROUTER) {
        assert (self->address);
        if (zframe_send (&self->address, output, ZFRAME_MORE)) {
            zframe_destroy (&frame);
            zre_log_msg_destroy (self_p);
            return -1;
        }
    }
    //  Now send the data frame
    if (zframe_send (&frame, output, frame_flags)) {
        zframe_destroy (&frame);
        zre_log_msg_destroy (self_p);
        return -1;
    }
    //  Destroy zre_log_msg object
    zre_log_msg_destroy (self_p);
    return 0;
}
Ejemplo n.º 21
0
zmsg_t *
zre_msg_encode (zre_msg_t *self, int socket_type)
{
    assert (self);
    zmsg_t *msg = zmsg_new ();

    //  If we're sending to a ROUTER, send the routing_id first
    if (socket_type == ZMQ_ROUTER)
        zmsg_prepend (msg, &self->routing_id);
        
    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case ZRE_MSG_HELLO:
            //  sequence is a 2-byte integer
            frame_size += 2;
            //  ipaddress is a string with 1-byte length
            frame_size++;       //  Size is one octet
            if (self->ipaddress)
                frame_size += strlen (self->ipaddress);
            //  mailbox is a 2-byte integer
            frame_size += 2;
            //  groups is an array of strings
            frame_size += 4;    //  Size is 4 octets
            if (self->groups) {
                //  Add up size of list contents
                char *groups = (char *) zlist_first (self->groups);
                while (groups) {
                    frame_size += 4 + strlen (groups);
                    groups = (char *) zlist_next (self->groups);
                }
            }
            //  status is a 1-byte integer
            frame_size += 1;
            //  headers is an array of key=value strings
            frame_size += 4;    //  Size is 4 octets
            if (self->headers) {
                self->headers_bytes = 0;
                //  Add up size of dictionary contents
                zhash_foreach (self->headers, s_headers_count, self);
            }
            frame_size += self->headers_bytes;
            break;
            
        case ZRE_MSG_WHISPER:
            //  sequence is a 2-byte integer
            frame_size += 2;
            break;
            
        case ZRE_MSG_SHOUT:
            //  sequence is a 2-byte integer
            frame_size += 2;
            //  group is a string with 1-byte length
            frame_size++;       //  Size is one octet
            if (self->group)
                frame_size += strlen (self->group);
            break;
            
        case ZRE_MSG_JOIN:
            //  sequence is a 2-byte integer
            frame_size += 2;
            //  group is a string with 1-byte length
            frame_size++;       //  Size is one octet
            if (self->group)
                frame_size += strlen (self->group);
            //  status is a 1-byte integer
            frame_size += 1;
            break;
            
        case ZRE_MSG_LEAVE:
            //  sequence is a 2-byte integer
            frame_size += 2;
            //  group is a string with 1-byte length
            frame_size++;       //  Size is one octet
            if (self->group)
                frame_size += strlen (self->group);
            //  status is a 1-byte integer
            frame_size += 1;
            break;
            
        case ZRE_MSG_PING:
            //  sequence is a 2-byte integer
            frame_size += 2;
            break;
            
        case ZRE_MSG_PING_OK:
            //  sequence is a 2-byte integer
            frame_size += 2;
            break;
            
        default:
            printf ("E: bad message type '%d', not sent\n", self->id);
            //  No recovery, this is a fatal application error
            assert (false);
    }
    //  Now serialize message into the frame
    zframe_t *frame = zframe_new (NULL, frame_size);
    self->needle = zframe_data (frame);
    PUT_NUMBER2 (0xAAA0 | 1);
    PUT_NUMBER1 (self->id);

    switch (self->id) {
        case ZRE_MSG_HELLO:
            PUT_NUMBER2 (self->sequence);
            if (self->ipaddress) {
                PUT_STRING (self->ipaddress);
            }
            else
                PUT_NUMBER1 (0);    //  Empty string
            PUT_NUMBER2 (self->mailbox);
            if (self->groups) {
                PUT_NUMBER4 (zlist_size (self->groups));
                char *groups = (char *) zlist_first (self->groups);
                while (groups) {
                    PUT_LONGSTR (groups);
                    groups = (char *) zlist_next (self->groups);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty string array
            PUT_NUMBER1 (self->status);
            if (self->headers) {
                PUT_NUMBER4 (zhash_size (self->headers));
                zhash_foreach (self->headers, s_headers_write, self);
            }
            else
                PUT_NUMBER4 (0);    //  Empty dictionary
            break;

        case ZRE_MSG_WHISPER:
            PUT_NUMBER2 (self->sequence);
            break;

        case ZRE_MSG_SHOUT:
            PUT_NUMBER2 (self->sequence);
            if (self->group) {
                PUT_STRING (self->group);
            }
            else
                PUT_NUMBER1 (0);    //  Empty string
            break;

        case ZRE_MSG_JOIN:
            PUT_NUMBER2 (self->sequence);
            if (self->group) {
                PUT_STRING (self->group);
            }
            else
                PUT_NUMBER1 (0);    //  Empty string
            PUT_NUMBER1 (self->status);
            break;

        case ZRE_MSG_LEAVE:
            PUT_NUMBER2 (self->sequence);
            if (self->group) {
                PUT_STRING (self->group);
            }
            else
                PUT_NUMBER1 (0);    //  Empty string
            PUT_NUMBER1 (self->status);
            break;

        case ZRE_MSG_PING:
            PUT_NUMBER2 (self->sequence);
            break;

        case ZRE_MSG_PING_OK:
            PUT_NUMBER2 (self->sequence);
            break;

    }
    //  Now send the data frame
    if (zmsg_append (msg, &frame)) {
        zmsg_destroy (&msg);
        zre_msg_destroy (&self);
        return NULL;
    }
    //  Now send the content field if set
    if (self->id == ZRE_MSG_WHISPER) {
        zframe_t *content_part = zmsg_pop (self->content);
        while (content_part) {
            zmsg_append (msg, &content_part);
            content_part = zmsg_pop (self->content);
        }
    }
    //  Now send the content field if set
    if (self->id == ZRE_MSG_SHOUT) {
        zframe_t *content_part = zmsg_pop (self->content);
        while (content_part) {
            zmsg_append (msg, &content_part);
            content_part = zmsg_pop (self->content);
        }
    }
    //  Destroy zre_msg object
    zre_msg_destroy (&self);
    return msg;

}
Ejemplo n.º 22
0
void web_request(void *sweb, req_store_t * req_store, void *spss, void *sgraph)
{

	zmsg_t *msg = zmsg_recv(sweb);
	zframe_t *address = zmsg_unwrap(msg);
	json_t *req_json;
	json_error_t error;
	printf("\nbroker:sweb received: %s\n",
	       (const char *)zframe_data(zmsg_first(msg)));
	const char *data;
	size_t data_size = zframe_size(zmsg_first(msg));
	data = zframe_data(zmsg_first(msg));
	req_json = json_loadb(data, data_size, 0, &error);
	zmsg_destroy(&msg);

	int32_t requestId = request_store_add(req_store, address, req_json);

	json_t *clientRequest = json_object_get(req_json, "clientRequest");
	json_t *request = json_object_get(clientRequest, "request");

	const char *type = json_string_value(json_object_get(request, "type"));

	if (strcmp(type, "searchRequest") == 0)

		web_request_searchRequest(requestId, request, spss);

	else if (strcmp(type, "newNode") == 0)

		web_request_newNode(requestId, request, sgraph);

	else if (strcmp(type, "newPosition") == 0)

		web_request_newPosition(requestId, request, spss);

	else if (strcmp(type, "newLink") == 0)

		web_request_newLink(requestId, request, sgraph);

	else if (strcmp(type, "delLink") == 0)

		web_request_delLink(requestId, request, sgraph);

	else if (strcmp(type, "delNode") == 0)

		web_request_delNode(requestId, request, sgraph);

	else if (strcmp(type, "newNodeData") == 0)

		web_request_newNodeData(requestId, request, sgraph);
	else if (strcmp(type, "newLinkData") == 0)

		web_request_newLinkData(requestId, request, sgraph);
	else {

		//TODO process request
		//malformed request
		printf("\ni received a malformed request : %s", type);
		//delete request 
		zframe_destroy(&address);
		request_store_delete(req_store, requestId);
	}

}
Ejemplo n.º 23
0
static void
zyre_node_recv_peer (zyre_node_t *self)
{
    //  Router socket tells us the identity of this peer
    zre_msg_t *msg = zre_msg_recv (self->inbox);
    if (!msg)
        return;                 //  Interrupted

    //  First frame is sender identity
    byte *peerid_data = zframe_data (zre_msg_routing_id (msg));
    size_t peerid_size = zframe_size (zre_msg_routing_id (msg));

    //  Identity must be [1] followed by 16-byte UUID
    if (peerid_size != ZUUID_LEN + 1) {
        zre_msg_destroy (&msg);
        return;
    }
    zuuid_t *uuid = zuuid_new ();
    zuuid_set (uuid, peerid_data + 1);

    //  On HELLO we may create the peer if it's unknown
    //  On other commands the peer must already exist
    zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, zuuid_str (uuid));
    if (zre_msg_id (msg) == ZRE_MSG_HELLO) {
        if (peer) {
            //  Remove fake peers
            if (zyre_peer_ready (peer)) {
                zyre_node_remove_peer (self, peer);
                assert (!(zyre_peer_t *) zhash_lookup (self->peers, zuuid_str (uuid)));
            }
            else
            if (streq (zyre_peer_endpoint (peer), self->endpoint)) {
                //  We ignore HELLO, if peer has same endpoint as current node
                zre_msg_destroy (&msg);
                zuuid_destroy (&uuid);
                return;
            }
        }
        peer = zyre_node_require_peer (self, uuid, zre_msg_endpoint (msg));
        assert (peer);
        zyre_peer_set_ready (peer, true);
    }
    //  Ignore command if peer isn't ready
    if (peer == NULL || !zyre_peer_ready (peer)) {
        zre_msg_destroy (&msg);
        zuuid_destroy (&uuid);
        return;
    }
    if (zyre_peer_messages_lost (peer, msg)) {
        zsys_warning ("(%s) messages lost from %s", self->name, zyre_peer_name (peer));
        zyre_node_remove_peer (self, peer);
        zre_msg_destroy (&msg);
        zuuid_destroy (&uuid);
        return;
    }
    //  Now process each command
    if (zre_msg_id (msg) == ZRE_MSG_HELLO) {
        //  Store properties from HELLO command into peer
        zyre_peer_set_name (peer, zre_msg_name (msg));
        zyre_peer_set_headers (peer, zre_msg_headers (msg));

        //  Tell the caller about the peer
        zstr_sendm (self->outbox, "ENTER");
        zstr_sendm (self->outbox, zyre_peer_identity (peer));
        zstr_sendm (self->outbox, zyre_peer_name (peer));
        zframe_t *headers = zhash_pack (zyre_peer_headers (peer));
        zframe_send (&headers, self->outbox, ZFRAME_MORE);
        zstr_send (self->outbox, zre_msg_endpoint (msg));

        if (self->verbose)
            zsys_info ("(%s) ENTER name=%s endpoint=%s",
                self->name, zyre_peer_name (peer), zyre_peer_endpoint (peer));

        //  Join peer to listed groups
        const char *name = zre_msg_groups_first (msg);
        while (name) {
            zyre_node_join_peer_group (self, peer, name);
            name = zre_msg_groups_next (msg);
        }
        //  Now take peer's status from HELLO, after joining groups
        zyre_peer_set_status (peer, zre_msg_status (msg));
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_WHISPER) {
        //  Pass up to caller API as WHISPER event
        zstr_sendm (self->outbox, "WHISPER");
        zstr_sendm (self->outbox, zuuid_str (uuid));
        zstr_sendm (self->outbox, zyre_peer_name (peer));
        zmsg_t *content = zmsg_dup (zre_msg_content (msg));
        zmsg_send (&content, self->outbox);
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_SHOUT) {
        //  Pass up to caller as SHOUT event
        zstr_sendm (self->outbox, "SHOUT");
        zstr_sendm (self->outbox, zuuid_str (uuid));
        zstr_sendm (self->outbox, zyre_peer_name (peer));
        zstr_sendm (self->outbox, zre_msg_group (msg));
        zmsg_t *content = zmsg_dup (zre_msg_content (msg));
        zmsg_send (&content, self->outbox);
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_PING) {
        zre_msg_t *msg = zre_msg_new (ZRE_MSG_PING_OK);
        zyre_peer_send (peer, &msg);
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_JOIN) {
        zyre_node_join_peer_group (self, peer, zre_msg_group (msg));
        assert (zre_msg_status (msg) == zyre_peer_status (peer));
    }
    else
    if (zre_msg_id (msg) == ZRE_MSG_LEAVE) {
        zyre_node_leave_peer_group (self, peer, zre_msg_group (msg));
        assert (zre_msg_status (msg) == zyre_peer_status (peer));
    }
    zuuid_destroy (&uuid);
    zre_msg_destroy (&msg);

    //  Activity from peer resets peer timers
    zyre_peer_refresh (peer, self->evasive_timeout, self->expired_timeout);
}
Ejemplo n.º 24
0
void graph_response(void *sgraph, req_store_t * req_store, void *sweb,
		    void *spss)
{

	zmsg_t *msg = zmsg_recv(sgraph);
	zframe_t *null = zmsg_unwrap(msg);
	zframe_destroy(&null);
	json_error_t error;
	printf("\nbroker:sgraph received: %s\n",
	       (const char *)zframe_data(zmsg_first(msg)));
	const char *data;
	size_t data_size = zframe_size(zmsg_first(msg));
	data = zframe_data(zmsg_first(msg));

	json_t *graph_resp_json = json_loadb(data,
					     data_size, 0,
					     &error);
	zmsg_destroy(&msg);

	//identify the request
	int32_t requestId =
	    json_integer_value(json_object_get(graph_resp_json, "requestId"));

	req_t *req = request_store_req(req_store, requestId);

	json_t *response = json_object_get(graph_resp_json, "response");

	const char *resp_type =
	    json_string_value(json_object_get(response, "type"));

	json_t *request =
	    json_object_get(json_object_get(req->request, "clientRequest"),
			    "request");
	const char *req_type =
	    json_string_value(json_object_get(request, "type"));

	if ((strcmp(resp_type, "retrieveResponse") == 0)
	    && (strcmp(req_type, "searchRequest") == 0))

		graph_response_retrieveResponse(req, response,
						requestId, sweb, req_store);

	else if ((strcmp(resp_type, "newNodeResponse") == 0)
		 && (strcmp(req_type, "newNode") == 0))

		graph_response_newNodeResponse(request,
					       response,
					       requestId, spss, req_store);

	else if ((strcmp(resp_type, "newLinkResponse") == 0)
		 && (strcmp(req_type, "newLink") == 0))

		graph_response_newLinkResponse(req,
					       request,
					       response,
					       requestId, sweb, req_store);

	else if ((strcmp(resp_type, "delLinkResponse")
		  == 0) && (strcmp(req_type, "delLink")
			    == 0))

		graph_response_delLinkResponse(req,
					       request,
					       response,
					       requestId, sweb, req_store);

	else if ((strcmp(resp_type, "delNode") == 0)
		 && (strcmp(req_type, "delNode")
		     == 0))
		graph_response_delNodeResponse(req,
					       request,
					       response,
					       requestId, spss, req_store);

	else if ((strcmp(resp_type, "newNodeData")
		  == 0) && (strcmp(req_type, "newNodeData")
			    == 0))

		graph_response_newNodeDataResponse(req,
						   request,
						   response,
						   requestId, sweb, req_store);

	else if ((strcmp(resp_type, "newLinkData")
		  == 0) && (strcmp(req_type, "newLinkData")
			    == 0))

		graph_response_newLinkDataResponse(req,
						   request,
						   response,
						   requestId, sweb, req_store);

	json_decref(graph_resp_json);
}
Ejemplo n.º 25
0
zgossip_msg_t *
zgossip_msg_decode (zmsg_t **msg_p)
{
    assert (msg_p);
    zmsg_t *msg = *msg_p;
    if (msg == NULL)
        return NULL;
        
    zgossip_msg_t *self = zgossip_msg_new (0);
    //  Read and parse command in frame
    zframe_t *frame = zmsg_pop (msg);
    if (!frame) 
        goto empty;             //  Malformed or empty

    //  Get and check protocol signature
    self->needle = zframe_data (frame);
    self->ceiling = self->needle + zframe_size (frame);
    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 0))
        goto empty;             //  Invalid signature

    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case ZGOSSIP_MSG_HELLO:
            GET_NUMBER1 (self->version);
            if (self->version != 1)
                goto malformed;
            break;

        case ZGOSSIP_MSG_PUBLISH:
            GET_NUMBER1 (self->version);
            if (self->version != 1)
                goto malformed;
            GET_STRING (self->key);
            GET_LONGSTR (self->value);
            GET_NUMBER4 (self->ttl);
            break;

        case ZGOSSIP_MSG_PING:
            GET_NUMBER1 (self->version);
            if (self->version != 1)
                goto malformed;
            break;

        case ZGOSSIP_MSG_PONG:
            GET_NUMBER1 (self->version);
            if (self->version != 1)
                goto malformed;
            break;

        case ZGOSSIP_MSG_INVALID:
            GET_NUMBER1 (self->version);
            if (self->version != 1)
                goto malformed;
            break;

        default:
            goto malformed;
    }
    //  Successful return
    zframe_destroy (&frame);
    zmsg_destroy (msg_p);
    return self;

    //  Error returns
    malformed:
        zsys_error ("malformed message '%d'\n", self->id);
    empty:
        zframe_destroy (&frame);
        zmsg_destroy (msg_p);
        zgossip_msg_destroy (&self);
        return (NULL);
}
Ejemplo n.º 26
0
Archivo: lsd.c Proyecto: vperron/lsd
static void interface_task (void *args, zctx_t *ctx, void *pipe )
{
	lsd_handle_t *self = (lsd_handle_t*) args;

	assert(self);

	char *peer = NULL;
	char *group = NULL;
	zframe_t* msg_frame = NULL;

	zmq_pollitem_t pollitems [] = {
		{ pipe,                             0, ZMQ_POLLIN, 0 },
		{ zre_node_handle (self->interface), 0, ZMQ_POLLIN, 0 }
	};

	while (!zctx_interrupted) {
		if (zmq_poll (pollitems, 2, randof (1000) * ZMQ_POLL_MSEC) == -1) {
			debugLog ("I: Interrupted by user action.\n");
			break;              //  Interrupted
		}

		if (pollitems [0].revents & ZMQ_POLLIN) {
			debugLog ("I: Interrupted by parent.\n");
			break;              //  Any command fom parent means EXIT
		}

		//  Process an event from interface
		if (pollitems [1].revents & ZMQ_POLLIN) {
			zmsg_t *incoming = zre_node_recv (self->interface);
			if (!incoming) {
				debugLog ("I: Interrupted before end of read.\n");
				break;              //  Interrupted
			}

			char *event = zmsg_popstr (incoming);
			debugLog("I EVENT == %s", event);
			if (streq (event, "ENTER")) {
				peer = zmsg_popstr (incoming);
				debugLog ("I: ENTER '%s'", peer);
				if(self->callback) {
					(*self->callback)(self,
							LSD_EVENT_ENTER,
							peer,
							NULL,
							NULL,
							0, 
							self->class_ptr);
				}
			} else if (streq (event, "EXIT")) {
				peer = zmsg_popstr (incoming);
				debugLog ("I: EXIT '%s'", peer);
				if(self->callback) {
					(*self->callback)(self,
							LSD_EVENT_EXIT,
							peer,
							NULL,
							NULL,
							0,
							self->class_ptr);
				}
			} else if (streq (event, "WHISPER")) {
				peer = zmsg_popstr (incoming);
				msg_frame = zmsg_pop (incoming);
				debugLog ("I: WHISPER '%s' msglen %d", peer, (int)zframe_size(msg_frame));
				if(self->callback) {
					(*self->callback)(self,
							LSD_EVENT_WHISPER,
							peer,
							NULL,
							(const uint8_t*)zframe_data(msg_frame),
							zframe_size(msg_frame),
							self->class_ptr);
				}
			} else 	if (streq (event, "SHOUT")) {
				peer = zmsg_popstr (incoming);
				group = zmsg_popstr (incoming);
				msg_frame = zmsg_pop (incoming); 
				debugLog ("I: SHOUT from '%s' group '%s' msglen %d", peer, group, (int)zframe_size(msg_frame));
				if(self->callback) {
					(*self->callback)(self,
							LSD_EVENT_SHOUT,
							peer,
							group,
							zframe_data(msg_frame),
							zframe_size(msg_frame),
							self->class_ptr);
				}
			} else if (streq (event, "DELIVER")) {
				char *filename = zmsg_popstr (incoming);
				char *fullname = zmsg_popstr (incoming);
				debugLog ("I: DELIVER file %s", fullname);
				if(self->callback) {
					(*self->callback)(self,
							LSD_EVENT_DELIVER,
							NULL,
							NULL,
							(const uint8_t*)fullname,
							strlen(fullname),
							self->class_ptr);
				}
				free (fullname);
				free (filename);
			}else if (streq (event, "JOIN")) {
				peer = zmsg_popstr (incoming);
				group = zmsg_popstr (incoming);
				debugLog ("I: JOIN '%s - %s'", peer, group);
				if(self->callback) {
					(*self->callback)(self,
							LSD_EVENT_JOIN,
							peer,
							group,
							NULL,
							0,
							self->class_ptr);
				}
			} else if (streq (event, "LEAVE")) {
				peer = zmsg_popstr (incoming);
				group = zmsg_popstr (incoming);
				debugLog ("I: LEAVE '%s - %s'", peer, group);
				if(self->callback) {
					(*self->callback)(self,
							LSD_EVENT_LEAVE,
							peer,
							group,
							NULL,
							0,
							self->class_ptr);
				}
			}

			if(peer) {
				free(peer);
				peer = NULL;
			}
			if(group) {
				free(group);
				group = NULL;
			}
			if(msg_frame) {
				zframe_destroy(&msg_frame);
				msg_frame = NULL;
			}
			
			free (event);
			zmsg_destroy (&incoming);
		}
	}
}
Ejemplo n.º 27
0
void
curve_client_test (bool verbose)
{
    printf (" * curve_client: ");
    //  @selftest
    //  Create temporary directory for test files
    zsys_dir_create (TESTDIR);
    
    //  We'll create two new certificates and save the client public 
    //  certificate on disk; in a real case we'd transfer this securely
    //  from the client machine to the server machine.
    zcert_t *server_cert = zcert_new ();
    zcert_save (server_cert, TESTDIR "/server.cert");

    //  We'll run the server as a background task, and the
    //  client in this foreground thread.
    zthread_new (server_task, &verbose);

    zcert_t *client_cert = zcert_new ();
    zcert_save_public (client_cert, TESTDIR "/client.cert");

    curve_client_t *client = curve_client_new (&client_cert);
    curve_client_set_metadata (client, "Client", "CURVEZMQ/curve_client");
    curve_client_set_metadata (client, "Identity", "E475DA11");
    curve_client_set_verbose (client, verbose);
    curve_client_connect (client, "tcp://127.0.0.1:9005", (byte *)zcert_public_key (server_cert));

    curve_client_sendstr (client, "Hello, World");
    char *reply = curve_client_recvstr (client);
    assert (streq (reply, "Hello, World"));
    free (reply);

    //  Try a multipart message
    zmsg_t *msg = zmsg_new ();
    zmsg_addstr (msg, "Hello, World");
    zmsg_addstr (msg, "Second frame");
    curve_client_send (client, &msg);
    msg = curve_client_recv (client);
    assert (zmsg_size (msg) == 2);
    zmsg_destroy (&msg);

    //  Now send messages of increasing size, check they work
    int count;
    int size = 0;
    for (count = 0; count < 18; count++) {
        if (verbose)
            printf ("Testing message of size=%d...\n", size);

        zframe_t *data = zframe_new (NULL, size);
        int byte_nbr;
        //  Set data to sequence 0...255 repeated
        for (byte_nbr = 0; byte_nbr < size; byte_nbr++)
            zframe_data (data)[byte_nbr] = (byte) byte_nbr;
        msg = zmsg_new ();
        zmsg_prepend (msg, &data);
        curve_client_send (client, &msg);

        msg = curve_client_recv (client);
        data = zmsg_pop (msg);
        assert (data);
        assert (zframe_size (data) == size);
        for (byte_nbr = 0; byte_nbr < size; byte_nbr++) {
            assert (zframe_data (data)[byte_nbr] == (byte) byte_nbr);
        }
        zframe_destroy (&data);
        zmsg_destroy (&msg);
        size = size * 2 + 1;
    }
    //  Signal end of test
    curve_client_sendstr (client, "END");
    reply = curve_client_recvstr (client);
    free (reply);

    zcert_destroy (&server_cert);
    zcert_destroy (&client_cert);
    curve_client_destroy (&client);
    
    //  Delete all test files
    zdir_t *dir = zdir_new (TESTDIR, NULL);
    zdir_remove (dir, true);
    zdir_destroy (&dir);
    //  @end

    //  Ensure server thread has exited before we do
    zclock_sleep (100);
    printf ("OK\n");
}
Ejemplo n.º 28
0
void
zbeacon_test (bool verbose)
{
    printf (" * zbeacon: ");
    if (verbose)
        printf ("\n");

    //  @selftest
    //  Test 1 - two beacons, one speaking, one listening
    //  Create speaker beacon to broadcast our service
    zactor_t *speaker = zactor_new (zbeacon, NULL);
    assert (speaker);
    if (verbose)
        zstr_sendx (speaker, "VERBOSE", NULL);

    zsock_send (speaker, "si", "CONFIGURE", 9999);
    char *hostname = zstr_recv (speaker);
    if (!*hostname) {
        printf ("OK (skipping test, no UDP broadcasting)\n");
        zactor_destroy (&speaker);
        free (hostname);
        return;
    }
    free (hostname);

    //  Create listener beacon on port 9999 to lookup service
    zactor_t *listener = zactor_new (zbeacon, NULL);
    assert (listener);
    if (verbose)
        zstr_sendx (listener, "VERBOSE", NULL);
    zsock_send (listener, "si", "CONFIGURE", 9999);
    hostname = zstr_recv (listener);
    assert (*hostname);
    free (hostname);

    //  We will broadcast the magic value 0xCAFE
    byte announcement [2] = { 0xCA, 0xFE };
    zsock_send (speaker, "sbi", "PUBLISH", announcement, 2, 100);
    //  We will listen to anything (empty subscription)
    zsock_send (listener, "sb", "SUBSCRIBE", "", 0);

    //  Wait for at most 1/2 second if there's no broadcasting
    zsock_set_rcvtimeo (listener, 500);
    char *ipaddress = zstr_recv (listener);
    if (ipaddress) {
        zframe_t *content = zframe_recv (listener);
        assert (zframe_size (content) == 2);
        assert (zframe_data (content) [0] == 0xCA);
        assert (zframe_data (content) [1] == 0xFE);
        zframe_destroy (&content);
        zstr_free (&ipaddress);
        zstr_sendx (speaker, "SILENCE", NULL);
    }
    zactor_destroy (&listener);
    zactor_destroy (&speaker);

    //  Test subscription filter using a 3-node setup
    zactor_t *node1 = zactor_new (zbeacon, NULL);
    assert (node1);
    zsock_send (node1, "si", "CONFIGURE", 5670);
    hostname = zstr_recv (node1);
    assert (*hostname);
    free (hostname);

    zactor_t *node2 = zactor_new (zbeacon, NULL);
    assert (node2);
    zsock_send (node2, "si", "CONFIGURE", 5670);
    hostname = zstr_recv (node2);
    assert (*hostname);
    free (hostname);

    zactor_t *node3 = zactor_new (zbeacon, NULL);
    assert (node3);
    zsock_send (node3, "si", "CONFIGURE", 5670);
    hostname = zstr_recv (node3);
    assert (*hostname);
    free (hostname);

    zsock_send (node1, "sbi", "PUBLISH", "NODE/1", 6, 250);
    zsock_send (node2, "sbi", "PUBLISH", "NODE/2", 6, 250);
    zsock_send (node3, "sbi", "PUBLISH", "RANDOM", 6, 250);
    zsock_send (node1, "sb", "SUBSCRIBE", "NODE", 4);

    //  Poll on three API sockets at once
    zpoller_t *poller = zpoller_new (node1, node2, node3, NULL);
    assert (poller);
    int64_t stop_at = zclock_mono () + 1000;
    while (zclock_mono () < stop_at) {
        long timeout = (long) (stop_at - zclock_mono ());
        if (timeout < 0)
            timeout = 0;
        void *which = zpoller_wait (poller, timeout * ZMQ_POLL_MSEC);
        if (which) {
            assert (which == node1);
            char *ipaddress, *received;
            zstr_recvx (node1, &ipaddress, &received, NULL);
            assert (streq (received, "NODE/2"));
            zstr_free (&ipaddress);
            zstr_free (&received);
        }
    }
    zpoller_destroy (&poller);

    //  Stop listening
    zstr_sendx (node1, "UNSUBSCRIBE", NULL);

    //  Stop all node broadcasts
    zstr_sendx (node1, "SILENCE", NULL);
    zstr_sendx (node2, "SILENCE", NULL);
    zstr_sendx (node3, "SILENCE", NULL);

    //  Destroy the test nodes
    zactor_destroy (&node1);
    zactor_destroy (&node2);
    zactor_destroy (&node3);
    //  @end
    printf ("OK\n");
}
Ejemplo n.º 29
0
static void
s_self_handle_sink (self_t *self)
{
#if defined (ZMQ_EVENT_ALL)
#if (ZMQ_VERSION_MAJOR == 4)
    //  First frame is event number and value
    zframe_t *frame = zframe_recv (self->sink);
    int event = *(uint16_t *) (zframe_data (frame));
    int value = *(uint32_t *) (zframe_data (frame) + 2);
    //  Address is in second message frame
    char *address = zstr_recv (self->sink);
    zframe_destroy (&frame);

#elif (ZMQ_VERSION_MAJOR == 3 && ZMQ_VERSION_MINOR == 2)
    //  zmq_event_t is passed as-is in the frame
    zframe_t *frame = zframe_recv (self->sink);
    zmq_event_t *eptr = (zmq_event_t *) zframe_data (frame);
    int event = eptr->event;
    int value = eptr->data.listening.fd;
    char *address = strdup (eptr->data.listening.addr);
    zframe_destroy (&frame);

#else
    //  We can't plausibly be here with other versions of libzmq
    assert (false);
#endif

    //  Now map event to text equivalent
    char *name;
    switch (event) {
        case ZMQ_EVENT_ACCEPTED:
            name = "ACCEPTED";
            break;
        case ZMQ_EVENT_ACCEPT_FAILED:
            name = "ACCEPT_FAILED";
            break;
        case ZMQ_EVENT_BIND_FAILED:
            name = "BIND_FAILED";
            break;
        case ZMQ_EVENT_CLOSED:
            name = "CLOSED";
            break;
        case ZMQ_EVENT_CLOSE_FAILED:
            name = "CLOSE_FAILED";
            break;
        case ZMQ_EVENT_DISCONNECTED:
            name = "DISCONNECTED";
            break;
        case ZMQ_EVENT_CONNECTED:
            name = "CONNECTED";
            break;
        case ZMQ_EVENT_CONNECT_DELAYED:
            name = "CONNECT_DELAYED";
            break;
        case ZMQ_EVENT_CONNECT_RETRIED:
            name = "CONNECT_RETRIED";
            break;
        case ZMQ_EVENT_LISTENING:
            name = "LISTENING";
            break;
#if (ZMQ_VERSION_MAJOR == 4)
        case ZMQ_EVENT_MONITOR_STOPPED:
            name = "MONITOR_STOPPED";
            break;
#endif
        default:
            zsys_error ("illegal socket monitor event: %d", event);
            name = "UNKNOWN";
            break;
    }
    if (self->verbose)
        zsys_info ("zmonitor: %s - %s", name, address);

    zstr_sendfm (self->pipe, "%s", name);
    zstr_sendfm (self->pipe, "%d", value);
    zstr_send (self->pipe, address);
    free (address);
#endif
}
Ejemplo n.º 30
0
void
zre_msg_dump (zre_msg_t *self)
{
    assert (self);
    switch (self->id) {
        case ZRE_MSG_HELLO:
            puts ("HELLO:");
            printf ("    sequence=%ld\n", (long) self->sequence);
            if (self->ipaddress)
                printf ("    ipaddress='%s'\n", self->ipaddress);
            else
                printf ("    ipaddress=\n");
            printf ("    mailbox=%ld\n", (long) self->mailbox);
            printf ("    groups={");
            if (self->groups) {
                char *groups = (char *) zlist_first (self->groups);
                while (groups) {
                    printf (" '%s'", groups);
                    groups = (char *) zlist_next (self->groups);
                }
            }
            printf (" }\n");
            printf ("    status=%ld\n", (long) self->status);
            printf ("    headers={\n");
            if (self->headers)
                zhash_foreach (self->headers, s_headers_dump, self);
            printf ("    }\n");
            break;
            
        case ZRE_MSG_WHISPER:
            puts ("WHISPER:");
            printf ("    sequence=%ld\n", (long) self->sequence);
            printf ("    content={\n");
            if (self->content) {
                size_t size = zframe_size (self->content);
                byte *data = zframe_data (self->content);
                printf ("        size=%td\n", zframe_size (self->content));
                if (size > 32)
                    size = 32;
                int content_index;
                for (content_index = 0; content_index < size; content_index++) {
                    if (content_index && (content_index % 4 == 0))
                        printf ("-");
                    printf ("%02X", data [content_index]);
                }
            }
            printf ("    }\n");
            break;
            
        case ZRE_MSG_SHOUT:
            puts ("SHOUT:");
            printf ("    sequence=%ld\n", (long) self->sequence);
            if (self->group)
                printf ("    group='%s'\n", self->group);
            else
                printf ("    group=\n");
            printf ("    content={\n");
            if (self->content) {
                size_t size = zframe_size (self->content);
                byte *data = zframe_data (self->content);
                printf ("        size=%td\n", zframe_size (self->content));
                if (size > 32)
                    size = 32;
                int content_index;
                for (content_index = 0; content_index < size; content_index++) {
                    if (content_index && (content_index % 4 == 0))
                        printf ("-");
                    printf ("%02X", data [content_index]);
                }
            }
            printf ("    }\n");
            break;
            
        case ZRE_MSG_JOIN:
            puts ("JOIN:");
            printf ("    sequence=%ld\n", (long) self->sequence);
            if (self->group)
                printf ("    group='%s'\n", self->group);
            else
                printf ("    group=\n");
            printf ("    status=%ld\n", (long) self->status);
            break;
            
        case ZRE_MSG_LEAVE:
            puts ("LEAVE:");
            printf ("    sequence=%ld\n", (long) self->sequence);
            if (self->group)
                printf ("    group='%s'\n", self->group);
            else
                printf ("    group=\n");
            printf ("    status=%ld\n", (long) self->status);
            break;
            
        case ZRE_MSG_PING:
            puts ("PING:");
            printf ("    sequence=%ld\n", (long) self->sequence);
            break;
            
        case ZRE_MSG_PING_OK:
            puts ("PING_OK:");
            printf ("    sequence=%ld\n", (long) self->sequence);
            break;
            
    }
}