Beispiel #1
0
/*!
 * \brief Callback handler for Stasis application messages.
 */
static void app_handler(void *data, const char *app_name,
			struct ast_json *message)
{
	struct event_session *session = data;
	int res;
	const char *msg_type = S_OR(
		ast_json_string_get(ast_json_object_get(message, "type")),
		"");
	const char *msg_application = S_OR(
		ast_json_string_get(ast_json_object_get(message, "application")),
		"");
 
	/* Determine if we've been replaced */
	if (strcmp(msg_type, "ApplicationReplaced") == 0 &&
		strcmp(msg_application, app_name) == 0) {
		ao2_find(session->websocket_apps, msg_application,
			OBJ_UNLINK | OBJ_NODATA);
	}

	res = ast_json_object_set(message, "application",
				  ast_json_string_create(app_name));
	if(res != 0) {
		return;
	}

	ao2_lock(session);
	if (session->ws_session) {
		ast_ari_websocket_session_write(session->ws_session, message);
	}
	ao2_unlock(session);
}
Beispiel #2
0
static int iftime(struct ast_channel *chan, char *cmd, char *data, char *buf,
		  size_t len)
{
	struct ast_timing timing;
	char *expr;
	char *iftrue;
	char *iffalse;

	data = ast_strip_quoted(data, "\"", "\"");
	expr = strsep(&data, "?");
	iftrue = strsep(&data, ":");
	iffalse = data;

	if (ast_strlen_zero(expr) || !(iftrue || iffalse)) {
		ast_log(LOG_WARNING,
				"Syntax IFTIME(<timespec>?[<true>][:<false>])\n");
		return -1;
	}

	if (!ast_build_timing(&timing, expr)) {
		ast_log(LOG_WARNING, "Invalid Time Spec.\n");
		return -1;
	}

	if (iftrue)
		iftrue = ast_strip_quoted(iftrue, "\"", "\"");
	if (iffalse)
		iffalse = ast_strip_quoted(iffalse, "\"", "\"");

	ast_copy_string(buf, ast_check_timing(&timing) ? S_OR(iftrue, "") : S_OR(iffalse, ""), len);

	return 0;
}
Beispiel #3
0
static int callerid_read(struct ast_channel *chan, char *cmd, char *data,
			 char *buf, size_t len)
{
	char *opt = data;

	if (!chan)
		return -1;

	if (strchr(opt, '|')) {
		char name[80], num[80];

		data = strsep(&opt, "|");
		ast_callerid_split(opt, name, sizeof(name), num, sizeof(num));

		if (!strncasecmp("all", data, 3)) {
			snprintf(buf, len, "\"%s\" <%s>", name, num);
		} else if (!strncasecmp("name", data, 4)) {
			ast_copy_string(buf, name, len);
		} else if (!strncasecmp("num", data, 3) ||
			   !strncasecmp("number", data, 6)) {

			ast_copy_string(buf, num, len);
		} else {
			ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
		}
	} else {
		if (!strncasecmp("all", data, 3)) {
			snprintf(buf, len, "\"%s\" <%s>",
				 S_OR(chan->cid.cid_name, ""),
				 S_OR(chan->cid.cid_num, ""));
		} else if (!strncasecmp("name", data, 4)) {
			if (chan->cid.cid_name) {
				ast_copy_string(buf, chan->cid.cid_name, len);
			}
		} else if (!strncasecmp("num", data, 3)
				   || !strncasecmp("number", data, 6)) {
			if (chan->cid.cid_num) {
				ast_copy_string(buf, chan->cid.cid_num, len);
			}
		} else if (!strncasecmp("ani", data, 3)) {
			if (chan->cid.cid_ani) {
				ast_copy_string(buf, chan->cid.cid_ani, len);
			}
		} else if (!strncasecmp("dnid", data, 4)) {
			if (chan->cid.cid_dnid) {
				ast_copy_string(buf, chan->cid.cid_dnid, len);
			}
		} else if (!strncasecmp("rdnis", data, 5)) {
			if (chan->cid.cid_rdnis) {
				ast_copy_string(buf, chan->cid.cid_rdnis, len);
			}
		} else {
			ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
		}
	}

	return 0;
}
Beispiel #4
0
static int __ssl_setup(struct ast_tls_config *cfg, int client)
{
#ifndef DO_SSL
	cfg->enabled = 0;
	return 0;
#else
	if (!cfg->enabled)
		return 0;

	SSL_load_error_strings();
	SSLeay_add_ssl_algorithms();

	if (!(cfg->ssl_ctx = SSL_CTX_new( client ? SSLv23_client_method() : SSLv23_server_method() ))) {
		ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n");
		cfg->enabled = 0;
		return 0;
	}
	if (!ast_strlen_zero(cfg->certfile)) {
		if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 ||
		    SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 ||
		    SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 ) {
			if (!client) {
				/* Clients don't need a certificate, but if its setup we can use it */
				ast_verb(0, "SSL cert error <%s>", cfg->certfile);
				sleep(2);
				cfg->enabled = 0;
				return 0;
			}
		}
	}
	if (!ast_strlen_zero(cfg->cipher)) {
		if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) {
			if (!client) {
				ast_verb(0, "SSL cipher error <%s>", cfg->cipher);
				sleep(2);
				cfg->enabled = 0;
				return 0;
			}
		}
	}
	if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) {
		if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0)
			ast_verb(0, "SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath);
	}

	ast_verb(0, "SSL certificate ok\n");
	return 1;
