The facility ie queue needs to remove facilities that have been sent.

The facility ie queue needs to remove facilities that have been sent.
Otherwise, the queue just grows until the call is terminated.  AOC
messages can clog the queue during a long call and the dummy call
reference may never be deleted.

Also removed unneeded elements of struct apdu_event.  The callback
function was not a good idea since many facility messages do not have
responses and the callback would prevents removal of events from the list.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1283 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Richard Mudgett 2009-11-10 21:51:26 +00:00
parent 44ad020fe8
commit 6a121d4c74
4 changed files with 75 additions and 76 deletions

View File

@ -1022,7 +1022,7 @@ int rose_diverting_leg_information1_encode(struct pri *ctrl, q931_call *call)
return -1; return -1;
} }
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer);
} }
/*! /*!
@ -1191,7 +1191,7 @@ static int rose_diverting_leg_information2_encode(struct pri *ctrl, q931_call *c
return -1; return -1;
} }
return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer);
} }
/*! /*!
@ -1313,7 +1313,7 @@ int rose_diverting_leg_information3_encode(struct pri *ctrl, q931_call *call,
return -1; return -1;
} }
return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, messagetype, buffer, end - buffer);
} }
/*! /*!
@ -1384,7 +1384,7 @@ int rlt_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
return -1; return -1;
} }
if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, end - buffer, NULL, NULL)) { if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, end - buffer)) {
return -1; return -1;
} }
@ -1447,7 +1447,7 @@ static int add_dms100_transfer_ability_apdu(struct pri *ctrl, q931_call *call)
return -1; return -1;
} }
return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer);
} }
/*! /*!
@ -1556,7 +1556,7 @@ static int add_callername_facility_ies(struct pri *ctrl, q931_call *call, int cp
return -1; return -1;
} }
if (pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL, NULL)) { if (pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer)) {
return -1; return -1;
} }
@ -1579,15 +1579,11 @@ static int add_callername_facility_ies(struct pri *ctrl, q931_call *call, int cp
mymessage = Q931_FACILITY; mymessage = Q931_FACILITY;
} }
return pri_call_apdu_queue(call, mymessage, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, mymessage, buffer, end - buffer);
} }
/* End Callername */ /* End Callername */
/* MWI related encode and decode functions */ /* MWI related encode and decode functions */
static void mwi_activate_encode_cb(void *data)
{
return;
}
/*! /*!
* \internal * \internal
@ -1717,8 +1713,7 @@ int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int
return -1; return -1;
} }
return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer);
mwi_activate_encode_cb, NULL);
} }
/* End MWI */ /* End MWI */
@ -1777,7 +1772,7 @@ int eect_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
return -1; return -1;
} }
if (pri_call_apdu_queue(c1, Q931_FACILITY, buffer, end - buffer, NULL, NULL)) { if (pri_call_apdu_queue(c1, Q931_FACILITY, buffer, end - buffer)) {
pri_message(ctrl, "Could not queue APDU in facility message\n"); pri_message(ctrl, "Could not queue APDU in facility message\n");
return -1; return -1;
} }
@ -2098,7 +2093,7 @@ static int rose_reroute_request_encode(struct pri *ctrl, q931_call *call,
return -1; return -1;
} }
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer);
} }
/*! /*!
@ -2232,9 +2227,7 @@ static int anfpr_pathreplacement_respond(struct pri *ctrl, q931_call *call, q931
} }
/* Send message */ /* Send message */
res = res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len);
pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, NULL,
NULL);
if (res) { if (res) {
pri_message(ctrl, "Could not queue ADPU in facility message\n"); pri_message(ctrl, "Could not queue ADPU in facility message\n");
return -1; return -1;
@ -2302,7 +2295,7 @@ int anfpr_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
return -1; return -1;
} }
res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, pos - buffer, NULL, NULL); res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, pos - buffer);
if (res) { if (res) {
pri_message(ctrl, "Could not queue ADPU in facility message\n"); pri_message(ctrl, "Could not queue ADPU in facility message\n");
return -1; return -1;
@ -2331,7 +2324,7 @@ int anfpr_initiate_transfer(struct pri *ctrl, q931_call *c1, q931_call *c2)
return -1; return -1;
} }
res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer, pos - buffer, NULL, NULL); res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer, pos - buffer);
if (res) { if (res) {
pri_message(ctrl, "Could not queue ADPU in facility message\n"); pri_message(ctrl, "Could not queue ADPU in facility message\n");
return -1; return -1;
@ -2416,7 +2409,7 @@ static int aoc_aoce_charging_unit_encode(struct pri *ctrl, q931_call *call,
/* Remember that if we queue a facility IE for a facility message we /* Remember that if we queue a facility IE for a facility message we
* have to explicitly send the facility message ourselves */ * have to explicitly send the facility message ourselves */
if (pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL, NULL) if (pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer)
|| q931_facility(call->pri, call)) { || q931_facility(call->pri, call)) {
pri_message(ctrl, "Could not schedule facility message for call %d\n", call->cr); pri_message(ctrl, "Could not schedule facility message for call %d\n", call->cr);
return -1; return -1;
@ -2562,7 +2555,7 @@ static int rose_call_transfer_complete_encode(struct pri *ctrl, q931_call *call,
return -1; return -1;
} }
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer);
} }
/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */ /* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
@ -2630,7 +2623,7 @@ int rose_called_name_encode(struct pri *ctrl, q931_call *call, int messagetype)
return -1; return -1;
} }
return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, messagetype, buffer, end - buffer);
} }
/*! /*!
@ -2696,7 +2689,7 @@ int rose_connected_name_encode(struct pri *ctrl, q931_call *call, int messagetyp
return -1; return -1;
} }
return pri_call_apdu_queue(call, messagetype, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, messagetype, buffer, end - buffer);
} }
/*! /*!
@ -2706,40 +2699,49 @@ int rose_connected_name_encode(struct pri *ctrl, q931_call *call, int messagetyp
* \param messagetype Q.931 message type. * \param messagetype Q.931 message type.
* \param apdu Facility ie contents buffer. * \param apdu Facility ie contents buffer.
* \param apdu_len Length of the contents buffer. * \param apdu_len Length of the contents buffer.
* \param function Callback function for when response is received. (Not implemented)
* \param data Parameter to callback function.
* *
* \retval 0 on success. * \retval 0 on success.
* \retval -1 on error. * \retval -1 on error.
*/ */
int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len)
void (*function)(void *data), void *data)
{ {
struct apdu_event *cur = NULL; struct apdu_event *cur = NULL;
struct apdu_event *new_event = NULL; struct apdu_event *new_event = NULL;
if (!call || !messagetype || !apdu || (apdu_len < 1) || (apdu_len > 255)) if (!call || !messagetype || !apdu
|| apdu_len < 1 || sizeof(new_event->apdu) < apdu_len) {
return -1; return -1;
}
switch (messagetype) {
case Q931_FACILITY:
break;
default:
if (q931_is_dummy_call(call)) {
pri_error(call->pri, "!! Cannot send %s message on dummy call reference.\n",
msg2str(messagetype));
return -1;
}
break;
}
if (!(new_event = calloc(1, sizeof(*new_event)))) { new_event = calloc(1, sizeof(*new_event));
if (!new_event) {
pri_error(call->pri, "!! Malloc failed!\n"); pri_error(call->pri, "!! Malloc failed!\n");
return -1; return -1;
} }
new_event->message = messagetype; new_event->message = messagetype;
new_event->callback = function;
new_event->data = data;
memcpy(new_event->apdu, apdu, apdu_len);
new_event->apdu_len = apdu_len; new_event->apdu_len = apdu_len;
memcpy(new_event->apdu, apdu, apdu_len);
/* Append APDU to the end of the list. */
if (call->apdus) { if (call->apdus) {
cur = call->apdus; for (cur = call->apdus; cur->next; cur = cur->next) {
while (cur->next) {
cur = cur->next;
} }
cur->next = new_event; cur->next = new_event;
} else } else {
call->apdus = new_event; call->apdus = new_event;
}
return 0; return 0;
} }
@ -2750,13 +2752,13 @@ int pri_call_apdu_queue_cleanup(q931_call *call)
if (call && call->apdus) { if (call && call->apdus) {
cur_event = call->apdus; cur_event = call->apdus;
call->apdus = NULL;
while (cur_event) { while (cur_event) {
/* TODO: callbacks, some way of giving return res on status of apdu */ /* TODO: callbacks, some way of giving return res on status of apdu */
free_event = cur_event; free_event = cur_event;
cur_event = cur_event->next; cur_event = cur_event->next;
free(free_event); free(free_event);
} }
call->apdus = NULL;
} }
return 0; return 0;
@ -2945,7 +2947,7 @@ static int rose_facility_error_encode(struct pri *ctrl, q931_call *call, int inv
return -1; return -1;
} }
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer);
} }
/*! /*!
@ -3077,7 +3079,7 @@ static int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype,
return -1; return -1;
} }
return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL, NULL); return pri_call_apdu_queue(call, msgtype, buffer, end - buffer);
} }
/*! /*!

View File

@ -87,10 +87,7 @@ int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int
int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype); int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype);
int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype); int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
/* Use this function to queue a facility-IE born APDU onto a call int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len);
* call is the call to use, messagetype is any one of the Q931 messages,
* apdu is the apdu data, apdu_len is the length of the apdu data */
int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data);
/* Used by q931.c to cleanup the apdu queue upon destruction of a call */ /* Used by q931.c to cleanup the apdu queue upon destruction of a call */
int pri_call_apdu_queue_cleanup(q931_call *call); int pri_call_apdu_queue_cleanup(q931_call *call);

