提交 f012b7ab authored 作者: Stefan Knoblich's avatar Stefan Knoblich

ftmod_libpri: Major rework of runtime thread, lpwrap event loop, restart…

ftmod_libpri: Major rework of runtime thread, lpwrap event loop, restart b-channel handling and some new features.

Add per b-channel private data (ftdm_libpri_b_data_t), move the q.931 libpri
call pointer into it and use channel->call_data to make it accessible.

Use ftdm_channel_wait() instead of select() to wait for I/O events on
the D-Channel and rewrite the timeout handling, adding support for custom
timers that can be added to the b-channel private data and started/stopped
with lpwrap_timer_start()/_stop().

The (sorted) list of active lpwrap timers is protected by the timer_mutex,
which is initialized in the now unified lpwrap_init_pri() (see below) and
destroyed in the new lpwrap_destroy_pri() function.

Unify lpwrap_init_pri() and lpwrap_init_bri(). Use the span type to select
BRI/PRI and Point-to-Point vs. Multipoint settings.

Use the new custom lpwrap timer API to implement T302 (aka overlap receiving
digit timeout). The default T302 timeout is 3000 miliseconds and can be set
via the "digit_timeout" or "t302" span configuration parameter
(0 = disable timer, valid range = 3000 ... 30000 miliseconds).

The lpwrap_pri_init() changes made it neccessarry to rewrite the span runtime
thread event loop. The d-channel initialization and libpri event handler
registration have been moved out of the event loop. The b-channel restart
handling in the event loop has been left as-is, pending a further clean up in
the future.

Rename on_info() to on_information() and add a new on_keypad_digit() event
handler to convert incoming KEYPAD DIGIT messages to channel DTMF events
(only useful on BRI PTMP NT-mode).

The channel restart handling has been improved to distinguish between locally
triggered and restarts caused by the remote end (= incoming RESTART messages).
Restarts on the D-Channel now use pri_restart(), causing a Q.921 reset on
the span.

Large patch, i'd have loved to split this into smaller pieces and actually
test some of the bits more toroughly (restart handling), but some people
are f*cking annoying, so here it is.
Signed-off-by: 's avatarStefan Knoblich <stkn@openisdn.net>
上级 f3cd4f41
...@@ -35,6 +35,10 @@ ...@@ -35,6 +35,10 @@
#include "freetdm.h" #include "freetdm.h"
#include "lpwrap_pri.h" #include "lpwrap_pri.h"
#define OVERLAP_TIMEOUT_MS_DEFAULT 5000 /* 5 sec */
#define OVERLAP_TIMEOUT_MS_MIN 3000 /* 3 sec */
#define OVERLAP_TIMEOUT_MS_MAX 30000 /* 30 sec */
typedef enum { typedef enum {
SERVICE_CHANGE_STATUS_INSERVICE = 0, SERVICE_CHANGE_STATUS_INSERVICE = 0,
SERVICE_CHANGE_STATUS_MAINTENANCE, SERVICE_CHANGE_STATUS_MAINTENANCE,
...@@ -71,6 +75,7 @@ struct ftdm_libpri_data { ...@@ -71,6 +75,7 @@ struct ftdm_libpri_data {
int mode; int mode;
int dialect; int dialect;
int overlap; /*!< Overlap dial flags */ int overlap; /*!< Overlap dial flags */
int overlap_timeout_ms; /*!< Overlap dial timeout */
unsigned int layer1; unsigned int layer1;
unsigned int ton; unsigned int ton;
unsigned int service_message_support; unsigned int service_message_support;
...@@ -84,6 +89,27 @@ struct ftdm_libpri_data { ...@@ -84,6 +89,27 @@ struct ftdm_libpri_data {
typedef struct ftdm_libpri_data ftdm_libpri_data_t; typedef struct ftdm_libpri_data ftdm_libpri_data_t;
/*
* b-channel flags
*/
enum {
FTDM_LIBPRI_B_NONE = 0,
FTDM_LIBPRI_B_REMOTE_RESTART = (1 << 0), /*!< Remote triggered channel restart */
};
/**
* Per-b-channel private data
*/
struct ftdm_libpri_b_chan {
struct lpwrap_timer t302; /*!< T302 overlap receive timer */
ftdm_channel_t *channel; /*!< back-pointer to b-channel */
q931_call *call; /*!< libpri opaque call handle */
uint32_t flags; /*!< channel flags */
};
typedef struct ftdm_libpri_b_chan ftdm_libpri_b_chan_t;
#endif #endif
/* For Emacs: /* For Emacs:
......
...@@ -92,10 +92,14 @@ typedef enum { ...@@ -92,10 +92,14 @@ typedef enum {
} lpwrap_pri_switch_t; } lpwrap_pri_switch_t;
typedef enum { typedef enum {
LPWRAP_PRI_READY = (1 << 0) LPWRAP_PRI_READY = (1 << 0),
LPWRAP_PRI_ABORT = (1 << 1)
} lpwrap_pri_flag_t; } lpwrap_pri_flag_t;
struct lpwrap_pri; struct lpwrap_pri;
struct lpwrap_timer;
typedef int (*timeout_handler)(struct lpwrap_pri *, struct lpwrap_timer *);
typedef int (*event_handler)(struct lpwrap_pri *, lpwrap_pri_event_t, pri_event *); typedef int (*event_handler)(struct lpwrap_pri *, lpwrap_pri_event_t, pri_event *);
typedef int (*loop_handler)(struct lpwrap_pri *); typedef int (*loop_handler)(struct lpwrap_pri *);
...@@ -108,6 +112,8 @@ struct lpwrap_pri { ...@@ -108,6 +112,8 @@ struct lpwrap_pri {
event_handler eventmap[LPWRAP_PRI_EVENT_MAX]; event_handler eventmap[LPWRAP_PRI_EVENT_MAX];
loop_handler on_loop; loop_handler on_loop;
int errs; int errs;
struct lpwrap_timer *timer_list;
ftdm_mutex_t *timer_mutex;
}; };
typedef struct lpwrap_pri lpwrap_pri_t; typedef struct lpwrap_pri lpwrap_pri_t;
...@@ -118,15 +124,21 @@ struct lpwrap_pri_event_list { ...@@ -118,15 +124,21 @@ struct lpwrap_pri_event_list {
const char *name; const char *name;
}; };
struct lpwrap_timer {
struct lpwrap_timer *next;
ftdm_time_t timeout;
timeout_handler callback;
};
int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, const uint32_t timeout_ms, timeout_handler callback);
int lpwrap_stop_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer);
#define LPWRAP_MAP_PRI_EVENT(spri, event, func) spri.eventmap[event] = func; #define LPWRAP_MAP_PRI_EVENT(spri, event, func) spri.eventmap[event] = func;
const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id); const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id);
int lpwrap_one_loop(struct lpwrap_pri *spri);
int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug); int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug);
int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptp, int debug); int lpwrap_destroy_pri(struct lpwrap_pri *spri);
int lpwrap_run_pri_once(struct lpwrap_pri *spri);
int lpwrap_run_pri(struct lpwrap_pri *spri); int lpwrap_run_pri(struct lpwrap_pri *spri);
#define lpwrap_run_bri(x) lpwrap_run_pri(x) int lpwrap_stop_pri(struct lpwrap_pri *spri);
#endif #endif
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论