示例#1
0
/*!
 * \internal
 * \brief Send the peer channel on its way on bridge start failure.
 * \since 12.0.0
 *
 * \param chan Chan to put into autoservice.
 * \param peer Chan to send to after bridge goto or run hangup handlers and hangup.
 *
 * \return Nothing
 */
static void bridge_failed_peer_goto(struct ast_channel *chan, struct ast_channel *peer)
{
	if (ast_bridge_setup_after_goto(peer)
		|| ast_pbx_start(peer)) {
		ast_autoservice_chan_hangup_peer(chan, peer);
	}
}
示例#2
0
static int offer_session(struct respoke_session *session)
{
	if (session->channel) {
		return 0;
	}

	if (!(session->channel = channel_create(session, AST_STATE_RING,
		      respoke_session_get_exten(session), NULL, NULL))) {
		return -1;
	}

	switch (ast_pbx_start(session->channel)) {
	case AST_PBX_CALL_LIMIT:
		ast_log(LOG_WARNING, "PBX call limit reached\n");
	case AST_PBX_FAILED:
		ast_log(LOG_WARNING, "Failed to start PBX\n");
		ast_channel_hangupcause_set(session->channel, AST_CAUSE_SWITCH_CONGESTION);
		ast_hangup(session->channel);
		return -1;
	case AST_PBX_SUCCESS:
		break;
	}

	ast_debug(3, "Started PBX on new RESPOKE channel %s\n",
		  ast_channel_name(session->channel));

	return 0;
}
示例#3
0
static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *context)
{
	struct ast_channel *tmp;
	tmp = ast_channel_alloc(1);
	if (tmp) {
		snprintf(tmp->name, sizeof(tmp->name), "Phone/%s", i->dev + 5);
		tmp->type = type;
		tmp->fds[0] = i->fd;
		/* XXX Switching formats silently causes kernel panics XXX */
		tmp->nativeformats = prefformat;
		tmp->pvt->rawreadformat = prefformat;
		tmp->pvt->rawwriteformat = prefformat;
		ast_setstate(tmp, state);
		if (state == AST_STATE_RING)
			tmp->rings = 1;
		tmp->pvt->pvt = i;
		tmp->pvt->send_digit = phone_digit;
		tmp->pvt->call = phone_call;
		tmp->pvt->hangup = phone_hangup;
		tmp->pvt->answer = phone_answer;
		tmp->pvt->read = phone_read;
		tmp->pvt->write = phone_write;
		tmp->pvt->exception = phone_exception;
		strncpy(tmp->context, context, sizeof(tmp->context)-1);
		if (strlen(i->ext))
			strncpy(tmp->exten, i->ext, sizeof(tmp->exten)-1);
		else
			strncpy(tmp->exten, "s",  sizeof(tmp->exten) - 1);
		if (strlen(i->language))
			strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
		if (strlen(i->callerid))
			tmp->callerid = strdup(i->callerid);
		i->owner = tmp;
		ast_mutex_lock(&usecnt_lock);
		usecnt++;
		ast_mutex_unlock(&usecnt_lock);
		ast_update_use_count();
		if (state != AST_STATE_DOWN) {
			if (state == AST_STATE_RING) {
				ioctl(tmp->fds[0], PHONE_RINGBACK);
				i->cpt = 1;
			}
			if (ast_pbx_start(tmp)) {
				ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
				ast_hangup(tmp);
			}
		}
	} else
		ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
	return tmp;
}
示例#4
0
static inline int at_response_clip (pvt_t* pvt, char* str, size_t len)
{
	struct ast_channel*	channel;
	char*			clip;

	if (pvt->initialized && pvt->has_voice && pvt->needring == 0)
	{
		pvt->incoming = 1;

		if ((clip = at_parse_clip (pvt, str, len)) == NULL)
		{
			ast_log (LOG_ERROR, "[%s] Error parsing CLIP: %s\n", pvt->id, str);
		}

		// pvt->number ? pvt->number : pvt->exten???
		if (!(channel = channel_new (pvt, AST_STATE_RING, clip, pvt->number ? pvt->number : NULL, NULL)))
		{
			ast_log (LOG_ERROR, "[%s] Unable to allocate channel for incoming call\n", pvt->id);

			if (at_send_chup (pvt) || at_fifo_queue_add (pvt, CMD_AT_CHUP, RES_OK))
			{
				ast_log (LOG_ERROR, "[%s] Error sending AT+CHUP command\n", pvt->id);
			}

			return -1;
		}

		pvt->needchup = 1;
		pvt->needring = 1;

		if (ast_pbx_start (channel))
		{
			ast_log (LOG_ERROR, "[%s] Unable to start pbx on incoming call\n", pvt->id);
			channel_ast_hangup (pvt);

			return -1;
		}
	}

	return 0;
}
示例#5
0
/*! \brief Initiate new call, part of PBX interface
 *         dest is the dial string */
