Example #1
0
void on_wat_con_ind(unsigned char span_id, uint8_t call_id, wat_con_event_t *con_event)
{
	//fprintf(stdout, "s%d: Incoming call (id:%d) Calling Number:%s  Calling Name:\"%s\" type:%d plan:%d\n", span_id, call_id, con_event->calling_num.digits, con_event->calling_name, con_event->calling_num.type, con_event->calling_num.plan);
	
	ftdm_log(FTDM_LOG_INFO, "s%d: Incoming call (id:%d) Calling Number:%s  Calling Name:\"%s\" type:%d plan:%d\n", span_id, call_id, con_event->calling_num.digits, con_event->calling_name, con_event->calling_num.type, con_event->calling_num.plan);
	
	ftdm_span_t *span = NULL;
	//ftdm_status_t ftdm_status = FTDM_FAIL;
	ftdm_gsm_span_data_t *gsm_data = NULL;

	if(!(span = GetSpanByID(span_id, &gsm_data))) {
		return;
	}	  

	gsm_data->call_id = call_id;			
	
	#define ZERO_ARRAY(arr) memset(arr, 0, sizeof(arr))
	// cid date
	{
		time_t t;
		struct tm *tmp;
		t = time(NULL);
		tmp = localtime(&t);
		if (tmp == NULL) {
			ZERO_ARRAY(gsm_data->bchan->caller_data.cid_date);
			strftime(gsm_data->bchan->caller_data.cid_date, sizeof(gsm_data->bchan->caller_data.cid_date), "%y/%m/%d", tmp);
		}

	}

	// cid name
	ZERO_ARRAY(gsm_data->bchan->caller_data.cid_name);
	strncpy(gsm_data->bchan->caller_data.cid_name, con_event->calling_name,sizeof(gsm_data->bchan->caller_data.cid_name));

	// dnis
	ZERO_ARRAY(gsm_data->bchan->caller_data.dnis.digits);
	strncpy(gsm_data->bchan->caller_data.dnis.digits, con_event->calling_num.digits, FTDM_DIGITS_LIMIT);
	
	//collected
	ZERO_ARRAY(gsm_data->bchan->caller_data.collected);
	strncpy(gsm_data->bchan->caller_data.collected, con_event->calling_num.digits, FTDM_DIGITS_LIMIT);
	
	ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_RING);

	if (ftdm_channel_open_chan(gsm_data->bchan) != FTDM_SUCCESS) {
		ftdm_log_chan(gsm_data->bchan, FTDM_LOG_ERROR, "Failed to open GSM b-channel of span %s!\n", span->name);
	}
	
}
Example #2
0
static __inline__ ftdm_channel_t *tap_pri_get_fchan(pritap_t *pritap, passive_call_t *pcall, int channel)
{
    ftdm_channel_t *fchan = NULL;
    int err = 0;
    int chanpos = PRI_CHANNEL(channel);
    if (!chanpos || chanpos > pritap->span->chan_count) {
        ftdm_log(FTDM_LOG_CRIT, "Invalid pri tap channel %d requested in span %s\n", channel, pritap->span->name);
        return NULL;
    }

    fchan = pritap->span->channels[PRI_CHANNEL(channel)];

    ftdm_channel_lock(fchan);

    if (ftdm_test_flag(fchan, FTDM_CHANNEL_INUSE)) {
        ftdm_log(FTDM_LOG_ERROR, "Channel %d requested in span %s is already in use!\n", channel, pritap->span->name);
        err = 1;
        goto done;
    }

    if (ftdm_channel_open_chan(fchan) != FTDM_SUCCESS) {
        ftdm_log(FTDM_LOG_ERROR, "Could not open tap channel %d requested in span %s\n", channel, pritap->span->name);
        err = 1;
        goto done;
    }

    memset(&fchan->caller_data, 0, sizeof(fchan->caller_data));

    ftdm_set_string(fchan->caller_data.cid_num.digits, pcall->callingnum.digits);
    if (!ftdm_strlen_zero(pcall->callingname)) {
        ftdm_set_string(fchan->caller_data.cid_name, pcall->callingname);
    } else {
        ftdm_set_string(fchan->caller_data.cid_name, pcall->callingnum.digits);
    }
    ftdm_set_string(fchan->caller_data.ani.digits, pcall->callingani.digits);
    ftdm_set_string(fchan->caller_data.dnis.digits, pcall->callednum.digits);

done:
    if (fchan) {
        ftdm_channel_unlock(fchan);
    }

    if (err) {
        return NULL;
    }

    return fchan;
}
Example #3
0
static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj)
{

	ftdm_log(FTDM_LOG_INFO,"ftdm_gsm_run\r\n");

	ftdm_channel_t *ftdmchan = NULL;
	ftdm_span_t *span = (ftdm_span_t *) obj;
	ftdm_gsm_span_data_t *gsm_data = NULL;
	ftdm_interrupt_t *data_sources[2] = {NULL, NULL};
	int waitms = 0;
	
	gsm_data = span->signal_data;

	ftdm_assert_return(gsm_data != NULL, NULL, "No gsm data attached to span\n");

	ftdm_log(FTDM_LOG_DEBUG, "GSM monitor thread for span %s started\n", span->name);
	if (!gsm_data->dchan || ftdm_channel_open_chan(gsm_data->dchan) != FTDM_SUCCESS) {
		ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to open GSM d-channel of span %s!\n", span->name);
		gsm_data->dchan = NULL;
		goto done;
	}




	while (ftdm_running()) {

		wat_span_run(span->span_id);

		waitms = wat_span_schedule_next(span->span_id);
		if (waitms > GSM_POLL_INTERVAL_MS) {
			waitms = GSM_POLL_INTERVAL_MS;
		}

/////////////////////
		

		{
			ftdm_wait_flag_t flags = FTDM_READ | FTDM_EVENTS;
			ftdm_status_t status = ftdm_channel_wait(gsm_data->dchan, &flags, waitms);
			
	
			/* double check that this channel has a state change pending */
			ftdm_channel_lock(gsm_data->bchan);
			ftdm_channel_advance_states(gsm_data->bchan);
					
			if(FTDM_SUCCESS == status ) {
		
				if(flags &FTDM_READ ) {
					char buffer[1025];
					int n = 0, m = 0;
					memset(buffer, 0, sizeof(buffer));

					n = read_channel(gsm_data->dchan, buffer, sizeof(buffer)-1);
					m = strlen(buffer);	
					wat_span_process_read(span->span_id, buffer, m);
#if 	 LOG_SIG_DATA
						printf("<<======================= incomming data len = %d, %s\r\n", n, buffer);
#endif

				}
			}
			
			ftdm_channel_advance_states(gsm_data->bchan);
			
			ftdm_channel_unlock(gsm_data->bchan);
			

		}


		

		ftdm_span_trigger_signals(span);


	}

done:
	if (data_sources[0]) {
		ftdm_interrupt_destroy(&data_sources[0]);
	}

	ftdm_log(FTDM_LOG_DEBUG, "GSM thread ending.\n");

	return NULL;
}
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
{
	ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
	
	int16_t suId = sngisdn_event->suId;
	uint32_t suInstId = sngisdn_event->suInstId;
	uint32_t spInstId = sngisdn_event->spInstId;
	int16_t dChan = sngisdn_event->dChan;
	uint8_t ces = sngisdn_event->ces;
	sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;	
	ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
	ConEvnt *conEvnt = &sngisdn_event->event.conEvnt;

	ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
	
	ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
	
	switch (ftdmchan->state) {
		case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
			if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ||
				ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {

				ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP but channel is in USE, saving call for later processing\n");
				/* the flag the channel as having a collision */
				sngisdn_set_flag(sngisdn_info, FLAG_GLARE);

				/* save the SETUP for processing once the channel has gone to DOWN */
				memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
				sngisdn_info->glare.suId = suId;
				sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
				sngisdn_info->glare.spInstId = spInstId;
				sngisdn_info->glare.dChan = dChan;
				sngisdn_info->glare.ces = ces;
				break;
			}
			
			sngisdn_info->suInstId = get_unique_suInstId(suId);
			sngisdn_info->spInstId = spInstId;

			/* If this is a glared call that was previously saved, we moved
			all the info to the current call, so clear the glared saved data */
			if (sngisdn_info->glare.spInstId == spInstId) {
				clear_call_glare_data(sngisdn_info);
			}			

			ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
			g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
			ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);

			ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);

			if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
				signal_data->signalling == SNGISDN_SIGNALING_NET) {
				sngisdn_info->ces = ces;
			}

			/* try to open the channel */
			if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
				ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
				sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
				ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
				break;
			}

