[libpri-commits] rmudgett: branch 1.4 r982 - /branches/1.4/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Tue Aug 18 18:53:40 CDT 2009
Author: rmudgett
Date: Tue Aug 18 18:53:32 2009
New Revision: 982
URL: http://svn.asterisk.org/svn-view/libpri?view=rev&rev=982
Log:
Add COLP support to libpri for ETSI PTP, ETSI PTMP, and Q.SIG.
Add Connected Line Presentation (COLP) support to chan_dahdi/libpri as an
addition to issue 8824. This is the libpri portion. COLP support is now
available for ETSI PTP, ETSI PTMP, and Q.SIG with this patch.
(closes issue #14068)
Tested by: rmudgett
Review: https://reviewboard.asterisk.org/r/339/
Added:
branches/1.4/rose_etsi_diversion.c
- copied unchanged from r981, team/group/issue14068/rose_etsi_diversion.c
branches/1.4/rose_etsi_ect.c
- copied unchanged from r981, team/group/issue14068/rose_etsi_ect.c
Modified:
branches/1.4/Makefile
branches/1.4/libpri.h
branches/1.4/pri.c
branches/1.4/pri_facility.c
branches/1.4/pri_facility.h
branches/1.4/pri_internal.h
branches/1.4/q931.c
branches/1.4/rose.c
branches/1.4/rose.h
branches/1.4/rose_internal.h
branches/1.4/rosetest.c
Modified: branches/1.4/Makefile
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/Makefile?view=diff&rev=982&r1=981&r2=982
==============================================================================
--- branches/1.4/Makefile (original)
+++ branches/1.4/Makefile Tue Aug 18 18:53:32 2009
@@ -52,6 +52,8 @@
rose.o \
rose_address.o \
rose_etsi_aoc.o \
+ rose_etsi_diversion.o \
+ rose_etsi_ect.o \
rose_other.o \
rose_q931.o \
rose_qsig_aoc.o \
@@ -71,6 +73,8 @@
rose.lo \
rose_address.lo \
rose_etsi_aoc.lo \
+ rose_etsi_diversion.lo \
+ rose_etsi_ect.lo \
rose_other.lo \
rose_q931.lo \
rose_qsig_aoc.lo \
Modified: branches/1.4/libpri.h
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/libpri.h?view=diff&rev=982&r1=981&r2=982
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Tue Aug 18 18:53:32 2009
@@ -80,7 +80,8 @@
#define PRI_EVENT_ANSWER 8 /* Call has been answered (CONNECT) */
#define PRI_EVENT_HANGUP_ACK 9 /* Call hangup has been acknowledged */
#define PRI_EVENT_RESTART_ACK 10 /* Restart complete on a given channel (RESTART_ACKNOWLEDGE) */
-#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility */
+#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility (DEPRECATED) */
+#define PRI_EVENT_FACILITY 11 /* Facility received (FACILITY) */
#define PRI_EVENT_INFO_RECEIVED 12 /* Additional info (digits) received (INFORMATION) */
#define PRI_EVENT_PROCEEDING 13 /* When we get CALL_PROCEEDING */
#define PRI_EVENT_SETUP_ACK 14 /* When we get SETUP_ACKNOWLEDGE */
@@ -301,8 +302,8 @@
#define PRI_RATE_ADAPT_ASYNC 0x40
/* Notifications */
-#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended */
-#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed */
+#define PRI_NOTIFY_USER_SUSPENDED 0x00 /* User suspended (Q.931) (Call is placed on hold) */
+#define PRI_NOTIFY_USER_RESUMED 0x01 /* User resumed (Q.931) (Call is taken off hold) */
#define PRI_NOTIFY_BEARER_CHANGE 0x02 /* Bearer service change (DSS1) */
#define PRI_NOTIFY_ASN1_COMPONENT 0x03 /* ASN.1 encoded component (DSS1) */
#define PRI_NOTIFY_COMPLETION_DELAY 0x04 /* Call completion delay */
@@ -317,12 +318,12 @@
#define PRI_NOTIFY_CONF_OTHER_DISCONNECTED 0x4a /* Other party disconnected */
#define PRI_NOTIFY_CONF_FLOATING 0x4b /* Conference floating */
#define PRI_NOTIFY_WAITING_CALL 0x60 /* Call is waiting call */
-#define PRI_NOTIFY_DIVERSION_ACTIVATED 0x68 /* Diversion activated (DSS1) */
-#define PRI_NOTIFY_TRANSFER_ALERTING 0x69 /* Call transfer, alerting */
-#define PRI_NOTIFY_TRANSFER_ACTIVE 0x6a /* Call transfer, active */
+#define PRI_NOTIFY_DIVERSION_ACTIVATED 0x68 /* Diversion activated (DSS1) (cfu, cfb, cfnr) (EN 300 207-1 Section 7.2.1) */
+#define PRI_NOTIFY_TRANSFER_ALERTING 0x69 /* Call transfer, alerting (EN 300 369-1 Section 7.2) */
+#define PRI_NOTIFY_TRANSFER_ACTIVE 0x6a /* Call transfer, active(answered) (EN 300 369-1 Section 7.2) */
#define PRI_NOTIFY_REMOTE_HOLD 0x79 /* Remote hold */
#define PRI_NOTIFY_REMOTE_RETRIEVAL 0x7a /* Remote retrieval */
-#define PRI_NOTIFY_CALL_DIVERTING 0x7b /* Call is diverting */
+#define PRI_NOTIFY_CALL_DIVERTING 0x7b /* Call is diverting (EN 300 207-1 Section 7.2.1) */
#define PRI_COPY_DIGITS_CALLED_NUMBER
@@ -347,6 +348,151 @@
typedef struct q931_call q931_call;
+/* Name character set enumeration values */
+#define PRI_CHAR_SET_UNKNOWN 0
+#define PRI_CHAR_SET_ISO8859_1 1
+#define PRI_CHAR_SET_WITHDRAWN 2
+#define PRI_CHAR_SET_ISO8859_2 3
+#define PRI_CHAR_SET_ISO8859_3 4
+#define PRI_CHAR_SET_ISO8859_4 5
+#define PRI_CHAR_SET_ISO8859_5 6
+#define PRI_CHAR_SET_ISO8859_7 7
+#define PRI_CHAR_SET_ISO10646_BMPSTRING 8
+#define PRI_CHAR_SET_ISO10646_UTF_8STRING 9
+
+/*! \brief Q.SIG name information. */
+struct pri_party_name {
+ /*! \brief TRUE if the name information is valid/present */
+ int valid;
+ /*!
+ * \brief Q.931 presentation-indicator encoded field
+ * \note Must tollerate the Q.931 screening-indicator field values being present.
+ */
+ int presentation;
+ /*!
+ * \brief Character set the name is using.
+ * \details
+ * unknown(0),
+ * iso8859-1(1),
+ * enum-value-withdrawn-by-ITU-T(2)
+ * iso8859-2(3),
+ * iso8859-3(4),
+ * iso8859-4(5),
+ * iso8859-5(6),
+ * iso8859-7(7),
+ * iso10646-BmpString(8),
+ * iso10646-utf-8String(9)
+ * \details
+ * Set to iso8859-1(1) if unsure what to use.
+ */
+ int char_set;
+ /*! \brief Name data with null terminator. */
+ char str[64];
+};
+
+struct pri_party_number {
+ /*! \brief TRUE if the number information is valid/present */
+ int valid;
+ /*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
+ int presentation;
+ /*! \brief Q.931 Type-Of-Number and numbering-plan encoded fields */
+ int plan;
+ /*! \brief Number data with null terminator. */
+ char str[64];
+};
+
+/*!
+ * \note This structure is a place holder for possible future subaddress support
+ * to maintain ABI compatibility.
+ */
+struct pri_party_subaddress {
+ /*! \brief TRUE if the subaddress information is valid/present */
+ int valid;
+ /*!
+ * \brief Subaddress type.
+ * \details
+ * nsap(0),
+ * user_specified(2)
+ */
+ int type;
+ /*!
+ * \brief TRUE if odd number of address signals
+ * \note The odd/even indicator is used when the type of subaddress is
+ * user_specified and the coding is BCD.
+ */
+ int odd_even_indicator;
+ /*! \brief Length of the subaddress data */
+ int length;
+ /*!
+ * \brief Subaddress data with null terminator.
+ * \note The null terminator is a convenience only since the data could be
+ * BCD/binary and thus have a null byte as part of the contents.
+ */
+ char data[32];
+};
+
+/*! \brief Information needed to identify an endpoint in a call. */
+struct pri_party_id {
+ /*! \brief Subscriber name */
+ struct pri_party_name name;
+ /*! \brief Subscriber phone number */
+ struct pri_party_number number;
+ /*! \brief Subscriber subaddress */
+ struct pri_party_subaddress subaddress;
+};
+
+/*! \brief Connected Line/Party information */
+struct pri_party_connected_line {
+ /*! Connected party ID */
+ struct pri_party_id id;
+};
+
+/*!
+ * \brief Redirecting Line information.
+ * \details
+ * RDNIS (Redirecting Directory Number Information Service)
+ * Where a call diversion or transfer was invoked.
+ */
+struct pri_party_redirecting {
+ /*! Who is redirecting the call (Sent to the party the call is redirected toward) */
+ struct pri_party_id from;
+ /*! Call is redirecting to a new party (Sent to the caller) */
+ struct pri_party_id to;
+ /*! Originally called party (in cases of multiple redirects) */
+ struct pri_party_id orig_called;
+ /*! Number of times the call was redirected */
+ int count;
+ /*! Original reason for redirect (in cases of multiple redirects) */
+ int orig_reason;
+ /*! Redirection reason */
+ int reason;
+};
+
+/* Subcommands derived from supplementary services. */
+#define PRI_SUBCMD_REDIRECTING 1
+#define PRI_SUBCMD_CONNECTED_LINE 2
+
+
+struct pri_subcommand {
+ /*! PRI_SUBCMD_xxx defined values */
+ int cmd;
+ union {
+ /*! Reserve room for possible expansion to maintain ABI compatibility. */
+ char reserve_space[512];
+ struct pri_party_connected_line connected_line;
+ struct pri_party_redirecting redirecting;
+ } u;
+};
+
+/* Max number of subcommands per event message */
+#define PRI_MAX_SUBCOMMANDS 8
+
+struct pri_subcommands {
+ int counter_subcmd;
+ struct pri_subcommand subcmd[PRI_MAX_SUBCOMMANDS];
+};
+
+
typedef struct pri_event_generic {
/* Events with no additional information fall in this category */
int e;
@@ -370,6 +516,7 @@
int progressmask;
q931_call *call;
char useruserinfo[260]; /* User->User info */
+ struct pri_subcommands *subcmds;
} pri_event_ringing;
typedef struct pri_event_answer {
@@ -380,8 +527,10 @@
int progressmask;
q931_call *call;
char useruserinfo[260]; /* User->User info */
+ struct pri_subcommands *subcmds;
} pri_event_answer;
+/*! Deprecated replaced by struct pri_event_facility. */
typedef struct pri_event_facname {
int e;
char callingname[256];
@@ -392,6 +541,18 @@
int callingpres; /* Presentation of Calling CallerID */
int callingplan; /* Dialing plan of Calling entity */
} pri_event_facname;
+
+struct pri_event_facility {
+ int e;
+ char callingname[256]; /*!< Deprecated, preserved for struct pri_event_facname compatibility */
+ char callingnum[256]; /*!< Deprecated, preserved for struct pri_event_facname compatibility */
+ int channel;
+ int cref;
+ q931_call *call;
+ int callingpres; /*!< Presentation of Calling CallerID (Deprecated, preserved for struct pri_event_facname compatibility) */
+ int callingplan; /*!< Dialing plan of Calling entity (Deprecated, preserved for struct pri_event_facname compatibility) */
+ struct pri_subcommands *subcmds;
+};
#define PRI_CALLINGPLANANI
#define PRI_CALLINGPLANRDNIS
@@ -426,6 +587,7 @@
int callingplanorigcalled; /* Dialing plan of Originally Called Number */
int origredirectingreason;
int reversecharge;
+ struct pri_subcommands *subcmds;
} pri_event_ring;
typedef struct pri_event_hangup {
@@ -436,6 +598,7 @@
q931_call *call; /* Opaque call pointer */
long aoc_units; /* Advise of Charge number of charged units */
char useruserinfo[260]; /* User->User info */
+ struct pri_subcommands *subcmds;
} pri_event_hangup;
typedef struct pri_event_restart_ack {
@@ -452,18 +615,21 @@
int progressmask;
int cause;
q931_call *call;
+ struct pri_subcommands *subcmds;
} pri_event_proceeding;
typedef struct pri_event_setup_ack {
int e;
int channel;
q931_call *call;
+ struct pri_subcommands *subcmds;
} pri_event_setup_ack;
typedef struct pri_event_notify {
int e;
int channel;
int info;
+ struct pri_subcommands *subcmds;
} pri_event_notify;
typedef struct pri_event_keypad_digit {
@@ -471,6 +637,7 @@
int channel;
q931_call *call;
char digits[64];
+ struct pri_subcommands *subcmds;
} pri_event_keypad_digit;
typedef struct pri_event_service {
@@ -490,7 +657,7 @@
pri_event_generic gen; /* Generic view */
pri_event_restart restart; /* Restart view */
pri_event_error err; /* Error view */
- pri_event_facname facname; /* Caller*ID Name on Facility */
+ pri_event_facname facname; /* Caller*ID Name on Facility (Deprecated, use pri_event.facility) */
pri_event_ring ring; /* Ring */
pri_event_hangup hangup; /* Hang up */
pri_event_ringing ringing; /* Ringing */
@@ -502,6 +669,7 @@
pri_event_keypad_digit digit; /* Digits that come during a call */
pri_event_service service; /* service message */
pri_event_service_ack service_ack; /* service acknowledgement message */
+ struct pri_event_facility facility;
} pri_event;
struct pri;
@@ -588,6 +756,18 @@
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
+/*!
+ * \brief Give connected line information to a call
+ * \note Could be used instead of pri_sr_set_caller_party() before calling pri_setup().
+ */
+int pri_connected_line_update(struct pri *pri, q931_call *call, const struct pri_party_connected_line *connected);
+
+/*!
+ * \brief Give redirection information to a call
+ * \note Could be used instead of pri_sr_set_redirecting_parties() before calling pri_setup().
+ */
+int pri_redirecting_update(struct pri *pri, q931_call *call, const struct pri_party_redirecting *redirecting);
+
/* Set CRV reference for GR-303 calls */
@@ -642,8 +822,31 @@
int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
+
+/*!
+ * \brief Set the caller party ID information in the call SETUP record.
+ *
+ * \param sr New call SETUP record.
+ * \param caller Caller party ID information to set.
+ *
+ * \return Nothing
+ */
+void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller);
+/*! \note Use pri_sr_set_caller_party() instead to pass more precise caller information. */
int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
+
+/*!
+ * \brief Set the redirecting information in the call SETUP record.
+ *
+ * \param sr New call SETUP record.
+ * \param caller Redirecting information to set.
+ *
+ * \return Nothing
+ */
+void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting);
+/*! \note Use pri_sr_set_redirecting_parties() instead to pass more precise redirecting information. */
int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
+
#define PRI_USER_USER_TX
/* Set the user user field. Warning! don't send binary data accross this field */
void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
Modified: branches/1.4/pri.c
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/pri.c?view=diff&rev=982&r1=981&r2=982
==============================================================================
--- branches/1.4/pri.c (original)
+++ branches/1.4/pri.c Tue Aug 18 18:53:32 2009
@@ -374,8 +374,8 @@
return "Hangup ACK";
case PRI_EVENT_RESTART_ACK:
return "Restart ACK";
- case PRI_EVENT_FACNAME:
- return "FacName";
+ case PRI_EVENT_FACILITY:
+ return "Facility";
case PRI_EVENT_INFO_RECEIVED:
return "Info Received";
case PRI_EVENT_PROCEEDING:
@@ -577,6 +577,203 @@
if (!pri || !call)
return -1;
return q931_connect(pri, call, channel, nonisdn);
+}
+
+/*!
+ * \internal
+ * \brief Copy the PRI party name to the Q.931 party name structure.
+ *
+ * \param q931_name Q.931 party name structure
+ * \param pri_name PRI party name structure
+ *
+ * \return Nothing
+ */
+static void pri_copy_party_name_to_q931(struct q931_party_name *q931_name, const struct pri_party_name *pri_name)
+{
+ q931_party_name_init(q931_name);
+ if (pri_name->valid) {
+ q931_name->valid = 1;
+ q931_name->presentation = pri_name->presentation;
+ q931_name->char_set = pri_name->char_set;
+ libpri_copy_string(q931_name->str, pri_name->str, sizeof(q931_name->str));
+ }
+}
+
+/*!
+ * \internal
+ * \brief Copy the PRI party number to the Q.931 party number structure.
+ *
+ * \param q931_number Q.931 party number structure
+ * \param pri_number PRI party number structure
+ *
+ * \return Nothing
+ */
+static void pri_copy_party_number_to_q931(struct q931_party_number *q931_number, const struct pri_party_number *pri_number)
+{
+ q931_party_number_init(q931_number);
+ if (pri_number->valid) {
+ q931_number->valid = 1;
+ q931_number->presentation = pri_number->presentation;
+ q931_number->plan = pri_number->plan;
+ libpri_copy_string(q931_number->str, pri_number->str, sizeof(q931_number->str));
+ }
+}
+
+/*!
+ * \internal
+ * \brief Copy the PRI party id to the Q.931 party id structure.
+ *
+ * \param q931_id Q.931 party id structure
+ * \param pri_id PRI party id structure
+ *
+ * \return Nothing
+ */
+static void pri_copy_party_id_to_q931(struct q931_party_id *q931_id, const struct pri_party_id *pri_id)
+{
+ pri_copy_party_name_to_q931(&q931_id->name, &pri_id->name);
+ pri_copy_party_number_to_q931(&q931_id->number, &pri_id->number);
+}
+
+int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pri_party_connected_line *connected)
+{
+ struct q931_party_id party_id;
+
+ if (!ctrl || !call) {
+ return -1;
+ }
+
+ pri_copy_party_id_to_q931(&party_id, &connected->id);
+ q931_party_id_fixup(ctrl, &party_id);
+ if (!q931_party_id_cmp(&party_id, &call->local_id)) {
+ /* The local party information did not change so do nothing. */
+ return 0;
+ }
+ call->local_id = party_id;
+
+ switch (call->ourcallstate) {
+ case Q931_CALL_STATE_CALL_INITIATED:
+ case Q931_CALL_STATE_OVERLAP_SENDING:
+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
+ case Q931_CALL_STATE_CALL_DELIVERED:
+ /*
+ * The local party transferred to someone else before
+ * the remote end answered.
+ */
+ case Q931_CALL_STATE_ACTIVE:
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ /* PTMP mode */
+ q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
+ &call->local_id.number);
+ } else {
+ /* PTP mode */
+ /* Immediately send EctInform APDU, callStatus=answered(0) */
+ send_call_transfer_complete(ctrl, call, 0);
+ }
+ break;
+ case PRI_SWITCH_QSIG:
+ /* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
+ send_call_transfer_complete(ctrl, call, 0);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ /* Just save the data for further developments. */
+ break;
+ }
+
+ return 0;
+}
+
+int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_party_redirecting *redirecting)
+{
+ if (!ctrl || !call) {
+ return -1;
+ }
+
+ /* Save redirecting.to information and reason. */
+ pri_copy_party_id_to_q931(&call->redirecting.to, &redirecting->to);
+ q931_party_id_fixup(ctrl, &call->redirecting.to);
+ call->redirecting.reason = redirecting->reason;
+
+ switch (call->ourcallstate) {
+ case Q931_CALL_STATE_NULL:
+ /* Save the remaining redirecting information before we place a call. */
+ pri_copy_party_id_to_q931(&call->redirecting.from, &redirecting->from);
+ q931_party_id_fixup(ctrl, &call->redirecting.from);
+ pri_copy_party_id_to_q931(&call->redirecting.orig_called, &redirecting->orig_called);
+ q931_party_id_fixup(ctrl, &call->redirecting.orig_called);
+ call->redirecting.orig_reason = redirecting->orig_reason;
+ if (redirecting->count <= 0) {
+ if (call->redirecting.from.number.valid) {
+ /*
+ * We are redirecting with an unknown count
+ * so assume the count is one.
+ */
+ call->redirecting.count = 1;
+ } else {
+ call->redirecting.count = 0;
+ }
+ } else if (redirecting->count < PRI_MAX_REDIRECTS) {
+ call->redirecting.count = redirecting->count;
+ } else {
+ call->redirecting.count = PRI_MAX_REDIRECTS;
+ }
+ break;
+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
+ case Q931_CALL_STATE_CALL_RECEIVED:
+ /* This is an incoming call that has not connected yet. */
+ if (!call->redirecting.to.number.valid) {
+ /* Not being redirected toward valid number data. Ignore. */
+ break;
+ }
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ /* PTMP mode */
+ q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING,
+ &call->redirecting.to.number);
+ break;
+ }
+ /* PTP mode - same behaviour as Q.SIG */
+ /* fall through */
+ case PRI_SWITCH_QSIG:
+ if (call->redirecting.state != Q931_REDIRECTING_STATE_PENDING_TX_DIV_LEG_3
+ || strcmp(call->redirecting.to.number.str, call->called.number.str) != 0) {
+ /* immediately send divertingLegInformation1 APDU */
+ if (rose_diverting_leg_information1_encode(ctrl, call)
+ || q931_facility(ctrl, call)) {
+ pri_message(ctrl,
+ "Could not schedule facility message for divertingLegInfo1\n");
+ }
+ }
+ call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
+
+ /* immediately send divertingLegInformation3 APDU */
+ if (rose_diverting_leg_information3_encode(ctrl, call, Q931_FACILITY)
+ || q931_facility(ctrl, call)) {
+ pri_message(ctrl,
+ "Could not schedule facility message for divertingLegInfo3\n");
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ pri_message(ctrl, "Ignored redirecting update because call in state %s(%d).\n",
+ q931_call_state_str(call->ourcallstate), call->ourcallstate);
+ break;
+ }
+
+ return 0;
}
#if 0
@@ -703,6 +900,9 @@
static void pri_sr_init(struct pri_sr *req)
{
memset(req, 0, sizeof(struct pri_sr));
+ q931_party_redirecting_init(&req->redirecting);
+ q931_party_id_init(&req->caller);
+ q931_party_address_init(&req->called);
req->reversecharge = PRI_REVERSECHARGE_NONE;
}
@@ -725,13 +925,8 @@
pri_sr_init(&req);
pri_sr_set_connection_call_independent(&req);
-
- req.caller = caller;
- req.callerplan = callerplan;
- req.callername = callername;
- req.callerpres = callerpres;
- req.called = called;
- req.calledplan = calledplan;
+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
+ pri_sr_set_called(&req, called, calledplan, 0);
if (mwi_message_send(pri, c, &req, 1) < 0) {
pri_message(pri, "Unable to send MWI activate message\n");
@@ -750,13 +945,8 @@
pri_sr_init(&req);
pri_sr_set_connection_call_independent(&req);
-
- req.caller = caller;
- req.callerplan = callerplan;
- req.callername = callername;
- req.callerpres = callerpres;
- req.called = called;
- req.calledplan = calledplan;
+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
+ pri_sr_set_called(&req, called, calledplan, 0);
if(mwi_message_send(pri, c, &req, 0) < 0) {
pri_message(pri, "Unable to send MWI deactivate message\n");
@@ -782,16 +972,12 @@
if (!pri || !c)
return -1;
pri_sr_init(&req);
+ pri_sr_set_caller(&req, caller, callername, callerplan, callerpres);
+ pri_sr_set_called(&req, called, calledplan, 0);
req.transmode = transmode;
req.channel = channel;
req.exclusive = exclusive;
req.nonisdn = nonisdn;
- req.caller = caller;
- req.callerplan = callerplan;
- req.callername = callername;
- req.callerpres = callerpres;
- req.called = called;
- req.calledplan = calledplan;
req.userl1 = ulayer1;
return q931_setup(pri, c, &req);
}
@@ -1002,30 +1188,81 @@
int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int numcomplete)
{
- sr->called = called;
- sr->calledplan = calledplan;
+ q931_party_address_init(&sr->called);
+ if (called) {
+ sr->called.number.valid = 1;
+ sr->called.number.plan = calledplan;
+ libpri_copy_string(sr->called.number.str, called, sizeof(sr->called.number.str));
+ }
sr->numcomplete = numcomplete;
return 0;
}
int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres)
{
- sr->caller = caller;
- sr->callername = callername;
- sr->callerplan = callerplan;
- sr->callerpres = callerpres;
+ q931_party_id_init(&sr->caller);
+ if (caller) {
+ sr->caller.number.valid = 1;
+ sr->caller.number.presentation = callerpres;
+ sr->caller.number.plan = callerplan;
+ libpri_copy_string(sr->caller.number.str, caller, sizeof(sr->caller.number.str));
+
+ if (callername) {
+ sr->caller.name.valid = 1;
+ sr->caller.name.presentation = callerpres;
+ sr->caller.name.char_set = PRI_CHAR_SET_ISO8859_1;
+ libpri_copy_string(sr->caller.name.str, callername,
+ sizeof(sr->caller.name.str));
+ }
+ }
return 0;
}
+void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller)
+{
+ pri_copy_party_id_to_q931(&sr->caller, caller);
+}
+
int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason)
{
- sr->redirectingnum = num;
- sr->redirectingplan = plan;
- sr->redirectingpres = pres;
- sr->redirectingreason = reason;
+ q931_party_redirecting_init(&sr->redirecting);
+ if (num && num[0]) {
+ sr->redirecting.from.number.valid = 1;
+ sr->redirecting.from.number.presentation = pres;
+ sr->redirecting.from.number.plan = plan;
+ libpri_copy_string(sr->redirecting.from.number.str, num,
+ sizeof(sr->redirecting.from.number.str));
+
+ sr->redirecting.count = 1;
+ sr->redirecting.reason = reason;
+ }
return 0;
}
+void pri_sr_set_redirecting_parties(struct pri_sr *sr, const struct pri_party_redirecting *redirecting)
+{
+ pri_copy_party_id_to_q931(&sr->redirecting.from, &redirecting->from);
+ pri_copy_party_id_to_q931(&sr->redirecting.to, &redirecting->to);
+ pri_copy_party_id_to_q931(&sr->redirecting.orig_called, &redirecting->orig_called);
+ sr->redirecting.orig_reason = redirecting->orig_reason;
+ sr->redirecting.reason = redirecting->reason;
+ if (redirecting->count <= 0) {
+ if (sr->redirecting.from.number.valid) {
+ /*
+ * We are redirecting with an unknown count
+ * so assume the count is one.
+ */
+ sr->redirecting.count = 1;
+ } else {
+ sr->redirecting.count = 0;
+ }
+ } else if (redirecting->count < PRI_MAX_REDIRECTS) {
+ sr->redirecting.count = redirecting->count;
+ } else {
+ sr->redirecting.count = PRI_MAX_REDIRECTS;
+ }
+}
+
void pri_sr_set_reversecharge(struct pri_sr *sr, int requested)
{
sr->reversecharge = requested;
Modified: branches/1.4/pri_facility.c
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/pri_facility.c?view=diff&rev=982&r1=981&r2=982
==============================================================================
--- branches/1.4/pri_facility.c (original)
+++ branches/1.4/pri_facility.c Tue Aug 18 18:53:32 2009
@@ -394,17 +394,374 @@
/*!
* \internal
- * \brief Encode the Q.SIG DivertingLegInformation2 invoke message.
+ * \brief Convert the Q.931 number presentation field to Q.SIG name presentation.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param presentation Q.931 presentation/screening octet.
+ * \param name_present Non-zero if the name is available.
+ *
+ * \return Name presentation enumeration value.
+ */
+static int qsig_name_presentation_from_q931(struct pri *ctrl, int presentation, int name_present)
+{
+ int value;
+
+ switch (presentation & PRI_PRES_RESTRICTION) {
+ case PRI_PRES_ALLOWED:
+ if (name_present) {
+ value = 1; /* presentation_allowed */
+ } else {
+ value = 4; /* name_not_available */
+ }
+ break;
+ default:
+ pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
+ presentation);
+ /* fall through */
+ case PRI_PRES_RESTRICTED:
+ if (name_present) {
+ value = 2; /* presentation_restricted */
+ } else {
+ value = 3; /* presentation_restricted_null */
+ }
+ break;
+ case PRI_PRES_UNAVAILABLE:
+ value = 4; /* name_not_available */
+ break;
+ }
+
+ return value;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Q.SIG name presentation to Q.931 presentation field value.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param presentation Q.SIG name presentation value.
+ *
+ * \return Q.931 presentation field value.
+ */
+static int qsig_name_presentation_for_q931(struct pri *ctrl, int presentation)
+{
+ int value;
+
+ switch (presentation) {
+ case 1: /* presentation_allowed */
+ value = PRI_PRES_ALLOWED;
+ break;
+ default:
+ pri_message(ctrl,
+ "!! Unsupported Q.SIG name presentation to Q.931 value (%d)\n",
+ presentation);
+ /* fall through */
+ case 2: /* presentation_restricted */
+ case 3: /* presentation_restricted_null */
+ value = PRI_PRES_RESTRICTED;
+ break;
+ case 0: /* optional_name_not_present */
+ case 4: /* name_not_available */
+ value = PRI_PRES_UNAVAILABLE;
+ break;
+ }
+
+ return value;
+}
+
+/*!
+ * \internal
+ * \brief Convert number presentation to Q.SIG diversion subscription notification.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param presentation Number presentation value.
+ *
+ * \return Q.SIG diversion subscription notification value.
+ */
+static int presentation_to_subscription(struct pri *ctrl, int presentation)
+{
+ /* derive subscription value from presentation value */
+
+ switch (presentation & PRI_PRES_RESTRICTION) {
+ case PRI_PRES_ALLOWED:
+ return QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR;
+ case PRI_PRES_RESTRICTED:
+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
+ case PRI_PRES_UNAVAILABLE: /* Number not available due to interworking */
+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR; /* ?? QSIG_NO_NOTIFICATION */
+ default:
+ pri_message(ctrl, "!! Unknown Q.SIG presentationIndicator 0x%02x\n",
+ presentation);
+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose party number to the q931_party_number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_number Q.931 party number structure
+ * \param rose_number ROSE party number structure
+ *
+ * \note It is assumed that the q931_number has been initialized before calling.
+ *
+ * \return Nothing
+ */
+static void rose_copy_number_to_q931(struct pri *ctrl,
+ struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number)
+{
+ libpri_copy_string(q931_number->str, (char *) rose_number->str,
+ sizeof(q931_number->str));
+ q931_number->plan = numbering_plan_for_q931(ctrl, rose_number->plan)
+ | typeofnumber_for_q931(ctrl, rose_number->ton);
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose presented screened party number to the q931_party_number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_number Q.931 party number structure
+ * \param rose_presented ROSE presented screened party number structure
+ *
+ * \return Nothing
+ */
+static void rose_copy_presented_number_screened_to_q931(struct pri *ctrl,
+ struct q931_party_number *q931_number,
+ const struct rosePresentedNumberScreened *rose_presented)
+{
+ q931_party_number_init(q931_number);
+ q931_number->valid = 1;
+ q931_number->presentation = presentation_for_q931(ctrl, rose_presented->presentation);
+ switch (rose_presented->presentation) {
+ case 0: /* presentationAllowedNumber */
+ case 3: /* presentationRestrictedNumber */
+ q931_number->presentation |=
+ (rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
+ rose_copy_number_to_q931(ctrl, q931_number,
+ &rose_presented->screened.number);
+ break;
+ default:
+ q931_number->presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose presented unscreened party number to the q931_party_number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_number Q.931 party number structure
+ * \param rose_presented ROSE presented unscreened party number structure
+ *
+ * \return Nothing
+ */
+static void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl,
+ struct q931_party_number *q931_number,
+ const struct rosePresentedNumberUnscreened *rose_presented)
+{
+ q931_party_number_init(q931_number);
+ q931_number->valid = 1;
+ q931_number->presentation = presentation_for_q931(ctrl,
+ rose_presented->presentation) | PRI_PRES_USER_NUMBER_UNSCREENED;
+ switch (rose_presented->presentation) {
+ case 0: /* presentationAllowedNumber */
+ case 3: /* presentationRestrictedNumber */
+ rose_copy_number_to_q931(ctrl, q931_number, &rose_presented->number);
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose presented screened party address to the q931_party_number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param q931_number Q.931 party number structure
+ * \param rose_presented ROSE presented screened party address structure
+ *
+ * \return Nothing
+ */
+static void rose_copy_presented_address_screened_to_q931(struct pri *ctrl,
+ struct q931_party_number *q931_number,
+ const struct rosePresentedAddressScreened *rose_presented)
+{
+ q931_party_number_init(q931_number);
+ q931_number->valid = 1;
+ q931_number->presentation = presentation_for_q931(ctrl, rose_presented->presentation);
+ switch (rose_presented->presentation) {
+ case 0: /* presentationAllowedAddress */
+ case 3: /* presentationRestrictedAddress */
+ q931_number->presentation |=
+ (rose_presented->screened.screening_indicator & PRI_PRES_NUMBER_TYPE);
+ rose_copy_number_to_q931(ctrl, q931_number,
+ &rose_presented->screened.number);
+ break;
+ default:
+ q931_number->presentation |= PRI_PRES_USER_NUMBER_UNSCREENED;
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief Copy the given rose party name to the q931_party_name
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param qsig_name Q.SIG party name structure
+ * \param rose_name Q.SIG ROSE party name structure
+ *
+ * \return Nothing
+ */
+static void rose_copy_name_to_q931(struct pri *ctrl,
+ struct q931_party_name *qsig_name, const struct roseQsigName *rose_name)
+{
+ //q931_party_name_init(qsig_name);
+ qsig_name->valid = 1;
+ qsig_name->presentation = qsig_name_presentation_for_q931(ctrl,
+ rose_name->presentation);
+ qsig_name->char_set = rose_name->char_set;
+ libpri_copy_string(qsig_name->str, (char *) rose_name->data, sizeof(qsig_name->str));
+}
+
+/*!
+ * \internal
+ * \brief Copy the given q931_party_number to the rose party number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_number ROSE party number structure
+ * \param q931_number Q.931 party number structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_number_to_rose(struct pri *ctrl,
+ struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number)
+{
+ rose_number->plan = numbering_plan_from_q931(ctrl, q931_number->plan);
+ rose_number->ton = typeofnumber_from_q931(ctrl, q931_number->plan);
+ /* Truncate the q931_number->str if necessary. */
+ libpri_copy_string((char *) rose_number->str, q931_number->str,
+ sizeof(rose_number->str));
+ rose_number->length = strlen((char *) rose_number->str);
+}
+
+/*!
+ * \internal
+ * \brief Copy the given q931_party_number to the rose presented screened party number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_presented ROSE presented screened party number structure
+ * \param q931_number Q.931 party number structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_presented_number_screened_to_rose(struct pri *ctrl,
+ struct rosePresentedNumberScreened *rose_presented,
+ const struct q931_party_number *q931_number)
+{
+ if (q931_number->valid) {
+ rose_presented->presentation =
+ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
+ rose_presented->screened.screening_indicator =
+ q931_number->presentation & PRI_PRES_NUMBER_TYPE;
+ q931_copy_number_to_rose(ctrl, &rose_presented->screened.number, q931_number);
+ } else {
+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
+ }
+}
+
+/*!
+ * \internal
+ * \brief Copy the given q931_party_number to the rose presented unscreened party number
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_presented ROSE presented unscreened party number structure
+ * \param q931_number Q.931 party number structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl,
+ struct rosePresentedNumberUnscreened *rose_presented,
+ const struct q931_party_number *q931_number)
+{
+ if (q931_number->valid) {
+ rose_presented->presentation =
+ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
+ q931_copy_number_to_rose(ctrl, &rose_presented->number, q931_number);
+ } else {
+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
+ }
+}
+
+#if 0 /* In case it is needed in the future */
+/*!
+ * \internal
+ * \brief Copy the given q931_party_number to the rose presented screened party address
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_presented ROSE presented screened party address structure
+ * \param q931_number Q.931 party number structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_presented_address_screened_to_rose(struct pri *ctrl,
+ struct rosePresentedAddressScreened *rose_presented,
+ const struct q931_party_number *q931_number)
+{
+ if (q931_number->valid) {
+ rose_presented->presentation =
+ presentation_from_q931(ctrl, q931_number->presentation, q931_number->str[0]);
+ rose_presented->screened.screening_indicator =
+ q931_number->presentation & PRI_PRES_NUMBER_TYPE;
+ q931_copy_number_to_rose(ctrl, &rose_presented->screened.number, q931_number);
+ rose_presented->screened.subaddress.length = 0;
+ } else {
+ rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
+ }
+}
+#endif /* In case it is needed in the future */
+
+/*!
+ * \internal
+ * \brief Copy the given q931_party_name to the rose party name
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param rose_name Q.SIG ROSE party name structure
+ * \param qsig_name Q.SIG party name structure
+ *
+ * \return Nothing
+ */
+static void q931_copy_name_to_rose(struct pri *ctrl,
+ struct roseQsigName *rose_name, const struct q931_party_name *qsig_name)
+{
+ if (qsig_name->valid) {
+ rose_name->presentation = qsig_name_presentation_from_q931(ctrl,
+ qsig_name->presentation, qsig_name->str[0]);
+ rose_name->char_set = qsig_name->char_set;
+ /* Truncate the qsig_name->str if necessary. */
+ libpri_copy_string((char *) rose_name->data, qsig_name->str, sizeof(rose_name->data));
+ rose_name->length = strlen((char *) rose_name->data);
+ } else {
+ rose_name->presentation = 4;/* name_not_available */
+ }
+}
+
+/*!
+ * \internal
+ * \brief Encode the Q.SIG DivertingLegInformation1 invoke message.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode the facility ie contents.
* \param end End of facility ie contents encoding data buffer.
- * \param call Call leg from which to encode diversion leg 2.
+ * \param call Call leg from which to encode diversion leg 1.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
-static unsigned char *enc_qsig_diverting_leg_information2(struct pri *ctrl,
+static unsigned char *enc_qsig_diverting_leg_information1(struct pri *ctrl,
unsigned char *pos, unsigned char *end, q931_call *call)
{
struct fac_extension_header header;
@@ -422,42 +779,19 @@
}
memset(&msg, 0, sizeof(msg));
- msg.operation = ROSE_QSIG_DivertingLegInformation2;
+ msg.operation = ROSE_QSIG_DivertingLegInformation1;
msg.invoke_id = get_invokeid(ctrl);
-
- /* diversionCounter always is 1 because other isn't available in the current design */
- msg.args.qsig.DivertingLegInformation2.diversion_counter = 1;
-
- msg.args.qsig.DivertingLegInformation2.diversion_reason =
- redirectingreason_from_q931(ctrl, call->redirectingreason);
-
- /* divertingNr */
- msg.args.qsig.DivertingLegInformation2.diverting_present = 1;
- msg.args.qsig.DivertingLegInformation2.diverting.presentation =
- presentation_from_q931(ctrl, call->redirectingpres, call->redirectingnum[0]);
- msg.args.qsig.DivertingLegInformation2.diverting.number.plan =
[... 5455 lines stripped ...]
More information about the libpri-commits
mailing list