static ftdm_status_t ftdm_gsm_state_advance(ftdm_channel_t *ftdmchan) { ftdm_log_chan(ftdmchan, STATE_ADVANCE_LOG_LEVEL , "Executing state handler for %s\n", ftdm_channel_state2str(ftdmchan->state)); ftdm_channel_complete_state(ftdmchan); switch (ftdmchan->state) { /* starting an incoming call */ case FTDM_CHANNEL_STATE_COLLECT: { } break; /* starting an outgoing call */ case FTDM_CHANNEL_STATE_DIALING: { uint32_t interval = 0; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Starting outgoing call with interval %d\n", interval); { ftdm_gsm_span_data_t *gsm_data; gsm_data = ftdmchan->span->signal_data; gsm_data->call_id = g_outbound_call_id++; wat_con_event_t con_event; memset(&con_event, 0, sizeof(con_event)); ftdm_set_string(con_event.called_num.digits, ftdmchan->caller_data.dnis.digits); ftdm_log(FTDM_LOG_DEBUG, "Dialing number %s\n", con_event.called_num.digits); wat_con_req(ftdmchan->span->span_id, gsm_data->call_id , &con_event); SEND_STATE_SIGNAL(FTDM_SIGEVENT_DIALING); } } break; /* incoming call was offered */ case FTDM_CHANNEL_STATE_RING: /* notify the user about the new call */ ftdm_log(FTDM_LOG_INFO, "Answering Incomming Call\r\n"); SEND_STATE_SIGNAL(FTDM_SIGEVENT_START); break; /* the call is making progress */ case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: { SEND_STATE_SIGNAL(FTDM_SIGEVENT_PROGRESS_MEDIA); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP); } break; /* the call was answered */ case FTDM_CHANNEL_STATE_UP: { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { SEND_STATE_SIGNAL(FTDM_SIGEVENT_UP); } else { ftdm_gsm_span_data_t *gsm_data; gsm_data = ftdmchan->span->signal_data; wat_con_cfm(ftdmchan->span->span_id, gsm_data->call_id); } } break; /* just got hangup */ case FTDM_CHANNEL_STATE_HANGUP: { ftdm_gsm_span_data_t *gsm_data; gsm_data = ftdmchan->span->signal_data; wat_rel_req(ftdmchan->span->span_id, gsm_data->call_id); gsm_data->call_id = 0; SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); } break; case FTDM_CHANNEL_STATE_TERMINATING: { SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); } break; /* finished call for good */ case FTDM_CHANNEL_STATE_DOWN: { ftdm_channel_t *closed_chan; closed_chan = ftdmchan; ftdm_channel_close(&closed_chan); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "State processing ended.\n"); SEND_STATE_SIGNAL(FTDM_SIGEVENT_STOP); } break; /* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */ case FTDM_CHANNEL_STATE_RINGING: ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n"); SEND_STATE_SIGNAL(FTDM_SIGEVENT_RINGING); break; /* put the r2 channel back to IDLE, close ftdmchan and set it's state as DOWN */ case FTDM_CHANNEL_STATE_RESET: { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RESET indicated, putting the R2 channel back to IDLE\n"); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } break; default: { ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state)); } break; } return FTDM_SUCCESS; }
static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan) { ftdm_status_t status; ftdm_sigmsg_t sig; pritap_t *pritap = ftdmchan->span->signal_data; pritap_t *peer_pritap = pritap->peerspan->signal_data; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state %s\n", ftdm_channel_state2str(ftdmchan->state)); memset(&sig, 0, sizeof(sig)); sig.chan_id = ftdmchan->chan_id; sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; ftdm_channel_complete_state(ftdmchan); switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_DOWN: { ftdm_channel_t *fchan = ftdmchan; /* Destroy the peer data first */ if (fchan->call_data) { ftdm_channel_t *peerchan = fchan->call_data; ftdm_channel_t *pchan = peerchan; ftdm_channel_lock(peerchan); pchan->call_data = NULL; pchan->pflags = 0; ftdm_channel_close(&pchan); ftdm_channel_unlock(peerchan); } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "No call data?\n"); } ftdmchan->call_data = NULL; ftdmchan->pflags = 0; ftdm_channel_close(&fchan); } break; case FTDM_CHANNEL_STATE_PROGRESS: case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: case FTDM_CHANNEL_STATE_HANGUP: break; case FTDM_CHANNEL_STATE_UP: { if (ftdm_test_pflag(ftdmchan, PRITAP_NETWORK_ANSWER)) { ftdm_clear_pflag(ftdmchan, PRITAP_NETWORK_ANSWER); sig.event_id = FTDM_SIGEVENT_UP; ftdm_span_send_signal(ftdmchan->span, &sig); } } break; case FTDM_CHANNEL_STATE_RING: { sig.event_id = FTDM_SIGEVENT_START; /* The ring interface (where the setup was received) is the peer, since we RING the channel * where PROCEED/PROGRESS is received */ ftdm_sigmsg_add_var(&sig, "pritap_ring_interface", PRITAP_GET_INTERFACE(peer_pritap->iface)); if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } break; case FTDM_CHANNEL_STATE_TERMINATING: { if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP) { sig.event_id = FTDM_SIGEVENT_STOP; status = ftdm_span_send_signal(ftdmchan->span, &sig); } ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } break; default: { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "ignoring state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(ftdmchan->state)); } break; } return FTDM_SUCCESS; }