Fix number type conversion

subscriber/national/international numbers are converted to and from dial
string correctly.
This commit is contained in:
Andreas Eversberg 2023-12-10 09:21:30 +01:00
parent 72a9a666a2
commit c89853f65a
6 changed files with 98 additions and 30 deletions

View File

@ -31,6 +31,22 @@
#include "../libosmocc/helper.h"
#include "common.h"
void print_help_common(void)
{
/* - - */
printf("\n");
printf("Digits are: '0'..'9'; 'd'=code 11; 'e'=code 12; 'a'=KP1; 'b'=KP2, 'c'=ST\n");
printf("Incoming call digits depends on type of number:\n");
printf(" subsriber/unknown: a<number>c (KP1-<number>-ST)\n");
printf(" national: a0<number>c (KP1-0-<number>-ST)\n");
printf(" international: b<cc>0<number>c (KP2-<cc>-0-<number>-ST)\n");
printf("Outgoing call type depends on received digits:\n");
printf(" a<number>c: subriber number, if first digit is not '0'\n");
printf(" a0<number>c: national number\n");
printf(" b<cc>X<number>c: international number, digit X is removed\n");
printf("<cc> and <number> are separated automatically by known list of country codes.\n");
}
/*
* generate messages towards CC
*/
@ -144,22 +160,29 @@ int generate_dial_string(uint8_t type, const char *dialing, char *string, int st
return -EINVAL;
}
if (!dialing[0]) {
PDEBUG(DSS5, DEBUG_NOTICE, "Dial string is empty, call is rejected!\n");
return -EINVAL;
}
/* check for correct digits */
for (i = 0, ii = strlen(dialing); i < ii; i++) {
/* string may start with 'a' or 'b', but then 'c' must be the last digit */
if (dialing[i] == 'a' || dialing[i] == 'b') {
full_string_given = 1;
if (dialing[ii - 1] != 'c') {
PDEBUG(DSS5, DEBUG_NOTICE, "Number starts with 'a' (KP1) or 'b' (KP2) but missing 'c' (ST) at the end, call is rejected!\n");
return -EINVAL;
}
/* remove check of last digit 'c' */
--ii;
continue;
i = 0;
ii = strlen(dialing);
/* string may start with 'a' or 'b', but then 'c' must be the last digit */
if (dialing[0] == 'a' || dialing[0] == 'b') {
full_string_given = 1;
if (dialing[ii - 1] != 'c') {
PDEBUG(DSS5, DEBUG_NOTICE, "Number starts with 'a' (KP1) or 'b' (KP2) but missing 'c' (ST) at the end, call is rejected!\n");
return -EINVAL;
}
/* string must only consist of numerical digits and '*' (code 11) and '#' (code 12) */
if (!strchr("0123456789*#", dialing[i])) {
PDEBUG(DSS5, DEBUG_NOTICE, "Number has invalid digits, call is rejected!\n");
/* remove first digit 'a' or 'b' and last digit 'c' */
i++;
--ii;
}
for (; i < ii; i++) {
/* string must only consist of numerical digits and 'd' (code 11) and 'e' (code 12) */
if (!strchr("0123456789de", dialing[i])) {
PDEBUG(DSS5, DEBUG_NOTICE, "Number has invalid digit '%c' at position %d, call is rejected!\n", dialing[i], i + 1);
return -EINVAL;
}
}
@ -167,15 +190,27 @@ int generate_dial_string(uint8_t type, const char *dialing, char *string, int st
/* if full string with 'a'/'b' and 'c' is given, we have complete dial string */
if (full_string_given) {
strcpy(string, dialing);
PDEBUG(DSS5, DEBUG_INFO, "Using given digit string '%s'.\n", dialing);
return 0;
}
/* if number is not of international type, create national dial string */
if (type != OSMO_CC_TYPE_INTERNATIONAL) {
/* if number is not (inter)national, create local dial string */
if (type != OSMO_CC_TYPE_NATIONAL && type != OSMO_CC_TYPE_INTERNATIONAL) {
// make GCC happy
strcpy(string, "a");
strcat(string, dialing);
strcat(string, "c");
PDEBUG(DSS5, DEBUG_INFO, "Converting subscriber number '%s' to digits '%s'.\n", dialing, string);
return 0;
}
/* if number is national, create national dial string */
if (type == OSMO_CC_TYPE_NATIONAL) {
// make GCC happy
strcpy(string, "a0");
strcat(string, dialing);
strcat(string, "c");
PDEBUG(DSS5, DEBUG_INFO, "Converting national number '%s' to digits '%s'.\n", dialing, string);
return 0;
}
@ -194,6 +229,7 @@ int generate_dial_string(uint8_t type, const char *dialing, char *string, int st
#pragma GCC diagnostic ignored "-Wformat-overflow"
sprintf(string, "b%c0%sc", dialing[0], dialing + 1);
#pragma GCC diagnostic pop
PDEBUG(DSS5, DEBUG_INFO, "Converting international number '%s' to digits '%s' (1 digit country code).\n", dialing, string);
return 0;
}
@ -213,6 +249,7 @@ int generate_dial_string(uint8_t type, const char *dialing, char *string, int st
#pragma GCC diagnostic ignored "-Wformat-overflow"
sprintf(string, "b%c%c0%sc", dialing[0], dialing[1], dialing + 2);
#pragma GCC diagnostic pop
PDEBUG(DSS5, DEBUG_INFO, "Converting international number '%s' to digits '%s' (2 digits country code).\n", dialing, string);
return 0;
}
@ -226,6 +263,7 @@ int generate_dial_string(uint8_t type, const char *dialing, char *string, int st
#pragma GCC diagnostic ignored "-Wformat-overflow"
sprintf(string, "b%c%c%c0%sc", dialing[0], dialing[1], dialing[2], dialing + 3);
#pragma GCC diagnostic pop
PDEBUG(DSS5, DEBUG_INFO, "Converting international number '%s' to digits '%s' (3 digits country code).\n", dialing, string);
return 0;
}
@ -234,6 +272,7 @@ int parse_dial_string(uint8_t *type, char *dialing, int dialing_size, const char
{
char kp_digit;
const char *prefix;
const char *orig_string = string;
int length;
int i;
@ -261,14 +300,19 @@ int parse_dial_string(uint8_t *type, char *dialing, int dialing_size, const char
/* received local or national call */
if (kp_digit == 'a') {
/* remove discriminaing digit */
if (string[0] == '0') {
string++;
length--;
*type = OSMO_CC_TYPE_NATIONAL;
} else
*type = OSMO_CC_TYPE_UNKNOWN;
if (string[0] != '0') {
*type = OSMO_CC_TYPE_SUBSCRIBER;
strncpy(dialing, string, length);
dialing[length] = '\0';
PDEBUG(DSS5, DEBUG_INFO, "Converting received digits '%s' to subscriber number '%s'.\n", orig_string, dialing);
return 0;
}
string++;
length--;
*type = OSMO_CC_TYPE_NATIONAL;
strncpy(dialing, string, length);
dialing[length] = '\0';
PDEBUG(DSS5, DEBUG_INFO, "Converting received digits '%s' to national number '%s'.\n", orig_string, dialing);
return 0;
}
@ -293,6 +337,7 @@ int parse_dial_string(uint8_t *type, char *dialing, int dialing_size, const char
dialing[0] = prefix[0];
strncpy(dialing + 1, string, length);
dialing[1 + length] = '\0';
PDEBUG(DSS5, DEBUG_INFO, "Converting received digits '%s' to international number '%s' (1 digit country code).\n", orig_string, dialing);
return 0;
}
@ -319,6 +364,7 @@ int parse_dial_string(uint8_t *type, char *dialing, int dialing_size, const char
dialing[1] = prefix[1];
strncpy(dialing + 2, string, length);
dialing[2 + length] = '\0';
PDEBUG(DSS5, DEBUG_INFO, "Converting rdigits dialing '%s' to international number '%s' (2 digits country code).\n", orig_string, dialing);
return 0;
}
@ -340,6 +386,7 @@ int parse_dial_string(uint8_t *type, char *dialing, int dialing_size, const char
dialing[2] = prefix[2];
strncpy(dialing + 3, string, length);
dialing[3 + length] = '\0';
PDEBUG(DSS5, DEBUG_INFO, "Converting digits dialing '%s' to international number '%s' (3 digits country code).\n", orig_string, dialing);
return 0;
}

View File

@ -1,4 +1,5 @@
void print_help_common(void);
void reject_call(osmo_cc_endpoint_t *cc_ep, uint32_t callref, uint8_t isdn_cause);
void release_call(osmo_cc_endpoint_t *cc_ep, uint32_t callref, uint8_t isdn_cause);
void disconnect_call(osmo_cc_endpoint_t *cc_ep, uint32_t callref, uint8_t isdn_cause);

View File

@ -164,8 +164,8 @@ static struct dsp_digits {
{ '8', 0x02 + 0x10 },
{ '9', 0x04 + 0x10 },
{ '0', 0x08 + 0x10 },
{ '*', 0x01 + 0x20 }, /* code 11 */
{ '#', 0x02 + 0x20 }, /* code 12 */
{ 'd', 0x01 + 0x20 }, /* code 11 */
{ 'e', 0x02 + 0x20 }, /* code 12 */
{ 'a', 0x04 + 0x20 }, /* KP1 */
{ 'b', 0x08 + 0x20 }, /* KP2 */
{ 'c', 0x10 + 0x20 }, /* ST */
@ -364,12 +364,12 @@ static char decode_one[8] =
/* detection matrix for two frequencies */
static char decode_two[8][8] =
{
{ ' ', '1', '2', '4', '7', '*', ' ', ' ' }, /* * = code 11 */
{ '1', ' ', '3', '5', '8', '#', ' ', ' ' }, /* # = code 12 */
{ ' ', '1', '2', '4', '7', 'd', ' ', ' ' }, /* * = code 11 */
{ '1', ' ', '3', '5', '8', 'e', ' ', ' ' }, /* # = code 12 */
{ '2', '3', ' ', '6', '9', 'a', ' ', ' ' }, /* a = KP1 */
{ '4', '5', '6', ' ', '0', 'b', ' ', ' ' }, /* b = KP2 */
{ '7', '8', '9', '0', ' ', 'c', ' ', ' ' }, /* c = ST */
{ '*', '#', 'a', 'b', 'c', ' ', ' ', ' ' },
{ 'd', 'e', 'a', 'b', 'c', ' ', ' ', ' ' },
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'C' }, /* C = 2600+2400 */
{ ' ', ' ', ' ', ' ', ' ', ' ', 'C', ' ' }
};

View File

@ -29,6 +29,7 @@
#include "../liboptions/options.h"
#include "../libg711/g711.h"
#include "r1.h"
#include "../common/common.h"
#include "../common/display.h"
#include "../common/sit.h"
@ -99,6 +100,7 @@ static void print_help()
printf(" second endpoint.\n");
printf(" --no-l16\n");
printf(" Disable L16 (linear 16 bit) codec.\n");
print_help_common();
}
#define OPT_SENSE 256

View File

@ -641,6 +641,7 @@ void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg)
uint8_t type, plan, present, screen;
char dialing[64];
const char *sdp;
int i;
int rc;
/* hunt for callref */
@ -694,9 +695,24 @@ void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg)
link_reset(r1);
goto done;
}
rc = generate_dial_string(type, dialing, r1->dialing, sizeof(r1->dialing));
if (rc < 0)
goto inv_nr;
if (r1->pulsedialing) {
if (strlen(dialing) + 1 > sizeof(r1->dialing)) {
PDEBUG(DR1, DEBUG_NOTICE, "Dial string is too long for our digit register, call is rejected!\n");
goto inv_nr;
}
for (i = 0; dialing[i]; i++) {
/* string must only consist of numerical digits and '*' (11 pulses) and '#' (12 pulses) */
if (!strchr("0123456789*#", dialing[i])) {
PDEBUG(DR1, DEBUG_NOTICE, "Number has invalid digit '%c' at position %d, call is rejected!\n", dialing[i], i + 1);
goto inv_nr;
}
}
strcpy(r1->dialing, dialing);
} else {
rc = generate_dial_string(type, dialing, r1->dialing, sizeof(r1->dialing));
if (rc < 0)
goto inv_nr;
}
/* sdp accept */
sdp = osmo_cc_helper_audio_accept(&r1->r1_ep->cc_ep.session_config, &r1->dsp, codecs + r1->r1_ep->no_l16, down_audio, msg, &r1->dsp.cc_session, &r1->dsp.codec, 0);
if (!sdp) {

View File

@ -29,6 +29,7 @@
#include "../liboptions/options.h"
#include "../libg711/g711.h"
#include "ss5.h"
#include "../common/common.h"
#include "../common/display.h"
ss5_endpoint_t *ss5_ep_sunset = NULL, *ss5_ep_sunrise = NULL;
@ -98,6 +99,7 @@ static void print_help()
printf(" second endpoint.\n");
printf(" --no-l16\n");
printf(" Disable L16 (linear 16 bit) codec.\n");
print_help_common();
}
#define OPT_SENSE 256