support for sending ETSI advice of charge
Review: https://reviewboard.asterisk.org/r/619/ git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1776 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
8c5eeeae79
commit
660609c45b
137
libpri.h
137
libpri.h
@ -543,8 +543,8 @@ struct pri_rerouting_data {
|
|||||||
#define PRI_SUBCMD_AOC_S 18 /*!< Advice Of Charge Start information (Rate list) */
|
#define PRI_SUBCMD_AOC_S 18 /*!< Advice Of Charge Start information (Rate list) */
|
||||||
#define PRI_SUBCMD_AOC_D 19 /*!< Advice Of Charge During information */
|
#define PRI_SUBCMD_AOC_D 19 /*!< Advice Of Charge During information */
|
||||||
#define PRI_SUBCMD_AOC_E 20 /*!< Advice Of Charge End information */
|
#define PRI_SUBCMD_AOC_E 20 /*!< Advice Of Charge End information */
|
||||||
//#define PRI_SUBCMD_AOC_CHARGING_REQ 21 /*!< Advice Of Charge Request information */
|
#define PRI_SUBCMD_AOC_CHARGING_REQ 21 /*!< Advice Of Charge Request information */
|
||||||
//#define PRI_SUBCMD_AOC_CHARGING_REQ_RSP 22 /*!< Advice Of Charge Request Response information */
|
#define PRI_SUBCMD_AOC_CHARGING_REQ_RSP 22 /*!< Advice Of Charge Request Response information */
|
||||||
#define PRI_SUBCMD_MCID_REQ 23 /*!< Malicious Call ID Request */
|
#define PRI_SUBCMD_MCID_REQ 23 /*!< Malicious Call ID Request */
|
||||||
#define PRI_SUBCMD_MCID_RSP 24 /*!< Malicious Call ID Request response */
|
#define PRI_SUBCMD_MCID_RSP 24 /*!< Malicious Call ID Request response */
|
||||||
|
|
||||||
@ -877,6 +877,64 @@ struct pri_subcmd_aoc_e {
|
|||||||
struct pri_aoc_e_charging_association associated;
|
struct pri_aoc_e_charging_association associated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum PRI_AOC_REQ_RSP {
|
||||||
|
/* Error Results */
|
||||||
|
PRI_AOC_REQ_RSP_ERROR_NOT_IMPLEMENTED,
|
||||||
|
PRI_AOC_REQ_RSP_ERROR_NOT_AVAILABLE,
|
||||||
|
PRI_AOC_REQ_RSP_ERROR_TIMEOUT,
|
||||||
|
PRI_AOC_REQ_RSP_ERROR_REJECT,
|
||||||
|
/* generic error result all other errors are lumped into */
|
||||||
|
PRI_AOC_REQ_RSP_ERROR,
|
||||||
|
|
||||||
|
/* AOC Results */
|
||||||
|
PRI_AOC_REQ_RSP_CHARGING_INFO_FOLLOWS,
|
||||||
|
PRI_AOC_REQ_RSP_CURRENCY_INFO_LIST,
|
||||||
|
PRI_AOC_REQ_RSP_SPECIAL_ARR,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PRI_AOC_REQUEST {
|
||||||
|
PRI_AOC_REQUEST_S = (1 << 0),
|
||||||
|
PRI_AOC_REQUEST_D = (1 << 1),
|
||||||
|
PRI_AOC_REQUEST_E = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pri_subcmd_aoc_request_response {
|
||||||
|
/*!
|
||||||
|
* \brief aoc_s data from response
|
||||||
|
*/
|
||||||
|
struct pri_subcmd_aoc_s aoc_s;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief if the aoc_s msg is present, this will be set
|
||||||
|
*/
|
||||||
|
int valid_aoc_s;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief What type of aoc was requested.
|
||||||
|
* \see enum PRI_AOC_REQUEST
|
||||||
|
*/
|
||||||
|
int charging_request;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief response to the charging_request
|
||||||
|
* \see enum PRI_AOC_REQ_RSP
|
||||||
|
*/
|
||||||
|
int charging_response;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pri_subcmd_aoc_request {
|
||||||
|
/*!
|
||||||
|
* \brief What types of aoc are being requested.
|
||||||
|
* \see enum PRI_AOC_REQUEST
|
||||||
|
*/
|
||||||
|
int charging_request;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Value given by the initiating request.
|
||||||
|
*/
|
||||||
|
int invoke_id;
|
||||||
|
};
|
||||||
|
|
||||||
struct pri_subcmd_mcid_req {
|
struct pri_subcmd_mcid_req {
|
||||||
/*!
|
/*!
|
||||||
* \brief Information libpri knows about the malicious caller.
|
* \brief Information libpri knows about the malicious caller.
|
||||||
@ -934,6 +992,8 @@ struct pri_subcommand {
|
|||||||
struct pri_subcmd_cc_id cc_call;
|
struct pri_subcmd_cc_id cc_call;
|
||||||
struct pri_subcmd_cc_cancel cc_cancel;
|
struct pri_subcmd_cc_cancel cc_cancel;
|
||||||
struct pri_subcmd_transfer transfer;
|
struct pri_subcmd_transfer transfer;
|
||||||
|
struct pri_subcmd_aoc_request aoc_request;
|
||||||
|
struct pri_subcmd_aoc_request_response aoc_request_response;
|
||||||
struct pri_subcmd_aoc_s aoc_s;
|
struct pri_subcmd_aoc_s aoc_s;
|
||||||
struct pri_subcmd_aoc_d aoc_d;
|
struct pri_subcmd_aoc_d aoc_d;
|
||||||
struct pri_subcmd_aoc_e aoc_e;
|
struct pri_subcmd_aoc_e aoc_e;
|
||||||
@ -1587,6 +1647,79 @@ void pri_set_inbanddisconnect(struct pri *pri, unsigned int enable);
|
|||||||
(and maybe some timers) */
|
(and maybe some timers) */
|
||||||
void pri_enslave(struct pri *master, struct pri *slave);
|
void pri_enslave(struct pri *master, struct pri *slave);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Request AOC on call setup
|
||||||
|
*
|
||||||
|
* \param call setup struct to set charging request info on
|
||||||
|
* \param charging request to set on setup struct
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval -1 on failure
|
||||||
|
*/
|
||||||
|
int pri_sr_set_aoc_charging_request(struct pri_sr *sr, int charging_request);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Send AOC Request Response to a request for AOC-S
|
||||||
|
*
|
||||||
|
* \param ctrl D channel controller.
|
||||||
|
* \param call Q.931 call leg.
|
||||||
|
* \param invoke_id for response message
|
||||||
|
* \param aoc_s message for response
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval -1 on failure
|
||||||
|
*/
|
||||||
|
int pri_aoc_s_request_response_send(struct pri *ctrl, q931_call *call, int invoke_id, const struct pri_subcmd_aoc_s *aoc_s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Send AOC Request Response to a request for AOC-D or AOC-E
|
||||||
|
*
|
||||||
|
* \param ctrl D channel controller.
|
||||||
|
* \param call Q.931 call leg.
|
||||||
|
* \param response in form of enum PRI_AOC_REQ_RSP
|
||||||
|
* \param invoke_id for response message
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval -1 on failure
|
||||||
|
*/
|
||||||
|
int pri_aoc_de_request_response_send(struct pri *ctrl, q931_call *call, int response, int invoke_id);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Send AOC-S message.
|
||||||
|
*
|
||||||
|
* \param ctrl D channel controller.
|
||||||
|
* \param call Q.931 call leg.
|
||||||
|
* \param aoc_s message to send
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval -1 on failure
|
||||||
|
*/
|
||||||
|
int pri_aoc_s_send(struct pri *ctrl, q931_call *c, const struct pri_subcmd_aoc_s *aoc_s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Send AOC-D message.
|
||||||
|
*
|
||||||
|
* \param ctrl D channel controller.
|
||||||
|
* \param call Q.931 call leg.
|
||||||
|
* \param aoc_d message to send
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval -1 on failure
|
||||||
|
*/
|
||||||
|
int pri_aoc_d_send(struct pri *ctrl, q931_call *c, const struct pri_subcmd_aoc_d *aoc_d);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Send AOC-E message.
|
||||||
|
*
|
||||||
|
* \param ctrl D channel controller.
|
||||||
|
* \param call Q.931 call leg.
|
||||||
|
* \param aoc_e message to send
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval -1 on failure
|
||||||
|
*/
|
||||||
|
int pri_aoc_e_send(struct pri *ctrl, q931_call *c, const struct pri_subcmd_aoc_e *aoc_e);
|
||||||
|
|
||||||
#define PRI_GR303_SUPPORT
|
#define PRI_GR303_SUPPORT
|
||||||
#define PRI_ENSLAVE_SUPPORT
|
#define PRI_ENSLAVE_SUPPORT
|
||||||
#define PRI_SETUP_CALL
|
#define PRI_SETUP_CALL
|
||||||
|
@ -3296,6 +3296,9 @@ int pri_call_add_standard_apdus(struct pri *ctrl, q931_call *call)
|
|||||||
switch (ctrl->switchtype) {
|
switch (ctrl->switchtype) {
|
||||||
case PRI_SWITCH_EUROISDN_E1:
|
case PRI_SWITCH_EUROISDN_E1:
|
||||||
case PRI_SWITCH_EUROISDN_T1:
|
case PRI_SWITCH_EUROISDN_T1:
|
||||||
|
if (call->aoc_charging_request) {
|
||||||
|
aoc_charging_request_send(ctrl, call, call->aoc_charging_request);
|
||||||
|
}
|
||||||
if (PTMP_MODE(ctrl)) {
|
if (PTMP_MODE(ctrl)) {
|
||||||
/* PTMP mode */
|
/* PTMP mode */
|
||||||
break;
|
break;
|
||||||
@ -4336,7 +4339,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROSE_ETSI_ChargingRequest:
|
case ROSE_ETSI_ChargingRequest:
|
||||||
/* Ignore messsage */
|
aoc_etsi_aoc_request(ctrl, call, invoke);
|
||||||
break;
|
break;
|
||||||
case ROSE_ETSI_AOCSCurrency:
|
case ROSE_ETSI_AOCSCurrency:
|
||||||
aoc_etsi_aoc_s_currency(ctrl, invoke);
|
aoc_etsi_aoc_s_currency(ctrl, invoke);
|
||||||
|
@ -128,15 +128,21 @@ union apdu_callback_param {
|
|||||||
/* So calls to pri_call_apdu_find() will not find an aliased event. */
|
/* So calls to pri_call_apdu_find() will not find an aliased event. */
|
||||||
#define APDU_INVALID_INVOKE_ID 0x10000
|
#define APDU_INVALID_INVOKE_ID 0x10000
|
||||||
|
|
||||||
|
#define APDU_TIMEOUT_MSGS_ONLY -1
|
||||||
|
|
||||||
struct apdu_callback_data {
|
struct apdu_callback_data {
|
||||||
/*! APDU invoke id to match with any response messages. (Result/Error/Reject) */
|
/*! APDU invoke id to match with any response messages. (Result/Error/Reject) */
|
||||||
int invoke_id;
|
int invoke_id;
|
||||||
/*!
|
/*!
|
||||||
* \brief Time to wait for responses to APDU in ms.
|
* \brief Time to wait for responses to APDU in ms.
|
||||||
* \note Set to 0 if send the message only.
|
* \note Set to 0 if send the message only.
|
||||||
* \note Set to less than 0 for PRI_TIMER_T_RESPONSE time.
|
* \note Set to APDU_TIMEOUT_MSGS_ONLY to "timeout" with the message_type list only.
|
||||||
*/
|
*/
|
||||||
int timeout_time;
|
int timeout_time;
|
||||||
|
/*! Number of Q.931 messages the APDU can "timeout" on. */
|
||||||
|
unsigned num_messages;
|
||||||
|
/*! Q.931 message list to "timeout" on. */
|
||||||
|
int message_type[5];
|
||||||
/*!
|
/*!
|
||||||
* \brief APDU callback function.
|
* \brief APDU callback function.
|
||||||
*
|
*
|
||||||
@ -245,6 +251,8 @@ void pri_cc_qsig_request(struct pri *ctrl, q931_call *call, int msgtype, const s
|
|||||||
void pri_cc_qsig_cancel(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
|
void pri_cc_qsig_cancel(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
|
||||||
void pri_cc_qsig_exec_possible(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
|
void pri_cc_qsig_exec_possible(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
|
||||||
|
|
||||||
|
int aoc_charging_request_send(struct pri *ctrl, q931_call *c, enum PRI_AOC_REQUEST aoc_request_flag);
|
||||||
|
void aoc_etsi_aoc_request(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
|
||||||
void aoc_etsi_aoc_s_currency(struct pri *ctrl, const struct rose_msg_invoke *invoke);
|
void aoc_etsi_aoc_s_currency(struct pri *ctrl, const struct rose_msg_invoke *invoke);
|
||||||
void aoc_etsi_aoc_s_special_arrangement(struct pri *ctrl, const struct rose_msg_invoke *invoke);
|
void aoc_etsi_aoc_s_special_arrangement(struct pri *ctrl, const struct rose_msg_invoke *invoke);
|
||||||
void aoc_etsi_aoc_d_currency(struct pri *ctrl, const struct rose_msg_invoke *invoke);
|
void aoc_etsi_aoc_d_currency(struct pri *ctrl, const struct rose_msg_invoke *invoke);
|
||||||
|
@ -366,6 +366,7 @@ struct pri_sr {
|
|||||||
const char *keypad_digits;
|
const char *keypad_digits;
|
||||||
int transferable;
|
int transferable;
|
||||||
int reversecharge;
|
int reversecharge;
|
||||||
|
int aoc_charging_request;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Internal switch types */
|
/* Internal switch types */
|
||||||
@ -632,6 +633,9 @@ struct q931_call {
|
|||||||
/*! TRUE if outgoing call was already redirected. */
|
/*! TRUE if outgoing call was already redirected. */
|
||||||
unsigned char initially_redirected;
|
unsigned char initially_redirected;
|
||||||
} cc;
|
} cc;
|
||||||
|
|
||||||
|
/* AOC charge requesting on Setup */
|
||||||
|
int aoc_charging_request;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CC_STATES {
|
enum CC_STATES {
|
||||||
|
69
q931.c
69
q931.c
@ -2437,17 +2437,18 @@ static int transmit_facility(int full_ie, struct pri *ctrl, q931_call *call, int
|
|||||||
cur->sent = 1;
|
cur->sent = 1;
|
||||||
|
|
||||||
if (cur->response.callback && cur->response.timeout_time) {
|
if (cur->response.callback && cur->response.timeout_time) {
|
||||||
int duration;
|
int failed;
|
||||||
|
|
||||||
if (0 < cur->response.timeout_time) {
|
if (0 < cur->response.timeout_time) {
|
||||||
/* Sender specified timeout duration. */
|
/* Sender specified a timeout duration. */
|
||||||
duration = cur->response.timeout_time;
|
cur->timer = pri_schedule_event(ctrl, cur->response.timeout_time,
|
||||||
|
q931_apdu_timeout, cur);
|
||||||
|
failed = !cur->timer;
|
||||||
} else {
|
} else {
|
||||||
/* Sender wants to use the typical timeout duration. */
|
/* Sender wants to "timeout" only when specified messages are received. */
|
||||||
duration = ctrl->timers[PRI_TIMER_T_RESPONSE];
|
failed = !cur->response.num_messages;
|
||||||
}
|
}
|
||||||
cur->timer = pri_schedule_event(ctrl, duration, q931_apdu_timeout, cur);
|
if (failed) {
|
||||||
if (!cur->timer) {
|
|
||||||
/* Remove APDU from list. */
|
/* Remove APDU from list. */
|
||||||
*prev = cur->next;
|
*prev = cur->next;
|
||||||
|
|
||||||
@ -2456,7 +2457,7 @@ static int transmit_facility(int full_ie, struct pri *ctrl, q931_call *call, int
|
|||||||
|
|
||||||
free(cur);
|
free(cur);
|
||||||
}
|
}
|
||||||
} else if (!cur->timer) {
|
} else {
|
||||||
/* Remove APDU from list. */
|
/* Remove APDU from list. */
|
||||||
*prev = cur->next;
|
*prev = cur->next;
|
||||||
free(cur);
|
free(cur);
|
||||||
@ -2576,6 +2577,52 @@ static void q931_handle_facilities(struct pri *ctrl, q931_call *call, int msgtyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief Check if any APDU responses "timeout" with the current Q.931 message.
|
||||||
|
*
|
||||||
|
* \param ctrl D channel controller.
|
||||||
|
* \param call Q.931 call leg.
|
||||||
|
* \param msgtype Q.931 message type received.
|
||||||
|
*
|
||||||
|
* \return Nothing
|
||||||
|
*/
|
||||||
|
static void q931_apdu_msg_expire(struct pri *ctrl, struct q931_call *call, int msgtype)
|
||||||
|
{
|
||||||
|
struct apdu_event **prev;
|
||||||
|
struct apdu_event **prev_next;
|
||||||
|
struct apdu_event *cur;
|
||||||
|
unsigned idx;
|
||||||
|
|
||||||
|
for (prev = &call->apdus; *prev; prev = prev_next) {
|
||||||
|
cur = *prev;
|
||||||
|
prev_next = &cur->next;
|
||||||
|
if (cur->sent) {
|
||||||
|
for (idx = 0; idx < cur->response.num_messages; ++idx) {
|
||||||
|
if (cur->response.message_type[idx] == msgtype) {
|
||||||
|
/*
|
||||||
|
* APDU response message "timeout".
|
||||||
|
*
|
||||||
|
* Extract the APDU from the list so it cannot be
|
||||||
|
* deleted from under us by the callback.
|
||||||
|
*/
|
||||||
|
prev_next = prev;
|
||||||
|
*prev = cur->next;
|
||||||
|
|
||||||
|
/* Stop any response timeout. */
|
||||||
|
pri_schedule_del(ctrl, cur->timer);
|
||||||
|
cur->timer = 0;
|
||||||
|
|
||||||
|
cur->response.callback(APDU_CALLBACK_REASON_TIMEOUT, ctrl, call, cur, NULL);
|
||||||
|
|
||||||
|
free(cur);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int transmit_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
|
static int transmit_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
|
||||||
{
|
{
|
||||||
int code, mask;
|
int code, mask;
|
||||||
@ -5093,6 +5140,8 @@ int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
|
|||||||
|
|
||||||
c->reversecharge = req->reversecharge;
|
c->reversecharge = req->reversecharge;
|
||||||
|
|
||||||
|
c->aoc_charging_request = req->aoc_charging_request;
|
||||||
|
|
||||||
pri_call_add_standard_apdus(ctrl, c);
|
pri_call_add_standard_apdus(ctrl, c);
|
||||||
|
|
||||||
/* Save the initial cc-parties. */
|
/* Save the initial cc-parties. */
|
||||||
@ -6423,6 +6472,7 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
|
|||||||
/* Now handle the facility ie's after all the other ie's were processed. */
|
/* Now handle the facility ie's after all the other ie's were processed. */
|
||||||
q931_handle_facilities(ctrl, c, mh->msg);
|
q931_handle_facilities(ctrl, c, mh->msg);
|
||||||
}
|
}
|
||||||
|
q931_apdu_msg_expire(ctrl, c, mh->msg);
|
||||||
|
|
||||||
/* Post handling */
|
/* Post handling */
|
||||||
switch (h->pd) {
|
switch (h->pd) {
|
||||||
@ -6436,6 +6486,9 @@ int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
|
|||||||
|
|
||||||
if (c->master_call->outboundbroadcast) {
|
if (c->master_call->outboundbroadcast) {
|
||||||
nt_ptmp_handle_q931_message(ctrl, mh, c, &allow_event, &allow_posthandle);
|
nt_ptmp_handle_q931_message(ctrl, mh, c, &allow_event, &allow_posthandle);
|
||||||
|
if (allow_event) {
|
||||||
|
q931_apdu_msg_expire(ctrl, c->master_call, mh->msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allow_posthandle) {
|
if (allow_posthandle) {
|
||||||
|
Loading…
Reference in New Issue
Block a user