Add option to give numbers or ranges to complete en-block dialing

This commit is contained in:
Andreas Eversberg 2023-02-05 10:27:35 +01:00
parent 887aaddeee
commit f2500899b8
3 changed files with 144 additions and 2 deletions

View File

@ -104,6 +104,12 @@ static void print_help()
printf(" Enable en-block dialing, to collect number before setup. The value\n");
printf(" given is the number of seconds to wait for more digits to be dialed.\n");
printf(" (default = %d)\n", enblock);
printf(" -D --dial-hint xxxx | xxxx-yyyy\n");
printf(" The given one or multpiple hits for numbers with a fixed length. This\n");
printf(" can be a single number or a range of number. If a range is given, xxxx\n");
printf(" and yyyy must have equal length. If one of the given numbers are dialed,\n");
printf(" the en-block dialing is complete and there is no need to wait for the\n");
printf(" timeout.\n");
printf(" --recall\n");
printf(" Enable recall / call waiting. (disabled by default)\n");
printf(" -R --ringing-type-incoming <type>\n");
@ -166,6 +172,7 @@ static void add_options(void)
option_add(OPT_TX_CID_BELL, "cid-bell", 0);
option_add(OPT_TX_CID_DTMF, "cid-dtmf", 1);
option_add(OPT_TX_ENBLOCK, "enblock", 1);
option_add('D', "dial-hint", 1);
option_add(OPT_TX_RECALL, "recall", 0);
option_add(OPT_TX_RING_I, "ringing-type-incoming", 1);
option_add(OPT_TX_RING_H, "ringing-type-hold", 1);
@ -245,6 +252,13 @@ static int handle_options(int short_option, int argi, char **argv)
case OPT_TX_RECALL:
recall = 1;
break;
case 'D':
rc = add_dial_hint(argv[argi]);
if (rc < 0) {
fprintf(stderr, "Given dial hint '%s' is not valid, please use -h for help.\n", argv[argi]);
return rc;
}
break;
case OPT_TX_RING_I:
if (ringing_type_incoming_num == SUBSCRIBER_MAX) {
fprintf(stderr, "Cannot define more than %d ringing types.\n", SUBSCRIBER_MAX);
@ -425,6 +439,8 @@ error:
pstn_destroy(pstn_ep);
}
purge_dial_hints();
options_free();
/* exit fm */

View File

@ -159,6 +159,112 @@ static const char *timer_ident_name(enum timer_ident ident)
}
};
/*
* dial hints
*/
static struct dial_hint *dial_hints = NULL;
int add_dial_hint(const char *arg)
{
struct dial_hint *hint;
int i, dash;
hint = calloc(1, sizeof(*hint));
if (!hint)
return -ENOMEM;
for (i = 0, dash = -1; arg[i]; i++) {
if (arg[i] == '-') {
/* only single dash is allowed */
if (dash >= 0)
goto error;
dash = i;
continue;
}
/* only digits 0..9 are allowd */
if (arg[i] < '0' || arg[i] > '9')
goto error;
}
if (dash < 0) {
/* number must have at least one digit */
if (i < 1)
goto error;
hint->length = i;
hint->from = calloc(1, i + 1);
if (!hint->from)
goto error;
strcpy(hint->from, arg);
PDEBUG(DTEL, DEBUG_INFO, "Added dial hint '%s'\n", hint->from);
} else {
/* both numbers must have same lenth */
if (dash != i - dash - 1)
goto error;
/* there must be digits at all */
if (dash < 1)
goto error;
hint->length = dash;
hint->from = calloc(1, dash + 1);
if (!hint->from)
goto error;
strncpy(hint->from, arg, dash);
hint->to = calloc(1, dash + 1);
if (!hint->to)
goto error;
strcpy(hint->to, arg + dash + 1);
/* second string must be greater than first string */
if (strcmp(hint->from, hint->to) > 0)
goto error;
PDEBUG(DTEL, DEBUG_INFO, "Added dial hint '%s' - '%s'\n", hint->from, hint->to);
}
hint->next = dial_hints;
dial_hints = hint;
return 0;
error:
free(hint->from);
free(hint->to);
free(hint);
return -EINVAL;
}
static int check_dial_hint(const char *number)
{
struct dial_hint *hint;
size_t length = strlen(number);
for (hint = dial_hints; hint; hint = hint->next) {
if (hint->length != length)
continue;
if (hint->from && !hint->to) {
if (strncmp(number, hint->from, hint->length) == 0)
return 1;
}
if (hint->from && hint->to) {
if (strncmp(number, hint->from, hint->length) >= 0
&& strncmp(number, hint->to, hint->length) <= 0)
return 1;
}
}
return 0;
}
void purge_dial_hints(void)
{
struct dial_hint *hint;
while ((hint = dial_hints)) {
dial_hints = hint->next;
free(hint->from);
free(hint->to);
free(hint);
}
}
/*
* Endpoint instance
*/
@ -521,7 +627,7 @@ void recv_dtmf(void *priv, char digit, dtmf_meas_t __attribute__((unused)) *meas
/* if we are receiving digits en block */
if (pstn->call[PSTN_CALL_ACTIVE]->state == CALL_STATE_ENBLOCK) {
if (digit == '#') {
PDEBUG(DTEL, DEBUG_DEBUG, "Number is complete, send setup\n");
PDEBUG(DTEL, DEBUG_DEBUG, "Digit '#' received, number is complete, send setup\n");
/* setup (en block) */
setup_ind(pstn, PSTN_CALL_ACTIVE, pstn->dialing, 1);
return;
@ -531,6 +637,12 @@ void recv_dtmf(void *priv, char digit, dtmf_meas_t __attribute__((unused)) *meas
char called[2] = { digit, '\0' };
strncat(pstn->dialing, called, sizeof(pstn->dialing) - 1);
PDEBUG(DTEL, DEBUG_DEBUG, "Appending digit, so dial string is now: '%s'.\n", pstn->dialing);
if (check_dial_hint(pstn->dialing)) {
PDEBUG(DTEL, DEBUG_DEBUG, "Number in list of dial hints received, number is complete, send setup\n");
/* setup (en block) */
setup_ind(pstn, PSTN_CALL_ACTIVE, pstn->dialing, 1);
return;
}
/* start dial timer */
timer_on(pstn, (double)pstn->enblock, TIMER_IDENT_DIALING);
return;
@ -1492,6 +1604,12 @@ static void v5_sig_ind(pstn_t *pstn, uint8_t *data, int len)
/* append digit */
strncat(pstn->dialing, called, sizeof(pstn->dialing) - 1);
PDEBUG(DTEL, DEBUG_DEBUG, "Appending digit, so dial string is now: '%s'.\n", pstn->dialing);
if (check_dial_hint(pstn->dialing)) {
PDEBUG(DTEL, DEBUG_DEBUG, "Number in list of dial hints received, number is complete, send setup\n");
/* setup (en block) */
setup_ind(pstn, PSTN_CALL_ACTIVE, pstn->dialing, 1);
break;
}
/* start dial timer */
timer_on(pstn, (double)pstn->enblock, TIMER_IDENT_DIALING);
break;

View File

@ -104,6 +104,12 @@ struct call {
int on_hold; /* track hold/retrieval notification */
};
struct dial_hint {
struct dial_hint *next;
size_t length;
char *from, *to;
};
typedef struct pstn {
osmo_cc_endpoint_t cc_ep;
@ -119,6 +125,7 @@ typedef struct pstn {
int cid_bell; /* use V.23 or Bell 202 FSK tones */
int cid_dtmf; /* use DTMF instead of FSK caller ID */
int enblock; /* receive digits before transmitting them via SETUP message (timeout as given) */
struct dial_hint dial_hints; /* list of numbers that are complete */
int recall; /* support recall / waiting call */
int *ringing_types_incoming;/* cadenced rining on incoming call */
int ringing_type_hold; /* cadenced rining on waiting call */
@ -153,9 +160,10 @@ typedef struct pstn {
int tx_buffer_pos; /* current position in transmit audio buffer */
} pstn_t;
int add_dial_hint(const char *arg);
void purge_dial_hints(void);
void pstn_destroy(pstn_t *pstn_ep);
pstn_t *pstn_create(void);
int pstn_init(pstn_t *pstn, const char *name, const char *socketname, const char **subscribers, int subscriber_num, uint8_t serving_location, int tx_delay, enum pstn_cid_method clip, int cid_bell, int cid_dtmf, int clip_date, int enblock, int recall, int *ringing_types_incoming, int ringing_type_hold, enum tones_type tones_type, char law);
void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg);
void rtp_work(pstn_t *pstn_ep);