static void event1(struct pri *pri, pri_event *e)
{
	/* Network */
	int x;
	static q931_call *calls[TEST_CALLS];
	char name[256], num[256], dest[256];
	switch(e->gen.e) {
	case PRI_EVENT_DCHAN_UP:
		printf("Network is up.  Sending blast of calls!\n");
		for (x=0;x<TEST_CALLS;x++) {
			sprintf(name, "Caller %d", x + 1);
			sprintf(num, "25642860%02d", x+1);
			sprintf(dest, "60%02d", x + 1);
			if (!(calls[x] = pri_new_call(pri))) {
				perror("pri_new_call");
				continue;
			}
#if 0
			{
				struct pri_sr *sr;
				sr = pri_sr_new();
				pri_sr_set_channel(sr, x+1, 0, 0);
				pri_sr_set_bearer(sr, 0, PRI_LAYER_1_ULAW);
				pri_sr_set_called(sr, dest, PRI_NATIONAL_ISDN, 1);
				pri_sr_set_caller(sr, num, name, PRI_NATIONAL_ISDN, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN);
				pri_sr_set_redirecting(sr, num, PRI_NATIONAL_ISDN, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL);
				if (pri_setup(pri, calls[x], sr))
					perror("pri_setup");
				pri_sr_free(sr);
			}
#else
			if (pri_call(pri, calls[x], PRI_TRANS_CAP_DIGITAL, x + 1, 1, 1, num, 
				PRI_NATIONAL_ISDN, name, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN,
				dest, PRI_NATIONAL_ISDN, PRI_LAYER_1_ULAW)) {
					perror("pri_call");
			}
#endif
		}
		printf("Setup %d calls!\n", TEST_CALLS);
		break;
	case PRI_EVENT_RINGING:
		printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
		q931_facility(pri, e->ringing.call);
		pri_answer(pri, e->ringing.call, e->ringing.channel, 0);
		break;
	case PRI_EVENT_HANGUP_REQ:
		printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
		pri_hangup(pri, e->hangup.call, e->hangup.cause);
		break;
	default:
		printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
	}
}
Exemplo n.º 2
0
void pri_dump_event(struct pri *pri, pri_event *e)
{
	if (!pri || !e)
		return;
	pri_message(pri, "Event type: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
	switch(e->gen.e) {
	case PRI_EVENT_DCHAN_UP:
	case PRI_EVENT_DCHAN_DOWN:
		break;
	case PRI_EVENT_CONFIG_ERR:
		pri_message(pri, "Error: %s", e->err.err);
		break;
	case PRI_EVENT_RESTART:
		pri_message(pri, "Restart on channel %d\n", e->restart.channel);
	case PRI_EVENT_RING:
		pri_message(pri, "Calling number: %s (%s, %s)\n", e->ring.callingnum, pri_plan2str(e->ring.callingplan), pri_pres2str(e->ring.callingpres));
		pri_message(pri, "Called number: %s (%s)\n", e->ring.callednum, pri_plan2str(e->ring.calledplan));
		pri_message(pri, "Channel: %d (%s) Reference number: %d\n", e->ring.channel, e->ring.flexible ? "Flexible" : "Not Flexible", e->ring.cref);
		break;
	case PRI_EVENT_HANGUP:
		pri_message(pri, "Hangup, reference number: %d, reason: %s\n", e->hangup.cref, pri_cause2str(e->hangup.cause));
		break;
	default:
		pri_message(pri, "Don't know how to dump events of type %d\n", e->gen.e);
	}
}
static void event2(struct pri *pri, pri_event *e)
{
	/* CPE */
	switch(e->gen.e) {
	case PRI_EVENT_RING:
		printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
		pri_proceeding(pri, e->ring.call, e->ring.channel, 0);
		pri_acknowledge(pri, e->ring.call, e->ring.channel, 0);
		break;
	case PRI_EVENT_ANSWER:
		printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
		pri_hangup(pri, e->answer.call, PRI_CAUSE_NORMAL_UNSPECIFIED);
		break;
	case PRI_EVENT_HANGUP:
		printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
		pri_hangup(pri, e->hangup.call, e->hangup.cause);
		break;
	case PRI_EVENT_DCHAN_UP:
	default:
		printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
	}
}
Exemplo n.º 4
0
static void handle_pri_passive_event(pritap_t *pritap, pri_event *e)
{
    passive_call_t *pcall = NULL;
    passive_call_t *peerpcall = NULL;
    ftdm_channel_t *fchan = NULL;
    ftdm_channel_t *peerfchan = NULL;
    int layer1, transcap = 0;
    int crv = 0;
    pritap_t *peertap = pritap->peerspan->signal_data;

    switch (e->e) {

    case PRI_EVENT_RING:
        /* we cannot use ftdm_channel_t because we still dont know which channel will be used
         * (ie, flexible channel was requested), thus, we need our own list of call references */
        crv = tap_pri_get_crv(pritap->pri, e->ring.call);
        ftdm_log(FTDM_LOG_DEBUG, "Ring on channel %s:%d:%d with callref %d\n",
                 pritap->span->name, PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), crv);
        pcall = tap_pri_get_pcall_bycrv(pritap, crv);
        if (pcall) {
            ftdm_log(FTDM_LOG_WARNING, "There is a call with callref %d already, ignoring duplicated ring event\n", crv);
            break;
        }

        /* Try to get a recycled call (ie, e->ring.call is a call that the PRI stack allocated previously and then
         * re-used for the next RING event because we did not destroy it fast enough) */
        pcall = tap_pri_get_pcall(pritap, e->ring.call);
        if (!pcall) {
            /* ok so the call is really not known to us, let's get a new one */
            pcall = tap_pri_get_pcall(pritap, NULL);
            if (!pcall) {
                ftdm_log(FTDM_LOG_ERROR, "Failed to get a free passive PRI call slot for callref %d, this is a bug!\n", crv);
                break;
            }
        }
        pcall->callref = e->ring.call;
        ftdm_set_string(pcall->callingnum.digits, e->ring.callingnum);
        ftdm_set_string(pcall->callingani.digits, e->ring.callingani);
        ftdm_set_string(pcall->callednum.digits, e->ring.callednum);
        ftdm_set_string(pcall->callingname, e->ring.callingname);
        break;

    case PRI_EVENT_PROGRESS:
        crv = tap_pri_get_crv(pritap->pri, e->proceeding.call);
        ftdm_log(FTDM_LOG_DEBUG, "Progress on channel %s:%d:%d with callref %d\n",
                 pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
        break;

    case PRI_EVENT_PROCEEDING:
        crv = tap_pri_get_crv(pritap->pri, e->proceeding.call);
        /* at this point we should know the real b chan that will be used and can therefore proceed to notify about the call, but
         * only if a couple of call tests are passed first */
        ftdm_log(FTDM_LOG_DEBUG, "Proceeding on channel %s:%d:%d with callref %d\n",
                 pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);

        /* check that we already know about this call in the peer PRI (which was the one receiving the PRI_EVENT_RING event) */
        if (!(pcall = tap_pri_get_pcall_bycrv(peertap, crv))) {
            ftdm_log(FTDM_LOG_DEBUG,
                     "ignoring proceeding in channel %s:%d:%d for callref %d since we don't know about it\n",
                     pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
            break;
        }
        if (pcall->proceeding) {
            ftdm_log(FTDM_LOG_DEBUG, "Ignoring duplicated proceeding with callref %d\n", crv);
            break;
        }
        pcall->proceeding = 1;

        /* This call should not be known to this PRI yet ... */
        if ((peerpcall = tap_pri_get_pcall_bycrv(pritap, crv))) {
            ftdm_log(FTDM_LOG_ERROR,
                     "ignoring proceeding in channel %s:%d:%d for callref %d, dup???\n",
                     pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
            break;
        }

        /* Check if the call pointer is being recycled */
        peerpcall = tap_pri_get_pcall(pritap, e->proceeding.call);
        if (!peerpcall) {
            peerpcall = tap_pri_get_pcall(pritap, NULL);
            if (!peerpcall) {
                ftdm_log(FTDM_LOG_ERROR, "Failed to get a free peer PRI passive call slot for callref %d in span %s, this is a bug!\n",
                         crv, pritap->span->name);
                break;
            }
            peerpcall->callref = e->proceeding.call;
        }

        /* check that the layer 1 and trans capability are supported */
        layer1 = pri_get_layer1(peertap->pri, pcall->callref);
        transcap = pri_get_transcap(peertap->pri, pcall->callref);

        if (PRI_LAYER_1_ULAW != layer1 && PRI_LAYER_1_ALAW != layer1) {
            ftdm_log(FTDM_LOG_NOTICE, "Not monitoring callref %d with unsupported layer 1 format %d\n", crv, layer1);
            break;
        }

        if (transcap != PRI_TRANS_CAP_SPEECH && transcap != PRI_TRANS_CAP_3_1K_AUDIO && transcap != PRI_TRANS_CAP_7K_AUDIO) {
            ftdm_log(FTDM_LOG_NOTICE, "Not monitoring callref %d with unsupported capability %d\n", crv, transcap);
            break;
        }

        fchan = tap_pri_get_fchan(pritap, pcall, e->proceeding.channel);
        if (!fchan) {
            ftdm_log(FTDM_LOG_ERROR, "Proceeding requested on odd/unavailable channel %s:%d:%d for callref %d\n",
                     pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
            break;
        }

        peerfchan = tap_pri_get_fchan(peertap, pcall, e->proceeding.channel);
        if (!peerfchan) {
            ftdm_log(FTDM_LOG_ERROR, "Proceeding requested on odd/unavailable channel %s:%d:%d for callref %d\n",
                     peertap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
            break;
        }
        pcall->fchan = fchan;
        peerpcall->fchan = fchan;

        ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "Starting new tapped call with callref %d\n", crv);

        ftdm_channel_lock(fchan);
        fchan->call_data = peerfchan;
        ftdm_set_state(fchan, FTDM_CHANNEL_STATE_RING);
        ftdm_channel_unlock(fchan);

        ftdm_channel_lock(peerfchan);
        peerfchan->call_data = fchan;
        ftdm_channel_unlock(peerfchan);

        break;

    case PRI_EVENT_ANSWER:
        crv = tap_pri_get_crv(pritap->pri, e->answer.call);
        ftdm_log(FTDM_LOG_DEBUG, "Answer on channel %s:%d:%d with callref %d\n",
                 pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv);
        if (!(pcall = tap_pri_get_pcall_bycrv(pritap, crv))) {
            ftdm_log(FTDM_LOG_DEBUG,
                     "ignoring answer in channel %s:%d:%d for callref %d since we don't know about it\n",
                     pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->proceeding.channel), crv);
            break;
        }
        if (!pcall->fchan) {
            ftdm_log(FTDM_LOG_ERROR,
                     "Received answer in channel %s:%d:%d for callref %d but we never got a channel\n",
                     pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv);
            break;
        }
        ftdm_channel_lock(pcall->fchan);
        ftdm_log_chan(pcall->fchan, FTDM_LOG_NOTICE, "Tapped call was answered in state %s\n", ftdm_channel_state2str(pcall->fchan->state));
        ftdm_set_pflag(pcall->fchan, PRITAP_NETWORK_ANSWER);
        ftdm_set_state(pcall->fchan, FTDM_CHANNEL_STATE_UP);
        ftdm_channel_unlock(pcall->fchan);
        break;

    case PRI_EVENT_HANGUP_REQ:
        crv = tap_pri_get_crv(pritap->pri, e->hangup.call);

        ftdm_log(FTDM_LOG_DEBUG, "Hangup on channel %s:%d:%d with callref %d\n",
                 pritap->span->name, PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), crv);

        if (!(pcall = tap_pri_get_pcall_bycrv(pritap, crv))) {
            ftdm_log(FTDM_LOG_DEBUG,
                     "ignoring hangup in channel %s:%d:%d for callref %d since we don't know about it",
                     pritap->span->name, PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), crv);
            break;
        }

        if (pcall->fchan) {
            fchan = pcall->fchan;
            ftdm_channel_lock(fchan);
            if (fchan->state < FTDM_CHANNEL_STATE_TERMINATING) {
                ftdm_set_state(fchan, FTDM_CHANNEL_STATE_TERMINATING);
            }
            pcall->fchan = NULL; /* after this event we're not supposed to need to do anything with the channel anymore */
            ftdm_channel_unlock(fchan);
        }

        tap_pri_put_pcall(pritap, e->hangup.call);
        tap_pri_put_pcall(peertap, e->hangup.call);
        break;

    case PRI_EVENT_HANGUP_ACK:
        crv = tap_pri_get_crv(pritap->pri, e->hangup.call);
        ftdm_log(FTDM_LOG_DEBUG, "Hangup ack on channel %s:%d:%d with callref %d\n",
                 pritap->span->name, PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), crv);
        tap_pri_put_pcall(pritap, e->hangup.call);
        tap_pri_put_pcall(peertap, e->hangup.call);
        break;

    default:
        ftdm_log(FTDM_LOG_DEBUG, "Ignoring passive event %s on span %s\n", pri_event2str(e->gen.e), pritap->span->name);
        break;

    }
}