2020-01-25 07:50:20 +00:00
# warning warum kommt kein ton, wenn ich bei watson ins timeout komme?:
/* layer3 handling
*
* ( C ) 2020 by Andreas Eversberg < jolly @ eversberg . eu >
* All Rights Reserved
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <stdio.h>
# include <unistd.h>
# include <errno.h>
# include <string.h>
# include <stdint.h>
# include <stdlib.h>
# include <mISDN/mbuffer.h>
2024-01-09 11:24:14 +00:00
# include "../liblogging/logging.h"
# include <osmocom/cc/g711.h>
2020-01-25 07:50:20 +00:00
# include "isdn.h"
# include "dss1.h"
2022-06-24 17:58:41 +00:00
# include "bridge.h"
2020-01-25 07:50:20 +00:00
# include "ie.h"
# ifndef u_char
# define u_char unsigned char
# endif
# include <mISDN/mlayer3.h>
# include <mISDN/q931.h>
# include <mISDN/suppserv.h>
2022-07-03 19:06:17 +00:00
static struct osmo_cc_helper_audio_codecs codecs_offer_alaw_ulaw [ ] = {
2020-01-25 07:50:20 +00:00
{ " PCMA " , 8000 , 1 , g711_transcode_flipped , g711_transcode_flipped } ,
{ " PCMU " , 8000 , 1 , g711_transcode_alaw_flipped_to_ulaw , g711_transcode_ulaw_to_alaw_flipped } ,
{ NULL , 0 , 0 , NULL , NULL } ,
} ;
2022-07-03 19:06:17 +00:00
static struct osmo_cc_helper_audio_codecs codecs_offer_ulaw_alaw [ ] = {
2020-01-25 07:50:20 +00:00
{ " PCMU " , 8000 , 1 , g711_transcode_flipped , g711_transcode_flipped } ,
{ " PCMA " , 8000 , 1 , g711_transcode_ulaw_flipped_to_alaw , g711_transcode_alaw_to_ulaw_flipped } ,
{ NULL , 0 , 0 , NULL , NULL } ,
} ;
2022-07-03 19:06:17 +00:00
static struct osmo_cc_helper_audio_codecs codecs_offer_clearmode [ ] = {
{ " CLEARMODE " , 8000 , 1 , NULL , NULL } ,
{ NULL , 0 , 0 , NULL , NULL } ,
} ;
static struct osmo_cc_helper_audio_codecs codecs_accept_alaw_ulaw_clearmode [ ] = {
{ " PCMA " , 8000 , 1 , g711_transcode_flipped , g711_transcode_flipped } ,
{ " PCMU " , 8000 , 1 , g711_transcode_alaw_flipped_to_ulaw , g711_transcode_ulaw_to_alaw_flipped } ,
{ " CLEARMODE " , 8000 , 1 , NULL , NULL } ,
{ NULL , 0 , 0 , NULL , NULL } ,
} ;
static struct osmo_cc_helper_audio_codecs codecs_accept_ulaw_alaw_clearmode [ ] = {
{ " PCMA " , 8000 , 1 , g711_transcode_flipped , g711_transcode_flipped } ,
{ " PCMU " , 8000 , 1 , g711_transcode_alaw_flipped_to_ulaw , g711_transcode_ulaw_to_alaw_flipped } ,
{ " CLEARMODE " , 8000 , 1 , NULL , NULL } ,
{ NULL , 0 , 0 , NULL , NULL } ,
} ;
2020-01-25 07:50:20 +00:00
static struct l3_msg * create_l3msg ( void )
{
struct l3_msg * l3m ;
l3m = alloc_l3_msg ( ) ;
if ( ! l3m ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " No MEM! \n " ) ;
2020-01-25 07:50:20 +00:00
abort ( ) ;
}
return l3m ;
}
static void free_l3msg ( struct l3_msg * l3m )
{
free_l3_msg ( l3m ) ;
}
static const char * state_names [ ] = {
" IDLE " ,
" IN-SETUP " ,
" OUT-SETUP " ,
" IN-OVERLAP " ,
" OUT-OVERLAP " ,
" IN-PROCEEDING " ,
" OUT-PROCEEDING " ,
" IN-ALERTING " ,
" OUT-ALERTING " ,
" IN-CONNECTING " ,
" OUT-CONNECTING " ,
" CONNECT " ,
" IN-DISCONNECT " ,
" OUT-DISCONNECT " ,
" OUT-RELEASE " ,
" SUSPENDED " ,
} ;
static void new_state ( call_t * call , enum isdn_state state )
{
if ( call - > state = = state )
return ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Changing state %s -> %s \n " , state_names [ call - > state ] , state_names [ state ] ) ;
2020-01-25 07:50:20 +00:00
call - > state = state ;
}
static void release_and_destroy ( call_t * call , uint8_t cc_isdn_cause , uint16_t cc_sip_cause , uint8_t isdn_cause )
{
osmo_cc_msg_t * msg ;
struct l3_msg * l3m ;
if ( cc_isdn_cause | | cc_sip_cause ) {
/* create osmo-cc message */
2022-07-03 19:06:17 +00:00
if ( call - > state = = ISDN_STATE_IDLE
| | call - > state = = ISDN_STATE_OUT_SETUP )
2020-01-25 07:50:20 +00:00
msg = osmo_cc_new_msg ( OSMO_CC_MSG_REJ_IND ) ;
else
msg = osmo_cc_new_msg ( OSMO_CC_MSG_REL_IND ) ;
/* cause */
osmo_cc_add_ie_cause ( msg , call - > isdn_ep - > serving_location , cc_isdn_cause , cc_sip_cause , 0 ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
if ( isdn_cause ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " REJECT REQUEST (pid = 0x%x callref = %d) \n " , call - > l3_pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* creating release complete */
l3m = create_l3msg ( ) ;
/* cause */
enc_ie_cause ( l3m , call - > isdn_ep - > serving_location , isdn_cause ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_RELEASE_COMPLETE , call - > l3_pid , l3m ) ;
}
/* call terminated */
new_state ( call , ISDN_STATE_IDLE ) ;
call_destroy ( call ) ;
}
static void split_3pty ( call_t * call )
{
call_t * other ;
osmo_cc_msg_t * msg ;
/* call must be a conference call */
if ( ! call - > conference_3pty )
return ;
/* search for other 3pty party on same terminal */
other = call - > isdn_ep - > call_list ;
while ( other ) {
if ( other ! = call
& & other - > l3_ces = = call - > l3_ces
& & other - > conference_3pty )
break ;
other = other - > next ;
}
/* remove conference state */
if ( other ) {
other - > conference_3pty = 0 ;
2022-06-24 17:58:41 +00:00
/* process local briding capability */
2022-08-19 14:27:41 +00:00
bridge_socket_client_update ( other , 1 ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_NOTIFY_IND ) ;
/* notify the facility */
osmo_cc_add_ie_notify ( msg , OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & other - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
}
2024-01-09 12:28:05 +00:00
/* Generate AOC-S facility IE from metering information */
# define AOCS_CURRENCY_AMOUNT_PER_UNIT 5
static void generate_aocs_ie ( call_t * call , struct l3_msg * l3m )
{
uint8_t fac_ie [ 256 ] ;
struct asn1_parm fac ;
if ( call - > isdn_ep - > ntmode & & call - > isdn_ep - > aocs & & call - > metering_info_received ) {
memset ( & fac , 0 , sizeof ( fac ) ) ;
fac . Valid = 1 ;
fac . comp = CompInvoke ;
fac . u . inv . invokeId = 2 ; /* doesn't matter since no response is expected */
fac . u . inv . operationValue = Fac_AOCSCurrency ;
LOGP ( DISDN , LOGL_DEBUG , " Sending AOC-S information from metering data: connect_units=%d unit_period_decisecs=%d \n " , call - > metering_connect_units , call - > metering_unit_period_decisecs ) ;
if ( call - > metering_connect_units = = 0 ) { // Free call
LOGP ( DISDN , LOGL_DEBUG , " AOC-S currencyInfoList: BasicComm FreeOfCharge \n " ) ;
fac . u . inv . o . AOCcuril . currencyInfoCount = 1 ;
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . chargedItem = 0x00 ; // basic comm
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . currencyType = 0x84 ; // free
}
else if ( call - > metering_unit_period_decisecs = = 0 ) { // setup/connect FlatRate
/* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item, therefore we don't use 'call setup' charged item */
LOGP ( DISDN , LOGL_DEBUG , " AOC-S currencyInfoList: BasicComm FlatRate \n " ) ;
fac . u . inv . o . AOCcuril . currencyInfoCount = 1 ;
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . chargedItem = 0x00 ; // basic comm
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . currencyType = 0xA2 ; // FlatRate
strncpy ( ( char * ) fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . FlatRateCurrency . currency , " EUR " , 10 ) ; // Currency value
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . FlatRateCurrency . currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call - > metering_connect_units ;
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . FlatRateCurrency . multiplier = 1 ; // 1/100 EUR
}
else if ( call - > metering_connect_units = = 1 ) { // Normal call
LOGP ( DISDN , LOGL_DEBUG , " AOC-S currencyInfoList: BasicComm DurationCurrency \n " ) ;
fac . u . inv . o . AOCcuril . currencyInfoCount = 1 ;
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . chargedItem = 0x00 ; // basic comm
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . currencyType = 0xA1 ; // DurationCurrency
strncpy ( ( char * ) fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . currency , " EUR " , 10 ) ; // Currency value
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT ;
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . multiplier = 1 ; // 1/100 EUR
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . typeOfCharging = 0x00 ; // Contin. Charging
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . durLengthTimeUnit = call - > metering_unit_period_decisecs * 10 ; // Unit duration
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . durLengthTimeScale = 0x00 ; // 1/100 s
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . granLengthTimeUnit = 1 ; // Granularity 1
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . granLengthTimeScale = 2 ; // 1/1 s
}
else { // Special call with setup/connect FlatRate
/* note some payphones (e.g. BluePhone) only interpret 'basic comm' charged item */
LOGP ( DISDN , LOGL_DEBUG , " AOC-S currencyInfoList: BasicComm DurationCurrency / CallSetup FlatRate \n " ) ;
fac . u . inv . o . AOCcuril . currencyInfoCount = 2 ;
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . chargedItem = 0x00 ; // basic comm
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . currencyType = 0xA1 ; // DurationCurrency
strncpy ( ( char * ) fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . currency , " EUR " , 10 ) ; // Currency value
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT ;
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . multiplier = 1 ; // 1/100 EUR
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . typeOfCharging = 0x00 ; // Contin. Charging
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . durLengthTimeUnit = call - > metering_unit_period_decisecs * 10 ; // Unit duration
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . durLengthTimeScale = 0x00 ; // 1/100 s
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . granLengthTimeUnit = 1 ; // Granularity 1
fac . u . inv . o . AOCcuril . currencyInfo [ 0 ] . durationCurrency . granLengthTimeScale = 2 ; // 1/1 s
fac . u . inv . o . AOCcuril . currencyInfo [ 1 ] . chargedItem = 0x02 ; // call setup
fac . u . inv . o . AOCcuril . currencyInfo [ 1 ] . currencyType = 0xA2 ; // FlatRate
strncpy ( ( char * ) fac . u . inv . o . AOCcuril . currencyInfo [ 1 ] . FlatRateCurrency . currency , " EUR " , 10 ) ; // Currency value
fac . u . inv . o . AOCcuril . currencyInfo [ 1 ] . FlatRateCurrency . currencyAmount = AOCS_CURRENCY_AMOUNT_PER_UNIT * call - > metering_connect_units ;
fac . u . inv . o . AOCcuril . currencyInfo [ 1 ] . FlatRateCurrency . multiplier = 1 ; // 1/100 EUR
}
encodeFac ( fac_ie , & fac ) ;
enc_ie_facility ( l3m , fac_ie + 2 , fac_ie [ 1 ] ) ;
}
}
/* AOC-D timer callback */
static void aocd_timer_cb ( void * data )
{
uint8_t fac_ie [ 256 ] ;
struct asn1_parm fac ;
struct l3_msg * l3m ;
call_t * call = data ;
call - > metering_total_units + + ;
LOGP ( DISDN , LOGL_DEBUG , " Sending next AOC-D unit information, total_units=%d \n " , call - > metering_total_units ) ;
osmo_timer_schedule ( & call - > aocd_unit_timer , call - > metering_unit_period_decisecs / 10 , ( call - > metering_unit_period_decisecs % 10 ) * 100000 ) ;
memset ( & fac , 0 , sizeof ( fac ) ) ;
fac . Valid = 1 ;
fac . comp = CompInvoke ;
fac . u . inv . invokeId = 2 ; /* doesn't matter since no response is expected */
fac . u . inv . operationValue = Fac_AOCDChargingUnit ;
fac . u . inv . o . AOCchu . recordedUnits = call - > metering_total_units ;
encodeFac ( fac_ie , & fac ) ;
// sending facility
l3m = create_l3msg ( ) ;
enc_ie_facility ( l3m , fac_ie + 2 , fac_ie [ 1 ] ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_FACILITY , call - > l3_pid , l3m ) ;
}
2020-01-25 07:50:20 +00:00
/*
* handles all indications from ISDN stack
*/
/* CC-SETUP INDICATION */
void setup_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t type , plan , present , screen , reason ;
int has_mode , has_multi , has_user , has_present , has_reason ;
uint8_t coding , capability , mode , rate , multi , user ;
int exclusive , channel ;
int sending_complete ;
char callerid [ 33 ] ;
char called [ 33 ] ;
char keypad [ 33 ] ;
char redir [ 33 ] ;
char display [ 128 ] ;
int rc ;
2022-07-03 19:06:17 +00:00
struct osmo_cc_helper_audio_codecs * codecs ;
int clearmode = 0 ;
2020-01-25 07:50:20 +00:00
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " SETUP INDICATION (pid = 0x%x) \n " , pid ) ;
2020-01-25 07:50:20 +00:00
2021-01-01 21:13:47 +00:00
/* assign pid */
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " -> new L3ID assigned (l3id = 0x%x) \n " , pid ) ;
2020-01-25 07:50:20 +00:00
call - > l3_pid = pid ;
call - > l3_ces = pid > > 16 ;
msg = osmo_cc_new_msg ( OSMO_CC_MSG_SETUP_IND ) ;
/* newtwork + interface */
osmo_cc_add_ie_calling_network ( msg , OSMO_CC_NETWORK_ISDN_NONE , " " ) ;
osmo_cc_add_ie_calling_interface ( msg , call - > isdn_ep - > portname ) ;
/* caller info */
rc = dec_ie_calling_pn ( l3m , 0 , & type , & plan , & has_present , & present , & screen , callerid , sizeof ( callerid ) ) ;
if ( rc > = 0 ) {
if ( ! has_present )
present = screen = 0 ;
/* check MSN */
struct msn_list * m = call - > isdn_ep - > msn_list ;
if ( m ) {
/* we have an MSN list */
while ( m ) {
if ( ! strcmp ( callerid , m - > msn ) )
break ;
2021-03-28 10:52:58 +00:00
m = m - > next ;
2020-01-25 07:50:20 +00:00
}
/* not found, so we use first MSN */
if ( ! m ) {
strncpy ( callerid , call - > isdn_ep - > msn_list - > msn , sizeof ( callerid ) - 1 ) ;
callerid [ sizeof ( callerid ) - 1 ] = ' \0 ' ;
}
}
osmo_cc_add_ie_calling ( msg , type , plan , present , screen , callerid ) ;
/* secondary caller info */
rc = dec_ie_calling_pn ( l3m , 1 , & type , & plan , & has_present , & present , & screen , callerid , sizeof ( callerid ) ) ;
if ( rc > = 0 ) {
if ( ! has_present )
present = screen = 0 ;
osmo_cc_add_ie_calling ( msg , type , plan , present , screen , callerid ) ;
}
} else {
/* no caller ID, use MSN, if exists */
if ( call - > isdn_ep - > msn_list ) {
strncpy ( callerid , call - > isdn_ep - > msn_list - > msn , sizeof ( callerid ) - 1 ) ;
callerid [ sizeof ( callerid ) - 1 ] = ' \0 ' ;
type = OSMO_CC_TYPE_UNKNOWN ;
plan = OSMO_CC_PLAN_TELEPHONY ;
present = OSMO_CC_PRESENT_ALLOWED ;
screen = OSMO_CC_SCREEN_NETWORK ;
osmo_cc_add_ie_calling ( msg , type , plan , present , screen , callerid ) ;
}
}
/* dialing information */
rc = dec_ie_called_pn ( l3m , & type , & plan , called , sizeof ( called ) ) ;
if ( rc > = 0 ) {
osmo_cc_add_ie_called ( msg , type , plan , called ) ;
if ( called [ 0 ] )
call - > any_dialing = 1 ;
}
/* keypad */
rc = dec_ie_keypad ( l3m , keypad , sizeof ( keypad ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_keypad ( msg , keypad ) ;
/* redirecting number */
rc = dec_ie_redirecting ( l3m , & type , & plan , & has_present , & present , & screen , & has_reason , & reason , redir , sizeof ( redir ) ) ;
if ( rc > = 0 ) {
if ( ! has_present )
present = screen = 0 ;
if ( ! has_reason )
reason = 0 ;
osmo_cc_add_ie_redir ( msg , type , plan , present , screen , reason , redir ) ;
}
2022-07-03 19:06:17 +00:00
/* bearer capability */
2020-01-25 07:50:20 +00:00
rc = dec_ie_bearer ( l3m , & coding , & capability , & has_mode , & mode , & rate , & has_multi , & multi , & has_user , & user ) ;
if ( rc > = 0 ) {
if ( ! has_mode )
mode = 0 ;
osmo_cc_add_ie_bearer ( msg , coding , capability , mode ) ;
2022-07-03 19:06:17 +00:00
/* use clear mode */
2020-01-25 07:50:20 +00:00
if ( capability = = OSMO_CC_CAPABILITY_DATA
| | capability = = OSMO_CC_CAPABILITY_DATA_RESTRICTED
| | capability = = OSMO_CC_CAPABILITY_VIDEO )
2022-07-03 19:06:17 +00:00
clearmode = 1 ;
2020-01-25 07:50:20 +00:00
}
2022-07-03 19:06:17 +00:00
/* select codec */
2022-08-19 14:27:41 +00:00
if ( clearmode ) {
2022-07-03 19:06:17 +00:00
codecs = codecs_offer_clearmode ;
2022-08-19 14:27:41 +00:00
/* init jitter buffer */
call_create_jitter ( call , 1 ) ;
} else {
if ( call - > isdn_ep - > law = = ' a ' )
codecs = codecs_offer_alaw_ulaw ;
else
codecs = codecs_offer_ulaw_alaw ;
/* init jitter buffer */
call_create_jitter ( call , 0 ) ;
}
2022-07-03 19:06:17 +00:00
2020-01-25 07:50:20 +00:00
/* sdp offer */
2022-08-19 14:27:41 +00:00
call - > cc_session = osmo_cc_helper_audio_offer ( & call - > isdn_ep - > cc_ep . session_config , call , codecs , rtp_receive , msg , 1 ) ;
2020-01-25 07:50:20 +00:00
/* dialing complete */
dec_ie_complete ( l3m , & sending_complete ) ;
if ( sending_complete ) {
call - > sending_complete = 1 ;
osmo_cc_add_ie_complete ( msg ) ;
}
/* display */
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
/* hunt channel */
dec_ie_channel_id ( l3m , call - > isdn_ep - > pri , & exclusive , & channel ) ;
rc = channel = hunt_bchannel_in ( call - > isdn_ep , channel , exclusive ) ;
if ( rc < 0 ) {
no_channel :
osmo_cc_free_msg ( msg ) ;
/* send MT_RELEASE_COMPLETE to "REJECT" the channel */
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RELEASE-COMPLETE REQUEST (pid = 0x%x) \n " , pid ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
enc_ie_cause ( l3m , call - > isdn_ep - > serving_location , - rc ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_RELEASE_COMPLETE , call - > l3_pid , l3m ) ;
new_state ( call , ISDN_STATE_IDLE ) ;
call_destroy ( call ) ;
return ;
}
/* open channel */
rc = open_bchannel_in ( call , channel , 1 ) ;
if ( rc < 0 )
goto no_channel ;
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 1 ) ;
2020-01-25 07:50:20 +00:00
/* create endpoint */
osmo_cc_call_t * cc_call = osmo_cc_call_new ( & call - > isdn_ep - > cc_ep ) ;
call - > cc_callref = cc_call - > callref ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " -> new callref assigned (callref = %d) \n " , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
2024-01-09 12:28:05 +00:00
/* reset AOC information */
call - > metering_info_received = 0 ;
call - > aocd_unit_timer_started = 0 ;
2020-01-25 07:50:20 +00:00
new_state ( call , ISDN_STATE_IN_SETUP ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* CC-SETUP-ACKNOWLEDGE INDICATION */
void setup_ack_ind ( call_t * call , uint32_t cmd , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
int exclusive , channel ;
uint8_t coding , location , progress ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " SETUP-ACKNOWLEDGE INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_SETUP_ACK_IND ) ;
/* progress indicator */
rc = dec_ie_progress ( l3m , & coding , & location , & progress ) ;
if ( rc > = 0 )
osmo_cc_add_ie_progress ( msg , coding , location , progress ) ;
else {
coding = OSMO_CC_CODING_ITU_T ;
progress = 0 ;
}
/* display */
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
/* complete channel negotiation */
rc = dec_ie_channel_id ( l3m , call - > isdn_ep - > pri , & exclusive , & channel ) ;
rc = open_bchannel_out ( call , cmd , ( rc < 0 ) ? - 1 : channel , ( rc < 0 ) ? - 1 : exclusive ) ;
if ( rc < 0 ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_NOTICE , " Channel negotiation failed. \n " ) ;
2020-01-25 07:50:20 +00:00
osmo_cc_free_msg ( msg ) ;
release_and_destroy ( call , OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL , 0 , - rc ) ;
return ;
}
/* send SDP answer */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) & & ! call - > codec_negotiated ) {
call - > codec_negotiated = 1 ;
2022-08-19 14:27:41 +00:00
if ( call - > sdp ) {
/* send SDP */
2020-01-25 07:50:20 +00:00
osmo_cc_add_ie_sdp ( msg , call - > sdp ) ;
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 1 ) ;
}
2020-01-25 07:50:20 +00:00
}
/* the audio path is throughconnected */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) )
call - > audio_path = 1 ;
new_state ( call , ISDN_STATE_OUT_OVERLAP ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* CC-PROCEEDING INDICATION */
void proc_ind ( call_t * call , uint32_t cmd , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
int exclusive , channel ;
uint8_t coding , location , progress ;
uint8_t notify , type , plan , present ;
int has_present ;
char redir [ 32 ] ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " PREOCEEDING INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_PROC_IND ) ;
/* progress indicator */
rc = dec_ie_progress ( l3m , & coding , & location , & progress ) ;
if ( rc > = 0 )
osmo_cc_add_ie_progress ( msg , coding , location , progress ) ;
else {
coding = OSMO_CC_CODING_ITU_T ;
progress = 0 ;
}
/* display */
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
/* notify */
rc = dec_ie_notify ( l3m , & notify ) ;
if ( rc > = 0 )
osmo_cc_add_ie_notify ( msg , notify ) ;
/* redirection info */
rc = dec_ie_redirection ( l3m , & type , & plan , & has_present , & present , redir , sizeof ( redir ) ) ;
if ( rc > = 0 ) {
if ( ! has_present )
present = 0 ;
osmo_cc_add_ie_redir ( msg , type , plan , present , 0 , 0 , redir ) ;
}
/* complete channel negotiation */
rc = dec_ie_channel_id ( l3m , call - > isdn_ep - > pri , & exclusive , & channel ) ;
rc = open_bchannel_out ( call , cmd , ( rc < 0 ) ? - 1 : channel , ( rc < 0 ) ? - 1 : exclusive ) ;
if ( rc < 0 ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_NOTICE , " Channel negotiation failed. \n " ) ;
2020-01-25 07:50:20 +00:00
osmo_cc_free_msg ( msg ) ;
release_and_destroy ( call , OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL , 0 , - rc ) ;
return ;
}
/* send SDP answer */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) & & ! call - > codec_negotiated ) {
call - > codec_negotiated = 1 ;
2022-08-19 14:27:41 +00:00
if ( call - > sdp ) {
/* send SDP */
2020-01-25 07:50:20 +00:00
osmo_cc_add_ie_sdp ( msg , call - > sdp ) ;
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 1 ) ;
}
2020-01-25 07:50:20 +00:00
}
/* the audio path is throughconnected */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) )
call - > audio_path = 1 ;
new_state ( call , ISDN_STATE_OUT_PROCEEDING ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* CC-ALERTING INDICATION */
void alert_ind ( call_t * call , uint32_t cmd , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
int exclusive , channel ;
uint8_t coding , location , progress ;
uint8_t notify , type , plan , present ;
int has_present ;
char redir [ 32 ] ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " ALERTING INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_ALERT_IND ) ;
/* progress indicator */
rc = dec_ie_progress ( l3m , & coding , & location , & progress ) ;
if ( rc > = 0 )
osmo_cc_add_ie_progress ( msg , coding , location , progress ) ;
else {
coding = OSMO_CC_CODING_ITU_T ;
progress = 0 ;
}
/* display */
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
/* notify */
rc = dec_ie_notify ( l3m , & notify ) ;
if ( rc > = 0 )
osmo_cc_add_ie_notify ( msg , notify ) ;
/* redir info */
rc = dec_ie_redirection ( l3m , & type , & plan , & has_present , & present , redir , sizeof ( redir ) ) ;
if ( rc > = 0 ) {
if ( ! has_present )
present = 0 ;
osmo_cc_add_ie_redir ( msg , type , plan , present , 0 , 0 , redir ) ;
}
/* complete channel negotiation */
rc = dec_ie_channel_id ( l3m , call - > isdn_ep - > pri , & exclusive , & channel ) ;
rc = open_bchannel_out ( call , cmd , ( rc < 0 ) ? - 1 : channel , ( rc < 0 ) ? - 1 : exclusive ) ;
if ( rc < 0 ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_NOTICE , " Channel negotiation failed. \n " ) ;
2020-01-25 07:50:20 +00:00
osmo_cc_free_msg ( msg ) ;
release_and_destroy ( call , OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL , 0 , - rc ) ;
return ;
}
/* send SDP answer */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) & & ! call - > codec_negotiated ) {
call - > codec_negotiated = 1 ;
2022-08-19 14:27:41 +00:00
if ( call - > sdp ) {
/* send SDP */
2020-01-25 07:50:20 +00:00
osmo_cc_add_ie_sdp ( msg , call - > sdp ) ;
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 1 ) ;
}
2020-01-25 07:50:20 +00:00
}
/* the audio path is throughconnected */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) )
call - > audio_path = 1 ;
new_state ( call , ISDN_STATE_OUT_ALERTING ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* CC-CONNECT INDICATION */
void setup_cnf ( call_t * call , uint32_t cmd , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
int exclusive , channel ;
uint8_t coding , location , progress ;
uint8_t type , plan , present , screen ;
int has_present ;
char connected [ 33 ] ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " CONNECT INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_SETUP_CNF ) ;
/* progress indicator */
rc = dec_ie_progress ( l3m , & coding , & location , & progress ) ;
if ( rc > = 0 )
osmo_cc_add_ie_progress ( msg , coding , location , progress ) ;
else {
coding = OSMO_CC_CODING_ITU_T ;
progress = 0 ;
}
/* display */
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
/* connected info */
rc = dec_ie_connected_pn ( l3m , & type , & plan , & has_present , & present , & screen , connected , sizeof ( connected ) ) ;
if ( rc > = 0 ) {
if ( ! has_present )
present = screen = 0 ;
osmo_cc_add_ie_calling ( msg , type , plan , present , screen , connected ) ;
/* secondary connected info */
rc = dec_ie_connected_pn ( l3m , & type , & plan , & has_present , & present , & screen , connected , sizeof ( connected ) ) ;
if ( rc > = 0 ) {
if ( ! has_present )
present = screen = 0 ;
osmo_cc_add_ie_calling ( msg , type , plan , present , screen , connected ) ;
}
}
/* if we have no channel (answer call with no channel) we use this flag to assign later */
rc = dec_ie_channel_id ( l3m , call - > isdn_ep - > pri , & exclusive , & channel ) ;
if ( rc < 0 ) {
channel = - 1 ;
exclusive = - 1 ;
}
if ( channel < 0 )
call - > setup_comp_req_channel_assignment = 1 ;
/* complete channel negotiation */
rc = open_bchannel_out ( call , cmd , channel , exclusive ) ; /* channel and exclusive may be -1 */
if ( rc < 0 ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_NOTICE , " Channel negotiation failed. \n " ) ;
2020-01-25 07:50:20 +00:00
osmo_cc_free_msg ( msg ) ;
release_and_destroy ( call , OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL , 0 , - rc ) ;
return ;
}
/* send SDP answer */
if ( ! call - > codec_negotiated ) {
call - > codec_negotiated = 1 ;
2022-08-19 14:27:41 +00:00
if ( call - > sdp ) {
/* send SDP */
2020-01-25 07:50:20 +00:00
osmo_cc_add_ie_sdp ( msg , call - > sdp ) ;
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 1 ) ;
}
2020-01-25 07:50:20 +00:00
}
/* the audio path is throughconnected */
call - > audio_path = 1 ;
new_state ( call , ISDN_STATE_OUT_CONNECTING ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* CC-CONNECT-ACKNOWLEDGE INDICATION */
void setup_comp_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " CONNECT-ACKNOWLEDGE INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* only send in TE mode, because we automatically reply in NT mode */
if ( call - > isdn_ep - > ntmode )
return ;
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_SETUP_COMP_IND ) ;
/* display */
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
new_state ( call , ISDN_STATE_CONNECT ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* CC-INFORMATION INDICATION */
void info_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t type , plan ;
int sending_complete ;
char called [ 33 ] ;
char keypad [ 33 ] ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " INFO INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_INFO_IND ) ;
/* dialing information */
rc = dec_ie_called_pn ( l3m , & type , & plan , called , sizeof ( called ) ) ;
if ( rc > = 0 ) {
osmo_cc_add_ie_called ( msg , type , plan , called ) ;
if ( called [ 0 ] )
call - > any_dialing = 1 ;
}
/* keypad */
rc = dec_ie_keypad ( l3m , keypad , sizeof ( keypad ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_keypad ( msg , keypad ) ;
/* display */
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
/* dialing complete */
dec_ie_complete ( l3m , & sending_complete ) ;
if ( sending_complete ) {
call - > sending_complete = 1 ;
osmo_cc_add_ie_complete ( msg ) ;
}
/* reset overlap timeout */ // FIXME: is this still required?
new_state ( call , call - > state ) ;
/* stop tone, if something has been dialled */
if ( call - > send_local_tones & & call - > any_dialing & & call - > state = = ISDN_STATE_IN_OVERLAP ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Stop sending locally generated dial tone. (if not already) \n " ) ;
2020-01-25 07:50:20 +00:00
bchannel_tone ( call , 0 ) ;
}
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* CC-DISCONNECT INDICATION */
void disconnect_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t location , cause ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " DISCONNECT INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_DISC_IND ) ;
/* cause */
rc = dec_ie_cause ( l3m , & location , & cause ) ;
if ( rc < 0 ) {
cause = 0 ;
location = call - > isdn_ep - > serving_location ;
}
osmo_cc_add_ie_cause ( msg , location , cause , 0 , 0 ) ;
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
2022-08-19 14:27:41 +00:00
/* note: disconnect does not assign channel ID */
2020-01-25 07:50:20 +00:00
2022-08-19 14:27:41 +00:00
/* note: disconnect does not have progress indicator */
2020-01-25 07:50:20 +00:00
new_state ( call , ISDN_STATE_IN_DISCONNECT ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
2024-01-09 12:28:05 +00:00
/* stop AOC-D timer */
if ( call - > aocd_unit_timer_started )
{
osmo_timer_del ( & call - > aocd_unit_timer ) ;
call - > aocd_unit_timer_started = 0 ;
}
2020-01-25 07:50:20 +00:00
}
/* CC-DISCONNECT INDICATION of child instance */
void disconnect_ind_i ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
uint8_t location , cause ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " DISCONNECT INDICATION of child (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* collect cause */
rc = dec_ie_cause ( l3m , & location , & cause ) ;
if ( rc > = 0 ) {
call - > collect_cause = osmo_cc_collect_cause ( call - > collect_cause , cause ) ;
call - > collect_location = location ;
}
}
/* CC-RELEASE INDICATION */
void release_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t location , cause ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RELEASE INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_REL_IND ) ;
/* cause */
rc = dec_ie_cause ( l3m , & location , & cause ) ;
if ( rc < 0 ) {
cause = 0 ;
location = call - > isdn_ep - > serving_location ;
}
osmo_cc_add_ie_cause ( msg , location , cause , 0 , 0 ) ;
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* call terminated */
new_state ( call , ISDN_STATE_IDLE ) ;
split_3pty ( call ) ;
call_destroy ( call ) ;
}
/* CC-RELEASE-COMPLETE INDICATION (a reject) */
void release_complete_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t location , cause ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RELEASE-COMPLETE INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
switch ( call - > state ) {
case ISDN_STATE_OUT_SETUP :
msg = osmo_cc_new_msg ( OSMO_CC_MSG_REJ_IND ) ;
break ;
case ISDN_STATE_OUT_RELEASE :
msg = osmo_cc_new_msg ( OSMO_CC_MSG_REL_CNF ) ;
break ;
default :
msg = osmo_cc_new_msg ( OSMO_CC_MSG_REL_IND ) ;
}
/* cause */
2023-01-22 18:50:20 +00:00
/* in case layer 1 is down during setup, we send cause 27 */
2020-01-25 07:50:20 +00:00
if ( call - > state = = ISDN_STATE_OUT_SETUP & & call - > isdn_ep - > l1link = = 0 ) {
cause = 27 ;
location = call - > isdn_ep - > serving_location ;
} else {
rc = dec_ie_cause ( l3m , & location , & cause ) ;
if ( rc < 0 ) {
cause = 0 ;
location = call - > isdn_ep - > serving_location ;
}
}
osmo_cc_add_ie_cause ( msg , location , cause , 0 , 0 ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* call terminated */
new_state ( call , ISDN_STATE_IDLE ) ;
split_3pty ( call ) ;
call_destroy ( call ) ;
}
/* CC-RESTART INDICATION */
void restart_ind ( uint32_t pid )
{
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RESTART INDICATION (pid = 0x%x) \n " , pid ) ;
2020-01-25 07:50:20 +00:00
// L3 process is not touched. (not even by network stack)
}
/* T312 timeout */
void t312_timeout_ind ( void )
{
// not required, release is performed with MT_FREE
}
/* CC-NOTIFY INDICATION */
void notify_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t notify , type , plan , present ;
int has_present ;
char redir [ 33 ] ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " NOTIFY INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_NOTIFY_IND ) ;
/* notify */
rc = dec_ie_notify ( l3m , & notify ) ;
if ( rc > = 0 )
osmo_cc_add_ie_notify ( msg , notify ) ;
else {
osmo_cc_free_msg ( msg ) ;
return ;
}
/* redirection number */
rc = dec_ie_redirection ( l3m , & type , & plan , & has_present , & present , redir , sizeof ( redir ) ) ;
if ( rc > = 0 ) {
if ( ! has_present )
present = 0 ;
osmo_cc_add_ie_redir ( msg , type , plan , present , 0 , 0 , redir ) ;
}
/* display */
rc = dec_ie_display ( l3m , display , sizeof ( display ) ) ;
if ( rc > = 0 )
osmo_cc_add_ie_display ( msg , display ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* CC-HOLD INDICATION */
void hold_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " HOLD INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* reject, if we are on hold */
if ( call - > hold ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " HOLD-REJECT REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
enc_ie_cause ( l3m , call - > isdn_ep - > serving_location , call - > hold ? 101 : 31 ) ; /* normal unspecified / incompatible state */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_HOLD_REJECT , call - > l3_pid , l3m ) ;
return ;
}
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 0 ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_NOTIFY_IND ) ;
/* notify the hold of call */
osmo_cc_add_ie_notify ( msg , OSMO_CC_NOTIFY_REMOTE_HOLD ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* deactivate bchannel */
drop_bchannel ( call ) ;
/* set hold state */
call - > hold = 1 ;
2022-10-30 15:14:17 +00:00
/* reset jitter buffer, to ignore packets coming from remote */
jitter_reset ( & call - > tx_dejitter ) ;
2020-01-25 07:50:20 +00:00
2023-01-21 17:11:20 +00:00
/* generate hold tone, using local clock */
enable_hold_clock ( call - > isdn_ep ) ;
2020-01-25 07:50:20 +00:00
/* acknowledge hold */
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " HOLD-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_HOLD_ACKNOWLEDGE , call - > l3_pid , l3m ) ;
}
/* CC-RETRIEVE INDICATION */
void retrieve_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
int channel , exclusive ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RETRIEVE INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
if ( ! call - > hold ) {
rc = - 101 ; /* incompatible state */
no_channel :
/* reject retrieve */
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RETRIEVE-REJECT REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
enc_ie_cause ( l3m , call - > isdn_ep - > serving_location , rc ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_RETRIEVE_REJECT , call - > l3_pid , l3m ) ;
return ;
}
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_NOTIFY_IND ) ;
/* notify the retrieve of call */
osmo_cc_add_ie_notify ( msg , OSMO_CC_NOTIFY_REMOTE_RETRIEVAL ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* hunt channel */
dec_ie_channel_id ( l3m , call - > isdn_ep - > pri , & exclusive , & channel ) ;
rc = channel = hunt_bchannel_in ( call - > isdn_ep , channel , exclusive ) ;
if ( rc < 0 )
goto no_channel ;
/* open channel */
rc = open_bchannel_in ( call , channel , 1 ) ;
if ( rc < 0 )
goto no_channel ;
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 1 ) ;
2020-01-25 07:50:20 +00:00
/* set hold state */
call - > hold = 0 ;
2022-08-19 14:27:41 +00:00
/* reset jitter buffer */
jitter_reset ( & call - > tx_dejitter ) ;
2020-01-25 07:50:20 +00:00
/* acknowledge retrieve */
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RETRIEVE-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
enc_ie_channel_id ( l3m , call - > isdn_ep - > pri , 1 , call - > b_channel ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_RETRIEVE_ACKNOWLEDGE , call - > l3_pid , l3m ) ;
}
/* CC-SUSPEND INDICATION */
void suspend_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t callid [ 8 ] ;
int len ;
int rc = - 31 ; /* normal, unspecified */
call_t * check ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " SUSPEND INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
if ( 0 ) {
reject :
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " SUSPEND-REJECT REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
enc_ie_cause ( l3m , call - > isdn_ep - > serving_location , - rc ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_SUSPEND_REJECT , call - > l3_pid , l3m ) ;
return ;
}
/* call id */
rc = dec_ie_call_id ( l3m , callid , & len ) ;
if ( rc < 0 )
len = 0 ;
/* check if call id is in use */
check = call - > isdn_ep - > call_list ;
while ( check ) {
if ( check - > state = = ISDN_STATE_SUSPENDED
& & check - > park_len = = len
& & ! memcmp ( check - > park_callid , callid , len ) ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " Given Park ID is already in use, rejecting! \n " ) ;
2020-01-25 07:50:20 +00:00
rc = - 84 ; /* call id in use */
goto reject ;
}
check = check - > next ;
}
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 0 ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_NOTIFY_IND ) ;
/* notify the suspension of call */
osmo_cc_add_ie_notify ( msg , OSMO_CC_NOTIFY_USER_SUSPENDED ) ;
new_state ( call , ISDN_STATE_SUSPENDED ) ;
2022-09-17 13:00:11 +00:00
memcpy ( call - > park_callid , callid , len ) ;
call - > park_len = len ;
2022-10-30 15:14:17 +00:00
/* reset jitter buffer, to ignore packets coming from remote */
jitter_reset ( & call - > tx_dejitter ) ;
2020-01-25 07:50:20 +00:00
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* deactivate bchannel */
drop_bchannel ( call ) ;
2023-01-21 17:11:20 +00:00
/* generate hold tone, using local clock */
enable_hold_clock ( call - > isdn_ep ) ;
2020-01-25 07:50:20 +00:00
/* sending SUSPEND_ACKNOWLEDGE */
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " SUSPEND-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_SUSPEND_ACKNOWLEDGE , call - > l3_pid , l3m ) ;
}
/* CC-RESUME INDICATION */
void resume_ind ( isdn_t * isdn_ep , uint32_t pid , struct l3_msg * l3m )
{
call_t * call ;
osmo_cc_msg_t * msg ;
uint8_t callid [ 8 ] ;
int len ;
int channel , exclusive ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RESUME INDICATION (pid = 0x%x) \n " , pid ) ;
2020-01-25 07:50:20 +00:00
/* call id */
rc = dec_ie_call_id ( l3m , callid , & len ) ;
if ( rc < 0 )
len = 0 ;
/* check if call id is in use */
call = isdn_ep - > call_list ;
while ( call ) {
if ( call - > state = = ISDN_STATE_SUSPENDED
& & call - > park_len = = len
& & ! memcmp ( call - > park_callid , callid , len ) )
break ;
call = call - > next ;
}
/* process given callref */
if ( ! call ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_NOTICE , " No parked call found with given park ID, rejecting. \n " ) ;
2020-01-25 07:50:20 +00:00
rc = - 85 ;
no_channel :
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RESUME-REJECT REQUEST (pid = 0x%x) \n " , pid ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
2022-09-17 13:00:11 +00:00
enc_ie_cause ( l3m , isdn_ep - > serving_location , - rc ) ;
2020-01-25 07:50:20 +00:00
isdn_ep - > ml3 - > to_layer3 ( isdn_ep - > ml3 , MT_RESUME_REJECT , pid , l3m ) ;
return ;
}
2021-01-01 21:13:47 +00:00
/* assign pid */
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " new L3ID assigned (l3id = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
call - > l3_pid = pid ;
call - > l3_ces = pid > > 16 ;
/* channel_id (no channel is possible in message) */
exclusive = 0 ;
channel = - 1 ; /* any channel */
/* hunt channel */
rc = channel = hunt_bchannel_in ( call - > isdn_ep , channel , exclusive ) ;
if ( rc < 0 )
goto no_channel ;
/* open channel */
rc = open_bchannel_in ( call , channel , 1 ) ;
if ( rc < 0 )
goto no_channel ;
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 1 ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_NOTIFY_IND ) ;
/* notify the resume of call */
osmo_cc_add_ie_notify ( msg , OSMO_CC_NOTIFY_USER_RESUMED ) ;
new_state ( call , ISDN_STATE_CONNECT ) ;
2022-10-30 15:14:17 +00:00
/* reset jitter buffer */
jitter_reset ( & call - > tx_dejitter ) ;
2020-01-25 07:50:20 +00:00
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* sending RESUME_ACKNOWLEDGE */
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RESUME-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
l3m = create_l3msg ( ) ;
enc_ie_channel_id ( l3m , call - > isdn_ep - > pri , 1 , call - > b_channel ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_RESUME_ACKNOWLEDGE , call - > l3_pid , l3m ) ;
}
/* CC-FACILITY INDICATION */
void facility_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t fac_ie [ 256 ] ;
struct asn1_parm fac ;
int fac_len ;
uint8_t invokeid = 0 ;
int set_3pty = - 1 ;
uint8_t notify = 0 ;
call_t * other ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " FACILITY INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* facility */
rc = dec_ie_facility ( l3m , fac_ie + 1 , & fac_len ) ;
if ( rc < 0 )
return ;
fac_ie [ 0 ] = fac_len ;
if ( fac_len < = 0 )
return ;
decodeFac ( fac_ie , & fac ) ;
switch ( fac . comp ) {
case CompInvoke :
switch ( fac . u . inv . operationValue ) {
case Fac_Begin3PTY :
notify = OSMO_CC_NOTIFY_CONFERENCE_ESTABLISHED ;
invokeid = fac . u . inv . invokeId ;
set_3pty = 1 ;
break ;
case Fac_End3PTY :
notify = OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED ;
invokeid = fac . u . inv . invokeId ;
set_3pty = 0 ;
break ;
default :
2024-01-10 16:57:50 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Facility Operation=%x of Component=%x not implemented \n " , fac . u . inv . operationValue , fac . comp ) ;
break ;
2020-01-25 07:50:20 +00:00
}
break ;
default :
2024-01-10 16:57:50 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Facility Operation=%x of Component=%x not implemented \n " , fac . u . inv . operationValue , fac . comp ) ;
break ;
2020-01-25 07:50:20 +00:00
}
2024-01-10 16:57:50 +00:00
if ( set_3pty > = 0 ) {
/* find other terminal on hold */
other = call - > isdn_ep - > call_list ;
while ( other ) {
// printf("check: call=%p other=%p call_ces=%x other_ces=%x other_hold=%d\n", call, other, call->l3_ces, other->l3_ces, other->hold);
if ( other ! = call
& & other - > l3_ces = = call - > l3_ces ) {
/* if we got facility on active call */
if ( other - > hold & & ! call - > hold )
break ;
/* if we got facility on active call */
if ( ! other - > hold & & call - > hold )
break ;
}
other = other - > next ;
}
if ( other ) {
other - > conference_3pty = call - > conference_3pty = set_3pty ;
/* process local briding capability */
bridge_socket_client_update ( call , 0 ) ;
bridge_socket_client_update ( other , 0 ) ;
jitter_reset ( & call - > conf_dejitter ) ;
jitter_reset ( & call - > tx_dejitter ) ;
jitter_reset ( & other - > conf_dejitter ) ;
jitter_reset ( & other - > tx_dejitter ) ;
} else {
LOGP ( DDSS1 , LOGL_NOTICE , " Phone requests conference, but no call on hold! \n " ) ;
notify = 0 ;
2020-01-25 07:50:20 +00:00
}
2024-01-10 16:57:50 +00:00
/* encode 3PTY facility */
memset ( & fac , 0 , sizeof ( fac ) ) ;
fac . Valid = 1 ;
if ( notify ) {
fac . comp = CompReturnResult ;
fac . u . retResult . invokeId = invokeid ;
fac . u . retResult . operationValuePresent = 1 ;
if ( notify = = OSMO_CC_NOTIFY_CONFERENCE_ESTABLISHED )
fac . u . retResult . operationValue = Fac_Begin3PTY ;
if ( notify = = OSMO_CC_NOTIFY_CONFERENCE_DISCONNECTED )
fac . u . retResult . operationValue = Fac_End3PTY ;
} else {
fac . comp = CompReturnError ;
fac . u . retError . invokeId = invokeid ;
fac . u . retError . errorValue = FacError_Gen_InvalidCallState ;
}
encodeFac ( fac_ie , & fac ) ;
2020-01-25 07:50:20 +00:00
2024-01-10 16:57:50 +00:00
/* sending facility */
l3m = create_l3msg ( ) ;
enc_ie_facility ( l3m , fac_ie + 2 , fac_ie [ 1 ] ) ;
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_FACILITY , call - > l3_pid , l3m ) ;
if ( notify ) {
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_NOTIFY_IND ) ;
/* notify the facility */
osmo_cc_add_ie_notify ( msg , notify ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_NOTIFY_IND ) ;
/* notify the facility */
osmo_cc_add_ie_notify ( msg , notify ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & other - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
2020-01-25 07:50:20 +00:00
}
}
/* CC-PROGRESS INDICATION */
void progress_ind ( call_t * call , uint32_t pid , struct l3_msg * l3m )
{
osmo_cc_msg_t * msg ;
uint8_t coding , location , progress ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " PROGRESS INDICATION (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_PROGRESS_IND ) ;
/* progress indicator */
rc = dec_ie_progress ( l3m , & coding , & location , & progress ) ;
if ( rc > = 0 )
osmo_cc_add_ie_progress ( msg , coding , location , progress ) ;
else {
coding = OSMO_CC_CODING_ITU_T ;
progress = 0 ;
}
/* send SDP answer */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) & & ! call - > codec_negotiated ) {
call - > codec_negotiated = 1 ;
2022-08-19 14:27:41 +00:00
if ( call - > sdp ) {
/* send SDP */
2020-01-25 07:50:20 +00:00
osmo_cc_add_ie_sdp ( msg , call - > sdp ) ;
2022-08-19 14:27:41 +00:00
/* process local briding capability */
bridge_socket_client_update ( call , 1 ) ;
}
2020-01-25 07:50:20 +00:00
}
/* the audio path is throughconnected */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) )
call - > audio_path = 1 ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* all calls from multipoint interface have released */
void mt_free ( call_t * call )
{
osmo_cc_msg_t * msg ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Got MT_FREE (release from stack) (old pid 0x%x) \n " , call - > l3_pid ) ;
2020-01-25 07:50:20 +00:00
/* create osmo-cc message */
switch ( call - > state ) {
case ISDN_STATE_OUT_SETUP :
msg = osmo_cc_new_msg ( OSMO_CC_MSG_REJ_IND ) ;
break ;
2022-09-17 13:00:11 +00:00
case ISDN_STATE_SUSPENDED :
return ;
2020-01-25 07:50:20 +00:00
default :
msg = osmo_cc_new_msg ( OSMO_CC_MSG_REL_IND ) ;
}
/* cause */
osmo_cc_add_ie_cause ( msg , call - > collect_location , call - > collect_cause , 0 , 0 ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* terminate call */
new_state ( call , ISDN_STATE_IDLE ) ;
call_destroy ( call ) ;
}
/* take DSS1 message type and call sub routines (above) to handle each message */
void dss1_message ( isdn_t * isdn_ep , call_t * call , uint32_t cmd , uint32_t pid , struct l3_msg * l3m )
{
int timer = 0 ;
switch ( cmd ) {
case MT_TIMEOUT :
if ( ! l3m - > cause ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " timeout without cause. \n " ) ;
2020-01-25 07:50:20 +00:00
break ;
}
if ( l3m - > cause [ 0 ] ! = 5 ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " expecting timeout with timer diagnostic. (got len=%d) \n " , l3m - > cause [ 0 ] ) ;
2020-01-25 07:50:20 +00:00
break ;
}
timer = ( l3m - > cause [ 3 ] - ' 0 ' ) * 100 ;
timer + = ( l3m - > cause [ 4 ] - ' 0 ' ) * 10 ;
timer + = ( l3m - > cause [ 5 ] - ' 0 ' ) ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " isdn timer T%d timeout \n " , timer ) ;
2020-01-25 07:50:20 +00:00
if ( timer = = 312 )
t312_timeout_ind ( ) ;
break ;
case MT_SETUP :
if ( call - > state ! = ISDN_STATE_IDLE )
break ;
setup_ind ( call , pid , l3m ) ;
break ;
case MT_SETUP_ACKNOWLEDGE :
setup_ack_ind ( call , cmd , pid , l3m ) ;
break ;
case MT_CALL_PROCEEDING :
proc_ind ( call , cmd , pid , l3m ) ;
break ;
case MT_ALERTING :
alert_ind ( call , cmd , pid , l3m ) ;
break ;
case MT_CONNECT :
setup_cnf ( call , cmd , pid , l3m ) ;
break ;
case MT_CONNECT_ACKNOWLEDGE :
setup_comp_ind ( call , pid , l3m ) ;
break ;
case MT_INFORMATION :
info_ind ( call , pid , l3m ) ;
break ;
case MT_DISCONNECT :
disconnect_ind ( call , pid , l3m ) ;
break ;
case MT_RELEASE :
release_ind ( call , pid , l3m ) ;
break ;
case MT_RELEASE_COMPLETE :
release_complete_ind ( call , pid , l3m ) ;
break ;
case MT_RESTART :
restart_ind ( pid ) ;
break ;
case MT_NOTIFY :
notify_ind ( call , pid , l3m ) ;
break ;
case MT_HOLD :
hold_ind ( call , pid , l3m ) ;
break ;
case MT_RETRIEVE :
retrieve_ind ( call , pid , l3m ) ;
break ;
case MT_SUSPEND :
suspend_ind ( call , pid , l3m ) ;
break ;
case MT_RESUME :
resume_ind ( isdn_ep , pid , l3m ) ;
break ;
case MT_FACILITY :
facility_ind ( call , pid , l3m ) ;
break ;
case MT_PROGRESS :
progress_ind ( call , pid , l3m ) ;
break ;
case MT_FREE :
mt_free ( call ) ;
break ;
default :
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " unhandled message: cmd(0x%x) pid(0x%x) \n " , cmd , pid ) ;
2020-01-25 07:50:20 +00:00
}
}
/* receive message from L3 stack and associate with a call instance by searching or creating it */
int dss1_receive ( isdn_t * isdn_ep , uint32_t cmd , uint32_t pid , struct l3_msg * l3m )
{
call_t * call ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " message from L3 stack: cmd(0x%x) pid(0x%x) \n " , cmd , pid ) ;
2020-01-25 07:50:20 +00:00
/* find call that is associated with the pid */
call = isdn_ep - > call_list ;
while ( call ) {
if ( call - > l3_pid & MISDN_PID_CR_FLAG ) {
/* local callref, so match value only */
if ( ( call - > l3_pid & MISDN_PID_CRVAL_MASK ) = = ( pid & MISDN_PID_CRVAL_MASK ) ) {
break ;
}
} else {
/* remote callref, ref + channel id */
if ( call - > l3_pid = = pid ) {
break ;
}
}
call = call - > next ;
}
/* messages for a call */
if ( call ) {
/* after answering the phone, the PID will be completed and CES will be assigned */
if ( cmd = = MT_ASSIGN ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Got assignment (old pid 0x%x, new pid 0x%x) \n " , call - > l3_pid , pid ) ;
2020-01-25 07:50:20 +00:00
if ( ( call - > l3_pid & MISDN_PID_CRTYPE_MASK ) ! = MISDN_PID_MASTER )
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " strange setup-procid 0x%x \n " , call - > l3_pid ) ;
2020-01-25 07:50:20 +00:00
call - > l3_pid = pid ;
if ( call - > state = = ISDN_STATE_OUT_CONNECTING | | call - > state = = ISDN_STATE_CONNECT )
call - > l3_ces = pid > > 16 ;
}
/* if process id is master process, but a child disconnects */
if ( call - > isdn_ep - > ntmode
& & ( pid & MISDN_PID_CRTYPE_MASK ) ! = MISDN_PID_MASTER
& & ( call - > l3_pid & MISDN_PID_CRTYPE_MASK ) = = MISDN_PID_MASTER ) {
if ( cmd = = MT_DISCONNECT | | cmd = = MT_RELEASE ) {
/* send special indication for child disconnect */
disconnect_ind_i ( call , pid , l3m ) ;
return 0 ;
}
if ( cmd = = MT_RELEASE_COMPLETE )
return 0 ;
}
/* if we have child pid and got different child pid message, ignore */
if ( call - > isdn_ep - > ntmode
& & ( pid & MISDN_PID_CRTYPE_MASK ) ! = MISDN_PID_MASTER
& & ( call - > l3_pid & MISDN_PID_CRTYPE_MASK ) ! = MISDN_PID_MASTER
& & pid ! = call - > l3_pid )
return 0 ;
/* process message */
dss1_message ( isdn_ep , call , cmd , pid , l3m ) ;
return 0 ;
}
/* messages without call */
switch ( cmd ) {
case MT_SETUP :
/* creating call instance, transparent until setup with hdlc */
2022-06-24 17:58:41 +00:00
call = call_create ( isdn_ep , DIRECTION_ORIGINATOR , 0 , 0 , B_MODE_TRANSPARENT ) ;
2020-01-25 07:50:20 +00:00
if ( ! call ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " Cannot create call instance. \n " ) ;
2020-01-25 07:50:20 +00:00
abort ( ) ;
}
dss1_message ( isdn_ep , call , cmd , pid , l3m ) ;
break ;
case MT_RESUME :
/* resume existing call instance */
dss1_message ( isdn_ep , NULL , cmd , pid , l3m ) ;
break ;
case MT_FREE :
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " unused L3ID released (pid = 0x%x, call->cc_callref) \n " , pid ) ;
2020-01-25 07:50:20 +00:00
break ;
case MT_RELEASE_COMPLETE :
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " MT_RELEASE_COMPLETE must be ignored by stack, not sent to app \n " ) ;
2020-01-25 07:50:20 +00:00
break ;
case MT_FACILITY :
// facility als broadcast
break ;
case MT_L2IDLE :
// L2 became idle - we could sent a MT_L2RELEASE if we are the L2 master
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Got L2 idle \n " ) ;
2020-01-25 07:50:20 +00:00
break ;
default :
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " unhandled message: cmd(0x%x) pid(0x%x) \n " , cmd , pid ) ;
2020-01-25 07:50:20 +00:00
return - EINVAL ;
}
return 0 ;
}
/*
* handles all requests from osmo - cc
*/
/* CC-SETUP REQUEST */
void setup_req ( call_t * call , osmo_cc_msg_t * msg )
{
const char * sdp ;
struct l3_msg * l3m ;
uint8_t plan , type , screen , present , reason ;
uint8_t capability , mode , rate , coding , user ;
// uint8_t presentation, interpretation, hlc, exthlc;
int has_user ;
char callerid [ 33 ] ;
char dialing [ 33 ] ;
char redir [ 33 ] ;
char keypad [ 33 ] ;
char display [ 128 ] ;
int channel , exclusive ;
int rc ;
2022-07-03 19:06:17 +00:00
struct osmo_cc_helper_audio_codecs * codecs ;
2020-01-25 07:50:20 +00:00
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " SETUP REQUEST \n " ) ;
2020-01-25 07:50:20 +00:00
2022-07-03 19:06:17 +00:00
/* select codec */
if ( call - > isdn_ep - > law = = ' a ' )
codecs = codecs_accept_alaw_ulaw_clearmode ;
else
codecs = codecs_accept_ulaw_alaw_clearmode ;
2022-06-24 17:58:41 +00:00
/* sdp accept, force our codec, so we can use bchannel bridging if remote side supports it too */
2022-08-19 14:27:41 +00:00
sdp = osmo_cc_helper_audio_accept ( & call - > isdn_ep - > cc_ep . session_config , call , codecs , rtp_receive , msg , & call - > cc_session , & call - > codec , 1 /*force*/ ) ;
2020-01-25 07:50:20 +00:00
if ( ! sdp ) {
release_and_destroy ( call , 47 , 415 /* Unsupported Media*/ , 0 ) ;
return ;
}
call - > sdp = strdup ( sdp ) ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " Codec %s selected for transmission. \n " , call - > codec - > payload_name ) ;
2020-01-25 07:50:20 +00:00
/* get channel */
2022-05-01 08:10:35 +00:00
rc = hunt_bchannel_out ( call - > isdn_ep , & channel , & exclusive ) ;
2020-01-25 07:50:20 +00:00
if ( rc < 0 ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_NOTICE , " There is no channel available on the interface. \n " ) ;
2020-01-25 07:50:20 +00:00
release_and_destroy ( call , - rc , 0 , 0 ) ;
return ;
}
2022-05-01 08:10:35 +00:00
/* must seize it, if we gave a channel, so that requested channel is stored in call instance */
if ( channel )
seize_bchannel ( call , channel , exclusive ) ;
2020-01-25 07:50:20 +00:00
/* creating pid */
call - > l3_pid = request_new_pid ( call - > isdn_ep - > ml3 ) ;
if ( call - > l3_pid = = MISDN_PID_NONE ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_NOTICE , " There is no free L3ID on the mISDN stack, please restart! \n " ) ;
2020-01-25 07:50:20 +00:00
release_and_destroy ( call , OSMO_CC_ISDN_CAUSE_RESOURCE_UNAVAIL , 0 , 0 ) ;
return ;
}
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " new L3ID assigned (pid = 0x%x) \n " , call - > l3_pid ) ;
2020-01-25 07:50:20 +00:00
/* creating setup */
l3m = create_l3msg ( ) ;
2022-07-03 19:06:17 +00:00
/* bearer capability */
2020-01-25 07:50:20 +00:00
rc = osmo_cc_get_ie_bearer ( msg , 0 , & coding , & capability , & mode ) ;
if ( rc < 0 ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " No bearer capability given, generating from selected codec. \n " ) ;
2020-01-25 07:50:20 +00:00
coding = OSMO_CC_CODING_ITU_T ;
2022-07-03 19:06:17 +00:00
if ( ! strcmp ( call - > codec - > payload_name , " CLEARMODE " ) ) {
capability = OSMO_CC_CAPABILITY_DATA ;
mode = OSMO_CC_MODE_CIRCUIT ;
} else {
capability = OSMO_CC_CAPABILITY_AUDIO ;
mode = OSMO_CC_MODE_CIRCUIT ;
}
} else
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Bearer capability given, override what is defined by selected codec. \n " ) ;
2020-01-25 07:50:20 +00:00
rate = ( mode = = OSMO_CC_MODE_PACKET ) ? 0x00 : 0x10 ;
2022-07-03 19:06:17 +00:00
if ( capability = = OSMO_CC_CAPABILITY_AUDIO | | capability = = OSMO_CC_CAPABILITY_SPEECH ) {
2020-01-25 07:50:20 +00:00
has_user = 1 ;
2022-07-03 19:06:17 +00:00
if ( call - > isdn_ep - > law = = ' u ' )
user = 2 ;
else
user = 3 ;
2022-08-19 14:27:41 +00:00
/* init jitter buffer */
call_create_jitter ( call , 0 ) ;
2022-07-03 19:06:17 +00:00
} else {
has_user = 0 ;
user = 0 ;
2022-08-19 14:27:41 +00:00
/* init jitter buffer */
call_create_jitter ( call , 1 ) ;
2020-01-25 07:50:20 +00:00
}
enc_ie_bearer ( l3m , coding , capability , 1 , mode , rate , 0 , 0 , has_user , user ) ;
/* channel information */
if ( call - > isdn_ep - > ntmode | | channel ! = CHANNEL_ANY ) /* only omit channel id in te-mode/any channel */
enc_ie_channel_id ( l3m , call - > isdn_ep - > pri , exclusive , channel ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
/* keypad */
rc = osmo_cc_get_ie_keypad ( msg , 0 , keypad , sizeof ( keypad ) ) ;
if ( rc > = 0 )
enc_ie_keypad ( l3m , keypad ) ;
/* caller information */
rc = osmo_cc_get_ie_calling ( msg , 0 , & type , & plan , & present , & screen , callerid , sizeof ( callerid ) ) ;
if ( rc > = 0 ) {
enc_ie_calling_pn ( l3m , type , plan , 1 , present , screen , callerid ) ;
/* secondary caller info */
rc = osmo_cc_get_ie_calling ( msg , 1 , & type , & plan , & present , & screen , callerid , sizeof ( callerid ) ) ;
if ( rc > = 0 )
enc_ie_calling_pn ( l3m , type , 1 , plan , present , screen , callerid ) ;
}
/* dialing information */
rc = osmo_cc_get_ie_called ( msg , 0 , & type , & plan , dialing , sizeof ( dialing ) ) ;
if ( rc > = 0 ) {
/* check MSN */
struct msn_list * m = call - > isdn_ep - > msn_list ;
if ( m ) {
/* we have an MSN list */
while ( m ) {
if ( ! strcmp ( dialing , m - > msn ) )
break ;
2021-03-28 10:52:58 +00:00
m = m - > next ;
2020-01-25 07:50:20 +00:00
}
/* not found, so we use first MSN */
if ( ! m ) {
strncpy ( dialing , call - > isdn_ep - > msn_list - > msn , sizeof ( dialing ) - 1 ) ;
dialing [ sizeof ( dialing ) - 1 ] = ' \0 ' ;
}
}
enc_ie_called_pn ( l3m , type , plan , dialing ) ;
}
/* redirecting number */
rc = osmo_cc_get_ie_redir ( msg , 0 , & type , & plan , & present , & screen , & reason , redir , sizeof ( redir ) ) ;
if ( rc > = 0 ) {
/* sending redirecting number only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_redirecting ( l3m , type , plan , 1 , present , screen , 1 , reason , redir ) ;
}
rc = osmo_cc_get_ie_complete ( msg , 0 ) ;
if ( rc > = 0 ) {
call - > sending_complete = 1 ;
enc_ie_complete ( l3m , 1 ) ;
}
new_state ( call , ISDN_STATE_OUT_SETUP ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_SETUP , call - > l3_pid , l3m ) ;
2022-06-24 17:58:41 +00:00
/* process local briding capability */
2022-08-19 14:27:41 +00:00
bridge_socket_client_update ( call , 1 ) ;
2020-01-25 07:50:20 +00:00
}
void proc_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg , int with_ies ) ;
/* process progress message and handle tones */
int process_progress ( call_t * call , osmo_cc_msg_t * msg , struct l3_msg * l3m , int call_state , uint8_t cause )
{
uint8_t coding , location , progress ;
int tone ;
int rc ;
/* read progress message from upper layer */
rc = osmo_cc_get_ie_progress ( msg , 0 , & coding , & location , & progress ) ;
if ( rc < 0 ) {
coding = OSMO_CC_CODING_ITU_T ;
progress = 0 ;
}
/* the audio path is throughconnected */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) )
call - > audio_path = 1 ;
/* if local tones are not enabled, don't process them here */
if ( ! call - > isdn_ep - > local_tones )
goto finish ;
/* if we have remote tones, we don't process local tones */
if ( call - > send_remote_tones )
goto finish ;
/* if we are getting remote tones... */
if ( coding = = OSMO_CC_CODING_ITU_T & & ( progress = = 1 | | progress = = 8 ) ) {
/* if we are sending local tones, we stop them */
if ( call - > send_local_tones ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Stop sending locally generated tones. \n " ) ;
2020-01-25 07:50:20 +00:00
call - > send_local_tones = 0 ;
bchannel_tone ( call , 0 ) ;
}
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Using remote tones. \n " ) ;
2020-01-25 07:50:20 +00:00
call - > send_remote_tones = 1 ;
goto finish ;
}
/* if we have local tones the first time, send progress indicator */
if ( ! call - > send_local_tones ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Start sending locally generated tones. \n " ) ;
2020-01-25 07:50:20 +00:00
call - > send_local_tones = 1 ;
coding = OSMO_CC_CODING_ITU_T ;
location = call - > isdn_ep - > serving_location ;
progress = OSMO_CC_PROGRESS_INBAND_INFO_AVAILABLE ;
}
/* select local tones from call state */
switch ( call_state ) {
case ISDN_STATE_IN_OVERLAP :
if ( call - > any_dialing )
bchannel_tone ( call , 0 ) ;
else {
switch ( call - > isdn_ep - > local_tones ) {
case TONES_TYPE_GERMAN :
tone = TONE_GERMAN_DIALTONE ;
break ;
case TONES_TYPE_OLDGERMAN :
tone = TONE_GERMAN_OLDDIALTONE ;
break ;
default :
tone = TONE_AMERICAN_DIALTONE ;
}
bchannel_tone ( call , tone ) ;
}
break ;
case ISDN_STATE_IN_PROCEEDING :
bchannel_tone ( call , 0 ) ;
break ;
case ISDN_STATE_IN_ALERTING :
switch ( call - > isdn_ep - > local_tones ) {
case TONES_TYPE_GERMAN :
tone = TONE_GERMAN_RINGING ;
break ;
case TONES_TYPE_OLDGERMAN :
tone = TONE_GERMAN_OLDRINGING ;
break ;
default :
tone = TONE_AMERICAN_RINGING ;
}
bchannel_tone ( call , tone ) ;
break ;
case ISDN_STATE_OUT_DISCONNECT :
switch ( cause ) {
case 17 :
case 18 :
switch ( call - > isdn_ep - > local_tones ) {
case TONES_TYPE_GERMAN :
tone = TONE_GERMAN_BUSY ;
break ;
case TONES_TYPE_OLDGERMAN :
tone = TONE_GERMAN_OLDBUSY ;
break ;
default :
tone = TONE_AMERICAN_BUSY ;
}
break ;
case 16 :
case 19 :
switch ( call - > isdn_ep - > local_tones ) {
case TONES_TYPE_GERMAN :
tone = TONE_GERMAN_HANGUP ;
break ;
case TONES_TYPE_OLDGERMAN :
tone = TONE_GERMAN_OLDHANGUP ;
break ;
default :
tone = TONE_AMERICAN_BUSY ;
}
break ;
case 34 :
switch ( call - > isdn_ep - > local_tones ) {
case TONES_TYPE_GERMAN :
tone = TONE_GERMAN_GASSENBESETZT ;
break ;
case TONES_TYPE_OLDGERMAN :
tone = TONE_GERMAN_OLDHANGUP ;
break ;
default :
tone = TONE_SPECIAL_INFO ;
}
break ;
default :
switch ( call - > isdn_ep - > local_tones ) {
case TONES_TYPE_GERMAN :
tone = TONE_SPECIAL_INFO ;
break ;
case TONES_TYPE_OLDGERMAN :
tone = TONE_SPECIAL_INFO ;
break ;
default :
tone = TONE_SPECIAL_INFO ;
}
}
bchannel_tone ( call , tone ) ;
break ;
}
finish :
/* append progress message. return TRUE, if message was added */
if ( progress ) {
enc_ie_progress ( l3m , coding , location , progress ) ;
return 1 ;
}
return 0 ;
}
/* CC-SETUP-ACKNOWLEDGE REQUEST */
void setup_ack_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
char display [ 128 ] ;
int rc ;
/* in case of sending complete, we proceed */
if ( call - > sending_complete ) {
new_state ( call , ISDN_STATE_IN_PROCEEDING ) ;
proc_req ( call , pid , msg , 1 ) ;
return ;
}
/* in case of te-mode and multipoint, we proceed, because overlap dialing is not supported in that mode */
if ( ! call - > isdn_ep - > ntmode & & ! call - > isdn_ep - > ptp ) {
new_state ( call , ISDN_STATE_IN_PROCEEDING ) ;
proc_req ( call , pid , msg , 1 ) ;
return ;
}
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " SETUP-ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* creating setup acknowledge */
l3m = create_l3msg ( ) ;
/* channel information */
if ( ! call - > channel_negotiated ) {
call - > channel_negotiated = 1 ;
enc_ie_channel_id ( l3m , call - > isdn_ep - > pri , 1 , call - > b_channel ) ;
}
// NOTE: codec negotiation is performed at cc_message()
/* progress information */
process_progress ( call , msg , l3m , ISDN_STATE_IN_OVERLAP , 0 ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
new_state ( call , ISDN_STATE_IN_OVERLAP ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_SETUP_ACKNOWLEDGE , call - > l3_pid , l3m ) ;
}
/* CC-PROCEEDING REQUEST */
void proc_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg , int with_ies )
{
struct l3_msg * l3m ;
uint8_t plan , type , screen , present , reason ;
uint8_t notify ;
char redir [ 33 ] ;
char display [ 128 ] ;
int rc ;
if ( call - > proceeding_sent )
return ;
call - > proceeding_sent = 1 ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " PROCEEDING REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* creating proceeding */
l3m = create_l3msg ( ) ;
/* channel information */
if ( ! call - > channel_negotiated ) {
call - > channel_negotiated = 1 ;
enc_ie_channel_id ( l3m , call - > isdn_ep - > pri , 1 , call - > b_channel ) ;
}
// NOTE: codec negotiation is performed at cc_message()
if ( ! with_ies )
goto skip_ies ;
/* progress information */
process_progress ( call , msg , l3m , ISDN_STATE_IN_PROCEEDING , 0 ) ;
/* notify */
rc = osmo_cc_get_ie_notify ( msg , 0 , & notify ) ;
if ( rc > = 0 )
enc_ie_notify ( l3m , notify ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
/* redirection number */
rc = osmo_cc_get_ie_redir ( msg , 0 , & type , & plan , & present , & screen , & reason , redir , sizeof ( redir ) ) ;
/* sending redirection number only in ntmode */
if ( rc > = 0 & & call - > isdn_ep - > ntmode )
enc_ie_redirection ( l3m , type , plan , 1 , present , redir ) ;
2024-01-09 12:28:05 +00:00
/* Metering handling and AOC-S generation */
rc = osmo_cc_get_ie_metering ( msg , 0 , & ( call - > metering_connect_units ) , & ( call - > metering_unit_period_decisecs ) ) ;
if ( rc > = 0 ) {
call - > metering_info_received = 1 ;
generate_aocs_ie ( call , l3m ) ;
}
2020-01-25 07:50:20 +00:00
skip_ies :
new_state ( call , ISDN_STATE_IN_PROCEEDING ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_CALL_PROCEEDING , call - > l3_pid , l3m ) ;
}
/* CC-ALERTING REQUEST */
void alert_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
uint8_t plan , type , screen , present , reason ;
uint8_t notify ;
char redir [ 33 ] ;
char display [ 128 ] ;
int rc ;
/* NT-MODE in setup state we must send PROCEEDING first */
if ( ! call - > proceeding_sent & & call - > isdn_ep - > ntmode ) {
proc_req ( call , pid , msg , 0 ) ;
}
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " ALERTING REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* creating alerting */
l3m = create_l3msg ( ) ;
/* channel information */
if ( ! call - > channel_negotiated ) {
call - > channel_negotiated = 1 ;
enc_ie_channel_id ( l3m , call - > isdn_ep - > pri , 1 , call - > b_channel ) ;
}
// NOTE: codec negotiation is performed at cc_message()
/* progress information */
process_progress ( call , msg , l3m , ISDN_STATE_IN_ALERTING , 0 ) ;
/* notify */
rc = osmo_cc_get_ie_notify ( msg , 0 , & notify ) ;
if ( rc > = 0 )
enc_ie_notify ( l3m , notify ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
/* redirection number */
rc = osmo_cc_get_ie_redir ( msg , 0 , & type , & plan , & present , & screen , & reason , redir , sizeof ( redir ) ) ;
/* sending redirection number only in ntmode */
if ( rc > = 0 & & call - > isdn_ep - > ntmode )
enc_ie_redirection ( l3m , type , plan , 1 , present , redir ) ;
2024-01-09 12:28:05 +00:00
/* Metering handling and AOC-S generation */
rc = osmo_cc_get_ie_metering ( msg , 0 , & ( call - > metering_connect_units ) , & ( call - > metering_unit_period_decisecs ) ) ;
if ( rc > = 0 ) {
call - > metering_info_received = 1 ;
generate_aocs_ie ( call , l3m ) ;
}
2020-01-25 07:50:20 +00:00
new_state ( call , ISDN_STATE_IN_ALERTING ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_ALERTING , call - > l3_pid , l3m ) ;
}
/* CC-CONNECT REQUEST */
void setup_rsp ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
uint8_t type , plan , present , screen ;
uint8_t coding , location , progress ;
time_t current_time ;
char connected [ 33 ] ;
char display [ 128 ] ;
int rc ;
2024-01-09 12:28:05 +00:00
uint8_t fac_ie [ 256 ] ;
struct asn1_parm fac ;
2020-01-25 07:50:20 +00:00
/* NT-MODE in setup state we must send PROCEEDING first */
if ( ! call - > proceeding_sent & & call - > isdn_ep - > ntmode ) {
proc_req ( call , pid , msg , 0 ) ;
}
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " CONNECT REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* stop local tones, if sending until now */
if ( call - > send_local_tones ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " Stop sending locally generated tones. \n " ) ;
2020-01-25 07:50:20 +00:00
call - > send_local_tones = 0 ;
bchannel_tone ( call , 0 ) ;
}
/* creating connect */
l3m = create_l3msg ( ) ;
/* channel information */
if ( ! call - > channel_negotiated ) {
call - > channel_negotiated = 1 ;
enc_ie_channel_id ( l3m , call - > isdn_ep - > pri , 1 , call - > b_channel ) ;
}
// NOTE: codec negotiation is performed at cc_message()
/* progress information */
rc = osmo_cc_get_ie_progress ( msg , 0 , & coding , & location , & progress ) ;
if ( rc > = 0 )
enc_ie_progress ( l3m , coding , location , progress ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
/* date & time, in NT mode only */
if ( call - > isdn_ep - > ntmode ) {
time ( & current_time ) ;
enc_ie_date ( l3m , current_time , 0 ) ;
}
/* connected number */
rc = osmo_cc_get_ie_calling ( msg , 0 , & type , & plan , & present , & screen , connected , sizeof ( connected ) ) ;
if ( rc > = 0 ) {
enc_ie_connected_pn ( l3m , type , plan , 1 , present , screen , connected ) ;
rc = osmo_cc_get_ie_calling ( msg , 1 , & type , & plan , & present , & screen , connected , sizeof ( connected ) ) ;
/* secondary connected info */
if ( rc > = 0 )
enc_ie_connected_pn ( l3m , type , plan , 1 , present , screen , connected ) ;
}
2024-01-09 12:28:05 +00:00
/* Metering handling and AOC-S generation */
rc = osmo_cc_get_ie_metering ( msg , 0 , & ( call - > metering_connect_units ) , & ( call - > metering_unit_period_decisecs ) ) ;
if ( rc > = 0 ) {
call - > metering_info_received = 1 ;
generate_aocs_ie ( call , l3m ) ;
}
2020-01-25 07:50:20 +00:00
new_state ( call , ISDN_STATE_IN_CONNECTING ) ;
2024-01-09 12:28:05 +00:00
/* AOC-D handling on connect */
if ( call - > isdn_ep - > ntmode & & call - > isdn_ep - > aocd & & call - > metering_info_received & & call - > metering_connect_units > 0 )
{
LOGP ( DISDN , LOGL_DEBUG , " Attaching AOC-D connect facility, units: %d \n " , call - > metering_connect_units ) ;
call - > metering_total_units = call - > metering_connect_units ;
memset ( & fac , 0 , sizeof ( fac ) ) ;
fac . Valid = 1 ;
fac . comp = CompInvoke ;
fac . u . inv . invokeId = 2 ; /* doesn't matter since no response is expected */
fac . u . inv . operationValue = Fac_AOCDChargingUnit ;
fac . u . inv . o . AOCchu . recordedUnits = call - > metering_total_units ;
encodeFac ( fac_ie , & fac ) ;
enc_ie_facility ( l3m , fac_ie + 2 , fac_ie [ 1 ] ) ;
if ( call - > metering_unit_period_decisecs > 0 ) {
LOGP ( DISDN , LOGL_DEBUG , " Scheduling AOC-D unit information every %d deciseconds. \n " , call - > metering_unit_period_decisecs ) ;
call - > aocd_unit_timer_started = 1 ;
osmo_timer_setup ( & call - > aocd_unit_timer , aocd_timer_cb , call ) ;
osmo_timer_schedule ( & call - > aocd_unit_timer , call - > metering_unit_period_decisecs / 10 , ( call - > metering_unit_period_decisecs % 10 ) * 100000 ) ;
}
}
2020-01-25 07:50:20 +00:00
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_CONNECT , call - > l3_pid , l3m ) ;
/* in NT mode we might not receive CONNECT ACKNOWLEDGE */
if ( call - > isdn_ep - > ntmode ) {
new_state ( call , ISDN_STATE_CONNECT ) ;
/* create osmo-cc message */
msg = osmo_cc_new_msg ( OSMO_CC_MSG_SETUP_COMP_IND ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
}
/* the audio path is throughconnected */
call - > audio_path = 1 ;
}
/* CC-CONNECT ACKNOWLEDGE REQUEST */
void setup_comp_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " CONNECT ACKNOWLEDGE REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
new_state ( call , ISDN_STATE_CONNECT ) ;
/* only send in NT mode */
if ( ! call - > isdn_ep - > ntmode )
return ;
/* creating connect acknowledge */
l3m = create_l3msg ( ) ;
/* if we had no bchannel before, we send it now (answer call with NO_CHANNEL) */
if ( call - > setup_comp_req_channel_assignment & & call - > b_channel )
enc_ie_channel_id ( l3m , call - > isdn_ep - > pri , 1 , call - > b_channel ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_CONNECT_ACKNOWLEDGE , call - > l3_pid , l3m ) ;
}
/* CC-INFORMATION REQUEST */
void info_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
uint8_t type , plan ;
char keypad [ 33 ] ;
char dialing [ 33 ] ;
int rc_called , rc_kp ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " INFORMATION REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* keypad */
rc_kp = osmo_cc_get_ie_keypad ( msg , 0 , keypad , sizeof ( keypad ) ) ;
/* dialing information */
rc_called = osmo_cc_get_ie_called ( msg , 0 , & type , & plan , dialing , sizeof ( dialing ) ) ;
if ( rc_called > = 0 | | rc_kp > = 0 ) {
/* creating information */
l3m = create_l3msg ( ) ;
if ( rc_kp > = 0 )
enc_ie_keypad ( l3m , keypad ) ;
if ( rc_called > = 0 )
enc_ie_called_pn ( l3m , type , plan , dialing ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_INFORMATION , call - > l3_pid , l3m ) ;
}
/* reset overlap timeout */
new_state ( call , call - > state ) ;
}
/* CC-PROGRESS REQUEST */
void progress_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " PROGRESS REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* creating progress */
l3m = create_l3msg ( ) ;
/* progress information */
rc = process_progress ( call , msg , l3m , call - > state , 0 ) ;
2024-01-09 12:28:05 +00:00
/* Metering handling and AOC-S generation */
rc = osmo_cc_get_ie_metering ( msg , 0 , & ( call - > metering_connect_units ) , & ( call - > metering_unit_period_decisecs ) ) ;
if ( rc > = 0 ) {
call - > metering_info_received = 1 ;
generate_aocs_ie ( call , l3m ) ;
}
2020-01-25 07:50:20 +00:00
/* send message to ISDN */
if ( rc )
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_PROGRESS , call - > l3_pid , l3m ) ;
else
free_l3msg ( l3m ) ;
}
/* CC-NOTIFY REQUEST */
void notify_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
uint8_t notify ;
uint8_t plan , type , screen , present , reason ;
char redir [ 32 ] ;
char display [ 128 ] ;
int rc_notify , rc_redir , rc_display ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " NOTIFY REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* notify */
rc_notify = osmo_cc_get_ie_notify ( msg , 0 , & notify ) ;
/* redirection number */
rc_redir = osmo_cc_get_ie_redir ( msg , 0 , & type , & plan , & present , & screen , & reason , redir , sizeof ( redir ) ) ;
/* display */
rc_display = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc_notify > = 0 ) {
/* creating notify */
l3m = create_l3msg ( ) ;
enc_ie_notify ( l3m , notify ) ;
/* sending display only in ntmode */
if ( rc_display > = 0 & & call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
/* sending redirection number only in ntmode */
if ( rc_redir > = 0 & & call - > isdn_ep - > ntmode )
enc_ie_redirection ( l3m , type , plan , 1 , present , redir ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_NOTIFY , call - > l3_pid , l3m ) ;
2022-12-04 10:02:58 +00:00
} else {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " NOTIFY REQUEST without notification indicator, ignoring. \n " ) ;
2020-01-25 07:50:20 +00:00
}
}
/* CC-REJECT REQUEST */
void rej_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
uint8_t location , isdn_cause , socket_cause ;
uint16_t sip_cause ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " REJECT REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* creating release complete */
l3m = create_l3msg ( ) ;
/* cause */
rc = osmo_cc_get_ie_cause ( msg , 0 , & location , & isdn_cause , & sip_cause , & socket_cause ) ;
if ( rc < 0 ) {
location = OSMO_CC_LOCATION_BEYOND_INTERWORKING ;
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR ;
}
enc_ie_cause ( l3m , location , isdn_cause ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_RELEASE_COMPLETE , call - > l3_pid , l3m ) ;
/* call terminated */
new_state ( call , ISDN_STATE_IDLE ) ;
call_destroy ( call ) ;
}
/* CC-DISCONNECT REQUEST */
void disc_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
uint8_t location ;
uint8_t isdn_cause , socket_cause ;
uint16_t sip_cause ;
char display [ 128 ] ;
int rc ;
/* send a proceeding and open channel if we are still in setup state */
if ( call - > state = = ISDN_STATE_IN_SETUP ) {
proc_req ( call , pid , msg , 0 ) ;
}
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " DISCONNECT REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* creating disconnect */
l3m = create_l3msg ( ) ;
/* cause */
rc = osmo_cc_get_ie_cause ( msg , 0 , & location , & isdn_cause , & sip_cause , & socket_cause ) ;
if ( rc < 0 ) {
location = OSMO_CC_LOCATION_BEYOND_INTERWORKING ;
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR ;
}
enc_ie_cause ( l3m , location , isdn_cause ) ;
/* reset states and handle progress information */
if ( call - > send_local_tones ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_DEBUG , " Stop sending locally generated tones. \n " ) ;
2020-01-25 07:50:20 +00:00
call - > send_local_tones = 0 ;
bchannel_tone ( call , 0 ) ;
}
call - > send_remote_tones = 0 ;
call - > audio_path = 0 ;
process_progress ( call , msg , l3m , ISDN_STATE_OUT_DISCONNECT , isdn_cause ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
2024-01-09 12:28:05 +00:00
/* stop AOC-D timer */
if ( call - > aocd_unit_timer_started )
{
osmo_timer_del ( & call - > aocd_unit_timer ) ;
call - > aocd_unit_timer_started = 0 ;
}
2020-01-25 07:50:20 +00:00
new_state ( call , ISDN_STATE_OUT_DISCONNECT ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_DISCONNECT , call - > l3_pid , l3m ) ;
}
/* CC-RELEASE REQUEST */
void rel_req ( call_t * call , uint32_t pid , osmo_cc_msg_t * msg )
{
struct l3_msg * l3m ;
uint8_t location , isdn_cause , socket_cause ;
uint16_t sip_cause ;
char display [ 128 ] ;
int rc ;
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_INFO , " RELEASE REQUEST (pid = 0x%x callref = %d) \n " , pid , call - > cc_callref ) ;
2020-01-25 07:50:20 +00:00
/* creating release */
l3m = create_l3msg ( ) ;
/* cause */
rc = osmo_cc_get_ie_cause ( msg , 0 , & location , & isdn_cause , & sip_cause , & socket_cause ) ;
if ( rc < 0 ) {
location = OSMO_CC_LOCATION_BEYOND_INTERWORKING ;
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR ;
}
enc_ie_cause ( l3m , location , isdn_cause ) ;
/* display */
rc = osmo_cc_get_ie_display ( msg , 0 , display , sizeof ( display ) ) ;
if ( rc > = 0 ) {
/* sending display text only in ntmode */
if ( call - > isdn_ep - > ntmode )
enc_ie_display ( l3m , display ) ;
}
new_state ( call , ISDN_STATE_OUT_RELEASE ) ;
/* send message to ISDN */
call - > isdn_ep - > ml3 - > to_layer3 ( call - > isdn_ep - > ml3 , MT_RELEASE , call - > l3_pid , l3m ) ;
}
2022-09-17 13:00:11 +00:00
/* special case where call is suspended */
void disc_rel_suspended ( call_t * call , osmo_cc_msg_t * msg )
{
uint8_t location , isdn_cause , socket_cause ;
uint16_t sip_cause ;
int rc ;
rc = osmo_cc_get_ie_cause ( msg , 0 , & location , & isdn_cause , & sip_cause , & socket_cause ) ;
if ( rc < 0 )
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR ;
msg = osmo_cc_new_msg ( ( msg - > type = = OSMO_CC_MSG_REL_REQ ) ? OSMO_CC_MSG_REL_CNF : OSMO_CC_MSG_REL_IND ) ;
/* cause */
osmo_cc_add_ie_cause ( msg , call - > isdn_ep - > serving_location , isdn_cause , 0 , 0 ) ;
/* send message to osmo-cc */
osmo_cc_ll_msg ( & call - > isdn_ep - > cc_ep , call - > cc_callref , msg ) ;
/* terminate call */
new_state ( call , ISDN_STATE_IDLE ) ;
call_destroy ( call ) ;
}
2020-01-25 07:50:20 +00:00
void cc_message ( osmo_cc_endpoint_t * ep , uint32_t callref , osmo_cc_msg_t * msg )
{
isdn_t * isdn_ep = ep - > priv ;
call_t * call ;
/* hunt for callref */
call = isdn_ep - > call_list ;
while ( call ) {
if ( call - > cc_callref = = callref )
break ;
call = call - > next ;
}
/* process SETUP */
if ( ! call ) {
if ( msg - > type ! = OSMO_CC_MSG_SETUP_REQ ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " received message without call instance, please fix! \n " ) ;
2020-01-25 07:50:20 +00:00
osmo_cc_free_msg ( msg ) ;
return ;
}
/* creating call instance, transparent until setup with hdlc */
2022-06-24 17:58:41 +00:00
call = call_create ( isdn_ep , DIRECTION_TERMINATOR , 0 , 0 , B_MODE_TRANSPARENT ) ;
2020-01-25 07:50:20 +00:00
if ( ! call ) {
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " Cannot create call instance. \n " ) ;
2020-01-25 07:50:20 +00:00
abort ( ) ;
}
/* link with cc */
call - > cc_callref = callref ;
}
switch ( msg - > type ) {
case OSMO_CC_MSG_SETUP_REQ : /* dial-out command received from epoint */
setup_req ( call , msg ) ;
break ;
case OSMO_CC_MSG_SETUP_ACK_REQ : /* more information is needed */
osmo_cc_helper_audio_negotiate ( msg , & call - > cc_session , & call - > codec ) ;
setup_ack_req ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_PROC_REQ : /* call of endpoint is proceeding */
osmo_cc_helper_audio_negotiate ( msg , & call - > cc_session , & call - > codec ) ;
proc_req ( call , call - > l3_pid , msg , 1 ) ;
break ;
case OSMO_CC_MSG_ALERT_REQ : /* call of endpoint is ringing */
osmo_cc_helper_audio_negotiate ( msg , & call - > cc_session , & call - > codec ) ;
alert_req ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_SETUP_RSP : /* call of endpoint is connected */
osmo_cc_helper_audio_negotiate ( msg , & call - > cc_session , & call - > codec ) ;
setup_rsp ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_SETUP_COMP_REQ : /* call of endpoint is connected */
setup_comp_req ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_INFO_REQ : /* overlap dialing */
if ( isdn_ep - > ntmode
& & call - > state ! = ISDN_STATE_OUT_OVERLAP
& & call - > state ! = ISDN_STATE_OUT_CONNECTING
& & call - > state ! = ISDN_STATE_IN_OVERLAP
& & call - > state ! = ISDN_STATE_IN_PROCEEDING
& & call - > state ! = ISDN_STATE_IN_ALERTING
& & call - > state ! = ISDN_STATE_IN_CONNECTING
& & call - > state ! = ISDN_STATE_CONNECT
& & call - > state ! = ISDN_STATE_OUT_DISCONNECT
& & call - > state ! = ISDN_STATE_IN_DISCONNECT )
break ;
if ( ! isdn_ep - > ntmode
& & call - > state ! = ISDN_STATE_OUT_OVERLAP
& & call - > state ! = ISDN_STATE_OUT_PROCEEDING
& & call - > state ! = ISDN_STATE_OUT_ALERTING
& & call - > state ! = ISDN_STATE_OUT_CONNECTING
& & call - > state ! = ISDN_STATE_IN_OVERLAP
& & call - > state ! = ISDN_STATE_IN_PROCEEDING
& & call - > state ! = ISDN_STATE_IN_ALERTING
& & call - > state ! = ISDN_STATE_IN_CONNECTING
& & call - > state ! = ISDN_STATE_CONNECT
& & call - > state ! = ISDN_STATE_OUT_DISCONNECT
& & call - > state ! = ISDN_STATE_IN_DISCONNECT )
break ;
info_req ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_PROGRESS_REQ : /* progress */
osmo_cc_helper_audio_negotiate ( msg , & call - > cc_session , & call - > codec ) ;
if ( isdn_ep - > ntmode
& & call - > state ! = ISDN_STATE_OUT_OVERLAP
& & call - > state ! = ISDN_STATE_OUT_PROCEEDING
& & call - > state ! = ISDN_STATE_IN_OVERLAP
& & call - > state ! = ISDN_STATE_IN_PROCEEDING
& & call - > state ! = ISDN_STATE_IN_ALERTING )
break ;
if ( ! isdn_ep - > ntmode
& & call - > state ! = ISDN_STATE_OUT_OVERLAP
& & call - > state ! = ISDN_STATE_OUT_PROCEEDING
& & call - > state ! = ISDN_STATE_OUT_ALERTING
& & call - > state ! = ISDN_STATE_IN_OVERLAP
& & call - > state ! = ISDN_STATE_IN_PROCEEDING )
break ;
progress_req ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_NOTIFY_REQ : /* display and notifications */
if ( call - > state ! = ISDN_STATE_IN_PROCEEDING
& & call - > state ! = ISDN_STATE_IN_ALERTING
& & call - > state ! = ISDN_STATE_IN_CONNECTING
& & call - > state ! = ISDN_STATE_CONNECT )
break ;
notify_req ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_REJ_REQ : /* call has been rejected */
rej_req ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_DISC_REQ : /* call has been disconnected */
osmo_cc_helper_audio_negotiate ( msg , & call - > cc_session , & call - > codec ) ;
2022-09-17 13:00:11 +00:00
if ( call - > state = = ISDN_STATE_SUSPENDED ) {
disc_rel_suspended ( call , msg ) ;
break ;
}
2020-01-25 07:50:20 +00:00
if ( call - > state ! = ISDN_STATE_IN_SETUP
& & call - > state ! = ISDN_STATE_IN_OVERLAP
& & call - > state ! = ISDN_STATE_IN_PROCEEDING
& & call - > state ! = ISDN_STATE_IN_ALERTING
& & call - > state ! = ISDN_STATE_IN_CONNECTING
& & call - > state ! = ISDN_STATE_OUT_OVERLAP
& & call - > state ! = ISDN_STATE_OUT_PROCEEDING
& & call - > state ! = ISDN_STATE_OUT_ALERTING
& & call - > state ! = ISDN_STATE_OUT_CONNECTING
& & call - > state ! = ISDN_STATE_CONNECT
& & call - > state ! = ISDN_STATE_IN_DISCONNECT )
break ;
disc_req ( call , call - > l3_pid , msg ) ;
break ;
case OSMO_CC_MSG_REL_REQ : /* release isdn port */
2022-09-17 13:00:11 +00:00
if ( call - > state = = ISDN_STATE_SUSPENDED ) {
disc_rel_suspended ( call , msg ) ;
break ;
}
2020-01-25 07:50:20 +00:00
rel_req ( call , call - > l3_pid , msg ) ;
break ;
default :
2024-01-09 11:24:14 +00:00
LOGP ( DDSS1 , LOGL_ERROR , " received an unsupported CC message: %d \n " , msg - > type ) ;
2020-01-25 07:50:20 +00:00
}
osmo_cc_free_msg ( msg ) ;
}