gsm improvements

code cleanup

	modified:   README
	modified:   action.cpp
	modified:   action_efi.cpp
	modified:   action_vbox.cpp
	modified:   alawulaw.c
	modified:   bchannel.c
	modified:   bootstrap.c
	modified:   callerid.c
	modified:   cause.c
	modified:   chan_lcr.c
	modified:   default/gsm.conf
	modified:   dss1.cpp
	modified:   gsm.cpp
	modified:   gsm.h
	modified:   gsm_conf.c
	modified:   message.h
This commit is contained in:
Andreas Eversberg 2009-06-06 23:46:21 +02:00
parent 063d622d53
commit 6bf7c7f9db
16 changed files with 654 additions and 860 deletions

1
README
View File

@ -502,5 +502,6 @@ Changes after Version 1.5
- Fixed some GSM information elements.
- OpenBSC api changes.
- Fixed disabling of DTMF using 'n' option of chan_lcr.
- Added GSM IMSI dialing by using dialing "imsi-<number>".

File diff suppressed because it is too large Load Diff

View File

@ -30,8 +30,7 @@ void EndpointAppPBX::action_init_efi(void)
struct port_list *portlist = ea_endpoint->ep_portlist;
/* if no caller id */
if (e_callerinfo.id[0] == '\0')
{
if (e_callerinfo.id[0] == '\0') {
/* facility rejected */
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@ -68,23 +67,20 @@ void EndpointAppPBX::efi_message_eof(void)
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) terminal %s end of file during state: %d\n", ea_endpoint->ep_serial, e_ext.number, e_vbox_state);
switch(e_efi_state)
{
switch(e_efi_state) {
case EFI_STATE_HELLO:
e_efi_state = EFI_STATE_DIE;
set_tone_efi("die");
break;
case EFI_STATE_DIE:
if (e_callerinfo.screen==INFO_SCREEN_USER)
{
if (e_callerinfo.screen==INFO_SCREEN_USER) {
e_efi_state = EFI_STATE_BENUTZERDEFINIERTE;
set_tone_efi("benutzerdefinierte");
break;
}
// fall through
case EFI_STATE_BENUTZERDEFINIERTE:
if (e_callerinfo.present==INFO_PRESENT_RESTRICTED)
{
if (e_callerinfo.present==INFO_PRESENT_RESTRICTED) {
e_efi_state = EFI_STATE_UNTERDRUECKTE;
set_tone_efi("unterdrueckte");
break;
@ -101,12 +97,10 @@ void EndpointAppPBX::efi_message_eof(void)
// fall through
case EFI_STATE_DIGIT:
digit[8] = numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international)[e_efi_digit];
if (digit[8])
{
if (digit[8]) {
set_tone_efi(digit);
e_efi_digit++;
} else
{
} else {
// e_efi_state = EFI_STATE_STOP;
e_efi_state = EFI_STATE_ICH_WIEDERHOLE;
// message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
@ -146,8 +140,7 @@ void EndpointAppPBX::set_tone_efi(const char *tone)
if (tone == NULL)
tone = "";
if (!ea_endpoint->ep_portlist)
{
if (!ea_endpoint->ep_portlist) {
PERROR("EPOINT(%d) no portlist\n", ea_endpoint->ep_serial);
}
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VBOX_TONE);

View File

@ -80,8 +80,7 @@ void EndpointAppPBX::action_init_vbox_play(void)
SCPY(e_vbox, e_ext.number);
if ((rparam = routeparam(e_action, PARAM_EXTENSION)))
SCPY(e_vbox, rparam->string_value);
if (e_vbox[0] == '\0')
{
if (e_vbox[0] == '\0') {
/* facility rejected */
message_disconnect_port(portlist, CAUSE_FACILITYREJECTED, LOCATION_PRIVATE_LOCAL, "");
new_state(EPOINT_STATE_OUT_DISCONNECT);
@ -110,8 +109,7 @@ void EndpointAppPBX::action_init_vbox_play(void)
vbox_index_read(e_vbox_play);
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) number of calls: %d\n", ea_endpoint->ep_serial, e_vbox_index_num);
if (e_vbox_index_num == 0)
{
if (e_vbox_index_num == 0) {
e_vbox_state = VBOX_STATE_NOTHING;
SCPY(e_vbox_display, (char *)((language)?"keine Anrufe":"no calls"));
e_vbox_display_refresh = 1;
@ -137,16 +135,14 @@ void EndpointAppPBX::vbox_index_read(int num)
e_vbox_index_num = 0;
SPRINT(filename, "%s/%s/vbox/index", EXTENSION_DATA, e_vbox);
if (!(fp = fopen(filename, "r")))
{
if (!(fp = fopen(filename, "r"))) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no files in index\n", ea_endpoint->ep_serial);
return;
}
fduse++;
i = 0;
while((fgets(buffer,sizeof(buffer),fp)))
{
while((fgets(buffer,sizeof(buffer),fp))) {
buffer[sizeof(buffer)-1] = '\0';
if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
@ -158,8 +154,7 @@ void EndpointAppPBX::vbox_index_read(int num)
continue;
/* the selected entry */
if (i == num)
{
if (i == num) {
SCPY(e_vbox_index_file, name);
e_vbox_index_year = year;
e_vbox_index_mon = mon;
@ -196,32 +191,27 @@ void EndpointAppPBX::vbox_index_remove(int num)
SPRINT(filename1, "%s/%s/vbox/index", EXTENSION_DATA, e_vbox);
SPRINT(filename2, "%s/%s/vbox/index-temp", EXTENSION_DATA, e_vbox);
if (!(fpr = fopen(filename1, "r")))
{
if (!(fpr = fopen(filename1, "r"))) {
return;
}
if (!(fpw = fopen(filename2, "w")))
{
if (!(fpw = fopen(filename2, "w"))) {
fclose(fpr);
return;
}
fduse += 2;
i = 0;
while((fgets(buffer,sizeof(buffer),fpr)))
{
while((fgets(buffer,sizeof(buffer),fpr))) {
buffer[sizeof(buffer)-1] = '\0';
if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
if (buffer[0]=='\0' || buffer[0]=='#')
{
if (buffer[0]=='\0' || buffer[0]=='#') {
fprintf(fpw, "%s\n", buffer);
continue;
}
/* the selected entry will not be written */
if (i != num)
{
if (i != num) {
fprintf(fpw, "%s\n", buffer);
}
@ -248,8 +238,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
portlist = ea_endpoint->ep_portlist;
if (e_extdialing[0] == '\0')
{
if (e_extdialing[0] == '\0') {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) called with no digit\n", ea_endpoint->ep_serial);
return;
}
@ -258,10 +247,8 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
e_vbox_display_refresh = 1;
if (e_vbox_state == VBOX_STATE_RECORD_RECORD)
{
if (e_extdialing[0] == '1' || e_extdialing[0] == '0')
{
if (e_vbox_state == VBOX_STATE_RECORD_RECORD) {
if (e_extdialing[0] == '1' || e_extdialing[0] == '0') {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) stopping recording of announcement.\n", ea_endpoint->ep_serial);
port = find_port_id(portlist->port_id);
@ -272,10 +259,8 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
goto done;
}
if (e_vbox_state == VBOX_STATE_RECORD_PLAY)
{
if (e_extdialing[0] == '1')
{
if (e_vbox_state == VBOX_STATE_RECORD_PLAY) {
if (e_extdialing[0] == '1') {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) stopping playback of announcement.\n", ea_endpoint->ep_serial);
goto record_ask;
@ -283,10 +268,8 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
goto done;
}
if (e_vbox_state == VBOX_STATE_RECORD_ASK)
{
switch(e_extdialing[0])
{
if (e_vbox_state == VBOX_STATE_RECORD_ASK) {
switch(e_extdialing[0]) {
case '3':
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) quit recoding menu.\n", ea_endpoint->ep_serial);
ask_abort:
@ -317,8 +300,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) record announcement.\n", ea_endpoint->ep_serial);
/* close recording if already recording */
port = find_port_id(portlist->port_id);
if (port)
{
if (port) {
port->close_record(0,0);
port->open_record(CODEC_MONO, 1, 4000, e_ext.number, 0, "", 0); /* record announcement, skip the first 4000 samples */
}
@ -336,12 +318,10 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
goto done;
}
if (e_vbox_state==VBOX_STATE_STORE_ASK || e_vbox_state==VBOX_STATE_DELETE_ASK)
{
if (e_vbox_state==VBOX_STATE_STORE_ASK || e_vbox_state==VBOX_STATE_DELETE_ASK) {
char filename[256], filename2[256];
switch(e_extdialing[0])
{
switch(e_extdialing[0]) {
case '3':
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) quit store/delete menu.\n", ea_endpoint->ep_serial);
goto ask_abort;
@ -351,13 +331,10 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
SPRINT(filename, "%s/%s/vbox/%s", EXTENSION_DATA, e_vbox, e_vbox_index_file);
/* move file */
if (e_vbox_state == VBOX_STATE_STORE_ASK)
{
if (e_vbox_state == VBOX_STATE_STORE_ASK) {
SPRINT(filename, "%s/%s/recordings", EXTENSION_DATA, e_vbox);
if (mkdir(filename, 0755) < 0)
{
if (errno != EEXIST)
{
if (mkdir(filename, 0755) < 0) {
if (errno != EEXIST) {
PERROR("EPOINT(%d) cannot create directory '%s'\n", ea_endpoint->ep_serial, filename);
goto done;
}
@ -373,8 +350,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
}
/* remove file */
if (e_vbox_state == VBOX_STATE_DELETE_ASK)
{
if (e_vbox_state == VBOX_STATE_DELETE_ASK) {
remove(filename);
e_vbox_state = VBOX_STATE_DELETE_DONE;
if (e_ext.vbox_language)
@ -388,8 +364,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
vbox_index_remove(e_vbox_play);
vbox_index_read(e_vbox_play);
/* stay at the last message+1, so we always get "no messages" */
if (e_vbox_play>e_vbox_index_num && e_vbox_play)
{
if (e_vbox_play>e_vbox_index_num && e_vbox_play) {
e_vbox_play = e_vbox_index_num-1;
}
default:
@ -399,13 +374,11 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
}
/* dialing during menu */
switch(e_extdialing[0])
{
switch(e_extdialing[0]) {
/* process the vbox functions */
case '1': /* previous */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) previous call is selected.\n", ea_endpoint->ep_serial);
if (e_vbox_index_num == 0) /* nothing to play */
{
if (e_vbox_index_num == 0) { /* nothing to play */
no_calls:
e_vbox_state = VBOX_STATE_MENU;
SCPY(e_vbox_display, (char *)((language)?"keine Anrufe":"no calls"));
@ -413,8 +386,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
break;
}
e_vbox_play--;
if (e_vbox_play < 0)
{
if (e_vbox_play < 0) {
e_vbox_play = 0;
e_vbox_state = VBOX_STATE_MENU;
@ -427,12 +399,10 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
e_vbox_state = VBOX_STATE_CALLINFO_INTRO;
SPRINT(e_vbox_display, "#%d", e_vbox_play+1);
vbox_index_read(e_vbox_play);
if (e_vbox_index_mon!=now_tm->tm_mon || e_vbox_index_year!=now_tm->tm_year)
{
if (e_vbox_index_mon!=now_tm->tm_mon || e_vbox_index_year!=now_tm->tm_year) {
UPRINT(strchr(e_vbox_display,'\0'), " %s", (language)?months_german[e_vbox_index_mon]:months_english[e_vbox_index_mon]);
}
if (e_vbox_index_mday!=now_tm->tm_mday || e_vbox_index_mon!=now_tm->tm_mon || e_vbox_index_year!=now_tm->tm_year)
{
if (e_vbox_index_mday!=now_tm->tm_mday || e_vbox_index_mon!=now_tm->tm_mon || e_vbox_index_year!=now_tm->tm_year) {
UPRINT(strchr(e_vbox_display,'\0'), " %d", e_vbox_index_mday);
}
UPRINT(strchr(e_vbox_display,'\0'), " %02d:%02d", e_vbox_index_hour, e_vbox_index_min);
@ -444,13 +414,11 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
case '2': /* play */
if (e_vbox_play >= e_vbox_index_num)
goto no_messages;
if (e_vbox_index_num == 0) /* nothing to play */
{
if (e_vbox_index_num == 0) { /* nothing to play */
goto no_calls;
}
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d.\n", ea_endpoint->ep_serial, e_vbox_play+1);
if (e_vbox_state>VBOX_STATE_CALLINFO_BEGIN && e_vbox_state<VBOX_STATE_CALLINFO_END)
{
if (e_vbox_state>VBOX_STATE_CALLINFO_BEGIN && e_vbox_state<VBOX_STATE_CALLINFO_END) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. abborting announcement and starting with playback\n", ea_endpoint->ep_serial, e_vbox_play+1);
/* the callinfo is played, so we start with the call */
e_vbox_counter = 0;
@ -464,23 +432,20 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
set_play_vbox(e_vbox_index_file, 0);
break;
} else
if (e_vbox_state==VBOX_STATE_PLAY && e_vbox_speed!=1)
{
if (e_vbox_state==VBOX_STATE_PLAY && e_vbox_speed!=1) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. play speed is different from 1, so we play now with normal speed\n", ea_endpoint->ep_serial, e_vbox_play+1);
/* we set play speed to normal */
e_vbox_speed = 1;
set_play_speed(e_vbox_speed);
} else
if (e_vbox_state == VBOX_STATE_PLAY)
{
if (e_vbox_state == VBOX_STATE_PLAY) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. play speed is equals 1, so we pause\n", ea_endpoint->ep_serial, e_vbox_play+1);
/* we pause the current play */
e_vbox_state = VBOX_STATE_PAUSE;
SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. wiedergabe":"press 2 to play"));
set_tone_vbox("pause");
} else
if (e_vbox_state == VBOX_STATE_PAUSE)
{
if (e_vbox_state == VBOX_STATE_PAUSE) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. currently pause, so we continue play\n", ea_endpoint->ep_serial, e_vbox_play+1);
/* we continue the current play */
e_vbox_state = VBOX_STATE_PLAY;
@ -488,8 +453,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
if (e_ext.vbox_display == VBOX_DISPLAY_DETAILED)
UPRINT(strchr(e_vbox_display,'\0'), " (%s)", e_vbox_index_callerid);
set_play_vbox(e_vbox_index_file, e_vbox_counter);
} else
{
} else {
/* now we have something else going on, so we announce the call */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) play call #%d. announcing call during any other state\n", ea_endpoint->ep_serial, e_vbox_play+1);
goto announce_call;
@ -498,13 +462,11 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
case '3': /* next */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) next call is selected.\n", ea_endpoint->ep_serial);
if (e_vbox_index_num == 0) /* nothing to play */
{
if (e_vbox_index_num == 0) { /* nothing to play */
goto no_calls;
}
e_vbox_play++;
if (e_vbox_play >= e_vbox_index_num)
{
if (e_vbox_play >= e_vbox_index_num) {
no_messages:
e_vbox_play = e_vbox_index_num;
@ -518,8 +480,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
break;
case '4': /* rewind */
if (e_vbox_state==VBOX_STATE_PLAY)
{
if (e_vbox_state==VBOX_STATE_PLAY) {
if (e_vbox_speed >= -1)
e_vbox_speed = -1;
e_vbox_speed = e_vbox_speed * 2;
@ -536,8 +497,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
break;
case '6': /* wind */
if (e_vbox_state==VBOX_STATE_PLAY)
{
if (e_vbox_state==VBOX_STATE_PLAY) {
if (e_vbox_speed <= 1)
e_vbox_speed = 1;
e_vbox_speed = e_vbox_speed * 2;
@ -558,8 +518,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) entering the store menu\n", ea_endpoint->ep_serial);
if (e_vbox_play >= e_vbox_index_num)
goto no_messages;
if (e_vbox_index_num == 0) /* nothing to play */
{
if (e_vbox_index_num == 0) { /* nothing to play */
goto no_calls;
}
e_vbox_state = VBOX_STATE_STORE_ASK;
@ -571,8 +530,7 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) entering the delete menu\n", ea_endpoint->ep_serial);
if (e_vbox_play >= e_vbox_index_num)
goto no_messages;
if (e_vbox_index_num == 0) /* nothing to play */
{
if (e_vbox_index_num == 0) { /* nothing to play */
goto no_calls;
}
e_vbox_state = VBOX_STATE_DELETE_ASK;
@ -595,12 +553,10 @@ void EndpointAppPBX::action_dialing_vbox_play(void)
break;
case '0':
if (e_vbox_menu < 0) /* only if menu selection is pressed before*/
{
if (e_vbox_menu < 0) { /* only if menu selection is pressed before*/
/* call if phonenumber is given */
if (e_vbox_index_num)
if (e_vbox_index_callerid[0]!='\0' && !!strcmp(e_vbox_index_callerid,"anonymous") && !!strcmp(e_vbox_index_callerid,"unknown"))
{
if (e_vbox_index_callerid[0]!='\0' && !!strcmp(e_vbox_index_callerid,"anonymous") && !!strcmp(e_vbox_index_callerid,"unknown")) {
set_tone(portlist, "dialing");
SPRINT(e_dialinginfo.id, "extern:%s", e_vbox_index_callerid);
e_extdialing = e_dialinginfo.id;
@ -651,15 +607,13 @@ void EndpointAppPBX::vbox_handler(void)
{
/* refresh if counter changes */
if (e_vbox_state==VBOX_STATE_PLAY || e_vbox_state==VBOX_STATE_RECORD_PLAY)
if (e_vbox_counter != e_vbox_counter_last)
{
if (e_vbox_counter != e_vbox_counter_last) {
e_vbox_counter_last = e_vbox_counter;
e_vbox_display_refresh = 1;
}
/* refresh display, if required (include counter) */
if (e_vbox_display_refresh && e_ext.vbox_display!=VBOX_DISPLAY_OFF)
{
if (e_vbox_display_refresh && e_ext.vbox_display!=VBOX_DISPLAY_OFF) {
char counter[32];
struct lcr_msg *message;
@ -688,8 +642,7 @@ void EndpointAppPBX::vbox_message_eof(void)
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) terminal %s end of file during state: %d\n", ea_endpoint->ep_serial, e_ext.number, e_vbox_state);
switch(e_vbox_state)
{
switch(e_vbox_state) {
case VBOX_STATE_MENU:
case VBOX_STATE_NOTHING:
e_vbox_state = VBOX_STATE_MENU;
@ -699,14 +652,12 @@ void EndpointAppPBX::vbox_message_eof(void)
break;
case VBOX_STATE_PLAY:
if (e_vbox_speed > 0)
{
if (e_vbox_speed > 0) {
e_vbox_state = VBOX_STATE_MENU;
SCPY(e_vbox_display, (char *)((language)?"druecke 3 f. Naechste":"press 3 for next"));
e_vbox_display_refresh = 1;
set_tone_vbox("menu");
} else
{
} else {
/* if we have endoffile because we were playing backwards, we continue to play forward */
e_vbox_speed = 1;
e_vbox_counter = 1;
@ -734,12 +685,10 @@ void EndpointAppPBX::vbox_message_eof(void)
case VBOX_STATE_CALLINFO_MONTH:
e_vbox_state = VBOX_STATE_CALLINFO_DAY; //german month
if (e_ext.vbox_language)
{
if (e_ext.vbox_language) {
/* done with month, so we send the month*/
SPRINT(buffer, "month_%02d", e_vbox_index_mon+1);
} else
{
} else {
/* done with day, so we send the day */
SPRINT(buffer, "day_%02d", e_vbox_index_mday);
}
@ -749,14 +698,12 @@ void EndpointAppPBX::vbox_message_eof(void)
case VBOX_STATE_CALLINFO_DAY: //german month
skip_day_month:
e_vbox_state = VBOX_STATE_CALLINFO_HOUR;
if (e_ext.vbox_language)
{
if (e_ext.vbox_language) {
if (e_vbox_index_hour == 1)
SCPY(buffer, "number_ein");
else
SPRINT(buffer, "number_%02d", e_vbox_index_hour); /* 1-23 hours */
} else
{
} else {
SPRINT(buffer, "number_%02d", ((e_vbox_index_hour+11)%12)+1); /* 12 hours am/pm */
}
set_tone_vbox(buffer);
@ -764,11 +711,9 @@ void EndpointAppPBX::vbox_message_eof(void)
case VBOX_STATE_CALLINFO_HOUR:
e_vbox_state = VBOX_STATE_CALLINFO_OCLOCK;
if (e_ext.vbox_language)
{
if (e_ext.vbox_language) {
set_tone_vbox("oclock");
} else
{
} else {
if (e_vbox_index_hour >= 12)
set_tone_vbox("oclock_pm");
else
@ -778,15 +723,13 @@ void EndpointAppPBX::vbox_message_eof(void)
case VBOX_STATE_CALLINFO_OCLOCK:
e_vbox_state = VBOX_STATE_CALLINFO_MIN;
if (e_ext.vbox_language)
{
if (e_ext.vbox_language) {
// german says "zwölfuhr und eins"
// if (e_vbox_index_min == 1)
// SCPY(buffer, "number_eine");
// else
SPRINT(buffer, "number_%02d", e_vbox_index_min); /* 1-59 minutes */
} else
{
} else {
SPRINT(buffer, "number_%02d", e_vbox_index_min);
}
set_tone_vbox(buffer);
@ -805,12 +748,10 @@ void EndpointAppPBX::vbox_message_eof(void)
case VBOX_STATE_CALLINFO_MINUTES:
start_digits:
e_vbox_state = VBOX_STATE_CALLINFO_DIGIT;
if (e_vbox_index_callerid[0]=='\0' || !strcmp(e_vbox_index_callerid,"anonymous") || !strcmp(e_vbox_index_callerid,"unknown"))
{
if (e_vbox_index_callerid[0]=='\0' || !strcmp(e_vbox_index_callerid,"anonymous") || !strcmp(e_vbox_index_callerid,"unknown")) {
set_tone_vbox("call_anonymous");
e_vbox_index_callerid_index = strlen(e_vbox_index_callerid);
} else
{
} else {
set_tone_vbox("call_from");
e_vbox_index_callerid_index = 0;
}
@ -819,13 +760,11 @@ void EndpointAppPBX::vbox_message_eof(void)
case VBOX_STATE_CALLINFO_DIGIT:
while (e_vbox_index_callerid[e_vbox_index_callerid_index] && (e_vbox_index_callerid[e_vbox_index_callerid_index]<'0' || e_vbox_index_callerid[e_vbox_index_callerid_index]>'9'))
e_vbox_index_callerid_index++;
if (e_vbox_index_callerid[e_vbox_index_callerid_index])
{
if (e_vbox_index_callerid[e_vbox_index_callerid_index]) {
SPRINT(buffer, "number_%02d", e_vbox_index_callerid[e_vbox_index_callerid_index]-'0');
set_tone_vbox(buffer);
e_vbox_index_callerid_index ++;
} else
{
} else {
/* the callinfo is played, so we start with the call */
e_vbox_counter = 0;
e_vbox_counter_last = 0;
@ -864,14 +803,12 @@ void EndpointAppPBX::vbox_message_eof(void)
case VBOX_STATE_STORE_DONE:
case VBOX_STATE_DELETE_DONE:
if (e_vbox_index_num == 0) /* nothing to play */
{
if (e_vbox_index_num == 0) { /* nothing to play */
e_vbox_state = VBOX_STATE_MENU;
SCPY(e_vbox_display, (char *)((language)?"keine Anrufe":"no calls"));
e_vbox_display_refresh = 1;
set_tone_vbox("nothing");
} else
{
} else {
e_vbox_state = VBOX_STATE_MENU;
SCPY(e_vbox_display, (char *)((language)?"druecke 2 f. wiedergabe":"press 2 to play"));
e_vbox_display_refresh = 1;
@ -897,8 +834,7 @@ void EndpointAppPBX::set_tone_vbox(const char *tone)
if (tone == NULL)
tone = "";
if (!ea_endpoint->ep_portlist)
{
if (!ea_endpoint->ep_portlist) {
PERROR("EPOINT(%d) no portlist\n", ea_endpoint->ep_serial);
}
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VBOX_TONE);
@ -932,8 +868,7 @@ void EndpointAppPBX::set_play_vbox(const char *file, int offset)
if (!strcmp(filename+strlen(filename)-5, ".isdn")) /* filename is always more than 5 digits long */
filename[strlen(filename)-5] = '\0';
if (!ea_endpoint->ep_portlist)
{
if (!ea_endpoint->ep_portlist) {
PERROR("EPOINT(%d) no portlist\n", ea_endpoint->ep_serial);
}
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VBOX_PLAY);
@ -953,8 +888,7 @@ void EndpointAppPBX::set_play_speed(int speed)
{
struct lcr_msg *message;
if (!ea_endpoint->ep_portlist)
{
if (!ea_endpoint->ep_portlist) {
PERROR("EPOINT(%d) no portlist\n", ea_endpoint->ep_serial);
}
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VBOX_PLAY_SPEED);

View File

@ -228,8 +228,7 @@ void generate_tables(char law)
{
int i, j;
if (law == 'a')
{
if (law == 'a') {
audio_law_to_s32=audio_alaw_to_s32;
/* generating alaw-table */
i = j = 0;
@ -242,8 +241,7 @@ void generate_tables(char law)
= audio_alaw_relations[(j<<1)|1];
i++;
}
} else
{
} else {
audio_law_to_s32=audio_ulaw_to_s32;
/* generating ulaw-table */
i = j = 0;

View File

@ -133,16 +133,14 @@ int bchannel_create(struct bchannel *bchannel, int mode)
unsigned int on = 1;
struct sockaddr_mISDN addr;
if (bchannel->b_sock > -1)
{
if (bchannel->b_sock > -1) {
CERROR(bchannel->call, NULL, "Socket already created for handle 0x%x\n", bchannel->handle);
return(0);
}
/* open socket */
bchannel->b_mode = mode;
switch(bchannel->b_mode)
{
switch(bchannel->b_mode) {
case 0:
CDEBUG(bchannel->call, NULL, "Open DSP audio\n");
bchannel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
@ -160,16 +158,14 @@ int bchannel_create(struct bchannel *bchannel, int mode)
bchannel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_HDLC);
break;
}
if (bchannel->b_sock < 0)
{
if (bchannel->b_sock < 0) {
CERROR(bchannel->call, NULL, "Failed to open bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDN_dsp.ko?\n", bchannel->handle);
return(0);
}
/* set nonblocking io */
ret = ioctl(bchannel->b_sock, FIONBIO, &on);
if (ret < 0)
{
if (ret < 0) {
CERROR(bchannel->call, NULL, "Failed to set bchannel-socket handle 0x%x into nonblocking IO\n", bchannel->handle);
close(bchannel->b_sock);
bchannel->b_sock = -1;
@ -181,8 +177,7 @@ int bchannel_create(struct bchannel *bchannel, int mode)
addr.dev = (bchannel->handle>>8);
addr.channel = bchannel->handle & 0xff;
ret = bind(bchannel->b_sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0)
{
if (ret < 0) {
CERROR(bchannel->call, NULL, "Failed to bind bchannel-socket for handle 0x%x with mISDN-DSP layer. (port %d, channel %d) Did you load mISDN_dsp.ko?\n", bchannel->handle, addr.dev, addr.channel);
close(bchannel->b_sock);
bchannel->b_sock = -1;
@ -202,8 +197,7 @@ void bchannel_activate(struct bchannel *bchannel, int activate)
/* activate bchannel */
CDEBUG(bchannel->call, NULL, "%sActivating B-channel.\n", activate?"":"De-");
switch(bchannel->b_mode)
{
switch(bchannel->b_mode) {
case 0:
case 2:
act.prim = (activate)?DL_ESTABLISH_REQ:DL_RELEASE_REQ;
@ -269,8 +263,7 @@ static void bchannel_activated(struct bchannel *bchannel)
*/
void bchannel_destroy(struct bchannel *bchannel)
{
if (bchannel->b_sock > -1)
{
if (bchannel->b_sock > -1) {
close(bchannel->b_sock);
bchannel->b_sock = -1;
}
@ -291,24 +284,20 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned char *buffer, i
struct bchannel *remote_bchannel;
int ret;
if (hh->prim == PH_CONTROL_IND)
{
if (hh->prim == PH_CONTROL_IND) {
/* non dsp -> ignore ph_control */
if (bchannel->b_mode == 1 || bchannel->b_mode == 3)
return;
if (len < 4)
{
if (len < 4) {
CERROR(bchannel->call, NULL, "SHORT READ OF PH_CONTROL INDICATION\n");
return;
}
if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
{
if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL) {
if (bchannel->call)
lcr_in_dtmf(bchannel->call, cont & DTMF_TONE_MASK);
return;
}
switch(cont)
{
switch(cont) {
case DSP_BF_REJECT:
CERROR(bchannel->call, NULL, "Blowfish crypt rejected.\n");
break;
@ -322,18 +311,15 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned char *buffer, i
}
return;
}
if (hh->prim == PH_DATA_REQ)
{
if (!bchannel->b_txdata)
{
if (hh->prim == PH_DATA_REQ) {
if (!bchannel->b_txdata) {
/* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
CDEBUG(bchannel->call, NULL, "ignoring tx data, because 'txdata' is turned off\n");
return;
}
return;
}
if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND)
{
if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND) {
CERROR(bchannel->call, NULL, "Bchannel received unknown primitve: 0x%lx\n", hh->prim);
return;
}
@ -364,32 +350,27 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned char *buffer, i
*/
/* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
if (bchannel->b_rxoff)
{
if (bchannel->b_rxoff) {
CDEBUG(bchannel->call, NULL, "ignoring data, because rx is turned off\n");
return;
}
if (!bchannel->call)
{
if (!bchannel->call) {
CDEBUG(bchannel->call, NULL, "ignoring data, because no call associated with bchannel\n");
return;
}
if (!bchannel->call->audiopath)
{
if (!bchannel->call->audiopath) {
/* return, because we have no audio from port */
return;
}
if (bchannel->call->pipe[1] < 0)
{
if (bchannel->call->pipe[1] < 0) {
/* nobody there */
return;
}
/* if no hdlc */
if (bchannel->b_mode == 0 || bchannel->b_mode == 1)
{
if (bchannel->b_mode == 0 || bchannel->b_mode == 1) {
d = data;
for (i = 0; i < len; i++) {
*d = flip_bits[*d];
@ -424,8 +405,7 @@ void bchannel_transmit(struct bchannel *bchannel, unsigned char *data, int len)
return;
if (len > 1024 || len < 1)
return;
switch(bchannel->b_mode)
{
switch(bchannel->b_mode) {
case 0:
for (i = 0; i < len; i++)
*p++ = flip_bits[*data++];
@ -467,8 +447,7 @@ void bchannel_join(struct bchannel *bchannel, unsigned short id)
bchannel->b_conf = 0;
bchannel->b_rxoff = 0;
}
if (bchannel->b_state == BSTATE_ACTIVE)
{
if (bchannel->b_state == BSTATE_ACTIVE) {
ph_control(sock, DSP_RECEIVE_OFF, bchannel->b_rxoff, "DSP-RX_OFF", bchannel->b_conf, bchannel->b_mode);
ph_control(sock, DSP_CONF_JOIN, bchannel->b_conf, "DSP-CONF", bchannel->b_conf, bchannel->b_mode);
}
@ -547,17 +526,13 @@ int bchannel_handle(void)
/* process all bchannels */
bchannel = bchannel_first;
while(bchannel)
{
while(bchannel) {
/* handle message from bchannel */
if (bchannel->b_sock > -1)
{
if (bchannel->b_sock > -1) {
ret = recv(bchannel->b_sock, buffer, sizeof(buffer), 0);
if (ret >= (int)MISDN_HEADER_LEN)
{
if (ret >= (int)MISDN_HEADER_LEN) {
work = 1;
switch(hh->prim)
{
switch(hh->prim) {
/* we don't care about confirms, we use rx data to sync tx */
case PH_DATA_CNF:
break;
@ -589,8 +564,7 @@ int bchannel_handle(void)
default:
CERROR(bchannel->call, NULL, "child message not handled: prim(0x%x) socket(%d) data len(%d)\n", hh->prim, bchannel->b_sock, ret - MISDN_HEADER_LEN);
}
} else
{
} else {
if (ret < 0 && errno != EWOULDBLOCK)
CERROR(bchannel->call, NULL, "Read from socket %d failed with return code %d\n", bchannel->b_sock, ret);
}
@ -611,8 +585,7 @@ struct bchannel *find_bchannel_handle(unsigned int handle)
{
struct bchannel *bchannel = bchannel_first;
while(bchannel)
{
while(bchannel) {
if (bchannel->handle == handle)
break;
bchannel = bchannel->next;
@ -625,8 +598,7 @@ struct bchannel *find_bchannel_ref(unsigned int ref)
{
struct bchannel *bchannel = bchannel_first;
while(bchannel)
{
while(bchannel) {
if (bchannel->ref == ref)
break;
bchannel = bchannel->next;
@ -656,15 +628,12 @@ void free_bchannel(struct bchannel *bchannel)
{
struct bchannel **temp = &bchannel_first;
while(*temp)
{
if (*temp == bchannel)
{
while(*temp) {
if (*temp == bchannel) {
*temp = (*temp)->next;
if (bchannel->b_sock > -1)
bchannel_destroy(bchannel);
if (bchannel->call)
{
if (bchannel->call) {
if (bchannel->call->bchannel)
bchannel->call->bchannel = NULL;
}

View File

@ -460,7 +460,6 @@ static void bootstrap_om_bs11(struct gsm_bts *bts)
/* Connect signalling of bts0/trx0 to e1_0/ts1/64kbps */
abis_nm_conn_terr_sign(trx, 0, 1, 0xff);
set_ts_e1link(&trx->ts[0], 0, 1, 0xff);
abis_nm_raw_msg(bts, sizeof(msg_6), msg_6); /* SET TRX ATTRIBUTES */
/* Use TEI 1 for signalling */
@ -477,43 +476,36 @@ static void bootstrap_om_bs11(struct gsm_bts *bts)
/* SET CHANNEL ATTRIBUTE TS1 */
abis_nm_set_channel_attr(&trx->ts[1], NM_CHANC_TCHFull);
/* Connect traffic of bts0/trx0/ts1 to e1_0/ts2/b */
set_ts_e1link(&trx->ts[1], 0, 2, 1);
abis_nm_conn_terr_traf(&trx->ts[1], 0, 2, 1);
/* SET CHANNEL ATTRIBUTE TS2 */
abis_nm_set_channel_attr(&trx->ts[2], NM_CHANC_TCHFull);
/* Connect traffic of bts0/trx0/ts2 to e1_0/ts2/c */
set_ts_e1link(&trx->ts[2], 0, 2, 2);
abis_nm_conn_terr_traf(&trx->ts[2], 0, 2, 2);
/* SET CHANNEL ATTRIBUTE TS3 */
abis_nm_set_channel_attr(&trx->ts[3], NM_CHANC_TCHFull);
/* Connect traffic of bts0/trx0/ts3 to e1_0/ts2/d */
set_ts_e1link(&trx->ts[3], 0, 2, 3);
abis_nm_conn_terr_traf(&trx->ts[3], 0, 2, 3);
/* SET CHANNEL ATTRIBUTE TS4 */
abis_nm_set_channel_attr(&trx->ts[4], NM_CHANC_TCHFull);
/* Connect traffic of bts0/trx0/ts4 to e1_0/ts3/a */
set_ts_e1link(&trx->ts[4], 0, 3, 0);
abis_nm_conn_terr_traf(&trx->ts[4], 0, 3, 0);
/* SET CHANNEL ATTRIBUTE TS5 */
abis_nm_set_channel_attr(&trx->ts[5], NM_CHANC_TCHFull);
/* Connect traffic of bts0/trx0/ts5 to e1_0/ts3/b */
set_ts_e1link(&trx->ts[5], 0, 3, 1);
abis_nm_conn_terr_traf(&trx->ts[5], 0, 3, 1);
/* SET CHANNEL ATTRIBUTE TS6 */
abis_nm_set_channel_attr(&trx->ts[6], NM_CHANC_TCHFull);
/* Connect traffic of bts0/trx0/ts6 to e1_0/ts3/c */
set_ts_e1link(&trx->ts[6], 0, 3, 2);
abis_nm_conn_terr_traf(&trx->ts[6], 0, 3, 2);
/* SET CHANNEL ATTRIBUTE TS7 */
abis_nm_set_channel_attr(&trx->ts[7], NM_CHANC_TCHFull);
/* Connect traffic of bts0/trx0/ts7 to e1_0/ts3/d */
set_ts_e1link(&trx->ts[7], 0, 3, 3);
abis_nm_conn_terr_traf(&trx->ts[7], 0, 3, 3);
/* end DB transmission */
@ -586,6 +578,48 @@ static u_int8_t si1[] = {
/* s1 reset*/0x2B
};
static u_int8_t *gsm48_si1(u_int8_t *arfcn_list, int arfcn_len, int max_trans, int tx_integer, int cell_barr, int re, int ec, u_int8_t *ac_list, int ac_len)
{
static u_int8_t si[23];
int i, bit, octet;
memset(&si, 0, sizeof(si));
/* header */
si[0] = 0x55;
si[1] = 0x06;
si[2] = 0x19;
/* ccdesc */
for (i = 0; i < arfcn_len; i++) {
if (arfcn_list[i] <= 124 && arfcn_list[i] > 0) {
bit = (arfcn_list[i] - 1) & 7;
octet = (arfcn_list[i] -1) / 8;
si[18 - octet] |= (1 << bit);
}
}
/* rach */
si[19] = (max_trans << 6);
si[19] |= (tx_integer << 2);
si[19] |= (cell_barr << 1);
si[19] |= re;
si[20] = (ec << 2);
for (i = 0; i < ac_len; i++) {
if (ac_list[i] <= 15 && ac_list[i] != 10) {
bit = ac_list[i] & 7;
octet = ac_list[i] / 8;
si[21 - octet] |= (1 << bit);
}
}
/* s1 rest */
si[22] = 0x2B;
/* testig */
if (memcmp(&si1, &si, sizeof(si)))
printf("SI1 does not match default template.\n");
return si;
}
/*
SYSTEM INFORMATION TYPE 2
Neighbour Cells Description
@ -609,6 +643,49 @@ static u_int8_t si2[] = {
/* rach*/0xD5, 0x00, 0x00
};
static u_int8_t *gsm48_si2(int ba, u_int8_t *arfcn_list, int arfcn_len, u_int8_t ncc, int max_trans, int tx_integer, int cell_barr, int re, int ec, u_int8_t *ac_list, int ac_len)
{
static u_int8_t si[23];
int i, bit, octet;
memset(&si, 0, sizeof(si));
/* header */
si[0] = 0x59;
si[1] = 0x06;
si[2] = 0x1A;
/* ncdesc */
si[3] = (ba << 4);
for (i = 0; i < arfcn_len; i++) {
if (arfcn_list[i] <= 124 && arfcn_list[i] > 0) {
bit = (arfcn_list[i] - 1) & 7;
octet = (arfcn_list[i] -1) / 8;
si[18 - octet] |= (1 << bit);
}
}
/* ncc */
si[19] = ncc;
/* rach */
si[20] = (max_trans << 6);
si[20] |= (tx_integer << 2);
si[20] |= (cell_barr << 1);
si[20] |= re;
si[21] = (ec << 2);
for (i = 0; i < ac_len; i++) {
if (ac_list[i] <= 15 && ac_list[i] != 10) {
bit = ac_list[i] & 7;
octet = ac_list[i] / 8;
si[22 - octet] |= (1 << bit);
}
}
/* testig */
if (memcmp(&si2, &si, sizeof(si)))
printf("SI2 does not match default template.\n");
return si;
}
/*
SYSTEM INFORMATION TYPE 3
Cell identity = 00001 (1h)
@ -711,6 +788,33 @@ static u_int8_t si5[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static u_int8_t *gsm48_si5(int ba, u_int8_t *arfcn_list, int arfcn_len)
{
static u_int8_t si[18];
int i, bit, octet;
memset(&si, 0, sizeof(si));
/* header */
si[0] = 0x06;
si[1] = 0x1D;
/* ncdesc */
si[2] = (ba << 4);
for (i = 0; i < arfcn_len; i++) {
if (arfcn_list[i] <= 124 && arfcn_list[i] > 0) {
bit = (arfcn_list[i] - 1) & 7;
octet = (arfcn_list[i] -1) / 8;
si[17 - octet] |= (1 << bit);
}
}
/* testig */
if (memcmp(&si3, &si, sizeof(si)))
printf("SI3 does not match default template.\n");
return si;
}
// SYSTEM INFORMATION TYPE 6
/*
@ -772,13 +876,37 @@ static_assert(sizeof(si6) >= sizeof(struct gsm48_system_information_type_6), typ
static int set_system_infos(struct gsm_bts_trx *trx)
{
unsigned int i;
u_int8_t *_si1;
u_int8_t *_si2;
u_int8_t *_si5;
u_int8_t arfcn_list[8];
for (i = 0; i < ARRAY_SIZE(bcch_infos); i++) {
arfcn_list[0] = trx->arfcn;
_si1 = gsm48_si1(arfcn_list, 1, 3, 5, 0, 1, 0, NULL, 0);
memset(arfcn_list, 0, sizeof(arfcn_list));
arfcn_list[0] = trx->arfcn;
arfcn_list[1] = 112;
arfcn_list[2] = 62;
arfcn_list[3] = 99;
arfcn_list[4] = 77;
arfcn_list[5] = 64;
arfcn_list[6] = 54;
arfcn_list[7] = 51;
_si2 = gsm48_si2(0, arfcn_list, 8, 0xff, 3, 5, 0, 1, 0, NULL, 0);
_si5 = gsm48_si5(0, arfcn_list, 8);
rsl_bcch_info(trx, RSL_SYSTEM_INFO_1, _si1, 23);
rsl_bcch_info(trx, RSL_SYSTEM_INFO_2, _si2, 23);
// rsl_bcch_info(trx, RSL_SYSTEM_INFO_3, _si3, );
// rsl_bcch_info(trx, RSL_SYSTEM_INFO_4, _si4, );
for (i = 2; i < ARRAY_SIZE(bcch_infos); i++) {
rsl_bcch_info(trx, bcch_infos[i].type,
bcch_infos[i].data,
bcch_infos[i].len);
}
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_5, si5, sizeof(si5));
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_5, _si5, 18);
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_6, si6, sizeof(si6));
return 0;
@ -790,6 +918,7 @@ static int set_system_infos(struct gsm_bts_trx *trx)
*/
static void patch_tables(struct gsm_bts *bts)
{
#warning todo
u_int8_t arfcn_low = bts->trx[0].arfcn & 0xff;
u_int8_t arfcn_high = (bts->trx[0].arfcn >> 8) & 0x0f;
/* covert the raw packet to the struct */
@ -880,6 +1009,30 @@ static int bootstrap_bts(struct gsm_bts *bts, int lac, int arfcn)
paging_init(bts);
if (bts->type == GSM_BTS_TYPE_BS11) {
struct gsm_bts_trx *trx = &bts->trx[0];
set_ts_e1link(&trx->ts[0], 0, 1, 0xff);
set_ts_e1link(&trx->ts[1], 0, 2, 1);
set_ts_e1link(&trx->ts[2], 0, 2, 2);
set_ts_e1link(&trx->ts[3], 0, 2, 3);
set_ts_e1link(&trx->ts[4], 0, 3, 0);
set_ts_e1link(&trx->ts[5], 0, 3, 1);
set_ts_e1link(&trx->ts[6], 0, 3, 2);
set_ts_e1link(&trx->ts[7], 0, 3, 3);
#ifdef HAVE_TRX1
/* TRX 1 */
trx = &bts->trx[1];
set_ts_e1link(&trx->ts[0], 0, 1, 0xff);
set_ts_e1link(&trx->ts[1], 0, 2, 1);
set_ts_e1link(&trx->ts[2], 0, 2, 2);
set_ts_e1link(&trx->ts[3], 0, 2, 3);
set_ts_e1link(&trx->ts[4], 0, 3, 0);
set_ts_e1link(&trx->ts[5], 0, 3, 1);
set_ts_e1link(&trx->ts[6], 0, 3, 2);
set_ts_e1link(&trx->ts[7], 0, 3, 3);
#endif
}
return 0;
}

View File

@ -20,13 +20,11 @@
*/
const char *nationalize_callerinfo(const char *string, int *ntype, const char *national, const char *international)
{
if (!strncmp(international, string, strlen(international)))
{
if (!strncmp(international, string, strlen(international))) {
*ntype = INFO_NTYPE_INTERNATIONAL;
return(string+strlen(international));
}
if (!strncmp(national, string, strlen(national)))
{
if (!strncmp(national, string, strlen(national))) {
*ntype = INFO_NTYPE_NATIONAL;
return(string+strlen(national));
}
@ -41,8 +39,7 @@ const char *numberrize_callerinfo(const char *string, int ntype, const char *nat
{
static char result[256];
switch(ntype)
{
switch(ntype) {
case INFO_NTYPE_NOTPRESENT:
return("");

21
cause.c
View File

@ -383,37 +383,30 @@ char *get_isdn_cause(int cause, int location, int type)
*/
void collect_cause(int *multicause, int *multilocation, int newcause, int newlocation)
{
if (newcause == CAUSE_REJECTED) /* call rejected */
{
if (newcause == CAUSE_REJECTED) { /* call rejected */
*multicause = newcause;
*multilocation = newlocation;
} else
if (newcause==CAUSE_NORMAL && *multicause!=CAUSE_REJECTED) /* reject via hangup */
{
if (newcause==CAUSE_NORMAL && *multicause!=CAUSE_REJECTED) { /* reject via hangup */
*multicause = newcause;
*multilocation = newlocation;
} else
if (newcause==CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) /* busy */
{
if (newcause==CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) { /* busy */
*multicause = newcause;
*multilocation = newlocation;
} else
if (newcause==CAUSE_OUTOFORDER && *multicause!=CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) /* no L1 */
{
if (newcause==CAUSE_OUTOFORDER && *multicause!=CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) { /* no L1 */
*multicause = newcause;
*multilocation = newlocation;
} else
if (newcause!=CAUSE_NOUSER && *multicause!=CAUSE_OUTOFORDER && *multicause!=CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) /* anything but not 18 */
{
if (newcause!=CAUSE_NOUSER && *multicause!=CAUSE_OUTOFORDER && *multicause!=CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) { /* anything but not 18 */
*multicause = newcause;
*multilocation = newlocation;
} else
if (newcause==CAUSE_NOUSER && *multicause==CAUSE_NOUSER) /* cause 18, use the location */
{
if (newcause==CAUSE_NOUSER && *multicause==CAUSE_NOUSER) { /* cause 18, use the location */
*multilocation = newlocation;
} else
if (*multicause==0) /* no cause yet, use newcause (should be 18) */
{
if (*multicause==0) { /* no cause yet, use newcause (should be 18) */
*multicause = newcause;
*multilocation = newlocation;
}

View File

@ -254,8 +254,7 @@ struct chan_call *find_call_ref(unsigned int ref)
struct chan_call *call = call_first;
int assigned = (ref > 0);
while(call)
{
while(call) {
if (call->ref == ref && call->ref_was_assigned == assigned)
break;
call = call->next;
@ -267,23 +266,19 @@ void free_call(struct chan_call *call)
{
struct chan_call **temp = &call_first;
while(*temp)
{
if (*temp == call)
{
while(*temp) {
if (*temp == call) {
*temp = (*temp)->next;
if (call->pipe[0] > -1)
close(call->pipe[0]);
if (call->pipe[1] > -1)
close(call->pipe[1]);
if (call->bchannel)
{
if (call->bchannel) {
if (call->bchannel->call != call)
CERROR(call, NULL, "Linked bchannel structure has no link to us.\n");
call->bchannel->call = NULL;
}
if (call->bridge_call)
{
if (call->bridge_call) {
if (call->bridge_call->bridge_call != call)
CERROR(call, NULL, "Linked call structure has no link to us.\n");
call->bridge_call->bridge_call = NULL;
@ -327,11 +322,9 @@ unsigned short new_bridge_id(void)
unsigned short id = 1;
/* search for lowest bridge id that is not in use and not 0 */
while(id)
{
while(id) {
call = call_first;
while(call)
{
while(call) {
if (call->bridge_id == id)
break;
call = call->next;
@ -391,8 +384,7 @@ void apply_opt(struct chan_call *call, char *data)
string[sizeof(string)-1] = '\0';
/* parse options */
while((opt = strsep(&p, ":")))
{
while((opt = strsep(&p, ":"))) {
switch(opt[0]) {
case 'd':
if (opt[1] == '\0') {
@ -437,8 +429,7 @@ void apply_opt(struct chan_call *call, char *data)
break;
}
i = 0;
while(*key)
{
while(*key) {
if (*key>='0' && *key<='9')
call->bf_key[i] = (*key-'0') << 8;
else if (*key>='a' && *key<='f')
@ -605,14 +596,12 @@ static void send_setup_to_lcr(struct chan_call *call)
strncpy(newparam.setup.callerinfo.id, call->cid_num, sizeof(newparam.setup.callerinfo.id)-1);
if (call->cid_name[0])
strncpy(newparam.setup.callerinfo.name, call->cid_name, sizeof(newparam.setup.callerinfo.name)-1);
if (call->cid_rdnis[0])
{
if (call->cid_rdnis[0]) {
strncpy(newparam.setup.redirinfo.id, call->cid_rdnis, sizeof(newparam.setup.redirinfo.id)-1);
newparam.setup.redirinfo.itype = INFO_ITYPE_CHAN;
newparam.setup.redirinfo.ntype = INFO_NTYPE_UNKNOWN;
}
switch(ast->cid.cid_pres & AST_PRES_RESTRICTION)
{
switch(ast->cid.cid_pres & AST_PRES_RESTRICTION) {
case AST_PRES_RESTRICTED:
newparam.setup.callerinfo.present = INFO_PRESENT_RESTRICTED;
break;
@ -623,8 +612,7 @@ static void send_setup_to_lcr(struct chan_call *call)
default:
newparam.setup.callerinfo.present = INFO_PRESENT_ALLOWED;
}
switch(ast->cid.cid_ton)
{
switch(ast->cid.cid_ton) {
case 4:
newparam.setup.callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
break;
@ -723,17 +711,14 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c
CDEBUG(call, ast, "Try to start pbx. (exten=%s context=%s complete=%s)\n", exten, ast->context, complete?"yes":"no");
if (complete)
{
if (complete) {
/* if not match */
if (!ast_canmatch_extension(ast, ast->context, exten, 1, call->oad))
{
if (!ast_canmatch_extension(ast, ast->context, exten, 1, call->oad)) {
CDEBUG(call, ast, "Got 'sending complete', but extension '%s' will not match at context '%s' - releasing.\n", exten, ast->context);
cause = 1;
goto release;
}
if (!ast_exists_extension(ast, ast->context, exten, 1, call->oad))
{
if (!ast_exists_extension(ast, ast->context, exten, 1, call->oad)) {
CDEBUG(call, ast, "Got 'sending complete', but extension '%s' would match at context '%s', if more digits would be dialed - releasing.\n", exten, ast->context);
cause = 28;
goto release;
@ -749,8 +734,7 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c
goto start;
}
if (ast_canmatch_extension(ast, ast->context, exten, 1, call->oad))
{
if (ast_canmatch_extension(ast, ast->context, exten, 1, call->oad)) {
/* send setup acknowledge to lcr */
if (call->state != CHAN_LCR_STATE_IN_DIALING) {
memset(&newparam, 0, sizeof(union parameter));
@ -801,8 +785,7 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c
#endif
ret = ast_pbx_start(ast);
if (ret < 0)
{
if (ret < 0) {
cause = (ret==-2)?34:27;
goto release;
}
@ -829,8 +812,7 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
#endif
if (!ast)
{
if (!ast) {
/* release */
CERROR(call, NULL, "Failed to create Asterisk channel - releasing.\n");
send_release_and_import(call, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL);
@ -857,8 +839,7 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
ast->cid.cid_name = strdup(param->setup.callerinfo.name);
if (param->setup.redirinfo.id[0])
ast->cid.cid_name = strdup(numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
switch (param->setup.callerinfo.present)
{
switch (param->setup.callerinfo.present) {
case INFO_PRESENT_ALLOWED:
ast->cid.cid_pres = AST_PRES_ALLOWED;
break;
@ -868,8 +849,7 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
default:
ast->cid.cid_pres = AST_PRES_UNAVAILABLE;
}
switch (param->setup.callerinfo.ntype)
{
switch (param->setup.callerinfo.ntype) {
case INFO_NTYPE_SUBSCRIBER:
ast->cid.cid_ton = 4;
break;
@ -988,8 +968,7 @@ static void lcr_in_disconnect(struct chan_call *call, int message_type, union pa
/* if bridge, forward disconnect and return */
#ifdef TODO
feature flag
if (call->bridge_call)
{
if (call->bridge_call) {
CDEBUG(call, call->ast, "Only signal disconnect via bridge.\n");
bridge_message_if_bridged(call, message_type, param);
return;
@ -1001,8 +980,7 @@ static void lcr_in_disconnect(struct chan_call *call, int message_type, union pa
/* change to release state */
call->state = CHAN_LCR_STATE_RELEASE;
/* queue release asterisk */
if (ast)
{
if (ast) {
ast->hangupcause = call->cause;
if (call->pbx_started)
strcpy(call->queue_string, "H"); // overwrite other indications
@ -1026,22 +1004,19 @@ static void lcr_in_release(struct chan_call *call, int message_type, union param
/* change to release state */
call->state = CHAN_LCR_STATE_RELEASE;
/* copy release info */
if (!call->cause)
{
if (!call->cause) {
call->cause = param->disconnectinfo.cause;
call->location = param->disconnectinfo.location;
}
/* if we have an asterisk instance, queue hangup, else we are done */
if (ast)
{
if (ast) {
ast->hangupcause = call->cause;
if (call->pbx_started)
strcpy(call->queue_string, "H");
else {
ast_hangup(ast); // call will be destroyed here
}
} else
{
} else {
free_call(call);
}
@ -1059,8 +1034,7 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
if (!ast) return;
/* pbx not started */
if (!call->pbx_started)
{
if (!call->pbx_started) {
CDEBUG(call, call->ast, "Asterisk not started, adding digits to number.\n");
strncat(ast->exten, param->information.id, AST_MAX_EXTENSION-1);
lcr_start_pbx(call, ast, param->information.sending_complete);
@ -1185,21 +1159,17 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
memset(&newparam, 0, sizeof(union parameter));
/* handle bchannel message*/
if (message_type == MESSAGE_BCHANNEL)
{
switch(param->bchannel.type)
{
if (message_type == MESSAGE_BCHANNEL) {
switch(param->bchannel.type) {
case BCHANNEL_ASSIGN:
CDEBUG(NULL, NULL, "Received BCHANNEL_ASSIGN message. (handle=%08lx) for ref %d\n", param->bchannel.handle, ref);
if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
{
if ((bchannel = find_bchannel_handle(param->bchannel.handle))) {
CERROR(NULL, NULL, "bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
return(-1);
}
/* create bchannel */
bchannel = alloc_bchannel(param->bchannel.handle);
if (!bchannel)
{
if (!bchannel) {
CERROR(NULL, NULL, "alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
return(-1);
}
@ -1208,8 +1178,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
bchannel->b_tx_gain = param->bchannel.tx_gain;
bchannel->b_rx_gain = param->bchannel.rx_gain;
strncpy(bchannel->b_pipeline, param->bchannel.pipeline, sizeof(bchannel->b_pipeline)-1);
if (param->bchannel.crypt_len && param->bchannel.crypt_len <= sizeof(bchannel->b_bf_key))
{
if (param->bchannel.crypt_len && param->bchannel.crypt_len <= sizeof(bchannel->b_bf_key)) {
bchannel->b_bf_len = param->bchannel.crypt_len;
memcpy(bchannel->b_bf_key, param->bchannel.crypt, param->bchannel.crypt_len);
}
@ -1220,8 +1189,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
* be created until it is removed again by LCR */
/* link to call */
call = find_call_ref(ref);
if (call)
{
if (call) {
bchannel->call = call;
call->bchannel = bchannel;
if (call->dsp_dtmf)
@ -1257,8 +1225,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
case BCHANNEL_REMOVE:
CDEBUG(NULL, NULL, "Received BCHANNEL_REMOVE message. (handle=%08lx)\n", param->bchannel.handle);
if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
{
if (!(bchannel = find_bchannel_handle(param->bchannel.handle))) {
CERROR(NULL, NULL, "Bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
return(-1);
}
@ -1279,14 +1246,11 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
}
/* handle new ref */
if (message_type == MESSAGE_NEWREF)
{
if (param->direction)
{
if (message_type == MESSAGE_NEWREF) {
if (param->direction) {
/* new ref from lcr */
CDEBUG(NULL, NULL, "Received new ref by LCR, due to incomming call. (ref=%ld)\n", ref);
if (!ref || find_call_ref(ref))
{
if (!ref || find_call_ref(ref)) {
CERROR(NULL, NULL, "Illegal new ref %ld received.\n", ref);
return(-1);
}
@ -1300,13 +1264,11 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
/* set dtmf (default, use option 'n' to disable */
call->dsp_dtmf = 1;
/* wait for setup (or release from asterisk) */
} else
{
} else {
/* new ref, as requested from this remote application */
CDEBUG(NULL, NULL, "Received new ref by LCR, as requested from chan_lcr. (ref=%ld)\n", ref);
call = find_call_ref(0);
if (!call)
{
if (!call) {
/* send release, if ref does not exist */
CDEBUG(NULL, NULL, "No call found, that requests a ref.\n");
send_release_and_import(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL);
@ -1319,8 +1281,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
send_setup_to_lcr(call);
/* release if asterisk has signed off */
else if (call->state == CHAN_LCR_STATE_RELEASE)
{
else if (call->state == CHAN_LCR_STATE_RELEASE) {
/* send release */
if (call->cause)
send_release_and_import(call, call->cause, call->location);
@ -1335,22 +1296,19 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
}
/* check ref */
if (!ref)
{
if (!ref) {
CERROR(NULL, NULL, "Received message %d without ref.\n", message_type);
return(-1);
}
call = find_call_ref(ref);
if (!call)
{
if (!call) {
/* ignore ref that is not used (anymore) */
CDEBUG(NULL, NULL, "Message %d from LCR ignored, because no call instance found.\n", message_type);
return(0);
}
/* handle messages */
switch(message_type)
{
switch(message_type) {
case MESSAGE_SETUP:
lcr_in_setup(call, message_type, param);
break;
@ -1463,29 +1421,23 @@ int handle_socket(void)
/* read from socket */
len = read(lcr_sock, &msg, sizeof(msg));
if (len == 0)
{
if (len == 0) {
CERROR(NULL, NULL, "Socket closed.\n");
return(-1); // socket closed
}
if (len > 0)
{
if (len != sizeof(msg))
{
if (len > 0) {
if (len != sizeof(msg)) {
CERROR(NULL, NULL, "Socket short read. (len %d)\n", len);
return(-1); // socket error
}
if (msg.message != ADMIN_MESSAGE)
{
if (msg.message != ADMIN_MESSAGE) {
CERROR(NULL, NULL, "Socket received illegal message %d.\n", msg.message);
return(-1);
}
receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
work = 1;
} else
{
if (errno != EWOULDBLOCK)
{
} else {
if (errno != EWOULDBLOCK) {
CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
return(-1);
}
@ -1496,15 +1448,12 @@ int handle_socket(void)
return(work);
admin = admin_first;
len = write(lcr_sock, &admin->msg, sizeof(msg));
if (len == 0)
{
if (len == 0) {
CERROR(NULL, NULL, "Socket closed.\n");
return(-1); // socket closed
}
if (len > 0)
{
if (len != sizeof(msg))
{
if (len > 0) {
if (len != sizeof(msg)) {
CERROR(NULL, NULL, "Socket short write. (len %d)\n", len);
return(-1); // socket error
}
@ -1513,10 +1462,8 @@ int handle_socket(void)
free(admin);
work = 1;
} else
{
if (errno != EWOULDBLOCK)
{
} else {
if (errno != EWOULDBLOCK) {
CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
return(-1);
}
@ -1537,8 +1484,7 @@ int open_socket(void)
union parameter param;
/* open socket */
if ((lcr_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
{
if ((lcr_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
CERROR(NULL, NULL, "Failed to create socket.\n");
return(lcr_sock);
}
@ -1549,8 +1495,7 @@ int open_socket(void)
sprintf(sock_address.sun_path, SOCKET_NAME, options.lock);
/* connect socket */
if ((conn = connect(lcr_sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
{
if ((conn = connect(lcr_sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0) {
close(lcr_sock);
lcr_sock = -1;
CDEBUG(NULL, NULL, "Failed to connect to socket '%s'. Is LCR running?\n", sock_address.sun_path);
@ -1558,8 +1503,7 @@ int open_socket(void)
}
/* set non-blocking io */
if ((ret = ioctl(lcr_sock, FIONBIO, (unsigned char *)(&on))) < 0)
{
if ((ret = ioctl(lcr_sock, FIONBIO, (unsigned char *)(&on))) < 0) {
close(lcr_sock);
lcr_sock = -1;
CERROR(NULL, NULL, "Failed to set socket into non-blocking IO.\n");
@ -1776,8 +1720,7 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
CDEBUG(NULL, NULL, "Received request from Asterisk. (data=%s)\n", (char *)data);
/* if socket is closed */
if (lcr_sock < 0)
{
if (lcr_sock < 0) {
CERROR(NULL, NULL, "Rejecting call from Asterisk, because LCR not running.\n");
ast_mutex_unlock(&chan_lock);
return NULL;
@ -1785,8 +1728,7 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
/* create call instance */
call = alloc_call();
if (!call)
{
if (!call) {
/* failed to create instance */
ast_mutex_unlock(&chan_lock);
return NULL;
@ -1802,8 +1744,7 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
ast = ast_channel_alloc(1);
#endif
if (!ast)
{
if (!ast) {
CERROR(NULL, NULL, "Failed to create Asterisk channel.\n");
free_call(call);
/* failed to create instance */
@ -1983,8 +1924,7 @@ static int lcr_digit(struct ast_channel *ast, char digit)
CDEBUG(call, ast, "Received digit '%c' from Asterisk.\n", digit);
/* send information or queue them */
if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
{
if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING) {
CDEBUG(call, ast, "Sending digit to LCR, because we are in dialing state.\n");
memset(&newparam, 0, sizeof(union parameter));
newparam.information.id[0] = digit;
@ -1992,8 +1932,7 @@ static int lcr_digit(struct ast_channel *ast, char digit)
send_message(MESSAGE_INFORMATION, call->ref, &newparam);
} else
if (!call->ref
&& (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP))
{
&& (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP)) {
CDEBUG(call, ast, "Queue digits, because we are in setup/dialing state and have no ref yet.\n");
*buf = digit;
strncat(call->dialque, buf, strlen(call->dialque)-1);
@ -2103,8 +2042,7 @@ static int lcr_hangup(struct ast_channel *ast)
/* disconnect asterisk, maybe not required */
ast->tech_pvt = NULL;
ast->fds[0] = -1;
if (call->ref)
{
if (call->ref) {
/* release */
CDEBUG(call, ast, "Releasing ref and freeing call instance.\n");
if (ast->hangupcause > 0)
@ -2116,16 +2054,13 @@ static int lcr_hangup(struct ast_channel *ast)
if (!pthread_equal(tid, chan_tid))
ast_mutex_unlock(&chan_lock);
return 0;
} else
{
} else {
/* ref is not set, due to prepare setup or release */
if (call->state == CHAN_LCR_STATE_RELEASE)
{
if (call->state == CHAN_LCR_STATE_RELEASE) {
/* we get the response to our release */
CDEBUG(call, ast, "Freeing call instance, because we have no ref AND we are requesting no ref.\n");
free_call(call);
} else
{
} else {
/* during prepare, we change to release state */
CDEBUG(call, ast, "We must wait until we received our ref, until we can free call instance.\n");
call->state = CHAN_LCR_STATE_RELEASE;
@ -2537,16 +2472,14 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
ast_mutex_lock(&chan_lock);
call1 = ast1->tech_pvt;
call2 = ast2->tech_pvt;
if (call1 && call1->bridge_id)
{
if (call1 && call1->bridge_id) {
call1->bridge_id = 0;
if (call1->bchannel)
bchannel_join(call1->bchannel, 0);
if (call1->bridge_call)
call1->bridge_call->bridge_call = NULL;
}
if (call2 && call1->bridge_id)
{
if (call2 && call1->bridge_id) {
call2->bridge_id = 0;
if (call2->bchannel)
bchannel_join(call2->bchannel, 0);
@ -2823,8 +2756,7 @@ int load_module(void)
#endif
quit = 0;
if ((pthread_create(&chan_tid, NULL, chan_thread, NULL)<0))
{
if ((pthread_create(&chan_tid, NULL, chan_thread, NULL)<0)) {
/* failed to create thread */
bchannel_deinitialize();
close_socket();

View File

@ -4,7 +4,7 @@
# Enable debugging of OpenBSC library.
# Refer to OpenBSC project for debugging options.
# By default, debugging is turned off.
#debug DRLL:DCC:DNM:DRR:DRSL:DNM:DSMS:DMNCC:DPAG:DMUX
#debug DRLL:DCC:DMM:DRR:DRSL:DNM:DSMS:DMNCC:DMNSMS:DPAG:DMUX
# Two Loopback interfaces for audio transfer between OpenBSC and mISDN.
# The first interface must provide B-channelis for each call mobile call.
@ -50,8 +50,9 @@ allow-all
# To keep layer 2 connection to BS11 when quitting, use this option.
# It is only usefull for developing. TRX will stay on.
# Also changes in frequency, mcc, mnc, lac while keeping layer 2 will cause
# malefunction of BSC.
# Warning: Keeping layer 2 link may prevent emergency calls. (See below)
# Layer 2 will only be kept, if lcr was killed manually.
#keep-l2
# You must define a list of your BTS'.
@ -72,6 +73,7 @@ bts bs11 9 123
# emergency facility. If you can't do that, don't touch it!
#no-emergency-shutdown
# Write BTS-Link traffic to PCAP file.
#pcapfile pcap

View File

@ -1064,8 +1064,10 @@ void Pdss1::disconnect_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3
dec_ie_display(l3m, (unsigned char *)display, sizeof(display));
end_trace();
if (cause < 0)
if (cause < 0) {
cause = 16;
location = LOCATION_PRIVATE_LOCAL;
}
/* release if remote sends us no tones */
if (!p_m_mISDNport->earlyb) {
@ -1152,8 +1154,10 @@ void Pdss1::release_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
dec_ie_display(l3m, (unsigned char *)display, sizeof(display));
end_trace();
if (cause < 0)
if (cause < 0) {
cause = 16;
location = LOCATION_PRIVATE_LOCAL;
}
/* sending release to endpoint */
if (location == LOCATION_PRIVATE_LOCAL)
@ -1203,8 +1207,10 @@ void Pdss1::release_complete_ind(unsigned int cmd, unsigned int pid, struct l3_m
if (location == LOCATION_PRIVATE_LOCAL)
location = LOCATION_PRIVATE_REMOTE;
if (cause < 0)
if (cause < 0) {
cause = 16;
location = LOCATION_PRIVATE_LOCAL;
}
/* sending release to endpoint */
while(p_epointlist) {

50
gsm.cpp
View File

@ -16,6 +16,7 @@ extern "C" {
#include "openbsc/trau_frame.h"
#include "openbsc/select.h"
#include "openbsc/debug.h"
#include "openbsc/e1_input.h"
#include "bootstrap.h"
#include "gsm_audio.h"
@ -440,6 +441,7 @@ void Pgsm::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mnc
SCPY(p_callerinfo.id, mncc->calling_number);
else
p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
SCPY(p_callerinfo.imsi, mncc->imsi);
p_callerinfo.screen = INFO_SCREEN_NETWORK;
p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
p_callerinfo.isdn_port = p_m_portnum;
@ -507,7 +509,11 @@ void Pgsm::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mnc
/* what infos did we got ... */
gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
add_trace("subscr", "number", "%s", p_callerinfo.id);
if (p_callerinfo.id[0])
add_trace("calling", "number", "%s", p_callerinfo.id);
else
SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
add_trace("dialing", "number", "%s", p_dialinginfo.id);
end_trace();
@ -656,13 +662,26 @@ void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mnc
gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
end_trace();
SCPY(p_connectinfo.id, mncc->calling_number);
SCPY(p_connectinfo.imsi, mncc->imsi);
p_connectinfo.present = INFO_PRESENT_ALLOWED;
p_connectinfo.screen = INFO_SCREEN_NETWORK;
p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
p_connectinfo.isdn_port = p_m_portnum;
SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name);
/* send resp */
gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
if (p_connectinfo.id[0])
add_trace("connect", "number", "%s", p_connectinfo.id);
else
SPRINT(p_connectinfo.id, "imsi-%s", p_connectinfo.imsi);
add_trace("connect", "imsi", "%s", p_connectinfo.imsi);
resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
end_trace();
send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
message_put(message);
new_state(PORT_STATE_CONNECT);
@ -1102,8 +1121,13 @@ void Pgsm::message_setup(unsigned int epoint_id, int message_id, union parameter
}
/* dialing information */
mncc->called = 1;
SCPY(mncc->called_number, p_dialinginfo.id);
add_trace("dialing", "number", "%s", mncc->called_number);
if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
SCPY(mncc->imsi, p_dialinginfo.id+5);
add_trace("dialing", "imsi", "%s", mncc->imsi);
} else {
SCPY(mncc->called_number, p_dialinginfo.id);
add_trace("dialing", "number", "%s", mncc->called_number);
}
/* sending user-user */
@ -1595,7 +1619,9 @@ int gsm_exit(int rc)
int gsm_init(void)
{
char hlr[128];
char hlr[128], filename[128];
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int pcapfd;
/* create gsm instance */
gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
@ -1621,17 +1647,33 @@ int gsm_init(void)
PERROR("Expecting exactly one BTS. You defined %d.\n", gsm->conf.numbts);
return gsm_exit(-1);
}
/* bootstrap network */
gsm->network = bootstrap_network(&message_bcs, gsm->conf.bts[0].type, gsm->conf.mcc, gsm->conf.mnc, gsm->conf.lac, gsm->conf.bts[0].frequency[0], gsm->conf.bts[0].card, !gsm->conf.keep_l2, gsm->conf.short_name, gsm->conf.long_name, hlr, gsm->conf.allow_all);
if (!gsm->network) {
PERROR("Failed to bootstrap GSM network.\n");
return gsm_exit(-1);
}
/* open gsm loop interface */
if (gsm_sock_open(gsm->conf.interface_bsc)) {
return gsm_exit(-1);
}
/* open pcap file */
if (gsm->conf.pcapfile[0]) {
if (gsm->conf.pcapfile[0] == '/')
SCPY(filename, gsm->conf.pcapfile);
else
SPRINT(filename, "%s/%s", CONFIG_DATA, gsm->conf.pcapfile);
pcapfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode);
if (pcapfd < 0) {
PERROR("Failed to open file for pcap\n");
return gsm_exit(-1);
}
e1_set_pcap_fd(pcapfd);
}
return 0;
}

1
gsm.h
View File

@ -21,6 +21,7 @@ struct gsm_conf {
int numbts; /* number of BTS' */
struct bts_conf bts[8]; /* configure BTS' */
int noemergshut; /* don't shut down on emergency */
char pcapfile[128]; /* open capture file for BS11 links */
};
struct lcr_gsm {

View File

@ -48,22 +48,19 @@ int gsm_conf(struct gsm_conf *gsm_conf)
SPRINT(filename, "%s/gsm.conf", CONFIG_DATA);
if (!(fp=fopen(filename,"r")))
{
if (!(fp=fopen(filename,"r"))) {
SPRINT(gsm_conf_error, "Cannot open %s\n",filename);
return(0);
}
line=0;
while((fgets(buffer,sizeof(buffer),fp)))
{
while((fgets(buffer,sizeof(buffer),fp))) {
line++;
buffer[sizeof(buffer)-1]=0;
if (buffer[0]) buffer[strlen(buffer)-1]=0;
p=buffer;
while(*p <= 32) /* skip spaces */
{
while(*p <= 32) { /* skip spaces */
if (*p == 0)
break;
p++;
@ -73,10 +70,8 @@ int gsm_conf(struct gsm_conf *gsm_conf)
option[0]=0;
i=0; /* read option */
while(*p > 32)
{
if (i+1 >= sizeof(option))
{
while(*p > 32) {
if (i+1 >= sizeof(option)) {
SPRINT(gsm_conf_error, "Error in %s (line %d): option too long.\n",filename,line);
goto error;
}
@ -84,8 +79,7 @@ int gsm_conf(struct gsm_conf *gsm_conf)
option[i++] = *p++;
}
while(*p <= 32) /* skip spaces */
{
while(*p <= 32) { /* skip spaces */
if (*p == 0)
break;
p++;
@ -93,21 +87,17 @@ int gsm_conf(struct gsm_conf *gsm_conf)
params[0][0] = 0;
pnum = 0;
while(*p!=0 && *p!='#' && pnum < 10) /* param */
{
while(*p!=0 && *p!='#' && pnum < 10) { /* param */
i=0; /* read param */
while(*p > 32)
{
if (i+1 >= sizeof(params[pnum]))
{
while(*p > 32) {
if (i+1 >= sizeof(params[pnum])) {
SPRINT(gsm_conf_error, "Error in %s (line %d): param too long.\n",filename,line);
goto error;
}
params[pnum][i+1] = '\0';
params[pnum][i++] = *p++;
}
while(*p <= 32) /* skip spaces */
{
while(*p <= 32) { /* skip spaces */
if (*p == 0)
break;
p++;
@ -119,133 +109,113 @@ int gsm_conf(struct gsm_conf *gsm_conf)
/* at this point we have option and param */
/* check option */
if (!strcmp(option,"debug"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"debug")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
goto error;
}
SCPY(gsm_conf->debug, params[0]);
} else
if (!strcmp(option,"interface-bsc"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"interface-bsc")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
SCPY(gsm_conf->interface_bsc, params[0]);
} else
if (!strcmp(option,"interface-lcr"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"interface-lcr")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
SCPY(gsm_conf->interface_lcr, params[0]);
} else
if (!strcmp(option,"short-name"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"short-name")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
SCPY(gsm_conf->short_name, params[0]);
} else
if (!strcmp(option,"long-name"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"long-name")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
SCPY(gsm_conf->long_name, params[0]);
} else
if (!strcmp(option,"mcc"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"mcc")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
gsm_conf->mcc = atoi(params[0]);
} else
if (!strcmp(option,"mnc"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"mnc")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
gsm_conf->mnc = atoi(params[0]);
} else
if (!strcmp(option,"lac"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"lac")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
gsm_conf->lac = atoi(params[0]);
} else
if (!strcmp(option,"hlr"))
{
if (params[0][0]==0)
{
if (!strcmp(option,"hlr")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
SCPY(gsm_conf->hlr, params[0]);
} else
if (!strcmp(option,"allow-all"))
{
if (!strcmp(option,"allow-all")) {
gsm_conf->allow_all = 1;
} else
if (!strcmp(option,"keep-l2"))
{
if (!strcmp(option,"keep-l2")) {
gsm_conf->keep_l2 = 1;
} else
if (!strcmp(option,"no-mergency-shutdown"))
{
if (!strcmp(option,"no-mergency-shutdown")) {
gsm_conf->noemergshut = 1;
} else
if (!strcmp(option,"bts"))
{
if (gsm_conf->numbts == 8)
{
if (!strcmp(option,"pcapfile")) {
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
goto error;
}
SCPY(gsm_conf->pcapfile, params[0]);
} else
if (!strcmp(option,"bts")) {
if (gsm_conf->numbts == 8) {
SPRINT(gsm_conf_error, "Error in %s (line %d): too many BTS defined.\n",filename,line);
goto error;
}
if (params[0][0]==0)
{
if (params[0][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter <bts-type> for option %s missing.\n",filename,line,option);
goto error;
}
if (params[1][0]==0)
{
if (params[1][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter <card number> for option %s missing.\n",filename,line,option);
goto error;
}
if (params[2][0]==0)
{
if (params[2][0]==0) {
SPRINT(gsm_conf_error, "Error in %s (line %d): parameter <frequency> for option %s missing.\n",filename,line,option);
goto error;
}
if (!strcmp(params[0], "bs11"))
{
if (!strcmp(params[0], "bs11")) {
gsm_conf->bts[gsm_conf->numbts].type = GSM_BTS_TYPE_BS11;
} else {
SPRINT(gsm_conf_error, "Error in %s (line %d): unknown BTS type '%s'.\n",filename,line,params[0]);
@ -253,18 +223,15 @@ int gsm_conf(struct gsm_conf *gsm_conf)
}
gsm_conf->bts[gsm_conf->numbts].card = atoi(params[1]);
gsm_conf->bts[gsm_conf->numbts].numtrx = 0;
while (params[gsm_conf->bts[gsm_conf->numbts].numtrx+2][0])
{
if (gsm_conf->bts[gsm_conf->numbts].numtrx == 8)
{
while (params[gsm_conf->bts[gsm_conf->numbts].numtrx+2][0]) {
if (gsm_conf->bts[gsm_conf->numbts].numtrx == 8) {
SPRINT(gsm_conf_error, "Error in %s (line %d): too many frequencies defined.\n",filename,line);
goto error;
}
gsm_conf->bts[gsm_conf->numbts].frequency[gsm_conf->bts[gsm_conf->numbts].numtrx++] = atoi(params[gsm_conf->bts[gsm_conf->numbts].numtrx+2]);
}
gsm_conf->numbts++;
} else
{
} else {
SPRINT(gsm_conf_error, "Error in %s (line %d): wrong option keyword %s.\n", filename,line,option);
goto error;
}

View File

@ -165,6 +165,7 @@ struct caller_info {
int ntype2; /* second type of number */
int present2; /* second presentation */
int screen2; /* second who provided the number */
char imsi[16]; /* IMSI for gsm originated calls */
};
/* call-info structure DIALING */
@ -189,6 +190,7 @@ struct connect_info {
int present; /* presentation */
int screen; /* who provided the number */
char display[84]; /* display information */
char imsi[16]; /* IMSI for gsm terminated calls */
};
/* call-info structure DISCONNECT */