SWITCH_DECLARE_CONSTRUCTOR Event::Event(const char *type, const char *subclass_name) { switch_event_types_t event_id; if (!strcasecmp(type, "json") && !zstr(subclass_name)) { if (switch_event_create_json(&event, subclass_name) != SWITCH_STATUS_SUCCESS) { return; } event_id = event->event_id; } else { if (switch_name_event(type, &event_id) != SWITCH_STATUS_SUCCESS) { event_id = SWITCH_EVENT_MESSAGE; } if (!zstr(subclass_name) && event_id != SWITCH_EVENT_CUSTOM) { switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_WARNING, "Changing event type to custom because you specified a subclass name!\n"); event_id = SWITCH_EVENT_CUSTOM; } if (switch_event_create_subclass(&event, event_id, subclass_name) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Failed to create event!\n"); event = NULL; } } serialized_string = NULL; mine = 1; }
static switch_status_t handle_msg_session_event(listener_t *listener, erlang_msg *msg, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char atom[MAXATOMLEN]; if (arity == 1) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { session_elem_t *session; if ((session = find_session_elem_by_pid(listener, &msg->from))) { int custom = 0; switch_event_types_t type; int i = 0; switch_thread_rwlock_wrlock(session->event_rwlock); for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { if (custom) { switch_core_hash_insert(session->event_hash, atom, MARKER); } else if (switch_name_event(atom, &type) == SWITCH_STATUS_SUCCESS) { if (type == SWITCH_EVENT_ALL) { uint32_t x = 0; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ALL events enabled for %s\n", session->uuid_str); for (x = 0; x < SWITCH_EVENT_ALL; x++) { session->event_list[x] = 1; } } if (type <= SWITCH_EVENT_ALL) { session->event_list[type] = 1; } if (type == SWITCH_EVENT_CUSTOM) { custom++; } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "enable event %s for session %s\n", atom, session->uuid_str); } } switch_thread_rwlock_unlock(session->event_rwlock); ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "notlistening"); } } return SWITCH_STATUS_SUCCESS; }
static switch_status_t handle_msg_session_nixevent(listener_t *listener, erlang_msg *msg, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char atom[MAXATOMLEN]; if (arity == 1) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { session_elem_t *session; if ((session = find_session_elem_by_pid(listener, &msg->from))) { int custom = 0; int i = 0; switch_event_types_t type; switch_thread_rwlock_wrlock(session->event_rwlock); for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { if (custom) { switch_core_hash_delete(session->event_hash, atom); } else if (switch_name_event(atom, &type) == SWITCH_STATUS_SUCCESS) { uint32_t x = 0; if (type == SWITCH_EVENT_CUSTOM) { custom++; } else if (type == SWITCH_EVENT_ALL) { for (x = 0; x <= SWITCH_EVENT_ALL; x++) { session->event_list[x] = 0; } } else { if (session->event_list[SWITCH_EVENT_ALL]) { session->event_list[SWITCH_EVENT_ALL] = 0; for (x = 0; x < SWITCH_EVENT_ALL; x++) { session->event_list[x] = 1; } } session->event_list[type] = 0; } } } } switch_thread_rwlock_unlock(session->event_rwlock); ei_x_encode_atom(rbuf, "ok"); } else { /* no session for this pid */ ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "notlistening"); } } return SWITCH_STATUS_SUCCESS; }
static switch_status_t handle_msg_event(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char atom[MAXATOMLEN]; if (arity == 1) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { int custom = 0; switch_event_types_t type; int i = 0; if (!switch_test_flag(listener, LFLAG_EVENTS)) { switch_set_flag_locked(listener, LFLAG_EVENTS); } switch_thread_rwlock_wrlock(listener->event_rwlock); for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { if (custom) { switch_core_hash_insert(listener->event_hash, atom, MARKER); } else if (switch_name_event(atom, &type) == SWITCH_STATUS_SUCCESS) { if (type == SWITCH_EVENT_ALL) { uint32_t x = 0; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ALL events enabled\n"); for (x = 0; x < SWITCH_EVENT_ALL; x++) { listener->event_list[x] = 1; } } if (type <= SWITCH_EVENT_ALL) { listener->event_list[type] = 1; } if (type == SWITCH_EVENT_CUSTOM) { custom++; } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "enable event %s\n", atom); } } switch_thread_rwlock_unlock(listener->event_rwlock); ei_x_encode_atom(rbuf, "ok"); } return SWITCH_STATUS_SUCCESS; }
static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char ename[MAXATOMLEN + 1]; char esname[MAXATOMLEN + 1]; int headerlength; memset(esname, 0, MAXATOMLEN); if (ei_decode_atom(buf->buff, &buf->index, ename) || (!strncasecmp(ename, "CUSTOM", MAXATOMLEN) && ei_decode_atom(buf->buff, &buf->index, esname)) || ei_decode_list_header(buf->buff, &buf->index, &headerlength)) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { switch_event_types_t etype; if (switch_name_event(ename, &etype) == SWITCH_STATUS_SUCCESS) { switch_event_t *event; if ((strlen(esname) && switch_event_create_subclass(&event, etype, esname) == SWITCH_STATUS_SUCCESS) || switch_event_create(&event, etype) == SWITCH_STATUS_SUCCESS) { char key[1024]; char value[1024]; int i = 0; switch_bool_t fail = SWITCH_FALSE; while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) { fail = SWITCH_TRUE; break; } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value); } if (headerlength != i || fail) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { switch_event_fire(&event); ei_x_encode_atom(rbuf, "ok"); } } } } return SWITCH_STATUS_SUCCESS; }
static switch_status_t handle_msg_nixevent(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char atom[MAXATOMLEN]; if (arity == 1) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { int custom = 0; int i = 0; switch_event_types_t type; for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { if (custom) { switch_core_hash_delete(listener->event_hash, atom); } else if (switch_name_event(atom, &type) == SWITCH_STATUS_SUCCESS) { uint32_t x = 0; if (type == SWITCH_EVENT_CUSTOM) { custom++; } else if (type == SWITCH_EVENT_ALL) { for (x = 0; x <= SWITCH_EVENT_ALL; x++) { listener->event_list[x] = 0; } } else { if (listener->event_list[SWITCH_EVENT_ALL]) { listener->event_list[SWITCH_EVENT_ALL] = 0; for (x = 0; x < SWITCH_EVENT_ALL; x++) { listener->event_list[x] = 1; } } listener->event_list[type] = 0; } } } } ei_x_encode_atom(rbuf, "ok"); } return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE_CONSTRUCTOR EventConsumer::EventConsumer(const char *event_name, const char *subclass_name) { switch_name_event(event_name, &e_event_id); switch_core_new_memory_pool(&pool); if (!zstr(subclass_name)) { e_subclass_name = switch_core_strdup(pool, subclass_name); } else { e_subclass_name = NULL; } switch_queue_create(&events, 5000, pool); if (switch_event_bind_removable(__FILE__, e_event_id, e_subclass_name, event_handler, this, &node) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "bound to %s %s\n", event_name, switch_str_nil(e_subclass_name)); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot bind to %s %s\n", event_name, switch_str_nil(e_subclass_name)); } }
SWITCH_DECLARE(int) EventConsumer::bind(const char *event_name, const char *subclass_name) { switch_event_types_t event_id = SWITCH_EVENT_CUSTOM; switch_name_event(event_name, &event_id); if (zstr(subclass_name)) { subclass_name = NULL; } if (node_index <= SWITCH_EVENT_ALL && switch_event_bind_removable(__FILE__, event_id, subclass_name, event_handler, this, &enodes[node_index]) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "bound to %s %s\n", event_name, switch_str_nil(subclass_name)); node_index++; return 1; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot bind to %s %s\n", event_name, switch_str_nil(subclass_name)); return 0; } }
abyss_bool websocket_hook(TSession *r) { wsh_t *wsh; int ret; int i; ws_opcode_t opcode; uint8_t *data; switch_event_node_t *nodes[MAX_EVENT_BIND_SLOTS]; int node_count = 0; char *p; char *key = NULL; char *version = NULL; char *proto = NULL; char *upgrade = NULL; for (i = 0; i < r->requestHeaderFields.size; i++) { TTableItem * const item = &r->requestHeaderFields.item[i]; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "headers %s: %s\n", item->name, item->value); } key = RequestHeaderValue(r, "sec-websocket-key"); version = RequestHeaderValue(r, "sec-websocket-version"); proto = RequestHeaderValue(r, "sec-websocket-protocol"); upgrade = RequestHeaderValue(r, "upgrade"); if (!key || !version || !proto || !upgrade) return FALSE; if (strncasecmp(upgrade, "websocket", 9) || strncasecmp(proto, "websocket", 9)) return FALSE; wsh = ws_init(r); if (!wsh) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "websocket error %d\n", ret); return FALSE; } ret = ws_handshake_kvp(wsh, key, version, proto); if (ret < 0) wsh->down = 1; if (ret != 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "handshake error %d\n", ret); return FALSE; } if (switch_event_bind_removable("websocket", SWITCH_EVENT_CUSTOM, "websocket::stophook", stop_hook_event_handler, wsh, &nodes[node_count++]) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't bind!\n"); node_count--; } while (!wsh->down) { int bytes = ws_read_frame(wsh, &opcode, &data); if (bytes < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d %s\n", opcode, (char *)data); switch_yield(100000); continue; } switch (opcode) { case WSOC_CLOSE: ws_close(wsh, 1000); break; case WSOC_CONTINUATION: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "continue\n"); continue; case WSOC_TEXT: p = data; if (!p) continue; if (!strncasecmp(data, "event ", 6)) { switch_event_types_t type; char *subclass; if (node_count == MAX_EVENT_BIND_SLOTS - 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot subscribe more than %d events\n", node_count); continue; } p += 6; if (p = strchr(p, ' ')) p++; if (!strncasecmp(p, "json ", 5)) { p += 5; } else if (!strncasecmp(p, "xml ", 4)) { p += 4; } else if (!strncasecmp(p, "plain ", 6)) { p += 6; } if (!*p) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "missing event type in [%s]\n", data); break; } else { } if (subclass = strchr(p, ' ')) { *subclass++ = '\0'; if (!*subclass) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing subclass\n"); continue; } } else { subclass = SWITCH_EVENT_SUBCLASS_ANY; } if (switch_name_event(p, &type) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown event %s\n", p); continue; } if (switch_event_bind_removable("websocket", type, subclass, event_handler, wsh, &nodes[node_count++]) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't bind!\n"); node_count--; continue; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Bind %s\n", data); } } break; default: break; } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "wsh->down = %d, node_count = %d\n", wsh->down, node_count); switch_yield(2000); while (--node_count >= 0) switch_event_unbind(&nodes[node_count]); switch_safe_free(wsh); return FALSE; }
static switch_status_t load_config(void) { switch_status_t status = SWITCH_STATUS_SUCCESS; char *cf = "event_multicast.conf"; switch_xml_t cfg, xml, settings, param; char *next, *cur; uint32_t count = 0; uint8_t custom = 0; globals.ttl = 1; globals.key_count = 0; if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); return SWITCH_STATUS_TERM; } if ((settings = switch_xml_child(cfg, "settings"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "address")) { set_global_address(val); } else if (!strcasecmp(var, "bindings")) { set_global_bindings(val); } else if (!strcasecmp(var, "port")) { globals.port = (switch_port_t) atoi(val); } else if (!strcasecmp(var, "psk")) { #ifdef HAVE_OPENSSL set_global_psk(val); #else switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot use pre shared key encryption without OpenSSL support\n"); #endif } else if (!strcasecmp(var, "ttl")) { int ttl = atoi(val); if ((ttl && ttl <= 255) || !strcmp(val, "0")) { globals.ttl = (uint8_t) ttl; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid ttl '%s' specified, using default of 1\n", val); } } } } switch_xml_free(xml); if (globals.bindings) { for (cur = globals.bindings; cur; count++) { switch_event_types_t type; if ((next = strchr(cur, ' '))) { *next++ = '\0'; } if (custom) { switch_core_hash_insert(globals.event_hash, cur, MARKER); } else if (switch_name_event(cur, &type) == SWITCH_STATUS_SUCCESS) { globals.key_count++; if (type == SWITCH_EVENT_ALL) { uint32_t x = 0; for (x = 0; x < SWITCH_EVENT_ALL; x++) { globals.event_list[x] = 0; } } if (type <= SWITCH_EVENT_ALL) { globals.event_list[type] = 1; } if (type == SWITCH_EVENT_CUSTOM) { custom++; } } cur = next; } } if (!globals.key_count) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "No Bindings\n"); } return status; }
static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char ename[MAXATOMLEN + 1]; char esname[MAXATOMLEN + 1]; int headerlength; memset(esname, 0, MAXATOMLEN); if (ei_decode_atom(buf->buff, &buf->index, ename) || (!strncasecmp(ename, "CUSTOM", MAXATOMLEN) && ei_decode_atom(buf->buff, &buf->index, esname)) || ei_decode_list_header(buf->buff, &buf->index, &headerlength)) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { switch_event_types_t etype; if (switch_name_event(ename, &etype) == SWITCH_STATUS_SUCCESS) { switch_event_t *event; if ((strlen(esname) && switch_event_create_subclass(&event, etype, esname) == SWITCH_STATUS_SUCCESS) || switch_event_create(&event, etype) == SWITCH_STATUS_SUCCESS) { char key[1024]; char *value; int type; int size; int i = 0; switch_bool_t fail = SWITCH_FALSE; while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; ei_get_type(buf->buff, &buf->index, &type, &size); if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } ei_get_type(buf->buff, &buf->index, &type, &size); value = malloc(size + 1); if (ei_decode_string(buf->buff, &buf->index, value)) { fail = SWITCH_TRUE; break; } if (!fail && !strcmp(key, "body")) { switch_safe_free(event->body); event->body = value; } else if (!fail) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); } /* Do not free malloc here! The above commands utilize the raw allocated memory and skip any copying/duplication. Faster. */ } if (headerlength != i || fail) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { switch_event_fire(&event); ei_x_encode_atom(rbuf, "ok"); } } /* If the event wasn't successfully fired, or failed for any other reason, then make sure not to leak it. */ if ( event ) { switch_event_destroy(&event); } } } return SWITCH_STATUS_SUCCESS; }
static switch_status_t handle_msg_session_setevent(listener_t *listener, erlang_msg *msg, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char atom[MAXATOMLEN]; if (arity == 1){ ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { session_elem_t *session; if ((session = find_session_elem_by_pid(listener, &msg->from))) { uint8_t event_list[SWITCH_EVENT_ALL + 1]; switch_hash_t *event_hash; int custom = 0; int i = 0; switch_event_types_t type; uint32_t x = 0; /* clear any previous event registrations */ for (x = 0; x <= SWITCH_EVENT_ALL; x++){ event_list[x] = 0; } /* create new hash */ switch_core_hash_init(&event_hash, session->pool); for (i = 1; i < arity; i++){ if (!ei_decode_atom(buf->buff, &buf->index, atom)) { if (custom) { switch_core_hash_insert(event_hash, atom, MARKER); } else if (switch_name_event(atom, &type) == SWITCH_STATUS_SUCCESS) { if (type == SWITCH_EVENT_ALL) { ei_x_encode_tuple_header(rbuf, 1); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); break; } if (type <= SWITCH_EVENT_ALL) { event_list[type] = 1; } if (type == SWITCH_EVENT_CUSTOM) { custom++; } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "enable event %s for session %s\n", atom, session->uuid_str); } } /* update the event subscriptions with the new ones */ switch_thread_rwlock_wrlock(session->event_rwlock); memcpy(session->event_list, event_list, sizeof(uint8_t) * (SWITCH_EVENT_ALL + 1)); /* wipe the old hash, and point the pointer at the new one */ switch_core_hash_destroy(&session->event_hash); session->event_hash = event_hash; switch_thread_rwlock_unlock(session->event_rwlock); /* TODO - we should flush any non-matching events from the queue */ ei_x_encode_atom(rbuf, "ok"); } else { /* no session for this pid */ ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "notlistening"); } } return SWITCH_STATUS_SUCCESS; }