Example #1
0
File: manage.c Project: Eelis/i3
/*
 * The following function sends a new window event, which consists
 * of fields "change" and "container", the latter containing a dump
 * of the window's container.
 *
 */
static void ipc_send_window_new_event(Con *con) {
    setlocale(LC_NUMERIC, "C");
    yajl_gen gen = ygenalloc();

    y(map_open);

    ystr("change");
    ystr("new");

    ystr("container");
    dump_node(gen, con, false);

    y(map_close);

    const unsigned char *payload;
    ylength length;
    y(get_buf, &payload, &length);

    ipc_send_event("window", I3_IPC_EVENT_WINDOW, (const char *)payload);
    y(free);
    setlocale(LC_NUMERIC, "");
}
Example #2
0
File: hooks.c Project: op5/merlin
static int send_generic(merlin_event *pkt, void *data)
{
	int result = 0;
	uint i, ntable_stop = num_masters + num_peers;
	linked_item *li;

	if ((!num_nodes || pkt->hdr.code == MAGIC_NONET) && !daemon_wants(pkt->hdr.type)) {
		ldebug("ipcfilter: Not sending %s event. %s, and daemon doesn't want it",
			   callback_name(pkt->hdr.type),
			   pkt->hdr.code == MAGIC_NONET ? "No-net magic" : "No nodes");
		return 0;
	}
	if (!pkt->hdr.code == MAGIC_NONET && !daemon_wants(pkt->hdr.type)) {
		ldebug("ipcfilter: Not sending %s event. No-net magic and daemon doesn't want it",
			   callback_name(pkt->hdr.type));
		return 0;
	}

	pkt->hdr.len = merlin_encode_event(pkt, data);
	if (!pkt->hdr.len) {
		lerr("Header len is 0 for callback %d. Update offset in hookinfo.h", pkt->hdr.type);
		return -1;
	}

	if (is_dupe(pkt)) {
		ldebug("ipcfilter: Not sending %s event: Duplicate packet",
		       callback_name(pkt->hdr.type));
		return 0;
	}

	if (daemon_wants(pkt->hdr.type)) {
		result = ipc_send_event(pkt);
		/*
		 * preserve the event so we can check for dupes,
		 * but only if we successfully sent it
		 */
		if (result < 0)
			memset(&last_pkt, 0, sizeof(last_pkt));
		else
			memcpy(&last_pkt, pkt, packet_size(pkt));
	}

	if (!num_nodes)
		return 0;
	if (pkt->hdr.code == MAGIC_NONET)
		return 0;

	/*
	 * The module can mark certain packets with a magic destination.
	 * Such packets avoid all other inspection and get sent to where
	 * the module wants us to.
	 */
	if (magic_destination(pkt)) {
		if ((pkt->hdr.selection & DEST_MASTERS) == DEST_MASTERS) {
			for (i = 0; i < num_masters; i++) {
				net_sendto(node_table[i], pkt);
			}
		}
		if ((pkt->hdr.selection & DEST_PEERS) == DEST_PEERS) {
			for (i = 0; i < num_peers; i++) {
				net_sendto(peer_table[i], pkt);
			}
		}
		if ((pkt->hdr.selection & DEST_POLLERS) == DEST_POLLERS) {
			for (i = 0; i < num_pollers; i++) {
				net_sendto(poller_table[i], pkt);
			}
		}

		return 0;
	}

	/*
	 * "normal" packets get sent to all peers and masters, and possibly
	 * a group of, or all, pollers as well
	 */

	/* general control packets are for everyone */
	if (pkt->hdr.selection == CTRL_GENERIC && pkt->hdr.type == CTRL_PACKET) {
		ntable_stop = num_nodes;
	}

	/* Send this to all who should have it */
	for (i = 0; i < ntable_stop; i++) {
		net_sendto(node_table[i], pkt);
	}

	/* if we've already sent to everyone we return early */
	if (ntable_stop == num_nodes || !num_pollers)
		return 0;

	li = nodes_by_sel_id(pkt->hdr.selection);
	if (!li) {
		lerr("No matching selection for id %d", pkt->hdr.selection);
		return -1;
	}

	for (; li; li = li->next_item) {
		net_sendto((merlin_node *)li->item, pkt);
	}

	return result;
}
Example #3
0
File: net.c Project: ageric/merlin
/*
 * Passes an event from a remote node to the broker module,
 * any and all nocs and the database handling routines. The
 * exception to this rule is control packets from peers and
 * pollers, which never get forwarded to our masters.
 */
static int handle_network_event(merlin_node *node, merlin_event *pkt)
{
	uint i;

	if (pkt->hdr.type == CTRL_PACKET) {
		/*
		 * if this is a CTRL_ALIVE packet from a remote module, we
		 * must take care to stash the start-time here so we can
		 * forward it to our module later. It only matters for
		 * peers, but we might as well set it for all modules
		 */
		if (pkt->hdr.code == CTRL_ACTIVE) {
			int result = handle_ctrl_active(node, pkt);

			/*
			 * If the CTRL_ACTIVE packet shows compatibility
			 * problems, we ignore it and move on
			 */
			if (result < 0) {
				return 0;
			}

			/*
			 * If the info is new, we run the confsync check
			 * for the recently activated node
			 */
			if (!result) {
				ldebug("Module @ %s is ACTIVE", node->name);
				csync_node_active(node);
			}
		}
		if (pkt->hdr.code == CTRL_INACTIVE) {
			memset(&node->info, 0, sizeof(node->info));
			ldebug("Module @ %s is INACTIVE", node->name);
			db_mark_node_inactive(node);
		}
	} else if (node->type == MODE_POLLER && num_masters) {
		ldebug("Passing on event from poller %s to %d masters",
		       node->name, num_masters);
		net_sendto_many(noc_table, num_masters, pkt);
	} else if (node->type == MODE_MASTER && num_pollers) {
		/*
		 * @todo maybe we should also check if self.peer_id == 0
		 * before we forward events to our pollers. Hmm...
		 */
		if (pkt->hdr.type != NEBCALLBACK_PROGRAM_STATUS_DATA &&
		    pkt->hdr.type != NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA)
		{
			for (i = 0; i < num_pollers; i++) {
				merlin_node *node = poller_table[i];
				net_sendto(node, pkt);
			}
		}
	}

	/*
	 * let the various handler know which node sent the packet
	 */
	pkt->hdr.selection = node->id;

	/* not all packets get delivered to the merlin module */
	switch (pkt->hdr.type) {
	case NEBCALLBACK_PROGRAM_STATUS_DATA:
	case NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA:
		/*
		 * PROGRAM_STATUS_DATA can't sanely be transferred
		 * CONTACT_NOTIFICATION_METHOD is left as-is, since we by
		 * default want pollers to send notifications for their
		 * respective contacts. This is by customer request, since
		 * sending text-messages across country borders is a lot
		 * more expensive than just buying a GSM device extra for
		 * where one wants to place the poller
		 */
		mrm_db_update(node, pkt);
		return 0;

	/* and not all packets get sent to the database */
	case CTRL_PACKET:
	case NEBCALLBACK_EXTERNAL_COMMAND_DATA:
		return ipc_send_event(pkt);

	case NEBCALLBACK_DOWNTIME_DATA:
	case NEBCALLBACK_COMMENT_DATA:
		/*
		 * These two used to be handled specially here, but
		 * we've moved it to the database update layer instead,
		 * which will discard queries it can't run properly
		 * without bouncing the data against the module.
		 */
	default:
		/*
		 * IMPORTANT NOTE:
		 * It's absolutely vital that we send the event to the
		 * ipc socket *before* we ship it off to the db_update
		 * function, since the db_update function merlin_decode()'s
		 * the event, which makes unusable for sending to the
		 * ipc (or, indeed, anywhere else) afterwards.
		 */
		ipc_send_event(pkt);
		mrm_db_update(node, pkt);
		return 0;
	}

	return 0;
}