#endif
}
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);
}
Beispiel #6
0
/*! \brief Custom handler for TLS cipher setting */
static int transport_tls_cipher_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
	struct ast_sip_transport *transport = obj;
	char *parse;
	char *name;
	int res = 0;
	RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup);

	if (!state) {
		return -1;
	}

	parse = ast_strdupa(S_OR(var->value, ""));
	while ((name = ast_strip(strsep(&parse, ",")))) {
		if (ast_strlen_zero(name)) {
			continue;
		}
		if (ARRAY_LEN(state->ciphers) <= state->tls.ciphers_num) {
			ast_log(LOG_ERROR, "Too many ciphers specified\n");
			res = -1;
			break;
		}
		res |= transport_cipher_add(state, name);
	}
	return res ? -1 : 0;
}
Beispiel #7
0
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));
}
static void channel_enter_cb(void *data, struct stasis_subscription *sub,
				    struct stasis_message *message)
{
	static const char *swap_name = "SwapUniqueid: ";
	struct ast_bridge_blob *blob = stasis_message_data(message);
	RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
	RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
	const char *swap_id;

	bridge_text = ast_manager_build_bridge_state_string(blob->bridge);
	channel_text = ast_manager_build_channel_state_string(blob->channel);
	if (!bridge_text || !channel_text) {
		return;
	}

	swap_id = ast_json_string_get(ast_json_object_get(blob->blob, "swap"));

	manager_event(EVENT_FLAG_CALL, "BridgeEnter",
		"%s"
		"%s"
		"%s%s%s",
		ast_str_buffer(bridge_text),
		ast_str_buffer(channel_text),
		swap_id ? swap_name : "",
		S_OR(swap_id, ""),
		swap_id ? "\r\n" : "");
}
Beispiel #9
0
static struct ast_event *alloc_event(const struct ast_security_event_common *sec)
{
	struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
	struct timeval tv = ast_tvnow();
	const char *severity_str;

	if (check_event_type(sec->event_type)) {
		return NULL;
	}

	encode_timestamp(&str, &tv);

	severity_str = S_OR(
		ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
		"Unknown"
	);

	return ast_event_new(AST_EVENT_SECURITY,
		AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type,
		AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version,
		AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, ast_str_buffer(str),
		AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service,
		AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str,
		AST_EVENT_IE_END);
}
Beispiel #10
0
static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf)
{
	RAII_VAR(struct ast_variable *, objset, ast_sorcery_objectset_create2(
			 ast_sip_get_sorcery(), aor, AST_HANDLER_ONLY_STRING), ast_variables_destroy);
	struct ast_variable *i;

	if (!objset) {
		return -1;
	}

	ast_str_append(buf, 0, "ObjectType: %s\r\n",
		       ast_sorcery_object_get_type(aor));
	ast_str_append(buf, 0, "ObjectName: %s\r\n",
		       ast_sorcery_object_get_id(aor));

	for (i = objset; i; i = i->next) {
		char *camel = ast_to_camel_case(i->name);
		if (strcmp(camel, "Contact") == 0) {
			ast_free(camel);
			camel = NULL;
		}
		ast_str_append(buf, 0, "%s: %s\r\n", S_OR(camel, "Contacts"), i->value);
		ast_free(camel);
	}

	return 0;
}
/*
   Copyright (C) 2010
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */

#include "dc_config.h"
#include <asterisk/callerid.h>				/* ast_parse_caller_presentation() */

static struct ast_jb_conf jbconf_default = 
{
	.flags			= 0,
	.max_size		= -1,
	.resync_threshold	= -1,
	.impl			= "",
	.target_extra		= -1,
};


static const char * const dtmf_values[] = { "off", "inband", "relax" };

EXPORT_DEF int dc_dtmf_str2setting(const char * value)
{
    return str2enum(value, dtmf_values, ITEMS_OF(dtmf_values));
}