View File

@ -308,13 +308,10 @@ struct pri_sr {
#define Q931_MAX_TEI 8 #define Q931_MAX_TEI 8
struct apdu_event { struct apdu_event {
int message; /* What message to send the ADPU in */
void (*callback)(void *data); /* Callback function for when response is received */
void *data; /* Data to callback */
unsigned char apdu[255]; /* ADPU to send */
int apdu_len; /* Length of ADPU */
int sent; /* Have we been sent already? */
struct apdu_event *next; /* Linked list pointer */ struct apdu_event *next; /* Linked list pointer */
int message; /* What message to send the ADPU in */
int apdu_len; /* Length of ADPU */
unsigned char apdu[255]; /* ADPU to send */
}; };
/*! \brief Incoming call transfer states. */ /*! \brief Incoming call transfer states. */
@ -568,6 +565,7 @@ void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id);
int q931_party_id_presentation(const struct q931_party_id *id); int q931_party_id_presentation(const struct q931_party_id *id);
const char *q931_call_state_str(enum Q931_CALL_STATE callstate); const char *q931_call_state_str(enum Q931_CALL_STATE callstate);
const char *msg2str(int msg);
int q931_is_ptmp(const struct pri *ctrl); int q931_is_ptmp(const struct pri *ctrl);
int q931_master_pass_event(struct pri *ctrl, struct q931_call *subcall, int msg_type); int q931_master_pass_event(struct pri *ctrl, struct q931_call *subcall, int msg_type);

