Add option to give numbers or ranges to complete en-block dialing
This commit is contained in:
parent
887aaddeee
commit
f2500899b8
|
@ -104,6 +104,12 @@ static void print_help()
|
||||||
printf(" Enable en-block dialing, to collect number before setup. The value\n");
|
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(" given is the number of seconds to wait for more digits to be dialed.\n");
|
||||||
printf(" (default = %d)\n", enblock);
|
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(" --recall\n");
|
||||||
printf(" Enable recall / call waiting. (disabled by default)\n");
|
printf(" Enable recall / call waiting. (disabled by default)\n");
|
||||||
printf(" -R --ringing-type-incoming <type>\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_BELL, "cid-bell", 0);
|
||||||
option_add(OPT_TX_CID_DTMF, "cid-dtmf", 1);
|
option_add(OPT_TX_CID_DTMF, "cid-dtmf", 1);
|
||||||
option_add(OPT_TX_ENBLOCK, "enblock", 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_RECALL, "recall", 0);
|
||||||
option_add(OPT_TX_RING_I, "ringing-type-incoming", 1);
|
option_add(OPT_TX_RING_I, "ringing-type-incoming", 1);
|
||||||
option_add(OPT_TX_RING_H, "ringing-type-hold", 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:
|
case OPT_TX_RECALL:
|
||||||
recall = 1;
|
recall = 1;
|
||||||
break;
|
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:
|
case OPT_TX_RING_I:
|
||||||
if (ringing_type_incoming_num == SUBSCRIBER_MAX) {
|
if (ringing_type_incoming_num == SUBSCRIBER_MAX) {
|
||||||
fprintf(stderr, "Cannot define more than %d ringing types.\n", SUBSCRIBER_MAX);
|
fprintf(stderr, "Cannot define more than %d ringing types.\n", SUBSCRIBER_MAX);
|
||||||
|
@ -425,6 +439,8 @@ error:
|
||||||
pstn_destroy(pstn_ep);
|
pstn_destroy(pstn_ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
purge_dial_hints();
|
||||||
|
|
||||||
options_free();
|
options_free();
|
||||||
|
|
||||||
/* exit fm */
|
/* exit fm */
|
||||||
|
|
120
src/pstn/pstn.c
120
src/pstn/pstn.c
|
@ -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
|
* 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 we are receiving digits en block */
|
||||||
if (pstn->call[PSTN_CALL_ACTIVE]->state == CALL_STATE_ENBLOCK) {
|
if (pstn->call[PSTN_CALL_ACTIVE]->state == CALL_STATE_ENBLOCK) {
|
||||||
if (digit == '#') {
|
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 (en block) */
|
||||||
setup_ind(pstn, PSTN_CALL_ACTIVE, pstn->dialing, 1);
|
setup_ind(pstn, PSTN_CALL_ACTIVE, pstn->dialing, 1);
|
||||||
return;
|
return;
|
||||||
|
@ -531,6 +637,12 @@ void recv_dtmf(void *priv, char digit, dtmf_meas_t __attribute__((unused)) *meas
|
||||||
char called[2] = { digit, '\0' };
|
char called[2] = { digit, '\0' };
|
||||||
strncat(pstn->dialing, called, sizeof(pstn->dialing) - 1);
|
strncat(pstn->dialing, called, sizeof(pstn->dialing) - 1);
|
||||||
PDEBUG(DTEL, DEBUG_DEBUG, "Appending digit, so dial string is now: '%s'.\n", pstn->dialing);
|
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 */
|
/* start dial timer */
|
||||||
timer_on(pstn, (double)pstn->enblock, TIMER_IDENT_DIALING);
|
timer_on(pstn, (double)pstn->enblock, TIMER_IDENT_DIALING);
|
||||||
return;
|
return;
|
||||||
|
@ -1492,6 +1604,12 @@ static void v5_sig_ind(pstn_t *pstn, uint8_t *data, int len)
|
||||||
/* append digit */
|
/* append digit */
|
||||||
strncat(pstn->dialing, called, sizeof(pstn->dialing) - 1);
|
strncat(pstn->dialing, called, sizeof(pstn->dialing) - 1);
|
||||||
PDEBUG(DTEL, DEBUG_DEBUG, "Appending digit, so dial string is now: '%s'.\n", pstn->dialing);
|
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 */
|
/* start dial timer */
|
||||||
timer_on(pstn, (double)pstn->enblock, TIMER_IDENT_DIALING);
|
timer_on(pstn, (double)pstn->enblock, TIMER_IDENT_DIALING);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -104,6 +104,12 @@ struct call {
|
||||||
int on_hold; /* track hold/retrieval notification */
|
int on_hold; /* track hold/retrieval notification */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dial_hint {
|
||||||
|
struct dial_hint *next;
|
||||||
|
size_t length;
|
||||||
|
char *from, *to;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct pstn {
|
typedef struct pstn {
|
||||||
osmo_cc_endpoint_t cc_ep;
|
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_bell; /* use V.23 or Bell 202 FSK tones */
|
||||||
int cid_dtmf; /* use DTMF instead of FSK caller ID */
|
int cid_dtmf; /* use DTMF instead of FSK caller ID */
|
||||||
int enblock; /* receive digits before transmitting them via SETUP message (timeout as given) */
|
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 recall; /* support recall / waiting call */
|
||||||
int *ringing_types_incoming;/* cadenced rining on incoming call */
|
int *ringing_types_incoming;/* cadenced rining on incoming call */
|
||||||
int ringing_type_hold; /* cadenced rining on waiting 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 */
|
int tx_buffer_pos; /* current position in transmit audio buffer */
|
||||||
} pstn_t;
|
} pstn_t;
|
||||||
|
|
||||||
|
int add_dial_hint(const char *arg);
|
||||||
|
void purge_dial_hints(void);
|
||||||
void pstn_destroy(pstn_t *pstn_ep);
|
void pstn_destroy(pstn_t *pstn_ep);
|
||||||
pstn_t *pstn_create(void);
|
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);
|
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 cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg);
|
||||||
void rtp_work(pstn_t *pstn_ep);
|
void rtp_work(pstn_t *pstn_ep);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue