static void publish_to_corosync(struct stasis_message *message) { struct ast_event *event; event = stasis_message_to_event(message); if (!event) { return; } if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) { /* If the event didn't originate from this server, don't send it back out. */ ast_event_destroy(event); return; } if (ast_event_get_type(event) == AST_EVENT_PING) { const struct ast_eid *eid; char buf[128] = ""; eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID); ast_eid_to_str(buf, sizeof(buf), (struct ast_eid *) eid); ast_log(LOG_NOTICE, "Sending event PING from this server with EID: '%s'\n", buf); } publish_event_to_corosync(event); }
static void cpg_deliver_cb(cpg_handle_t handle, const struct cpg_name *group_name, uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len) { struct ast_event *event; void (*publish_handler)(struct ast_event *) = NULL; enum ast_event_type event_type; if (msg_len < ast_event_minimum_length()) { ast_debug(1, "Ignoring event that's too small. %u < %u\n", (unsigned int) msg_len, (unsigned int) ast_event_minimum_length()); return; } if (!ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(msg, AST_EVENT_IE_EID))) { /* Don't feed events back in that originated locally. */ return; } event_type = ast_event_get_type(msg); if (event_type > AST_EVENT_TOTAL) { /* Egads, we don't support this */ return; } ast_rwlock_rdlock(&event_types_lock); publish_handler = event_types[event_type].publish_to_stasis; if (!event_types[event_type].subscribe || !publish_handler) { /* We are not configured to subscribe to these events or we have no way to publish it internally. */ ast_rwlock_unlock(&event_types_lock); return; } ast_rwlock_unlock(&event_types_lock); if (!(event = ast_malloc(msg_len))) { return; } memcpy(event, msg, msg_len); if (event_type == AST_EVENT_PING) { const struct ast_eid *eid; char buf[128] = ""; eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID); ast_eid_to_str(buf, sizeof(buf), (struct ast_eid *) eid); ast_log(LOG_NOTICE, "Got event PING from server with EID: '%s'\n", buf); } ast_debug(5, "Publishing event %s (%u) to stasis\n", ast_event_get_type_name(event), event_type); publish_handler(event); }
/*! \brief Publish a received device state \ref ast_event to \ref stasis */ static void publish_device_state_to_stasis(struct ast_event *event) { const char *device; enum ast_device_state state; unsigned int cachable; struct ast_eid *event_eid; ast_assert(ast_event_get_type(event) == AST_EVENT_DEVICE_STATE_CHANGE); device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); cachable = ast_event_get_ie_uint(event, AST_EVENT_IE_CACHABLE); event_eid = (struct ast_eid *)ast_event_get_ie_raw(event, AST_EVENT_IE_EID); if (ast_strlen_zero(device)) { return; } if (ast_publish_device_state_full(device, state, cachable, event_eid)) { char eid[18]; ast_eid_to_str(eid, sizeof(eid), event_eid); ast_log(LOG_WARNING, "Failed to publish device state message for %s from %s\n", device, eid); } }
static void cpg_deliver_cb(cpg_handle_t handle, const struct cpg_name *group_name, uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len) { struct ast_event *event; if (msg_len < ast_event_minimum_length()) { ast_debug(1, "Ignoring event that's too small. %u < %u\n", (unsigned int) msg_len, (unsigned int) ast_event_minimum_length()); return; } if (!ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(msg, AST_EVENT_IE_EID))) { /* Don't feed events back in that originated locally. */ return; } ast_rwlock_rdlock(&event_types_lock); if (!event_types[ast_event_get_type(msg)].subscribe) { /* We are not configured to subscribe to these events. */ ast_rwlock_unlock(&event_types_lock); return; } ast_rwlock_unlock(&event_types_lock); if (!(event = ast_malloc(msg_len))) { return; } memcpy(event, msg, msg_len); ast_event_queue_and_cache(event); }
static void publish_to_corosync(struct stasis_message *message) { cs_error_t cs_err; struct iovec iov; struct ast_event *event; event = stasis_message_to_event(message); if (!event) { return; } if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) { /* If the event didn't originate from this server, don't send it back out. */ ast_event_destroy(event); return; } if (ast_event_get_type(event) == AST_EVENT_PING) { const struct ast_eid *eid; char buf[128] = ""; eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID); ast_eid_to_str(buf, sizeof(buf), (struct ast_eid *) eid); ast_log(LOG_NOTICE, "Sending event PING from this server with EID: '%s'\n", buf); } iov.iov_base = (void *)event; iov.iov_len = ast_event_get_size(event); ast_debug(5, "Publishing event %s (%u) to corosync\n", ast_event_get_type_name(event), ast_event_get_type(event)); /* The stasis subscription will only exist if we are configured to publish * these events, so just send away. */ if ((cs_err = cpg_mcast_joined(cpg_handle, CPG_TYPE_FIFO, &iov, 1)) != CS_OK) { ast_log(LOG_WARNING, "CPG mcast failed (%u)\n", cs_err); } }
static struct corosync_node *corosync_node_alloc(struct ast_event *event) { struct corosync_node *node; node = ao2_alloc_options(sizeof(*node), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!node) { return NULL; } memcpy(&node->eid, (struct ast_eid *)ast_event_get_ie_raw(event, AST_EVENT_IE_EID), sizeof(node->eid)); node->id = ast_event_get_ie_uint(event, AST_EVENT_IE_NODE_ID); ast_sockaddr_parse(&node->addr, ast_event_get_ie_str(event, AST_EVENT_IE_LOCAL_ADDR), PARSE_PORT_IGNORE); return node; }
/*! \brief Publish a received cluster discovery \ref ast_event to \ref stasis */ static void publish_cluster_discovery_to_stasis(struct ast_event *event) { struct corosync_node *node; int id = ast_event_get_ie_uint(event, AST_EVENT_IE_NODE_ID); struct ast_eid *event_eid; ast_assert(ast_event_get_type(event) == AST_EVENT_CLUSTER_DISCOVERY); event_eid = (struct ast_eid *)ast_event_get_ie_raw(event, AST_EVENT_IE_EID); if (!ast_eid_cmp(&ast_eid_default, event_eid)) { /* Don't feed events back in that originated locally. */ return; } ao2_lock(nodes); node = ao2_find(nodes, &id, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (node) { /* We already know about this node */ ao2_unlock(nodes); ao2_ref(node, -1); return; } node = corosync_node_alloc(event); if (!node) { ao2_unlock(nodes); return; } ao2_link_flags(nodes, node, OBJ_NOLOCK); ao2_unlock(nodes); publish_cluster_discovery_to_stasis_full(node, 1); ao2_ref(node, -1); /* * When we get news that someone else has joined, we need to let them * know we exist as well. */ send_cluster_notify(); }
/*! \brief Publish a received MWI \ref ast_event to \ref stasis */ static void publish_mwi_to_stasis(struct ast_event *event) { const char *mailbox; const char *context; unsigned int new_msgs; unsigned int old_msgs; struct ast_eid *event_eid; ast_assert(ast_event_get_type(event) == AST_EVENT_MWI); mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX); context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT); new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); old_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); event_eid = (struct ast_eid *)ast_event_get_ie_raw(event, AST_EVENT_IE_EID); if (ast_strlen_zero(mailbox) || ast_strlen_zero(context)) { return; } if (new_msgs > INT_MAX) { new_msgs = INT_MAX; } if (old_msgs > INT_MAX) { old_msgs = INT_MAX; } if (ast_publish_mwi_state_full(mailbox, context, (int)new_msgs, (int)old_msgs, NULL, event_eid)) { char eid[18]; ast_eid_to_str(eid, sizeof(eid), event_eid); ast_log(LOG_WARNING, "Failed to publish MWI message for %s@%s from %s\n", mailbox, context, eid); } }
/*! \brief Convert a Corosync PING to a \ref ast_event */ static struct ast_event *corosync_ping_to_event(struct stasis_message *message) { struct corosync_ping_payload *payload; struct ast_event *event; struct ast_eid *event_eid; if (!message) { return NULL; } payload = stasis_message_data(message); if (!payload->event) { return NULL; } event_eid = (struct ast_eid *)ast_event_get_ie_raw(payload->event, AST_EVENT_IE_EID); event = ast_event_new(AST_EVENT_PING, AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, event_eid, sizeof(*event_eid), AST_EVENT_IE_END); return event; }
static int ie_is_present(const struct ast_event *event, const enum ast_event_ie_type ie_type) { return (ast_event_get_ie_raw(event, ie_type) != NULL); }
static int check_event(struct ast_event *event, struct ast_test *test, enum ast_event_type expected_type, const char *type_name, const char *str, uint32_t uint, uint32_t bitflags) { enum ast_event_type type; const void *foo; /* Check #1: Ensure event type is set properly. */ type = ast_event_get_type(event); if (ast_event_get_type(event) != type) { ast_test_status_update(test, "Expected event type: '%d', got '%d'\n", expected_type, type); return -1; } /* Check #2: Check string representation of event type */ if (strcmp(type_name, ast_event_get_type_name(event))) { ast_test_status_update(test, "Didn't get expected type name: '%s' != '%s'\n", type_name, ast_event_get_type_name(event)); return -1; } /* Check #3: Check for automatically included EID */ if (memcmp(&ast_eid_default, ast_event_get_ie_raw(event, AST_EVENT_IE_EID), sizeof(ast_eid_default))) { ast_test_status_update(test, "Failed to get EID\n"); return -1; } /* Check #4: Check for the string IE */ if (strcmp(str, ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX))) { ast_test_status_update(test, "Failed to get string IE.\n"); return -1; } /* Check #5: Check for the uint IE */ if (uint != ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS)) { ast_test_status_update(test, "Failed to get uint IE.\n"); return -1; } /* Check #6: Check for the bitflags IE */ if (bitflags != ast_event_get_ie_bitflags(event, AST_EVENT_IE_OLDMSGS)) { ast_test_status_update(test, "Failed to get bitflags IE.\n"); return -1; } /* Check #7: Check if a check for a str IE that isn't there works */ if ((foo = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE))) { ast_test_status_update(test, "DEVICE IE check returned non-NULL %p\n", foo); return -1; } /* Check #8: Check if a check for a uint IE that isn't there returns 0 */ if (ast_event_get_ie_uint(event, AST_EVENT_IE_STATE)) { ast_test_status_update(test, "OLDMSGS IE should be 0\n"); return -1; } ast_test_status_update(test, "Event looks good.\n"); return 0; }