static int manager_parking_status_single_lot(struct mansession *s, const struct message *m, const char *id_text, const char *lot_name) { RAII_VAR(struct parking_lot *, curlot, NULL, ao2_cleanup); struct parked_user *curuser; struct ao2_iterator iter_users; int total = 0; curlot = parking_lot_find_by_name(lot_name); if (!curlot) { astman_send_error(s, m, "Requested parking lot could not be found."); return RESULT_SUCCESS; } astman_send_ack(s, m, "Parked calls will follow"); iter_users = ao2_iterator_init(curlot->parked_users, 0); while ((curuser = ao2_iterator_next(&iter_users))) { RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup); RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free); payload = parked_call_payload_from_parked_user(curuser, PARKED_CALL); if (!payload) { astman_send_error(s, m, "Failed to retrieve parking data about a parked user."); return RESULT_FAILURE; } parked_call_string = manager_build_parked_call_string(payload); if (!parked_call_string) { astman_send_error(s, m, "Failed to retrieve parkingd ata about a parked user."); return RESULT_FAILURE; } total++; astman_append(s, "Event: ParkedCall\r\n" "%s" /* The parked call string */ "%s" /* The action ID */ "\r\n", ast_str_buffer(parked_call_string), id_text); ao2_ref(curuser, -1); } ao2_iterator_destroy(&iter_users); astman_append(s, "Event: ParkedCallsComplete\r\n" "Total: %d\r\n" "%s" "\r\n", total, id_text); return RESULT_SUCCESS; }
static int format_ami_aor_handler(void *obj, void *arg, int flags) { struct ast_sip_aor *aor = obj; struct ast_sip_ami *ami = arg; const struct ast_sip_endpoint *endpoint = ami->arg; RAII_VAR(struct ast_str *, buf, ast_sip_create_ami_event("AorDetail", ami), ast_free); int total_contacts; int num_permanent; RAII_VAR(struct ao2_container *, contacts, ast_sip_location_retrieve_aor_contacts(aor), ao2_cleanup); if (!buf) { return -1; } sip_aor_to_ami(aor, &buf); total_contacts = ao2_container_count(contacts); num_permanent = aor->permanent_contacts ? ao2_container_count(aor->permanent_contacts) : 0; ast_str_append(&buf, 0, "TotalContacts: %d\r\n", total_contacts); ast_str_append(&buf, 0, "ContactsRegistered: %d\r\n", total_contacts - num_permanent); ast_str_append(&buf, 0, "EndpointName: %s\r\n", ast_sorcery_object_get_id(endpoint)); astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); ami->count++; return 0; }
static int format_contact_status(void *obj, void *arg, int flags) { struct ast_sip_contact_wrapper *wrapper = obj; struct ast_sip_contact *contact = wrapper->contact; struct ast_sip_ami *ami = arg; struct ast_sip_contact_status *status; struct ast_str *buf; const struct ast_sip_endpoint *endpoint = ami->arg; buf = ast_sip_create_ami_event("ContactStatusDetail", ami); if (!buf) { return -1; } status = ast_sorcery_retrieve_by_id( ast_sip_get_sorcery(), CONTACT_STATUS, ast_sorcery_object_get_id(contact)); ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id); ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri); ast_str_append(&buf, 0, "Status: %s\r\n", ast_sip_get_contact_status_label(status->status)); if (status->status == UNKNOWN) { ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n"); } else { ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt); } ast_str_append(&buf, 0, "EndpointName: %s\r\n", ast_sorcery_object_get_id(endpoint)); astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); ami->count++; ast_free(buf); ao2_cleanup(status); return 0; }
static int send_bridge_info_item_cb(void *obj, void *arg, void *data, int flags) { char *uniqueid = obj; struct mansession *s = arg; char *id_text = data; RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); struct ast_channel_snapshot *snapshot; RAII_VAR(struct ast_str *, channel_text, NULL, ast_free); msg = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(), uniqueid); if (!msg) { return 0; } snapshot = stasis_message_data(msg); if (snapshot->tech_properties & AST_CHAN_TP_INTERNAL) { return 0; } channel_text = ast_manager_build_channel_state_string(snapshot); if (!channel_text) { return 0; } astman_append(s, "Event: BridgeInfoChannel\r\n" "%s" "%s" "\r\n", ast_str_buffer(channel_text), id_text); return 0; }
static int format_ami_auth_handler(void *obj, void *arg, int flags) { const struct ast_sip_auth *auth = obj; struct ast_sip_ami *ami = arg; const struct ast_sip_endpoint *endpoint = ami->arg; RAII_VAR(struct ast_str *, buf, ast_sip_create_ami_event("AuthDetail", ami), ast_free); if (!buf) { return -1; } if (sip_auth_to_ami(auth, &buf)) { return -1; } if (endpoint) { ast_str_append(&buf, 0, "EndpointName: %s\r\n", ast_sorcery_object_get_id(endpoint)); } astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); ami->count++; return 0; }
static int manager_parking_lot_list(struct mansession *s, const struct message *m) { const char *id = astman_get_header(m, "ActionID"); char id_text[256] = ""; struct ao2_container *lot_container; if (!ast_strlen_zero(id)) { snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); } lot_container = get_parking_lot_container(); if (!lot_container) { ast_log(LOG_ERROR, "Failed to obtain parking lot list. Action canceled.\n"); astman_send_error(s, m, "Could not create parking lot list"); return -1; } astman_send_ack(s, m, "Parking lots will follow"); ao2_callback_data(lot_container, OBJ_MULTIPLE | OBJ_NODATA, manager_append_event_parking_lot_data_cb, s, id_text); astman_append(s, "Event: ParkinglotsComplete\r\n" "%s" "\r\n",id_text); return RESULT_SUCCESS; }
static int format_ami_endpoint_transport(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami) { RAII_VAR(struct ast_str *, buf, NULL, ast_free); RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup); if (ast_strlen_zero(endpoint->transport)) { return 0; } buf = ast_sip_create_ami_event("TransportDetail", ami); if (!buf) { return -1; } transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", endpoint->transport); if (!transport) { astman_send_error_va(ami->s, ami->m, "Unable to retrieve " "transport %s\n", endpoint->transport); return -1; } sip_transport_to_ami(transport, &buf); ast_str_append(&buf, 0, "EndpointName: %s\r\n", ast_sorcery_object_get_id(endpoint)); astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); ami->count++; return 0; }
int ast_sip_format_contact_ami(void *obj, void *arg, int flags) { struct ast_sip_contact_wrapper *wrapper = obj; struct ast_sip_contact *contact = wrapper->contact; struct ast_sip_ami *ami = arg; struct ast_sip_contact_status *status; struct ast_str *buf; const struct ast_sip_endpoint *endpoint = ami->arg; buf = ast_sip_create_ami_event("ContactStatusDetail", ami); if (!buf) { return -1; } status = ast_sorcery_retrieve_by_id( ast_sip_get_sorcery(), CONTACT_STATUS, ast_sorcery_object_get_id(contact)); ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id); ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri); ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent); ast_str_append(&buf, 0, "RegExpire: %ld\r\n", contact->expiration_time.tv_sec); if (!ast_strlen_zero(contact->via_addr)) { ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr); if (contact->via_port) { ast_str_append(&buf, 0, ":%d", contact->via_port); } ast_str_append(&buf, 0, "\r\n"); } if (!ast_strlen_zero(contact->call_id)) { ast_str_append(&buf, 0, "CallID: %s\r\n", contact->call_id); } ast_str_append(&buf, 0, "Status: %s\r\n", ast_sip_get_contact_status_label(status->status)); if (status->status == UNKNOWN) { ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n"); } else { ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt); } ast_str_append(&buf, 0, "EndpointName: %s\r\n", endpoint ? ast_sorcery_object_get_id(endpoint) : S_OR(contact->endpoint_name, "")); ast_str_append(&buf, 0, "ID: %s\r\n", ast_sorcery_object_get_id(contact)); ast_str_append(&buf, 0, "AuthenticateQualify: %d\r\n", contact->authenticate_qualify); ast_str_append(&buf, 0, "OutboundProxy: %s\r\n", contact->outbound_proxy); ast_str_append(&buf, 0, "Path: %s\r\n", contact->path); ast_str_append(&buf, 0, "QualifyFrequency: %u\r\n", contact->qualify_frequency); ast_str_append(&buf, 0, "QualifyTimeout: %.3f\r\n", contact->qualify_timeout); astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); ami->count++; ast_free(buf); ao2_cleanup(status); return 0; }
static int manager_dbget(struct mansession *s, const struct message *m) { const char *id = astman_get_header(m,"ActionID"); char idText[256] = ""; const char *family = astman_get_header(m, "Family"); const char *key = astman_get_header(m, "Key"); char tmp[MAX_DB_FIELD]; int res; if (ast_strlen_zero(family)) { astman_send_error(s, m, "No family specified."); return 0; } if (ast_strlen_zero(key)) { astman_send_error(s, m, "No key specified."); return 0; } if (!ast_strlen_zero(id)) snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id); res = ast_db_get(family, key, tmp, sizeof(tmp)); if (res) { astman_send_error(s, m, "Database entry not found"); } else { astman_send_ack(s, m, "Result will follow"); astman_append(s, "Event: DBGetResponse\r\n" "Family: %s\r\n" "Key: %s\r\n" "Val: %s\r\n" "%s" "\r\n", family, key, tmp, idText); astman_append(s, "Event: DBGetComplete\r\n" "%s" "\r\n", idText); } return 0; }
static int manager_bridge_info(struct mansession *s, const struct message *m) { const char *id = astman_get_header(m, "ActionID"); const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid"); RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); RAII_VAR(struct ast_str *, bridge_info, NULL, ast_free); struct ast_bridge_snapshot *snapshot; struct bridge_list_data list_data; if (!id_text) { astman_send_error(s, m, "Internal error"); return -1; } if (ast_strlen_zero(bridge_uniqueid)) { astman_send_error(s, m, "BridgeUniqueid must be provided"); return 0; } if (!ast_strlen_zero(id)) { ast_str_set(&id_text, 0, "ActionID: %s\r\n", id); } msg = stasis_cache_get(ast_bridge_cache(), ast_bridge_snapshot_type(), bridge_uniqueid); if (!msg) { astman_send_error(s, m, "Specified BridgeUniqueid not found"); return 0; } snapshot = stasis_message_data(msg); bridge_info = ast_manager_build_bridge_state_string(snapshot); if (!bridge_info) { astman_send_error(s, m, "Internal error"); return -1; } astman_send_listack(s, m, "Bridge channel listing will follow", "start"); list_data.id_text = ast_str_buffer(id_text); list_data.count = 0; ao2_callback_data(snapshot->channels, OBJ_NODATA, send_bridge_info_item_cb, s, &list_data); astman_send_list_complete_start(s, m, "BridgeInfoComplete", list_data.count); if (!ast_strlen_zero(ast_str_buffer(bridge_info))) { astman_append(s, "%s", ast_str_buffer(bridge_info)); } astman_send_list_complete_end(s); return 0; }
static int manager_mutestream(struct mansession *s, const struct message *m) { const char *channel = astman_get_header(m, "Channel"); const char *id = astman_get_header(m,"ActionID"); const char *state = astman_get_header(m,"State"); const char *direction = astman_get_header(m,"Direction"); char id_text[256]; struct ast_channel *c = NULL; if (ast_strlen_zero(channel)) { astman_send_error(s, m, "Channel not specified"); return 0; } if (ast_strlen_zero(state)) { astman_send_error(s, m, "State not specified"); return 0; } if (ast_strlen_zero(direction)) { astman_send_error(s, m, "Direction not specified"); return 0; } /* Ok, we have everything */ c = ast_channel_get_by_name(channel); if (!c) { astman_send_error(s, m, "No such channel"); return 0; } if (mute_channel(c, direction, ast_true(state))) { astman_send_error(s, m, "Failed to mute/unmute stream"); ast_channel_unref(c); return 0; } ast_channel_unref(c); if (!ast_strlen_zero(id)) { snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); } else { id_text[0] = '\0'; } astman_append(s, "Response: Success\r\n" "%s" "\r\n", id_text); return 0; }
static int format_ami_authlist_handler(void *obj, void *arg, int flags) { struct ast_sip_auth *auth = obj; struct ast_sip_ami *ami = arg; struct ast_str *buf; buf = ast_sip_create_ami_event("AuthList", ami); if (!buf) { return CMP_STOP; } sip_auth_to_ami(auth, &buf); astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); ami->count++; ast_free(buf); return 0; }
static int send_bridge_list_item_cb(void *obj, void *arg, void *data, int flags) { struct ast_bridge_snapshot *snapshot = stasis_message_data(obj); struct mansession *s = arg; char *id_text = data; RAII_VAR(struct ast_str *, bridge_info, ast_manager_build_bridge_state_string(snapshot), ast_free_ptr); if (!bridge_info) { return 0; } astman_append(s, "Event: BridgeListItem\r\n" "%s" "%s" "\r\n", ast_str_buffer(bridge_info), id_text); return 0; }
static int ami_registrations_aor(void *obj, void *arg, int flags) { struct ast_sip_aor *aor = obj; struct ast_sip_ami *ami = arg; int *count = ami->arg; RAII_VAR(struct ast_str *, buf, ast_sip_create_ami_event("InboundRegistrationDetail", ami), ast_free); if (!buf) { return -1; } ast_sip_sorcery_object_to_ami(aor, &buf); ast_str_append(&buf, 0, "Contacts: "); ast_sip_for_each_contact(aor, sip_contact_to_str, &buf); ast_str_append(&buf, 0, "\r\n"); astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); (*count)++; return 0; }
static int manager_append_event_parking_lot_data_cb(void *obj, void *arg, void *data, int flags) { struct parking_lot *curlot = obj; struct mansession *s = arg; char *id_text = data; astman_append(s, "Event: Parkinglot\r\n" "Name: %s\r\n" "StartSpace: %d\r\n" "StopSpace: %d\r\n" "Timeout: %d\r\n" "%s" /* The Action ID */ "\r\n", curlot->name, curlot->cfg->parking_start, curlot->cfg->parking_stop, curlot->cfg->parkingtime, id_text); return 0; }
static int manager_bridges_list(struct mansession *s, const struct message *m) { const char *id = astman_get_header(m, "ActionID"); const char *type_filter = astman_get_header(m, "BridgeType"); RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free); RAII_VAR(struct ao2_container *, bridges, NULL, ao2_cleanup); if (!id_text) { astman_send_error(s, m, "Internal error"); return -1; } if (!ast_strlen_zero(id)) { ast_str_set(&id_text, 0, "ActionID: %s\r\n", id); } bridges = stasis_cache_dump(ast_bridge_cache(), ast_bridge_snapshot_type()); if (!bridges) { astman_send_error(s, m, "Internal error"); return -1; } astman_send_ack(s, m, "Bridge listing will follow"); if (!ast_strlen_zero(type_filter)) { char *type_filter_dup = ast_strdupa(type_filter); ao2_callback(bridges, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK, filter_bridge_type_cb, type_filter_dup); } ao2_callback_data(bridges, OBJ_NODATA, send_bridge_list_item_cb, s, ast_str_buffer(id_text)); astman_append(s, "Event: BridgeListComplete\r\n" "%s" "\r\n", ast_str_buffer(id_text)); return 0; }
static int manager_mutestream(struct mansession *s, const struct message *m) { const char *channel = astman_get_header(m, "Channel"); const char *id = astman_get_header(m,"ActionID"); const char *state = astman_get_header(m,"State"); const char *direction = astman_get_header(m,"Direction"); char id_text[256]; struct ast_channel *c = NULL; struct ast_datastore *datastore = NULL; struct mute_information *mute = NULL; int is_new = 0; int turnon; if (ast_strlen_zero(channel)) { astman_send_error(s, m, "Channel not specified"); return 0; } if (ast_strlen_zero(state)) { astman_send_error(s, m, "State not specified"); return 0; } if (ast_strlen_zero(direction)) { astman_send_error(s, m, "Direction not specified"); return 0; } /* Ok, we have everything */ c = ast_channel_get_by_name(channel); if (!c) { astman_send_error(s, m, "No such channel"); return 0; } ast_channel_lock(c); if (!(datastore = ast_channel_datastore_find(c, &mute_datastore, NULL))) { if (!(datastore = initialize_mutehook(c))) { ast_channel_unlock(c); ast_channel_unref(c); astman_send_error(s, m, "Memory allocation failure"); return 0; } is_new = 1; } mute = datastore->data; turnon = ast_true(state); if (!strcasecmp(direction, "in")) { mute->mute_read = turnon; } else if (!strcasecmp(direction, "out")) { mute->mute_write = turnon; } else if (!strcasecmp(direction, "all")) { mute->mute_read = mute->mute_write = turnon; } if (is_new) { if (mute_add_audiohook(c, mute, datastore)) { /* Can't add audiohook */ ast_datastore_free(datastore); ast_free(mute); ast_channel_unlock(c); ast_channel_unref(c); astman_send_error(s, m, "Couldn't add mute audiohook"); return 0; } } ast_channel_unlock(c); ast_channel_unref(c); if (!ast_strlen_zero(id)) { snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); } else { id_text[0] = '\0'; } astman_append(s, "Response: Success\r\n" "%s" "\r\n", id_text); return 0; }
static void manager_parking_status_all_lots(struct mansession *s, const struct message *m, const char *id_text) { struct parked_user *curuser; struct ao2_container *lot_container; struct ao2_iterator iter_lots; struct ao2_iterator iter_users; struct parking_lot *curlot; int total = 0; lot_container = get_parking_lot_container(); if (!lot_container) { ast_log(LOG_ERROR, "Failed to obtain parking lot list. Action canceled.\n"); astman_send_error(s, m, "Could not create parking lot list"); return; } astman_send_listack(s, m, "Parked calls will follow", "start"); iter_lots = ao2_iterator_init(lot_container, 0); while ((curlot = ao2_iterator_next(&iter_lots))) { iter_users = ao2_iterator_init(curlot->parked_users, 0); while ((curuser = ao2_iterator_next(&iter_users))) { RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup); RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free); payload = parked_call_payload_from_parked_user(curuser, PARKED_CALL); if (!payload) { ao2_ref(curuser, -1); ao2_iterator_destroy(&iter_users); ao2_ref(curlot, -1); goto abort_list; } parked_call_string = manager_build_parked_call_string(payload); if (!parked_call_string) { ao2_ref(curuser, -1); ao2_iterator_destroy(&iter_users); ao2_ref(curlot, -1); goto abort_list; } total++; astman_append(s, "Event: ParkedCall\r\n" "%s" /* The parked call string */ "%s" /* The action ID */ "\r\n", ast_str_buffer(parked_call_string), id_text); ao2_ref(curuser, -1); } ao2_iterator_destroy(&iter_users); ao2_ref(curlot, -1); } abort_list: ao2_iterator_destroy(&iter_lots); astman_send_list_complete_start(s, m, "ParkedCallsComplete", total); astman_append(s, "Total: %d\r\n", total); astman_send_list_complete_end(s); }
/*! * \internal * \brief Get the requested mailboxes. * \since 12.1.0 * * \param s AMI session. * \param m AMI message. * * \retval 0 to keep AMI connection. * \retval -1 to disconnect AMI connection. */ static int mwi_mailbox_get(struct mansession *s, const struct message *m) { char id_text[256]; const char *id; const char *mailbox_id = astman_get_header(m, "Mailbox"); const struct ast_mwi_mailbox_object *mailbox; struct ao2_container *mailboxes; unsigned count; struct ao2_iterator iter; if (ast_strlen_zero(mailbox_id)) { astman_send_error(s, m, "Missing mailbox parameter in request"); return 0; } if (*mailbox_id == '/') { struct ast_str *regex_string; regex_string = ast_str_create(strlen(mailbox_id) + 1); if (!regex_string) { astman_send_error(s, m, "Memory Allocation Failure"); return 0; } /* Make "/regex/" into "regex" */ if (ast_regex_string_to_regex_pattern(mailbox_id, ®ex_string) != 0) { astman_send_error_va(s, m, "Mailbox regex format invalid in: %s", mailbox_id); ast_free(regex_string); return 0; } mailboxes = ast_mwi_mailbox_get_by_regex(ast_str_buffer(regex_string)); ast_free(regex_string); } else { mailboxes = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL); if (mailboxes) { mailbox = ast_mwi_mailbox_get(mailbox_id); if (mailbox) { if (!ao2_link(mailboxes, (void *) mailbox)) { ao2_ref(mailboxes, -1); mailboxes = NULL; } ast_mwi_mailbox_unref(mailbox); } } } if (!mailboxes) { astman_send_error(s, m, "Mailbox container creation failure"); return 0; } astman_send_listack(s, m, "Mailboxes will follow", "start"); id = astman_get_header(m, "ActionID"); if (!ast_strlen_zero(id)) { snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); } else { id_text[0] = '\0'; } /* Output mailbox list. */ count = 0; iter = ao2_iterator_init(mailboxes, AO2_ITERATOR_UNLINK); for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) { ++count; astman_append(s, "Event: MWIGet\r\n" "Mailbox: %s\r\n" "OldMessages: %u\r\n" "NewMessages: %u\r\n" "%s" "\r\n", ast_mwi_mailbox_get_id(mailbox), ast_mwi_mailbox_get_msgs_old(mailbox), ast_mwi_mailbox_get_msgs_new(mailbox), id_text); } ao2_iterator_destroy(&iter); ao2_ref(mailboxes, -1); astman_send_list_complete_start(s, m, "MWIGetComplete", count); astman_send_list_complete_end(s); return 0; }