static struct ast_json *channel_connected_line( struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv) { struct ast_json *json_channel; /* No ChannelConnectedLine event on cache clear or first event */ if (!old_snapshot || !new_snapshot) { return NULL; } if (ast_channel_snapshot_connected_line_equal(old_snapshot, new_snapshot)) { return NULL; } json_channel = ast_channel_snapshot_to_json(new_snapshot, stasis_app_get_sanitizer()); if (!json_channel) { return NULL; } return ast_json_pack("{s: s, s: o, s: o}", "type", "ChannelConnectedLine", "timestamp", ast_json_timeval(*tv, NULL), "channel", json_channel); }
static struct ast_json *dtmf_end_to_json( struct stasis_message *message, const struct stasis_message_sanitizer *sanitize) { struct ast_channel_blob *channel_blob = stasis_message_data(message); struct ast_json *blob = channel_blob->blob; struct ast_channel_snapshot *snapshot = channel_blob->snapshot; const char *direction = ast_json_string_get(ast_json_object_get(blob, "direction")); const struct timeval *tv = stasis_message_timestamp(message); struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, sanitize); /* Only present received DTMF end events as JSON */ if (strcasecmp("Received", direction) != 0) { return NULL; } if (!json_channel) { return NULL; } return ast_json_pack("{s: s, s: o, s: O, s: O, s: o}", "type", "ChannelDtmfReceived", "timestamp", ast_json_timeval(*tv, NULL), "digit", ast_json_object_get(blob, "digit"), "duration_ms", ast_json_object_get(blob, "duration_ms"), "channel", json_channel); }
static struct ast_json *channel_callerid( struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv) { struct ast_json *json_channel; /* No NewCallerid event on cache clear or first event */ if (!old_snapshot || !new_snapshot) { return NULL; } if (ast_channel_snapshot_caller_id_equal(old_snapshot, new_snapshot)) { return NULL; } json_channel = ast_channel_snapshot_to_json(new_snapshot, stasis_app_get_sanitizer()); if (!json_channel) { return NULL; } return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}", "type", "ChannelCallerId", "timestamp", ast_json_timeval(*tv, NULL), "caller_presentation", new_snapshot->caller_pres, "caller_presentation_txt", ast_describe_caller_presentation( new_snapshot->caller_pres), "channel", json_channel); }
static struct ast_json *peerstatus_to_json(struct stasis_message *msg, const struct stasis_message_sanitizer *sanitize) { struct ast_endpoint_blob *obj = stasis_message_data(msg); struct ast_json *json_endpoint; struct ast_json *json_peer; struct ast_json *json_final; const struct timeval *tv = stasis_message_timestamp(msg); json_endpoint = ast_endpoint_snapshot_to_json(obj->snapshot, NULL); if (!json_endpoint) { return NULL; } json_peer = ast_json_object_create(); if (!json_peer) { ast_json_unref(json_endpoint); return NULL; } /* Copy all fields from the blob */ ast_json_object_update(json_peer, obj->blob); json_final = ast_json_pack("{s: s, s: o, s: o, s: o }", "type", "PeerStatusChange", "timestamp", ast_json_timeval(*tv, NULL), "endpoint", json_endpoint, "peer", json_peer); if (!json_final) { ast_json_unref(json_endpoint); ast_json_unref(json_peer); } return json_final; }
void ast_ari_asterisk_get_global_var(struct ast_variable *headers, struct ast_ari_asterisk_get_global_var_args *args, struct ast_ari_response *response) { RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); RAII_VAR(struct ast_str *, tmp, NULL, ast_free); const char *value; ast_assert(response != NULL); if (ast_strlen_zero(args->variable)) { ast_ari_response_error( response, 400, "Bad Request", "Variable name is required"); return; } tmp = ast_str_create(32); if (!tmp) { ast_ari_response_alloc_failed(response); return; } value = ast_str_retrieve_variable(&tmp, 0, NULL, NULL, args->variable); if (!(json = ast_json_pack("{s: s}", "value", S_OR(value, "")))) { ast_ari_response_alloc_failed(response); return; } ast_ari_response_ok(response, ast_json_ref(json)); }
struct ast_json *ast_json_party_id(struct ast_party_id *party) { RAII_VAR(struct ast_json *, json_party_id, NULL, ast_json_unref); int pres; /* Combined party presentation */ pres = ast_party_id_presentation(party); json_party_id = ast_json_pack("{s: i, s: s}", "presentation", pres, "presentation_txt", ast_describe_caller_presentation(pres)); if (!json_party_id) { return NULL; } /* Party number */ if (party->number.valid && ast_json_object_set(json_party_id, "number", json_party_number(&party->number))) { return NULL; } /* Party name */ if (party->name.valid && ast_json_object_set(json_party_id, "name", json_party_name(&party->name))) { return NULL; } /* Party subaddress */ if (party->subaddress.valid && ast_json_object_set(json_party_id, "subaddress", json_party_subaddress(&party->subaddress))) { return NULL; } return ast_json_ref(json_party_id); }
void ast_system_publish_registry(const char *channeltype, const char *username, const char *domain, const char *status, const char *cause) { RAII_VAR(struct ast_json *, registry, NULL, ast_json_unref); RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); if (!ast_system_registry_type()) { return; } registry = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s}", "type", "registry", "channeltype", channeltype, "username", username, "domain", domain, "status", status, "cause", S_OR(cause, "")); if (!(payload = ast_json_payload_create(registry))) { return; } if (!(message = stasis_message_create(ast_system_registry_type(), payload))) { return; } stasis_publish(ast_system_topic(), message); }
static struct ast_json *contactstatus_to_json(struct stasis_message *msg, const struct stasis_message_sanitizer *sanitize) { struct ast_endpoint_blob *obj = stasis_message_data(msg); struct ast_json *json_endpoint; struct ast_json *json_final; const struct timeval *tv = stasis_message_timestamp(msg); json_endpoint = ast_endpoint_snapshot_to_json(obj->snapshot, NULL); if (!json_endpoint) { return NULL; } json_final = ast_json_pack("{s: s, s: o, s: o, s: { s: s, s: s, s: s, s: s } } ", "type", "ContactStatusChange", "timestamp", ast_json_timeval(*tv, NULL), "endpoint", json_endpoint, "contact_info", "uri", ast_json_string_get(ast_json_object_get(obj->blob, "uri")), "contact_status", ast_json_string_get(ast_json_object_get(obj->blob, "contact_status")), "aor", ast_json_string_get(ast_json_object_get(obj->blob, "aor")), "roundtrip_usec", ast_json_string_get(ast_json_object_get(obj->blob, "roundtrip_usec"))); if (!json_final) { ast_json_unref(json_endpoint); } return json_final; }
/*! * \internal * Shared code for all handlers */ static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_ari_response *response) { struct ast_json *message = ast_json_pack("{s: s, s: {}, s: {}, s: {}}", "name", name, "get_params", "path_vars", "headers"); struct ast_json *get_params_obj = ast_json_object_get(message, "get_params"); struct ast_json *path_vars_obj = ast_json_object_get(message, "path_vars"); struct ast_json *headers_obj = ast_json_object_get(message, "headers"); for (; get_params != NULL; get_params = get_params->next) { ast_json_object_set(get_params_obj, get_params->name, ast_json_string_create(get_params->value)); } for (; path_vars != NULL; path_vars = path_vars->next) { ast_json_object_set(path_vars_obj, path_vars->name, ast_json_string_create(path_vars->value)); } for (; headers != NULL; headers = headers->next) { ast_json_object_set(headers_obj, headers->name, ast_json_string_create(headers->value)); } ++invocation_count; response->response_code = response_code; response->message = message; }
static struct ast_json *channel_dialplan( struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *tv) { struct ast_json *json_channel; /* No Newexten event on first channel snapshot */ if (!old_snapshot) { return NULL; } /* Empty application is not valid for a Newexten event */ if (ast_strlen_zero(new_snapshot->dialplan->appl)) { return NULL; } if (ast_channel_snapshot_cep_equal(old_snapshot, new_snapshot)) { return NULL; } json_channel = ast_channel_snapshot_to_json(new_snapshot, stasis_app_get_sanitizer()); if (!json_channel) { return NULL; } return ast_json_pack("{s: s, s: o, s: s, s: s, s: o}", "type", "ChannelDialplan", "timestamp", ast_json_timeval(*tv, NULL), "dialplan_app", new_snapshot->dialplan->appl, "dialplan_app_data", AST_JSON_UTF8_VALIDATE(new_snapshot->dialplan->data), "channel", json_channel); }
void app_update(struct stasis_app *app, stasis_app_cb handler, void *data) { SCOPED_AO2LOCK(lock, app); if (app->handler) { RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref); ast_verb(1, "Replacing Stasis app '%s'\n", app->name); msg = ast_json_pack("{s: s, s: s}", "type", "ApplicationReplaced", "application", app->name); if (msg) { app_send(app, msg); } } else { ast_verb(1, "Activating Stasis app '%s'\n", app->name); } app->handler = handler; ao2_cleanup(app->data); if (data) { ao2_ref(data, +1); } app->data = data; }
struct ast_json *ast_channel_snapshot_to_json( const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize) { RAII_VAR(struct ast_json *, json_chan, NULL, ast_json_unref); if (snapshot == NULL || (sanitize && sanitize->channel_snapshot && sanitize->channel_snapshot(snapshot))) { return NULL; } json_chan = ast_json_pack( /* Broken up into groups of three for readability */ "{ s: s, s: s, s: s," " s: o, s: o, s: s," " s: o, s: o }", /* First line */ "id", snapshot->uniqueid, "name", snapshot->name, "state", ast_state2str(snapshot->state), /* Second line */ "caller", ast_json_name_number( snapshot->caller_name, snapshot->caller_number), "connected", ast_json_name_number( snapshot->connected_name, snapshot->connected_number), "accountcode", snapshot->accountcode, /* Third line */ "dialplan", ast_json_dialplan_cep( snapshot->context, snapshot->exten, snapshot->priority), "creationtime", ast_json_timeval(snapshot->creationtime, NULL)); return ast_json_ref(json_chan); }
/*! \brief Callback for \ref ast_unreal_pvt_callbacks \ref optimization_finished_cb */ static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int success, unsigned int id) { RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref); RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); struct local_pvt *p = (struct local_pvt *)base; if (!ast_local_optimization_end_type()) { return; } json_object = ast_json_pack("{s: i, s: i}", "success", success, "id", id); if (!json_object) { return; } payload = local_channel_optimization_blob(p, json_object); if (!payload) { return; } msg = stasis_message_create(ast_local_optimization_end_type(), payload); if (!msg) { return; } stasis_publish(ast_channel_topic(p->base.owner), msg); }
struct ast_json *stasis_app_recording_to_json( const struct stasis_app_recording *recording) { RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); if (recording == NULL) { return NULL; } json = ast_json_pack("{s: s, s: s, s: s, s: s}", "name", recording->options->name, "format", recording->options->format, "state", state_to_string(recording->state), "target_uri", recording->options->target); if (json && recording->duration.total > -1) { ast_json_object_set(json, "duration", ast_json_integer_create(recording->duration.total)); } if (json && recording->duration.energy_only > -1) { ast_json_object_set(json, "talking_duration", ast_json_integer_create(recording->duration.energy_only)); ast_json_object_set(json, "silence_duration", ast_json_integer_create(recording->duration.total - recording->duration.energy_only)); } return ast_json_ref(json); }
struct ast_json *ast_json_dialplan_cep(const char *context, const char *exten, int priority) { return ast_json_pack("{s: o, s: o, s: o}", "context", context ? ast_json_string_create(context) : ast_json_null(), "exten", exten ? ast_json_string_create(exten) : ast_json_null(), "priority", priority != -1 ? ast_json_integer_create(priority) : ast_json_null()); }
static struct ast_json *mailbox_to_json( const struct ast_mwi_mailbox_object *mailbox) { return ast_json_pack("{s: s, s: i, s: i}", "name", ast_mwi_mailbox_get_id(mailbox), "old_messages", ast_mwi_mailbox_get_msgs_old(mailbox), "new_messages", ast_mwi_mailbox_get_msgs_new(mailbox)); }
/*! * \internal * \brief Post the \ref ast_local_bridge_type \ref stasis message * \since 12.0.0 * * \param p local_pvt to raise the local bridge message * * \return Nothing */ static void publish_local_bridge_message(struct local_pvt *p) { RAII_VAR(struct ast_multi_channel_blob *, multi_blob, NULL, ao2_cleanup); RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, one_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, two_snapshot, NULL, ao2_cleanup); struct ast_channel *owner; struct ast_channel *chan; if (!ast_local_bridge_type()) { return; } ast_unreal_lock_all(&p->base, &chan, &owner); blob = ast_json_pack("{s: s, s: s, s: b}", "context", p->context, "exten", p->exten, "can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION)); if (!blob) { goto end; } multi_blob = ast_multi_channel_blob_create(blob); if (!multi_blob) { goto end; } one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(owner)); if (!one_snapshot) { goto end; } two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)); if (!two_snapshot) { goto end; } ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot); ast_multi_channel_blob_add_channel(multi_blob, "2", two_snapshot); msg = stasis_message_create(ast_local_bridge_type(), multi_blob); if (!msg) { goto end; } stasis_publish(ast_channel_topic(owner), msg); end: ast_channel_unlock(owner); ast_channel_unref(owner); ast_channel_unlock(chan); ast_channel_unref(chan); ao2_unlock(&p->base); }
void ast_ari_websocket_events_event_websocket_established(struct ast_ari_websocket_session *ws_session, struct ast_variable *headers, struct ast_ari_events_event_websocket_args *args) { RAII_VAR(struct event_session *, session, NULL, session_cleanup); struct ast_json *msg; int res; size_t i; int (* register_handler)(const char *, stasis_app_cb handler, void *data); ast_debug(3, "/events WebSocket connection\n"); session = session_create(ws_session); if (!session) { ast_ari_websocket_session_write(ws_session, ast_ari_oom_json()); return; } if (args->subscribe_all) { register_handler = &stasis_app_register_all; } else { register_handler = &stasis_app_register; } res = 0; for (i = 0; i < args->app_count; ++i) { if (ast_strlen_zero(args->app[i])) { continue; } res |= session_register_app(session, args->app[i], register_handler); } if (ao2_container_count(session->websocket_apps) == 0) { RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref); msg = ast_json_pack("{s: s, s: [s]}", "type", "MissingParams", "params", "app"); if (!msg) { msg = ast_json_ref(ast_ari_oom_json()); } ast_ari_websocket_session_write(session->ws_session, msg); return; } if (res != 0) { ast_ari_websocket_session_write(ws_session, ast_ari_oom_json()); return; } /* We don't process any input, but we'll consume it waiting for EOF */ while ((msg = ast_ari_websocket_session_read(ws_session))) { ast_json_unref(msg); } }
static struct ast_json *json_party_subaddress(struct ast_party_subaddress *subaddress) { if (!subaddress->valid) { return NULL; } return ast_json_pack("{s: s, s: i, s: b}", "subaddress", subaddress->str, "type", subaddress->type, "odd", subaddress->odd_even_indicator); }
static struct ast_json *json_party_number(struct ast_party_number *number) { if (!number->valid) { return NULL; } return ast_json_pack("{s: s, s: i, s: i, s: s}", "number", number->str, "plan", number->plan, "presentation", number->presentation, "presentation_txt", ast_describe_caller_presentation(number->presentation)); }
static struct ast_json *json_party_name(struct ast_party_name *name) { if (!name->valid) { return NULL; } return ast_json_pack("{s: s, s: s, s: i, s: s}", "name", name->str, "character_set", ast_party_name_charset_describe(name->char_set), "presentation", name->presentation, "presentation_txt", ast_describe_caller_presentation(name->presentation)); }
struct ast_json *app_to_json(const struct stasis_app *app) { struct ast_json *json; struct ast_json *channels; struct ast_json *bridges; struct ast_json *endpoints; struct ao2_iterator i; struct app_forwards *forwards; json = ast_json_pack("{s: s, s: [], s: [], s: []}", "name", app->name, "channel_ids", "bridge_ids", "endpoint_ids"); if (!json) { return NULL; } channels = ast_json_object_get(json, "channel_ids"); bridges = ast_json_object_get(json, "bridge_ids"); endpoints = ast_json_object_get(json, "endpoint_ids"); i = ao2_iterator_init(app->forwards, 0); while ((forwards = ao2_iterator_next(&i))) { struct ast_json *array = NULL; int append_res; switch (forwards->forward_type) { case FORWARD_CHANNEL: array = channels; break; case FORWARD_BRIDGE: array = bridges; break; case FORWARD_ENDPOINT: array = endpoints; break; } /* If forward_type value is unexpected this will safely return an error. */ append_res = ast_json_array_append(array, ast_json_string_create(forwards->id)); ao2_ref(forwards, -1); if (append_res != 0) { ast_log(LOG_ERROR, "Error building response\n"); ao2_iterator_destroy(&i); ast_json_unref(json); return NULL; } } ao2_iterator_destroy(&i); return json; }
/*! * \internal * \brief Publish a hangup handler related message to \ref stasis */ static void publish_hangup_handler_message(const char *action, struct ast_channel *chan, const char *handler) { RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); blob = ast_json_pack("{s: s, s: s}", "type", action, "handler", S_OR(handler, "")); if (!blob) { return; } ast_channel_publish_blob(chan, ast_channel_hangup_handler_type(), blob); }
struct ast_json *app_to_json(const struct stasis_app *app) { RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); struct ast_json *channels; struct ast_json *bridges; struct ast_json *endpoints; struct ao2_iterator i; void *obj; json = ast_json_pack("{s: s, s: [], s: [], s: []}", "name", app->name, "channel_ids", "bridge_ids", "endpoint_ids"); channels = ast_json_object_get(json, "channel_ids"); bridges = ast_json_object_get(json, "bridge_ids"); endpoints = ast_json_object_get(json, "endpoint_ids"); i = ao2_iterator_init(app->forwards, 0); while ((obj = ao2_iterator_next(&i))) { RAII_VAR(struct app_forwards *, forwards, obj, ao2_cleanup); RAII_VAR(struct ast_json *, id, NULL, ast_json_unref); int append_res = -1; id = ast_json_string_create(forwards->id); switch (forwards->forward_type) { case FORWARD_CHANNEL: append_res = ast_json_array_append(channels, ast_json_ref(id)); break; case FORWARD_BRIDGE: append_res = ast_json_array_append(bridges, ast_json_ref(id)); break; case FORWARD_ENDPOINT: append_res = ast_json_array_append(endpoints, ast_json_ref(id)); break; } if (append_res != 0) { ast_log(LOG_ERROR, "Error building response\n"); ao2_iterator_destroy(&i); return NULL; } } ao2_iterator_destroy(&i); return ast_json_ref(json); }
static struct ast_json *simple_bridge_event( const char *type, struct ast_bridge_snapshot *snapshot, const struct timeval *tv) { struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()); if (!json_bridge) { return NULL; } return ast_json_pack("{s: s, s: o, s: o}", "type", type, "timestamp", ast_json_timeval(*tv, NULL), "bridge", json_bridge); }
void ast_ari_response_error(struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt, ...) { RAII_VAR(struct ast_json *, message, NULL, ast_json_unref); va_list ap; va_start(ap, message_fmt); message = ast_json_vstringf(message_fmt, ap); response->message = ast_json_pack("{s: o}", "message", ast_json_ref(message)); response->response_code = response_code; response->response_text = response_text; }
struct ast_json *stasis_app_recording_to_json( const struct stasis_app_recording *recording) { RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); if (recording == NULL) { return NULL; } json = ast_json_pack("{s: s, s: s, s: s}", "name", recording->options->name, "format", recording->options->format, "state", state_to_string(recording->state)); return ast_json_ref(json); }
/*! * \brief Process logger information and append to a json array * \param channel Resource logger channel name path * \param type Resource log type * \param status Resource log status * \param configuration Resource logger levels * \param log_data_list Resource array * * \retval -1 if no resource exists * \retval 0 if resource exists */ static int process_log_list(const char *channel, const char *type, const char *status, const char *configuration, void *log_data_list) { struct ast_json *logger_info; logger_info = ast_json_pack("{s: s, s: s, s: s, s: s}", "channel", channel, "type", type, "status", status, "configuration", configuration); if (!logger_info) { return AST_LOGGER_FAILURE; } ast_json_array_append(log_data_list, logger_info); return AST_LOGGER_SUCCESS; }
static void return_sorcery_object(struct ast_sorcery *sorcery, void *sorcery_obj, struct ast_ari_response *response) { RAII_VAR(struct ast_json *, return_set, NULL, ast_json_unref); struct ast_variable *change_set; struct ast_variable *it_change_set; return_set = ast_json_array_create(); if (!return_set) { ast_ari_response_alloc_failed(response); return; } /* Note that we can't use the sorcery JSON change set directly, * as it will hand us back an Object (with fields), and we need * a more generic representation of whatever the API call asked * for, i.e., a list of tuples. */ change_set = ast_sorcery_objectset_create(sorcery, sorcery_obj); if (!change_set) { ast_ari_response_alloc_failed(response); return; } for (it_change_set = change_set; it_change_set; it_change_set = it_change_set->next) { struct ast_json *tuple; tuple = ast_json_pack("{s: s, s: s}", "attribute", it_change_set->name, "value", it_change_set->value); if (!tuple) { ast_variables_destroy(change_set); ast_ari_response_alloc_failed(response); return; } if (ast_json_array_append(return_set, tuple)) { ast_json_unref(tuple); ast_variables_destroy(change_set); ast_ari_response_alloc_failed(response); return; } } ast_variables_destroy(change_set); ast_ari_response_ok(response, ast_json_ref(return_set)); }
static struct ast_json *channel_destroyed_event( struct ast_channel_snapshot *snapshot, const struct timeval *tv) { struct ast_json *json_channel = ast_channel_snapshot_to_json(snapshot, stasis_app_get_sanitizer()); if (!json_channel) { return NULL; } return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}", "type", "ChannelDestroyed", "timestamp", ast_json_timeval(*tv, NULL), "cause", snapshot->hangup->cause, "cause_txt", ast_cause2str(snapshot->hangup->cause), "channel", json_channel); }