EXPORT_DEF const char * dc_dtmf_setting2str(dc_dtmf_setting_t dtmf)
{
	return enum2str(dtmf, dtmf_values, ITEMS_OF(dtmf_values));
}

#/* assume config is zerofill */
static int dc_uconfig_fill(struct ast_config * cfg, const char * cat, struct dc_uconfig * config)
{
	const char * audio_tty;
	const char * data_tty;
	const char * imei;
	const char * imsi;

	audio_tty = ast_variable_retrieve (cfg, cat, "audio");
	data_tty  = ast_variable_retrieve (cfg, cat, "data");
	imei = ast_variable_retrieve (cfg, cat, "imei");
	imsi = ast_variable_retrieve (cfg, cat, "imsi");

	if(imei && strlen(imei) != IMEI_SIZE) {
		ast_log (LOG_WARNING, "[%s] Ignore invalid IMEI value '%s'\n", cat, imei);
		imei = NULL;
		}
	if(imsi && strlen(imsi) != IMSI_SIZE) {
		ast_log (LOG_WARNING, "[%s] Ignore invalid IMSI value '%s'\n", cat, imsi);
		imsi = NULL;
		}

	if(!audio_tty && !imei && !imsi)
	{
		ast_log (LOG_ERROR, "Skipping device %s. Missing required audio_tty setting\n", cat);
		return 1;
	}

	if(!data_tty && !imei && !imsi)
	{
		ast_log (LOG_ERROR, "Skipping device %s. Missing required data_tty setting\n", cat);
		return 1;
	}

	if((!data_tty && audio_tty) || (data_tty && !audio_tty))
	{
		ast_log (LOG_ERROR, "Skipping device %s. data_tty and audio_tty should use together\n", cat);
		return 1;
	}

	ast_copy_string (config->id,		cat,	             sizeof (config->id));
	ast_copy_string (config->data_tty,	S_OR(data_tty, ""),  sizeof (config->data_tty));
	ast_copy_string (config->audio_tty,	S_OR(audio_tty, ""), sizeof (config->audio_tty));
	ast_copy_string (config->imei,		S_OR(imei, ""),	     sizeof (config->imei));
	ast_copy_string (config->imsi,		S_OR(imsi, ""),	     sizeof (config->imsi));

	return 0;
}
Beispiel #12
0
struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func)
{
	if (ast_strlen_zero(name)) {
		return NULL;
	}

	return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func);
}
Beispiel #13
0
static void process_section(bfd *bfdobj, asection *section, void *obj)
{
	struct bfd_data *data = obj;
	const char *file, *func;
	unsigned int line;
	bfd_vma offset;
	bfd_vma vma;
	bfd_size_type size;
	bfd_boolean line_found = 0;
	char *fn;
	int inlined = 0;

	offset = data->pc - (data->dynamic ? (bfd_vma)(uintptr_t) data->dli.dli_fbase : 0);

	if (!(bfd_get_section_flags(bfdobj, section) & SEC_ALLOC)) {
		return;
	}

	vma = bfd_get_section_vma(bfdobj, section);
	size = bfd_get_section_size(section);

	if (offset < vma || offset >= vma + size) {
		/* Not in this section */
		return;
	}

	line_found = bfd_find_nearest_line(bfdobj, section, data->syms, offset - vma, &file,
		&func, &line);
	if (!line_found) {
		return;
	}

	/*
	 * If we find a line, we will want to continue calling bfd_find_inliner_info
	 * to capture any inlined functions that don't have their own stack frames.
	 */
	do {
		data->found++;
		/* file can possibly be null even with a success result from bfd_find_nearest_line */
		file = file ? file : "";
		fn = strrchr(file, '/');
#define FMT_INLINED     "[%s] %s %s:%u %s()"
#define FMT_NOT_INLINED "[%p] %s %s:%u %s()"

		snprintf(data->msg, MSG_BUFF_LEN, inlined ? FMT_INLINED : FMT_NOT_INLINED,
			inlined ? "inlined" : (char *)(uintptr_t) data->pc,
			data->libname,
			fn ? fn + 1 : file,
			line, S_OR(func, "???"));

		if (AST_VECTOR_APPEND(data->return_strings, strdup(data->msg))) {
			return;
		}

		inlined++;
		/* Let's see if there are any inlined functions */
	} while (bfd_find_inliner_info(bfdobj, &file, &func, &line));
}
Beispiel #14
0
const char *ast_cel_get_ama_flag_name(enum ast_cel_ama_flag flag)
{
	if (flag < 0 || flag >= ARRAY_LEN(cel_ama_flags)) {
		ast_log(LOG_WARNING, "Invalid AMA flag: %d\n", flag);
		return "Unknown";
	}

	return S_OR(cel_ama_flags[flag], "Unknown");
}
Beispiel #15
0
/*!
 * \internal \brief Handle reading RTP information
 */