#if 0
			/* Export ftdmchan variables here if we need to */
			ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
			ftdm_channel_add_var(ftdmchan, "isdn_crap", "morecrap");
			ftdm_channel_add_var(ftdmchan, "isdn_stuff", "s");
			ftdm_channel_add_var(ftdmchan, "isdn_d", "asdsadasdasdsad");
#endif
			/* Fill in call information */
			cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
			cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
			cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display);

			if (conEvnt->bearCap[0].eh.pres) {
				ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val);
				ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val);
			}

			if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
				if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
					if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
						snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
					}
				}

				
				if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
					/* Verify whether the Caller Name will come in a subsequent FACILITY message */
					uint16_t ret_val;
					char retrieved_str[255];
					
					ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
					/*
						return values for "sng_isdn_retrieve_facility_information_following":
						If there will be no information following, or fails to decode IE, returns -1
						If there will be no information following, but current FACILITY IE contains a caller name, returns 0
						If there will be information following, returns 1
					*/

					if (ret_val == 1) {
						ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
						ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
						/* Launch timer in case we never get a FACILITY msg */
						if (signal_data->facility_timeout) {
							ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, 
									sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
						}
						break;
					} else if (ret_val == 0) {
						strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
					}
				}
			}

			if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) {
				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
			} else {
				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
			}
			break;
		case FTDM_CHANNEL_STATE_TERMINATING:
			ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in TERMINATING state, saving SETUP info for later processing\n");
			ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare\n");
			
			sngisdn_set_flag(sngisdn_info, FLAG_GLARE);

			/* save the SETUP for processing once the channel has gone to DOWN */
			memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
			sngisdn_info->glare.suId = suId;
			sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
			sngisdn_info->glare.spInstId = spInstId;
			sngisdn_info->glare.dChan = dChan;
			sngisdn_info->glare.ces = ces;
			
			break;
		case FTDM_CHANNEL_STATE_DIALING:	/* glare */
			if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
				/* Save inbound call info so we can send a RELEASE when this channel goes to a different state */
				ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP in DIALING state, rejecting inbound call\n");
				sngisdn_set_flag(sngisdn_info, FLAG_DELAYED_REL);

				sngisdn_info->glare.suId = suId;
				sngisdn_info->glare.suInstId = get_unique_suInstId(suId);
				sngisdn_info->glare.spInstId = spInstId;

				sngisdn_info->glare.dChan = dChan;
				sngisdn_info->glare.ces = ces;
				ftdmchan->caller_data.hangup_cause = 0x2C; /* Channel requested not available */
				ftdm_sched_timer(signal_data->sched, "delayed_release", 1, sngisdn_delayed_release, (void*) sngisdn_info, NULL);
			} else {
				ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in DIALING state, saving SETUP info for later processing\n");
				
				/* the flag the channel as having a collision */
				ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare");
				sngisdn_set_flag(sngisdn_info, FLAG_GLARE);

				/* save the SETUP for processing once the channel has gone to DOWN */
				memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
				sngisdn_info->glare.suId = suId;
				sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
				sngisdn_info->glare.spInstId = spInstId;
				sngisdn_info->glare.dChan = dChan;
				sngisdn_info->glare.ces = ces;

				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
			}
			break;
		default:
			ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
			break;
	}
	ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
	return;
}