static int local_call(struct ast_channel *ast, const char *dest, int timeout)
{
	struct local_pvt *p = ast_channel_tech_pvt(ast);
	int pvt_locked = 0;

	struct ast_channel *owner = NULL;
	struct ast_channel *chan = NULL;
	int res;
	char *reduced_dest = ast_strdupa(dest);
	char *slash;
	const char *chan_cid;

	if (!p) {
		return -1;
	}

	/* since we are letting go of channel locks that were locked coming into
	 * this function, then we need to give the tech pvt a ref */
	ao2_ref(p, 1);
	ast_channel_unlock(ast);

	ast_unreal_lock_all(&p->base, &chan, &owner);
	pvt_locked = 1;

	if (owner != ast) {
		res = -1;
		goto return_cleanup;
	}

	if (!owner || !chan) {
		res = -1;
		goto return_cleanup;
	}

	ast_unreal_call_setup(owner, chan);

	/*
	 * If the local channel has /n on the end of it, we need to lop
	 * that off for our argument to setting up the CC_INTERFACES
	 * variable.
	 */
	if ((slash = strrchr(reduced_dest, '/'))) {
		*slash = '\0';
	}
	ast_set_cc_interfaces_chanvar(chan, reduced_dest);

	ao2_unlock(p);
	pvt_locked = 0;

	ast_channel_unlock(owner);

	chan_cid = S_COR(ast_channel_caller(chan)->id.number.valid,
		ast_channel_caller(chan)->id.number.str, NULL);
	if (chan_cid) {
		chan_cid = ast_strdupa(chan_cid);
	}
	ast_channel_unlock(chan);

	res = -1;
	switch (p->type) {
	case LOCAL_CALL_ACTION_DIALPLAN:
		if (!ast_exists_extension(NULL, p->context, p->exten, 1, chan_cid)) {
			ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
				p->exten, p->context);
		} else {
			publish_local_bridge_message(p);

			/* Start switch on sub channel */
			res = ast_pbx_start(chan);
		}
		break;
	case LOCAL_CALL_ACTION_BRIDGE:
		publish_local_bridge_message(p);
		ast_answer(chan);
		res = ast_bridge_impart(p->action.bridge.join, chan, p->action.bridge.swap,
			p->action.bridge.features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT);
		ao2_ref(p->action.bridge.join, -1);
		p->action.bridge.join = NULL;
		ao2_cleanup(p->action.bridge.swap);
		p->action.bridge.swap = NULL;
		p->action.bridge.features = NULL;
		break;
	case LOCAL_CALL_ACTION_MASQUERADE:
		publish_local_bridge_message(p);
		ast_answer(chan);
		res = ast_channel_move(p->action.masq, chan);
		if (!res) {
			/* Chan is now an orphaned zombie.  Destroy it. */
			ast_hangup(chan);
		}
		p->action.masq = ast_channel_unref(p->action.masq);
		break;
	}
	if (!res) {
		ao2_lock(p);
		ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
		ao2_unlock(p);
	}

	/* we already unlocked them, clear them here so the cleanup label won't touch them. */
	owner = ast_channel_unref(owner);
	chan = ast_channel_unref(chan);