static int channel_read_rtp(struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
{
	struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
	struct chan_pjsip_pvt *pvt;
	struct ast_sip_session_media *media = NULL;
	struct ast_sockaddr addr;

	if (!channel) {
		ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
		return -1;
	}

	pvt = channel->pvt;
	if (!pvt) {
		ast_log(AST_LOG_WARNING, "Channel %s has no chan_pjsip pvt!\n", ast_channel_name(chan));
		return -1;
	}

	if (ast_strlen_zero(type)) {
		ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtp' information\n");
		return -1;
	}

	if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
		media = pvt->media[SIP_MEDIA_AUDIO];
	} else if (!strcmp(field, "video")) {
		media = pvt->media[SIP_MEDIA_VIDEO];
	} else {
		ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtp' information\n", field);
		return -1;
	}

	if (!media || !media->rtp) {
		ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
			ast_channel_name(chan), S_OR(field, "audio"));
		return -1;
	}

	if (!strcmp(type, "src")) {
		ast_rtp_instance_get_local_address(media->rtp, &addr);
		ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
	} else if (!strcmp(type, "dest")) {
		ast_rtp_instance_get_remote_address(media->rtp, &addr);
		ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
	} else if (!strcmp(type, "direct")) {
		ast_copy_string(buf, ast_sockaddr_stringify(&media->direct_media_addr), buflen);
	} else if (!strcmp(type, "secure")) {
		snprintf(buf, buflen, "%d", media->srtp ? 1 : 0);
	} else if (!strcmp(type, "hold")) {
		snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0);
	} else {
		ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);
		return -1;
	}

	return 0;
}
Beispiel #16
0
int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority)
{
    struct stasis_app_control_continue_data *continue_data;

    if (!(continue_data = ast_calloc(1, sizeof(*continue_data)))) {
        return -1;
    }
    ast_copy_string(continue_data->context, S_OR(context, ""), sizeof(continue_data->context));
    ast_copy_string(continue_data->extension, S_OR(extension, ""), sizeof(continue_data->extension));
    if (priority > 0) {
        continue_data->priority = priority;
    } else {
        continue_data->priority = -1;
    }

    stasis_app_send_command_async(control, app_control_continue, continue_data);

    return 0;
}
Beispiel #17
0
/*!
 * \brief Callback handler for Stasis application messages.
 *
 * \internal
 *
 * \param data      Void pointer to the event session (\ref event_session).
 * \param app_name  Name of the Stasis application that dispatched the message.
 * \param message   The dispatched message.
 */
static void stasis_app_message_handler(
		void *data, const char *app_name, struct ast_json *message)
{
	struct event_session *session = data;
	const char *msg_type, *msg_application;

	ast_assert(session != NULL);

	ao2_lock(session);

	msg_type = S_OR(ast_json_string_get(ast_json_object_get(message, "type")), "");
	msg_application = S_OR(
		ast_json_string_get(ast_json_object_get(message, "application")), "");

	/* If we've been replaced, remove the application from our local
	   websocket_apps container */
	if (strcmp(msg_type, "ApplicationReplaced") == 0 &&
		strcmp(msg_application, app_name) == 0) {
		ao2_find(session->websocket_apps, msg_application,
			OBJ_UNLINK | OBJ_NODATA);
	}

	/* Now, we need to determine our state to see how we will handle the message */
	if (ast_json_object_set(message, "application", ast_json_string_create(app_name))) {
		/* We failed to add an application element to our json message */
		ast_log(LOG_WARNING,
		        "Failed to dispatch '%s' message from Stasis app '%s'; could not update message\n",
		        msg_type,
		        msg_application);
	} else if (!session->ws_session) {
			/* If the websocket is NULL, the message goes to the queue */
			AST_VECTOR_APPEND(&session->message_queue, message);
			ast_log(LOG_WARNING,
			        "Queued '%s' message for Stasis app '%s'; websocket is not ready\n",
			        msg_type,
			        msg_application);
	} else {
		/* We are ready to publish the message */
		ast_ari_websocket_session_write(session->ws_session, message);
	}

	ao2_unlock(session);
}
Beispiel #18
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;
}
Beispiel #19
0
/*!
 * \internal
 * \brief Converts a pjsip_rx_data structure to an ast_msg structure.
 *
 * \details Attempts to fill in as much information as possible into the given
 * msg structure copied from the given request data.
 *
 * \param rdata The SIP request
 * \param msg The asterisk message structure to fill in.
 */
