예제 #1
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;
}
예제 #2
0
void * sccp_pbx_startchannel(void *data) {
	struct cw_channel * chan = data;
	sccp_channel_t * c;
	sccp_line_t * l;
	sccp_device_t * d;
	uint8_t res_exten = 0, res_wait = 0, res_timeout = 0;

	c = CS_CW_CHANNEL_PVT(chan);
	if ( !c || !(l = c->line) || !(d = c->device) ) {
		cw_hangup(chan);
		return NULL;
	}

	sccp_log(1)( VERBOSE_PREFIX_3 "%s: New call on line %s\n", d->id, l->name);

	cw_mutex_lock(&c->lock);
	c->calltype = SKINNY_CALLTYPE_OUTBOUND;
	c->hangupok = 0;
	cw_mutex_unlock(&c->lock);
	
	sccp_channel_set_callingparty(c, l->cid_name, l->cid_num);

	if (!cw_strlen_zero(c->dialedNumber)) {
		/* we have a number to dial. Let's do it */
		sccp_log(10)( VERBOSE_PREFIX_3 "%s: Dialing %s on channel %s-%d\n", l->device->id, c->dialedNumber, l->name, c->callid);
		sccp_channel_set_calledparty(c, c->dialedNumber, c->dialedNumber);
		sccp_indicate_lock(c, SCCP_CHANNELSTATE_DIALING);
		goto dial;
	}

	/* we have to collect the number */
	/* the phone is on TsOffHook state */
	sccp_log(10)( VERBOSE_PREFIX_3 "%s: Waiting for the number to dial on channel %s-%d\n", l->device->id, l->name, c->callid);
	/* let's use the keypad to collect digits */
	cw_mutex_lock(&c->lock);
	c->digittimeout = time(0)+GLOB(firstdigittimeout);
	cw_mutex_unlock(&c->lock);

	res_exten = 1;

	do {
		pthread_testcancel();
		usleep(100);
		cw_mutex_lock(&c->lock);
		if (!cw_strlen_zero(c->dialedNumber)) {
			res_exten = (c->dialedNumber[0] == '*' || cw_matchmore_extension(chan, chan->context, c->dialedNumber, 1, l->cid_num));
		}
		if (! (res_wait = ( c->state == SCCP_CHANNELSTATE_DOWN || chan->_state == CW_STATE_DOWN
							|| chan->_softhangup || c->calltype == SKINNY_CALLTYPE_INBOUND)) ) {
			if (CS_CW_CHANNEL_PVT(chan)) {
				res_timeout = (time(0) < c->digittimeout);
			} else
				res_timeout = 0;
		}
		cw_mutex_unlock(&c->lock);
	} while ( (res_wait == 0) && res_exten &&  res_timeout);

	if (res_wait != 0) {
		/* CW_STATE_DOWN or softhangup */
		sccp_log(10)(VERBOSE_PREFIX_3 "%s: return from the startchannel for DOWN, HANGUP or PICKUP cause\n", l->device->id);
		cw_mutex_lock(&c->lock);
		c->hangupok = 1;
		cw_mutex_unlock(&c->lock);
		return NULL;
	}

dial:

	cw_mutex_lock(&c->lock);
	cw_copy_string(chan->exten, c->dialedNumber, sizeof(chan->exten));
	cw_copy_string(d->lastNumber, c->dialedNumber, sizeof(d->lastNumber));
	sccp_channel_set_calledparty(c, c->dialedNumber, c->dialedNumber);
	/* proceed call state is needed to display the called number.
	The phone will not display callinfo in offhook state */
	sccp_channel_set_callstate(c, SKINNY_CALLSTATE_PROCEED);
	sccp_channel_send_callinfo(c);
	sccp_dev_clearprompt(d,c->line->instance, c->callid);
	sccp_dev_displayprompt(d, c->line->instance, c->callid, SKINNY_DISP_CALL_PROCEED, 0);
	c->hangupok = 1;
	cw_mutex_unlock(&c->lock);

	if ( !cw_strlen_zero(c->dialedNumber)
			&& cw_exists_extension(chan, chan->context, c->dialedNumber, 1, l->cid_num) ) {
		/* found an extension, let's dial it */
		sccp_log(10)(VERBOSE_PREFIX_3 "%s: channel %s-%d is dialing number %s\n", l->device->id, l->name, c->callid, c->dialedNumber);
		/* Answer dialplan command works only when in RINGING OR RING cw_state */
		sccp_cw_setstate(c, CW_STATE_RING);
		if (cw_pbx_run(chan)) {
			sccp_indicate_lock(c, SCCP_CHANNELSTATE_INVALIDNUMBER);
		}
	} else {
		/* timeout and no extension match */
		sccp_indicate_lock(c, SCCP_CHANNELSTATE_INVALIDNUMBER);
	}
	sccp_log(10)(VERBOSE_PREFIX_3 "%s: return from the startchannel on exit\n", l->device->id);
	return NULL;
}