return_cleanup:
	if (p) {
		if (pvt_locked) {
			ao2_unlock(p);
		}
		ao2_ref(p, -1);
	}
	if (chan) {
		ast_channel_unlock(chan);
		ast_channel_unref(chan);
	}

	/*
	 * owner is supposed to be == to ast, if it is, don't unlock it
	 * because ast must exit locked
	 */
	if (owner) {
		if (owner != ast) {
			ast_channel_unlock(owner);
			ast_channel_lock(ast);
		}
		ast_channel_unref(owner);
	} else {
		/* we have to exit with ast locked */
		ast_channel_lock(ast);
	}

	return res;
}
示例#6
0
static inline int at_response_cusd (pvt_t* pvt, char* str, size_t len)
{
	ssize_t		res;
	int		type;
	int		dcs;
	char*		text;
	char		text_utf8[1024];
	char		text_base64[8192];

	if (at_parse_cusd (pvt, str, len, &type, &text, &dcs))
	{
		ast_verb (1, "[%s] Error parsing CUSD: '%.*s'\n", pvt->id, (int) len, str);
		return 0;
	}

	if (pvt->ussd_use_ucs2_decoding)
	{
		res = conv_ucs2_8bit_hexstr_to_utf8 (text, strlen (text), text_utf8, sizeof (text_utf8));

		if (res > 0)
		{
			text = text_utf8;
		}
		else
		{
			ast_log (LOG_ERROR, "[%s] Error parsing CUSD (convert UCS-2 to UTF-8): %s\n", pvt->id, text);
			return -1;
		}
	}
	else
	{
		if (dcs == 0)
		{
			res = conv_latin1_8bit_hexstr_to_utf8 (text, strlen (text), text_utf8, sizeof (text_utf8));
		}
//		else if (dcs == 15)	// !!!!!
		else
		{
			res = conv_latin1_7bit_hexstr_to_utf8 (text, strlen (text), text_utf8, sizeof (text_utf8));
		}

		if (res > 0)
		{
			text = text_utf8;
		}
		else
		{
			ast_log (LOG_ERROR, "[%s] Error parsing CUSD (convert 8bit/7bit hexstring to UTF-8): %s\n", pvt->id, text);
			return -1;
		}
	}

	ast_verb (1, "[%s] Got USSD response: '%s'\n", pvt->id, text);
	ast_base64encode (text_base64, (unsigned char *) text, strlen (text), sizeof (text_base64));

#ifdef __MANAGER__
	manager_event_new_ussd		(pvt, text);
	manager_event_new_ussd_base64	(pvt, text_base64);
#endif

#ifdef __ALLOW_LOCAL_CHANNELS__
	struct ast_channel* channel;

	snprintf (pvt->d_send_buf, sizeof (pvt->d_send_buf), "ussd@%s", pvt->context);

	if (channel = channel_local_request (pvt, pvt->d_send_buf, pvt->id, "ussd"))
	{
		pbx_builtin_setvar_helper (channel, "USSD", text);
		pbx_builtin_setvar_helper (channel, "USSD_BASE64", text_base64);

		if (ast_pbx_start (channel))
		{
			ast_hangup (channel);
			ast_log (LOG_ERROR, "[%s] Unable to start pbx on incoming ussd\n", pvt->id);
		}
	}
#endif /* __ALLOW_LOCAL_CHANNELS__ */

	return 0;
}
示例#7
0
static inline int at_response_cmgr (pvt_t* pvt, char* str, size_t len)
{
	at_queue_t*	e;
	ssize_t		res;
	char*		from_number;
	char		from_number_utf8[1024];
	char*		text;
	char		text_utf8[1024];
	char		text_base64[8192];

	if ((e = at_fifo_queue_head (pvt)) && e->res == RES_CMGR)
	{
		if (pvt->auto_delete_sms && e->ptype == 1)
		{
			if (at_send_cmgd (pvt, e->param.num, 0) || at_fifo_queue_add (pvt, CMD_AT_CMGD, RES_OK))
			{
				ast_log (LOG_ERROR, "[%s] Error sending CMGD to delete SMS message\n", pvt->id);
			}
		}

		at_fifo_queue_rem (pvt);

		pvt->incoming_sms = 0;

		if (at_parse_cmgr (pvt, str, len, &from_number, &text))
		{
			ast_log (LOG_ERROR, "[%s] Error parsing SMS message, disconnecting\n", pvt->id);
			return 0;
		}

		ast_debug (1, "[%s] Successfully read SMS message\n", pvt->id);

		if (pvt->use_ucs2_encoding)
		{
			res = conv_ucs2_8bit_hexstr_to_utf8 (text, strlen (text), text_utf8, sizeof (text_utf8));

			if (res > 0)
			{
				text = text_utf8;
			}
			else
			{
				ast_log (LOG_ERROR, "[%s] Error parsing SMS (convert UCS-2 to UTF-8): %s\n", pvt->id, text);
			}

			res = conv_ucs2_8bit_hexstr_to_utf8 (from_number, strlen (from_number), from_number_utf8, sizeof (from_number_utf8));

			if (res > 0)
			{
				from_number = from_number_utf8;
			}
			else
			{
				ast_log (LOG_ERROR, "[%s] Error parsing SMS from_number (convert UCS-2 to UTF-8): %s\n", pvt->id, from_number);
			}
		}

		ast_base64encode (text_base64, (unsigned char *) text, strlen (text), sizeof (text_base64));
		ast_verb (1, "[%s] Got SMS from %s: '%s'\n", pvt->id, from_number, text);

#ifdef __MANAGER__
		manager_event_new_sms		(pvt, from_number, text);
		manager_event_new_sms_base64	(pvt, from_number, text_base64);
#endif

#ifdef __ALLOW_LOCAL_CHANNELS__
		struct ast_channel* channel;

		snprintf (pvt->d_send_buf, sizeof (pvt->d_send_buf), "sms@%s", pvt->context);

		if (channel = channel_local_request (pvt, pvt->d_send_buf, pvt->id, from_number))
		{
			pbx_builtin_setvar_helper (channel, "SMS",		text);
			pbx_builtin_setvar_helper (channel, "SMS_BASE64",	text_base64);

			if (ast_pbx_start (channel))
			{
				ast_hangup (channel);
				ast_log (LOG_ERROR, "[%s] Unable to start pbx on incoming sms\n", pvt->id);
			}
		}
#endif /* __ALLOW_LOCAL_CHANNELS__ */
	}
	else if (e)
	{
		ast_log (LOG_ERROR, "[%s] Received '+CMGR' when expecting '%s' response to '%s', ignoring\n", pvt->id,
				at_res2str (e->res), at_cmd2str (e->cmd));
	}
	else
	{
		ast_log (LOG_ERROR, "[%s] Received unexpected '+CMGR'\n", pvt->id);
	}

	return 0;
}
示例#8
0
/* Needs to be called with d->lock */
sccp_channel_t *
sccp_dev_allocate_channel(sccp_device_t * d, sccp_line_t * l, int outgoing, char * dial)
{
  sccp_channel_t * c = NULL;
  struct ast_channel * tmp = NULL;
  pthread_t t;
  int callId;

  if (!d->session) {
    ast_log(LOG_ERROR, "Tried to open channel on device without a session\n");
    return NULL;
  }

  // If there is no current line, then we can't make a call in, or out.
  if (!d->currentLine) {
    ast_log(LOG_ERROR, "Tried to open channel on a device with no selected line\n");
    return NULL;
  }

  if (l == NULL)
    l = d->currentLine;

  ast_mutex_lock(&callCountLock);
  callId = callCount++;
  ast_mutex_unlock(&callCountLock);

  c = malloc(sizeof(sccp_channel_t));
  memset(c, 0, sizeof(sccp_channel_t));
  c->callid = callId;
  c->line = l;

  ast_mutex_lock(&l->lock);
  l->channelCount++;
  ast_mutex_unlock(&l->lock);

  ast_log(LOG_DEBUG, "After: #Channel ->lnext = %p, c = %p, channels = %p\n", c->lnext, c, chans);
  tmp = sccp_new_channel(c, AST_STATE_OFFHOOK);
  ast_log(LOG_DEBUG, "New channel name is: %s\n", tmp->name);
  ast_log(LOG_DEBUG, "After: #Channel ->lnext = %p, c = %p, channels = %p\n", c->lnext, c, chans);

  ast_mutex_lock(&chanlock);
    c->lnext = chans;
    chans = c;
  ast_mutex_unlock(&chanlock);

  c->owner = tmp;

  c->next = l->channels;
  l->channels = c;
  l->activeChannel = c;

  if (outgoing) {

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    c->isOutgoing = 1;
    d->active_channel = c;

    ast_log(LOG_DEBUG, "After: #Channel ->lnext = %p, c = %p, channels = %p\n", c->lnext, c, chans);

    sccp_dev_set_speaker(d, StationSpeakerOn);
    sccp_channel_set_callstate(c, TsOffHook);
    sccp_dev_statusprompt_set(d, c, NULL, 0);
    sccp_dev_set_keyset(d, c, KEYMODE_OFFHOOK);
    sccp_dev_set_sptone(d, "InsideDialTone");

    if (dial) {

      strncpy(tmp->exten, dial, AST_MAX_EXTENSION);
      if (ast_pbx_start(tmp)) {
        ast_log(LOG_WARNING, "PBX exited non-zero\n");
        sccp_dev_statusprompt_set(l->device, c, "PBX Error", 10);
        sccp_dev_set_sptone(l->device, "ReorderTone");
        ast_indicate(tmp, AST_CONTROL_CONGESTION);
      }

  ast_log(LOG_DEBUG, "After: #Channel ->lnext = %p, c = %p, channels = %p\n", c->lnext, c, chans);

    } else if (pthread_create(&t, &attr, sccp_start_channel, tmp)) {
      ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
      ast_hangup(tmp);
      free(c);
      return NULL;
    }

  } else {

    // It's an incoming call.

  }

  ast_log(LOG_DEBUG, "After: #Channel ->lnext = %p, c = %p, chans = %p\n", c->lnext, c, chans);

  return c;
}