static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct ast_msg *msg)
{

#define CHECK_RES(z_) do { if (z_) { ast_msg_destroy(msg); \
		return PJSIP_SC_INTERNAL_SERVER_ERROR; } } while (0)

	int size;
	char buf[MAX_BODY_SIZE];
	pjsip_name_addr *name_addr;
	const char *field;
	pjsip_status_code code;
	struct ast_sip_endpoint *endpt = ast_pjsip_rdata_get_endpoint(rdata);
	const char *context = S_OR(endpt->message_context, endpt->context);

	/* make sure there is an appropriate context and extension*/
	if ((code = get_destination(rdata, context, buf)) != PJSIP_SC_OK) {
		return code;
	}

	CHECK_RES(ast_msg_set_context(msg, "%s", context));
	CHECK_RES(ast_msg_set_exten(msg, "%s", buf));

	/* to header */
	name_addr = (pjsip_name_addr *)rdata->msg_info.to->uri;
	if ((size = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, name_addr, buf, sizeof(buf)-1)) > 0) {
		buf[size] = '\0';
		/* prepend the tech */
		CHECK_RES(ast_msg_set_to(msg, "%s", sip_to_pjsip(buf, ++size, sizeof(buf)-1)));
	}

	/* from header */
	name_addr = (pjsip_name_addr *)rdata->msg_info.from->uri;
	if ((size = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, name_addr, buf, sizeof(buf)-1)) > 0) {
		buf[size] = '\0';
		CHECK_RES(ast_msg_set_from(msg, "%s", buf));
	}

	/* receive address */
	field = pj_sockaddr_print(&rdata->pkt_info.src_addr, buf, sizeof(buf)-1, 1);
	CHECK_RES(ast_msg_set_var(msg, "PJSIP_RECVADDR", field));

	/* body */
	if (print_body(rdata, buf, sizeof(buf) - 1) > 0) {
		CHECK_RES(ast_msg_set_body(msg, "%s", buf));
	}

	/* endpoint name */
	if (endpt->id.self.name.valid) {
		CHECK_RES(ast_msg_set_var(msg, "PJSIP_PEERNAME", endpt->id.self.name.str));
	}

	CHECK_RES(headers_to_vars(rdata, msg));

	return PJSIP_SC_OK;
}
/*! \brief Create a call structure */
static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *cap)
{
	struct local_pvt *pvt;
	char *parse;
	char *context;
	char *opts;

	pvt = (struct local_pvt *) ast_unreal_alloc(sizeof(*pvt), local_pvt_destructor, cap);
	if (!pvt) {
		return NULL;
	}
	pvt->base.callbacks = &local_unreal_callbacks;

	parse = ast_strdupa(data);

	/*
	 * Local channels intercept MOH by default.
	 *
	 * This is a silly default because it represents state held by
	 * the local channels.  Unless local channel optimization is
	 * disabled, the state will dissapear when the local channels
	 * optimize out.
	 */
	ast_set_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);

	/* Look for options */
	if ((opts = strchr(parse, '/'))) {
		*opts++ = '\0';
		if (strchr(opts, 'n')) {
			ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
		}
		if (strchr(opts, 'j')) {
			if (ast_test_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION)) {
				ast_set_flag(&pvt->base.jb_conf, AST_JB_ENABLED);
			} else {
				ast_log(LOG_ERROR, "You must use the 'n' option with the 'j' option to enable the jitter buffer\n");
			}
		}
		if (strchr(opts, 'm')) {
			ast_clear_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);
		}
	}

	/* Look for a context */
	if ((context = strchr(parse, '@'))) {
		*context++ = '\0';
	}

	ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
	ast_copy_string(pvt->exten, parse, sizeof(pvt->exten));
	snprintf(pvt->base.name, sizeof(pvt->base.name), "%s@%s", pvt->exten, pvt->context);

	return pvt; /* this is returned with a ref */
}
Beispiel #21
0
static int manager_park(struct mansession *s, const struct message *m)
{
	const char *channel = astman_get_header(m, "Channel");
	const char *timeout_channel = S_OR(astman_get_header(m, "TimeoutChannel"), astman_get_header(m, "Channel2"));
	const char *timeout = astman_get_header(m, "Timeout");
	const char *parkinglot = astman_get_header(m, "Parkinglot");
	char buf[BUFSIZ];
	int timeout_override = -1;

	RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
	RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);

	if (ast_strlen_zero(channel)) {
		astman_send_error(s, m, "Channel not specified");
		return 0;
	}

	if (!ast_strlen_zero(timeout)) {
		if (sscanf(timeout, "%30d", &timeout_override) != 1 || timeout < 0) {
			astman_send_error(s, m, "Invalid Timeout value.");
			return 0;
		}

		if (timeout_override > 0) {
			/* If greater than zero, convert to seconds for internal use. Must be >= 1 second. */
			timeout_override = MAX(1, timeout_override / 1000);
		}
	}

	if (!(chan = ast_channel_get_by_name(channel))) {
		snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
		astman_send_error(s, m, buf);
		return 0;
	}

	ast_channel_lock(chan);
	if (!ast_strlen_zero(timeout_channel)) {
		pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", timeout_channel);
	}
	ast_channel_unlock(chan);

	if (!(parking_bridge = park_common_setup(chan, chan, parkinglot, NULL, 0, 0, timeout_override, 0))) {
		astman_send_error(s, m, "Park action failed\n");
		return 0;
	}

	if (ast_bridge_add_channel(parking_bridge, chan, NULL, 0, NULL)) {
		astman_send_error(s, m, "Park action failed\n");
		return 0;
	}

	astman_send_ack(s, m, "Park successful\n");
	return 0;
}
Beispiel #22
0
/*!
 * \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);
}
Beispiel #23
0
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str,
			 int flags, int family)
{
	struct addrinfo hints, *res, *ai;
	char *s, *host, *port;
	int	e, i, res_cnt;

	if (!str) {
		return 0;
	}

	s = ast_strdupa(str);
	if (!ast_sockaddr_split_hostport(s, &host, &port, flags)) {
		return 0;
	}

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = family;
	hints.ai_socktype = SOCK_DGRAM;

	if ((e = getaddrinfo(host, port, &hints, &res))) {
		ast_log(LOG_ERROR, "getaddrinfo(\"%s\", \"%s\", ...): %s\n",
			host, S_OR(port, "(null)"), gai_strerror(e));
		return 0;
	}

	res_cnt = 0;
	for (ai = res; ai; ai = ai->ai_next) {
		res_cnt++;
	}

	if (res_cnt == 0) {
		goto cleanup;
	}

	if ((*addrs = ast_malloc(res_cnt * sizeof(struct ast_sockaddr))) == NULL) {
		res_cnt = 0;
		goto cleanup;
	}

	i = 0;
	for (ai = res; ai; ai = ai->ai_next) {
		(*addrs)[i].len = ai->ai_addrlen;
		memcpy(&(*addrs)[i].ss, ai->ai_addr, ai->ai_addrlen);
		++i;
	}

cleanup:
	freeaddrinfo(res);
	return res_cnt;
}
Beispiel #24
0
/*!
 * \brief Performs common setup for a bridge playback operation
 * with both new controls and when existing controls are  found.
 *
 * \param args_media medias to play
 * \param args_media_count number of media items in \c media
 * \param args_lang language string split from arguments
 * \param args_offset_ms milliseconds offset split from arguments
 * \param args_playback_id string to use for playback split from
 *        arguments (null valid)
 * \param response ARI response being built
 * \param bridge Bridge the playback is being peformed on
 * \param control Control being used for the playback channel
 * \param json contents of the response to ARI
 * \param playback_url stores playback URL for use with response
 *
 * \retval -1 operation failed
 * \retval operation was successful
 */