54
q931.c
View File

@ -228,7 +228,6 @@ static struct msgtype facilities[] = {
#define LOC_NETWORK_BEYOND_INTERWORKING 0xa #define LOC_NETWORK_BEYOND_INTERWORKING 0xa
static char *ie2str(int ie); static char *ie2str(int ie);
static char *msg2str(int msg);
#define FUNC_DUMP(name) void (name)(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix) #define FUNC_DUMP(name) void (name)(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix)
@ -2269,32 +2268,41 @@ static int receive_progress_indicator(int full_ie, struct pri *ctrl, q931_call *
static int transmit_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order) static int transmit_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
{ {
struct apdu_event *tmp; struct apdu_event **prev;
int i = 0; struct apdu_event *cur;
int apdu_len;
for (tmp = call->apdus; tmp; tmp = tmp->next) { for (prev = &call->apdus, cur = call->apdus;
if ((tmp->message == msgtype) && !tmp->sent) cur;
prev = &cur->next, cur = cur->next) {
if (cur->message == msgtype) {
/* Remove APDU from list. */
*prev = cur->next;
break; break;
}
} }
if (!tmp) /* No APDU found */ if (!cur) {
/* No APDU found */
return 0; return 0;
}
if (ctrl->debug & PRI_DEBUG_APDU) { if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, "Adding facility ie contents to send in %s message:\n", pri_message(ctrl, "Adding facility ie contents to send in %s message:\n",
msg2str(msgtype)); msg2str(msgtype));
facility_decode_dump(ctrl, tmp->apdu, tmp->apdu_len); facility_decode_dump(ctrl, cur->apdu, cur->apdu_len);
} }
if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */ if (cur->apdu_len > 235) { /* TODO: find out how much space we can use */
pri_message(ctrl, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len); pri_message(ctrl, "Requested APDU (%d bytes) is too long\n", cur->apdu_len);
free(cur);
return 0; return 0;
} }
memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len); memcpy(ie->data, cur->apdu, cur->apdu_len);
i += tmp->apdu_len; apdu_len = cur->apdu_len;
tmp->sent = 1; free(cur);
return i + 2; return apdu_len + 2;
} }
static int receive_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len) static int receive_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
@ -3277,7 +3285,7 @@ static inline unsigned int ielen(q931_ie *ie)
return 2 + ie->len; return 2 + ie->len;
} }
static char *msg2str(int msg) const char *msg2str(int msg)
{ {
unsigned int x; unsigned int x;
for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++) for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++)
@ -6501,13 +6509,11 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
libpri_copy_string(ctrl->ev.ringing.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.ringing.useruserinfo)); libpri_copy_string(ctrl->ev.ringing.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.ringing.useruserinfo));
c->useruserinfo[0] = '\0'; c->useruserinfo[0] = '\0';
cur = c->apdus; for (cur = c->apdus; cur; cur = cur->next) {
while (cur) { if (cur->message == Q931_FACILITY) {
if (!cur->sent && cur->message == Q931_FACILITY) {
q931_facility(ctrl, c); q931_facility(ctrl, c);
break; break;
} }
cur = cur->next;
} }
return Q931_RES_HAVEEVENT; return Q931_RES_HAVEEVENT;
@ -6608,13 +6614,11 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
ctrl->ev.proceeding.cref = c->cr; ctrl->ev.proceeding.cref = c->cr;
ctrl->ev.proceeding.call = c->master_call; ctrl->ev.proceeding.call = c->master_call;
cur = c->apdus; for (cur = c->apdus; cur; cur = cur->next) {
while (cur) { if (cur->message == Q931_FACILITY) {
if (!cur->sent && cur->message == Q931_FACILITY) {
q931_facility(ctrl, c); q931_facility(ctrl, c);
break; break;
} }
cur = cur->next;
} }
return Q931_RES_HAVEEVENT; return Q931_RES_HAVEEVENT;
case Q931_CONNECT_ACKNOWLEDGE: case Q931_CONNECT_ACKNOWLEDGE:
@ -6887,13 +6891,11 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
ctrl->ev.setup_ack.channel = q931_encode_channel(c); ctrl->ev.setup_ack.channel = q931_encode_channel(c);
ctrl->ev.setup_ack.call = c->master_call; ctrl->ev.setup_ack.call = c->master_call;
cur = c->apdus; for (cur = c->apdus; cur; cur = cur->next) {
while (cur) { if (cur->message == Q931_FACILITY) {
if (!cur->sent && cur->message == Q931_FACILITY) {
q931_facility(ctrl, c); q931_facility(ctrl, c);
break; break;
} }
cur = cur->next;
} }
return Q931_RES_HAVEEVENT; return Q931_RES_HAVEEVENT;