static int ari_bridges_play_helper(const char **args_media,
	size_t args_media_count,
	const char *args_lang,
	int args_offset_ms,
	int args_skipms,
	const char *args_playback_id,
	struct ast_ari_response *response,
	struct ast_bridge *bridge,
	struct stasis_app_control *control,
	struct ast_json **json,
	char **playback_url)
{
	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);

	const char *language;

	snapshot = stasis_app_control_get_snapshot(control);
	if (!snapshot) {
		ast_ari_response_error(
			response, 500, "Internal Error", "Failed to get control snapshot");
		return -1;
	}

	language = S_OR(args_lang, snapshot->language);

	playback = stasis_app_control_play_uri(control, args_media, args_media_count,
		language, bridge->uniqueid, STASIS_PLAYBACK_TARGET_BRIDGE, args_skipms,
		args_offset_ms, args_playback_id);

	if (!playback) {
		ast_ari_response_alloc_failed(response);
		return -1;
	}

	if (ast_asprintf(playback_url, "/playbacks/%s",
			stasis_app_playback_get_id(playback)) == -1) {
		playback_url = NULL;
		ast_ari_response_alloc_failed(response);
		return -1;
	}

	*json = stasis_app_playback_to_json(playback);
	if (!*json) {
		ast_ari_response_alloc_failed(response);
		return -1;
	}

	return 0;
}
Beispiel #25
0
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
{
	struct addrinfo hints;
	struct addrinfo	*res;
	char *s;
	char *host;
	char *port;
	int	e;

	s = ast_strdupa(str);
	if (!ast_sockaddr_split_hostport(s, &host, &port, flags)) {
		return 0;
	}

	memset(&hints, 0, sizeof(hints));
	/* Hint to get only one entry from getaddrinfo */
	hints.ai_socktype = SOCK_DGRAM;

#ifdef AI_NUMERICSERV
	hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
#else
	hints.ai_flags = AI_NUMERICHOST;
#endif
	if ((e = getaddrinfo(host, port, &hints, &res))) {
		if (e != EAI_NONAME) { /* if this was just a host name rather than a ip address, don't print error */
			ast_log(LOG_ERROR, "getaddrinfo(\"%s\", \"%s\", ...): %s\n",
				host, S_OR(port, "(null)"), gai_strerror(e));
		}
		return 0;
	}

	/*
	 * I don't see how this could be possible since we're not resolving host
	 * names. But let's be careful...
	 */
	if (res->ai_next != NULL) {
		ast_log(LOG_WARNING, "getaddrinfo() returned multiple "
			"addresses. Ignoring all but the first.\n");
	}

	if (addr) {
		addr->len = res->ai_addrlen;
		memcpy(&addr->ss, res->ai_addr, addr->len);
	}

	freeaddrinfo(res);

	return 1;
}
static int end_session(struct respoke_session *session, enum respoke_status status, const struct respoke_message *message)
{
	const char *endpoint, *type, *app;

	if (!session->channel) {
		return 0;
	}

	endpoint = respoke_message_redirected_endpoint_get(message);
	type = respoke_message_redirected_type_get(message);
	app = respoke_message_redirected_app_get(message);

	if (!ast_strlen_zero(endpoint) && !ast_strlen_zero(app)) {
		if (session->endpoint->redirect == RESPOKE_REDIRECT_INTERNAL) {
			char id[AST_UUID_STR_LEN];

			/* Since we are changing the session-id and because offer adds this session
			 * to the sessions container we need to unlink it now, which bye does
			 */
			respoke_session_bye(session, RESPOKE_STATUS_REDIRECTING);
			session->terminated = 0;

			ast_string_field_set(session, remote, endpoint);
			ast_string_field_set(session, remote_type, S_OR(type, "web"));
			ast_string_field_set(session, remote_appid, app);
			ast_string_field_set(session, remote_connection, "");
			ast_string_field_set(session, session_id, ast_uuid_generate_str(id, sizeof(id)));

			/* Send a new offer out to the new target, without the caller being any the wiser */
			if (!respoke_session_offer(session)) {
				return 0;
			}

			session->terminated = 1;
		} else if (session->endpoint->redirect == RESPOKE_REDIRECT_CORE) {
			ast_channel_call_forward_build(session->channel, "Respoke/%s/%s@%s", ast_sorcery_object_get_id(session->endpoint),
				endpoint, app);
		}
	}

	ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
	if (!ast_channel_hangupcause(session->channel)) {
		int cause = hangup_reason_to_cause(status);
		ast_queue_hangup_with_cause(session->channel, cause);
	} else {
		ast_queue_hangup(session->channel);
	}
	return 0;
}
Beispiel #27
0
static int pgsql_reconnect(const char *database)
{
	char my_database[50];

	ast_copy_string(my_database, S_OR(database, dbname), sizeof(my_database));

	/* mutex lock should have been locked before calling this function. */

	if (pgsqlConn && PQstatus(pgsqlConn) != CONNECTION_OK) {
		PQfinish(pgsqlConn);
		pgsqlConn = NULL;
	}

	if ((!pgsqlConn) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
		char *connInfo = NULL;
		unsigned int size = 100 + strlen(dbhost)
			+ strlen(dbuser)
			+ strlen(dbpass)
			+ strlen(my_database);
		
		if (!(connInfo = ast_malloc(size)))
			return 0;
		
		sprintf(connInfo, "host=%s port=%d dbname=%s user=%s password=%s",
					dbhost, dbport, my_database, dbuser, dbpass);
		ast_log(LOG_DEBUG, "%u connInfo=%s\n", size, connInfo);
		pgsqlConn = PQconnectdb(connInfo);
		ast_log(LOG_DEBUG, "%u connInfo=%s\n", size, connInfo);
		free(connInfo);
		connInfo = NULL;
		ast_log(LOG_DEBUG, "pgsqlConn=%p\n", pgsqlConn);
		if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
			ast_log(LOG_DEBUG, "Postgresql RealTime: Successfully connected to database.\n");
			connect_time = time(NULL);
			return 1;
		} else {
			ast_log(LOG_ERROR,
					"Postgresql RealTime: Failed to connect database server %s on %s. Check debug for more info.\n",
					dbname, dbhost);
			ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
					PQresultErrorMessage(NULL));
			return 0;
		}
	} else {
		ast_log(LOG_DEBUG, "Postgresql RealTime: Everything is fine.\n");
		return 1;
	}
}
Beispiel #28
0
int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
{
	SCOPED_AO2WRLOCK(lock, codecs);
	struct ast_codec *codec_new;

	/* Some types have specific requirements */
	if (codec->type == AST_MEDIA_TYPE_UNKNOWN) {
		ast_log(LOG_ERROR, "A media type must be specified for codec '%s'\n", codec->name);
		return -1;
	} else if (codec->type == AST_MEDIA_TYPE_AUDIO) {
		if (!codec->sample_rate) {
			ast_log(LOG_ERROR, "A sample rate must be specified for codec '%s' of type '%s'\n",
				codec->name, ast_codec_media_type2str(codec->type));
			return -1;
		}
	}

	codec_new = ao2_find(codecs, codec, OBJ_SEARCH_OBJECT | OBJ_NOLOCK);
	if (codec_new) {
		ast_log(LOG_ERROR, "A codec with name '%s' of type '%s' and sample rate '%u' is already registered\n",
			codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
		ao2_ref(codec_new, -1);
		return -1;
	}

	codec_new = ao2_t_alloc_options(sizeof(*codec_new), codec_dtor,
		AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
	if (!codec_new) {
		ast_log(LOG_ERROR, "Could not allocate a codec with name '%s' of type '%s' and sample rate '%u'\n",
			codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
		return -1;
	}
	*codec_new = *codec;
	codec_new->id = codec_id++;

	ao2_link_flags(codecs, codec_new, OBJ_NOLOCK);

	/* Once registered a codec can not be unregistered, and the module must persist until shutdown */
	ast_module_shutdown_ref(mod);

	ast_verb(2, "Registered '%s' codec '%s' at sample rate '%u' with id '%u'\n",
		ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->id);

	ao2_ref(codec_new, -1);

	return 0;
}
static int pgsql_reconnect(const char *database)
{
	char my_database[50];

	ast_copy_string(my_database, S_OR(database, dbname), sizeof(my_database));

	/* mutex lock should have been locked before calling this function. */

	if (pgsqlConn && PQstatus(pgsqlConn) != CONNECTION_OK) {
		PQfinish(pgsqlConn);
		pgsqlConn = NULL;
	}

	/* DB password can legitimately be 0-length */
	if ((!pgsqlConn) && (!ast_strlen_zero(dbhost) || !ast_strlen_zero(dbsock)) && !ast_strlen_zero(dbuser) && !ast_strlen_zero(my_database)) {
		struct ast_str *connInfo = ast_str_create(32);

		ast_str_set(&connInfo, 0, "host=%s port=%d dbname=%s user=%s",
			dbhost, dbport, my_database, dbuser);
		if (!ast_strlen_zero(dbpass))
			ast_str_append(&connInfo, 0, " password=%s", dbpass);

		ast_debug(1, "%u connInfo=%s\n", (unsigned int)connInfo->len, connInfo->str);
		pgsqlConn = PQconnectdb(connInfo->str);
		ast_debug(1, "%u connInfo=%s\n", (unsigned int)connInfo->len, connInfo->str);
		ast_free(connInfo);
		connInfo = NULL;

		ast_debug(1, "pgsqlConn=%p\n", pgsqlConn);
		if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
			ast_debug(1, "PostgreSQL RealTime: Successfully connected to database.\n");
			connect_time = time(NULL);
			return 1;
		} else {
			ast_log(LOG_ERROR,
					"PostgreSQL RealTime: Failed to connect database %s on %s: %s\n",
					dbname, dbhost, PQresultErrorMessage(NULL));
			return 0;
		}
	} else {
		ast_debug(1, "PostgreSQL RealTime: One or more of the parameters in the config does not pass our validity checks.\n");
		return 1;
	}
}
static int process_config(int reload)
{
	struct ast_config *config;
	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
	const char *bindaddr;
	const char *bindport;
	const char *prefix;
	const char *enabled;

	config = ast_config_load("http.conf", config_flags);
	if (!config || config == CONFIG_STATUS_FILEINVALID) {
		return -1;
	} else if (config == CONFIG_STATUS_FILEUNCHANGED) {
		return 0;
	}

	enabled = ast_config_option(config, "general", "enabled");
	if (!enabled || ast_false(enabled)) {
		ast_config_destroy(config);
		return -1;
	}

	/* Construct our Server URI */
	bindaddr = ast_config_option(config, "general", "bindaddr");
	if (!bindaddr) {
		ast_config_destroy(config);
		return -1;
	}

	bindport = ast_config_option(config, "general", "bindport");
	if (!bindport) {
		bindport = "8088";
	}

	prefix = ast_config_option(config, "general", "prefix");

	snprintf(server_uri, sizeof(server_uri), "http://%s:%s%s/%s", bindaddr, bindport, S_OR(prefix, ""), TEST_URI);

	ast_config_destroy(config);

	return 0;
}