[libpri-commits] rmudgett: branch group/issue14068 r670 - /team/group/issue14068/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Mon Jan 19 11:28:53 CST 2009
Author: rmudgett
Date: Mon Jan 19 11:28:53 2009
New Revision: 670
URL: http://svn.digium.com/svn-view/libpri?view=rev&rev=670
Log:
Applied the libpri-1.4-2008-12-12-colpconp-0.1.0.patch
from issue 14068 to new team/group/issue14068 branch from
branches/1.4 branch.
Modified:
team/group/issue14068/libpri.h
team/group/issue14068/pri.c
team/group/issue14068/pri_facility.c
team/group/issue14068/pri_facility.h
team/group/issue14068/pri_internal.h
team/group/issue14068/q931.c
Modified: team/group/issue14068/libpri.h
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14068/libpri.h?view=diff&rev=670&r1=669&r2=670
==============================================================================
--- team/group/issue14068/libpri.h (original)
+++ team/group/issue14068/libpri.h Mon Jan 19 11:28:53 2009
@@ -81,6 +81,7 @@
#define PRI_EVENT_NOTIFY 16 /* Notification received */
#define PRI_EVENT_PROGRESS 17 /* When we get CALL_PROCEEDING or PROGRESS */
#define PRI_EVENT_KEYPAD_DIGIT 18 /* When we receive during ACTIVE state */
+#define PRI_EVENT_FACILITY 19 /* Facility received */
/* Simple states */
#define PRI_STATE_DOWN 0
@@ -135,15 +136,44 @@
#define PRI_UNKNOWN 0x0
/* Presentation */
-#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
-#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
-#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
-#define PRES_ALLOWED_NETWORK_NUMBER 0x03
-#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
-#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
-#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
-#define PRES_PROHIB_NETWORK_NUMBER 0x23
-#define PRES_NUMBER_NOT_AVAILABLE 0x43
+#define PRES_NUMBER_TYPE 0x03
+#define PRES_USER_NUMBER_UNSCREENED 0x00
+#define PRES_USER_NUMBER_PASSED_SCREEN 0x01
+#define PRES_USER_NUMBER_FAILED_SCREEN 0x02
+#define PRES_NETWORK_NUMBER 0x03
+
+#define PRES_RESTRICTION 0x60
+#define PRES_ALLOWED 0x00
+#define PRES_RESTRICTED 0x20
+#define PRES_UNAVAILABLE 0x40
+#define PRES_RESERVED 0x60
+
+#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED \
+ (PRES_ALLOWED | PRES_USER_NUMBER_UNSCREENED)
+
+#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN \
+ (PRES_ALLOWED | PRES_USER_NUMBER_PASSED_SCREEN)
+
+#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN \
+ (PRES_ALLOWED | PRES_USER_NUMBER_FAILED_SCREEN)
+
+#define PRES_ALLOWED_NETWORK_NUMBER \
+ (PRES_ALLOWED | PRES_NETWORK_NUMBER)
+
+#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED \
+ (PRES_RESTRICTED | PRES_USER_NUMBER_UNSCREENED)
+
+#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN \
+ (PRES_RESTRICTED | PRES_USER_NUMBER_PASSED_SCREEN)
+
+#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN \
+ (PRES_RESTRICTED | PRES_USER_NUMBER_FAILED_SCREEN)
+
+#define PRES_PROHIB_NETWORK_NUMBER \
+ (PRES_RESTRICTED | PRES_NETWORK_NUMBER)
+
+#define PRES_NUMBER_NOT_AVAILABLE \
+ (PRES_UNAVAILABLE | PRES_NETWORK_NUMBER)
/* Causes for disconnection */
#define PRI_CAUSE_UNALLOCATED 1
@@ -305,6 +335,76 @@
typedef struct q931_call q931_call;
+/* Connected line update source code */
+enum PRI_CONNECTED_LINE_UPDATE_SOURCE {
+ PRI_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN, /* Update for unknown reason (May be interpreted to mean from answer) */
+ PRI_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, /* Update from normal call answering */
+ PRI_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION, /* Update from call diversion */
+ PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER /* Update from call transfer */
+};
+
+/* Information needed to identify an endpoint in a call. */
+struct pri_party_id {
+ char number[256]; /* Subscriber phone number */
+ char name[256]; /* Subscriber name */
+ int number_type; /* Q.931 encoded "type of number" and "numbering plan identification" */
+ int number_presentation; /* Q.931 encoded "presentation indicator" and "screening indicator" */
+};
+
+/* Connected Line/Party information */
+struct pri_party_connected_line {
+ struct pri_party_id id; /* Connected party ID */
+ int source; /* Information about the source of an update .
+ * enum PRI_CONNECTED_LINE_UPDATE_SOURCE values
+ * for Normal-Answer, Call-transfer, Call-diversion */
+};
+
+/* Redirecting Line information.
+ * RDNIS (Redirecting Directory Number Information Service)
+ * Where a call diversion or transfer was invoked. */
+struct pri_party_redirecting {
+ struct pri_party_id from; /* Who is redirecting the call (Sent to the party the call is redirected toward) */
+ struct pri_party_id to; /* Call is redirecting to a new party (Sent to the caller) */
+ int count; /* Number of times the call was redirected */
+ int reason; /* Redirection reasons */
+};
+
+/* Command derived from Facility */
+#define CMD_REDIRECTING 1
+#define CMD_CONNECTEDLINE 2
+
+
+typedef struct cmd_connectedline {
+ int e;
+ int channel;
+ q931_call *call;
+ struct pri_party_connected_line connected;
+} cmd_connectedline;
+
+typedef struct cmd_redirecting {
+ int e;
+ int channel;
+ q931_call *call;
+ struct pri_party_redirecting redirecting;
+} cmd_redirecting;
+
+typedef struct subcommand {
+ int cmd;
+ union {
+ cmd_connectedline connectedline;
+ cmd_redirecting redirecting;
+ };
+} subcommand;
+
+/* Max number of subcommands per event message */
+#define MAX_SUBCOMMANDS 4
+
+typedef struct subcommands {
+ int counter_subcmd;
+ subcommand subcmd[MAX_SUBCOMMANDS];
+} subcommands;
+
+
typedef struct pri_event_generic {
/* Events with no additional information fall in this category */
int e;
@@ -328,6 +428,10 @@
int progressmask;
q931_call *call;
char useruserinfo[260]; /* User->User info */
+ char calledname[256];
+ char callednum[256];
+ int calledpres;
+ int calledplan;
} pri_event_ringing;
typedef struct pri_event_answer {
@@ -338,6 +442,11 @@
int progressmask;
q931_call *call;
char useruserinfo[260]; /* User->User info */
+ int connectedpres;
+ int connectedplan;
+ char connectednum[256];
+ char connectedname[256];
+ int source;
} pri_event_answer;
typedef struct pri_event_facname {
@@ -350,6 +459,14 @@
int callingpres; /* Presentation of Calling CallerID */
int callingplan; /* Dialing plan of Calling entity */
} pri_event_facname;
+
+typedef struct pri_event_facility {
+ int e;
+ int channel;
+ int cref;
+ q931_call *call;
+ struct subcommands subcmds;
+} pri_event_facility;
#define PRI_CALLINGPLANANI
#define PRI_CALLINGPLANRDNIS
@@ -367,7 +484,9 @@
char callednum[256]; /* Called number */
char redirectingnum[256]; /* Redirecting number */
char redirectingname[256]; /* Redirecting name */
+ int redirectingpres;
int redirectingreason; /* Reason for redirect */
+ int redirectingcount;
int callingplanrdnis; /* Dialing plan of Redirecting Number */
char useruserinfo[260]; /* User->User info */
int flexible; /* Are we flexible with our channel selection? */
@@ -445,6 +564,7 @@
pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
pri_event_notify notify; /* Notification */
pri_event_keypad_digit digit; /* Digits that come during a call */
+ pri_event_facility facility;
} pri_event;
struct pri;
@@ -531,6 +651,12 @@
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);
+/* Give connected line information to a call */
+int pri_connected_line_update(struct pri *pri, q931_call *call, struct pri_party_connected_line *connected);
+
+/* Give redirection information to a call */
+int pri_redirecting_update(struct pri *pri, q931_call *call, struct pri_party_redirecting *redirecting);
+
/* Set CRV reference for GR-303 calls */
@@ -583,7 +709,7 @@
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);
int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
-int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
+int pri_sr_set_redirecting(struct pri_sr *sr, char *name, 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: team/group/issue14068/pri.c
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14068/pri.c?view=diff&rev=670&r1=669&r2=670
==============================================================================
--- team/group/issue14068/pri.c (original)
+++ team/group/issue14068/pri.c Mon Jan 19 11:28:53 2009
@@ -348,6 +348,8 @@
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:
@@ -549,6 +551,119 @@
if (!pri || !call)
return -1;
return q931_connect(pri, call, channel, nonisdn);
+}
+
+int pri_connected_line_update(struct pri *pri, q931_call *call, struct pri_party_connected_line *connected)
+{
+ if (!pri || !call)
+ return -1;
+
+ libpri_copy_string(call->connectednum, connected->id.number, sizeof(call->connectednum));
+ libpri_copy_string(call->connectedname, connected->id.name, sizeof(call->connectedname));
+ call->connectedplan = connected->id.number_type;
+ call->connectedpres = connected->id.number_presentation;
+
+ if (pri->switchtype == PRI_SWITCH_QSIG) {
+ switch (call->ourcallstate) {
+ case Q931_CALL_STATE_ACTIVE:
+ /* immediately send callTransferComplete APDU */
+ qsig_initiate_call_transfer_complete(pri, call);
+ break;
+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
+ /* queue updates for next ALERTING */
+ if (call->connectedname[0]) {
+ /* queue connectedName to be send with next Q931_ALERTING */
+ rose_called_name_encode(pri, call, Q931_ALERTING);
+ }
+
+ if (call->divertedstate != DIVERTEDSTATE_NONE) {
+ libpri_copy_string(call->divertedtonum, connected->id.number, sizeof(call->divertedtonum));
+ libpri_copy_string(call->divertedtoname, connected->id.name, sizeof(call->divertedtoname));
+ call->divertedtoplan = connected->id.number_type;
+ call->divertedtopres = connected->id.number_presentation;
+
+ if ((call->divertedstate == DIVERTEDSTATE_DIVERTED) && call->divertedtonum[0]) {
+ /* immediately send divertingLegInformation1 APDU */
+ qsig_initiate_diverting_leg_information1(pri, call);
+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO1SEND;
+ }
+ if ((call->divertedstate == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->divertedtoname[0]) {
+ /* queue divertingLegInformation3 to be send with next Q931_ALERTING */
+ rose_diverting_leg_information3_encode(pri, call, Q931_ALERTING);
+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO3SEND;
+ }
+ }
+ break;
+ case Q931_CALL_STATE_CALL_RECEIVED:
+ /* queue updates for next CONNECT */
+ if (call->connectedname[0] && ((call->divertedstate == DIVERTEDSTATE_NONE) || (call->divertedstate == DIVERTEDSTATE_DIVLEGINFO3SEND))) {
+ /* queue connectedName to be send with next Q931_CONNECT */
+ rose_connected_name_encode(pri, call, Q931_CONNECT);
+ }
+
+ if (call->divertedstate != DIVERTEDSTATE_NONE) {
+ libpri_copy_string(call->divertedtonum, connected->id.number, sizeof(call->divertedtonum));
+ libpri_copy_string(call->divertedtoname, connected->id.name, sizeof(call->divertedtoname));
+ call->divertedtoplan = connected->id.number_type;
+ call->divertedtopres = connected->id.number_presentation;
+
+ if ((call->divertedstate == DIVERTEDSTATE_DIVERTED) && call->divertedtonum[0]) {
+ /* queue divertingLegInformation1 to be send with next Q931_FACILITY */
+ rose_diverting_leg_information1_encode(pri, call);
+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO1SEND;
+
+ if (call->divertedtoname[0]) {
+ /* queue divertingLegInformation3 to be send with next Q931_FACILITY */
+ rose_diverting_leg_information3_encode(pri, call, Q931_FACILITY);
+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO3SEND;
+ }
+
+ /* immediately send Q931_FACILITY */
+ if (q931_facility(pri, call)) {
+ pri_message(pri, "Could not schedule facility message for divertingLegInfo1+3\n");
+ }
+ }
+ if ((call->divertedstate == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->divertedtoname[0]) {
+ /* queue divertingLegInformation3 to be send with next Q931_CONNECT */
+ rose_diverting_leg_information3_encode(pri, call, Q931_CONNECT);
+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO3SEND;
+ }
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int pri_redirecting_update(struct pri *pri, q931_call *call, struct pri_party_redirecting *redirecting)
+{
+ if (!pri || !call)
+ return -1;
+
+ libpri_copy_string(call->divertedtonum, redirecting->to.number, sizeof(call->divertedtonum));
+ libpri_copy_string(call->divertedtoname, redirecting->to.name, sizeof(call->divertedtoname));
+ call->divertedtoplan = redirecting->to.number_type;
+ call->divertedtopres = redirecting->to.number_presentation;
+ call->divertedtoreason = redirecting->reason;
+
+ if (pri->switchtype == PRI_SWITCH_QSIG) {
+ call->divertedstate = DIVERTEDSTATE_DIVERTED;
+
+ if (call->divertedtonum[0]) {
+ /* immediately send divertingLegInformation1 APDU */
+ qsig_initiate_diverting_leg_information1(pri, call);
+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO1SEND;
+ }
+ if ((call->divertedstate == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->divertedtoname[0]) {
+ /* queue divertingLegInformation3 to be send with next Q931_ALERTING */
+ rose_diverting_leg_information3_encode(pri, call, Q931_ALERTING);
+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO3SEND;
+ }
+ }
+
+ return 0;
}
#if 0
@@ -928,8 +1043,9 @@
return 0;
}
-int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason)
-{
+int pri_sr_set_redirecting(struct pri_sr *sr, char *name, char *num, int plan, int pres, int reason)
+{
+ sr->redirectingname = name;
sr->redirectingnum = num;
sr->redirectingplan = plan;
sr->redirectingpres = pres;
Modified: team/group/issue14068/pri_facility.c
URL: http://svn.digium.com/svn-view/libpri/team/group/issue14068/pri_facility.c?view=diff&rev=670&r1=669&r2=670
==============================================================================
--- team/group/issue14068/pri_facility.c (original)
+++ team/group/issue14068/pri_facility.c Mon Jan 19 11:28:53 2009
@@ -171,19 +171,57 @@
struct addressingdataelements_presentednumberunscreened {
char partyaddress[21];
- char partysubaddress[21];
+ char notused[21];
int npi; /* Numbering Plan Indicator */
int ton; /* Type Of Number */
int pres; /* Presentation */
};
struct addressingdataelements_presentednumberscreened {
+ char partyaddress[21];
+ char notused[21];
+ int npi; /* Numbering Plan Indicator */
+ int ton; /* Type Of Number */
+ int pres; /* Presentation */
+ int scrind; /* Screening Indicator */
+};
+
+struct addressingdataelements_presentedaddressscreened {
char partyaddress[21];
char partysubaddress[21];
int npi; /* Numbering Plan Indicator */
int ton; /* Type Of Number */
int pres; /* Presentation */
int scrind; /* Screening Indicator */
+};
+
+struct addressingdataelements_addressscreened {
+ char partyaddress[21];
+ char partysubaddress[21];
+ int npi; /* Numbering Plan Indicator */
+ int ton; /* Type Of Number */
+ int notused;
+ int scrind; /* Screening Indicator */
+};
+
+struct addressingdataelements_partysubaddress {
+ char notused[21];
+ char partysubaddress[21];
+};
+
+struct nameelements_name {
+ char name[51];
+ int characterset;
+ int namepres;
+};
+
+struct nameelements_nameset {
+ char name[51];
+ int characterset;
+};
+
+struct nameelements_namedata {
+ char name[51];
};
#define PRI_CHECKOVERFLOW(size) \
@@ -224,6 +262,92 @@
pri_message(pri, "%s", message);
}
#undef PRI_CHECKOVERFLOW
+
+static const char *namepres_to_str(int namepres)
+{
+ return (namepres == 0) ? "Restricted" : "Allowed";
+}
+
+static const char *characterset_to_str(int characterset)
+{
+ switch (characterset) {
+ case CHARACTER_SET_UNKNOWN:
+ return "Unknown";
+ case CHARACTER_SET_ISO8859_1:
+ return "ISO8859-1";
+ case CHARACTER_SET_ISO8859_2:
+ return "ISO8859-2";
+ case CHARACTER_SET_ISO8859_3:
+ return "ISO8859-3";
+ case CHARACTER_SET_ISO8859_4:
+ return "ISO8859-4";
+ case CHARACTER_SET_ISO8859_5:
+ return "ISO8859-5";
+ case CHARACTER_SET_ISO8859_7:
+ return "ISO8859-7";
+ default:
+ return "illegal value";
+ }
+}
+
+static const char *diversionreason_to_str(struct pri *pri, int diversionreason)
+{
+ if (pri->switchtype == PRI_SWITCH_QSIG) {
+ switch (diversionreason) {
+ case QSIG_DIVERT_REASON_UNKNOWN:
+ return "Unknown";
+ case QSIG_DIVERT_REASON_CFU:
+ return "Call Forwarding Unconditional";
+ case QSIG_DIVERT_REASON_CFB:
+ return "Call Forwarding Busy";
+ case QSIG_DIVERT_REASON_CFNR:
+ return "Call Forwarding No Reply";
+ default:
+ return "invalid value";
+ }
+ } else {
+ switch(diversionreason) {
+ case Q952_DIVERT_REASON_UNKNOWN:
+ return "Unknown";
+ case Q952_DIVERT_REASON_CFU:
+ return "Call Forwarding Unconditional";
+ case Q952_DIVERT_REASON_CFB:
+ return "Call Forwarding Busy";
+ case Q952_DIVERT_REASON_CFNR:
+ return "Call Forwarding No Reply";
+ case Q952_DIVERT_REASON_CD:
+ return "Call Deflection";
+ case Q952_DIVERT_REASON_IMMEDIATE:
+ return "Call Deflection Immediate";
+ default:
+ return "invalid value";
+ }
+ }
+}
+
+static const char *callstatus_to_str(int callstatus)
+{
+ switch (callstatus) {
+ case 0:
+ return "answered";
+ case 1:
+ return "alerting";
+ default:
+ return "illegal value";
+ }
+}
+
+static const char *enddesignation_to_str(int enddesignation)
+{
+ switch (enddesignation) {
+ case 0:
+ return "primaryEnd";
+ case 1:
+ return "secondaryEnd";
+ default:
+ return "illegal value";
+ }
+}
int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
{
@@ -350,7 +474,24 @@
}
}
-int asn1_name_decode(void * data, int len, char *namebuf, int buflen)
+static int presentation_to_subscription(struct pri *pri, int presentation)
+{
+ /* derive subscription value from presentation value */
+
+ switch (presentation & PRES_RESTRICTION) {
+ case PRES_ALLOWED:
+ return QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR;
+ case PRES_RESTRICTED:
+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
+ case PRES_UNAVAILABLE: /* Number not available due to interworking */
+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR; /* ?? QSIG_NO_NOTIFICATION */
+ default:
+ pri_message(pri, "!! Unknown Q.SIG presentationIndicator 0x%02x\n", presentation);
+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
+ }
+}
+
+int asn1_name_decode(void *data, int len, char *namebuf, int buflen)
{
struct rose_component *comp = (struct rose_component*)data;
int datalen = 0, res = 0;
@@ -361,11 +502,13 @@
} else
datalen = res = comp->len;
- if (datalen > buflen) {
+ if (datalen > buflen - 1) {
/* Truncate */
datalen = buflen;
}
memcpy(namebuf, comp->data, datalen);
+ namebuf[datalen] = '\0';
+
return res + 2;
}
@@ -407,38 +550,226 @@
return res;
}
-static int rose_number_digits_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
+static int rose_namedata_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct nameelements_namedata *value)
{
int i = 0;
struct rose_component *comp = NULL;
unsigned char *vdata = data;
- int datalen = 0;
- int res = 0;
+ int res;
+
+ do {
+ /* NameData */
+ if (!implicit) {
+ GET_COMPONENT(comp, i, vdata, len);
+ CHECK_COMPONENT(comp, ASN1_OCTETSTRING, "Don't know what to do if NameData is of type 0x%x\n");
+
+ data = comp->data;
+ if (comp->len == ASN1_LEN_INDEF) {
+ len = strlen((char *)comp->data);
+ res = len + 2 + 2;
+ } else {
+ len = comp->len;
+ res = len + 2;
+ }
+ } else
+ res = len;
+
+ if (len > sizeof(value->name)-1) {
+ pri_message(pri, "!! Oversized NameData component (%d)\n", len);
+ return -1;
+ }
+
+ memcpy(value->name, data, len);
+ value->name[len] = '\0';
+
+ return res;
+ }
+ while(0);
+
+ return -1;
+}
+
+static int rose_namedata_encode(struct pri *pri, unsigned char *dst, int implicit, char *name)
+{
+ int size = 0;
+ struct rose_component *comp;
+ int namesize;
+
+ namesize = strlen(name);
+ if (namesize > 50 ) {
+ pri_message(pri, "!! Encoding of oversized NameData component failed (%d)\n", namesize);
+ return -1;
+ } else if (namesize == 0){
+ pri_message(pri, "!! Encoding of undersized NameData component failed (%d)\n", namesize);
+ return -1;
+ }
+
+ if (!implicit) {
+ /* constructor component (0x04,len) */
+ comp = (struct rose_component *)dst;
+ comp->type = ASN1_OCTETSTRING;
+ comp->len = 2 + namesize;
+ size += 2;
+ dst += 2;
+ }
+
+ memcpy(dst, name, namesize);
+ size += namesize;
+
+ return size;
+}
+
+static int rose_nameset_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct nameelements_nameset *value)
+{
+ int size;
+ int i = 0;
+ struct rose_component *comp = NULL;
+ unsigned char *vdata = data;
+ int characterset;
+
+ value->characterset = CHARACTER_SET_ISO8859_1;
+
+ do {
+ /* NameSet */
+ if (!implicit) {
+ GET_COMPONENT(comp, i, vdata, len);
+ CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Don't know what to do if NameSet is of type 0x%x\n");
+ SUB_COMPONENT(comp, i);
+ }
+
+ /* nameData NameData */
+ GET_COMPONENT(comp, i, vdata, len);
+ size = rose_namedata_decode(pri, (u_int8_t *)comp, len, 0, (struct nameelements_namedata *)value);
+ if (size < 0)
+ return -1;
+ i += size;
+
+ if (i < len) {
+ /* characterSet CharacterSet OPTIONAL */
+ GET_COMPONENT(comp, i, vdata, len);
+ CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if CharacterSet is of type 0x%x\n");
+ ASN1_GET_INTEGER(comp, characterset);
+ NEXT_COMPONENT(comp, i);
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message(pri, " NameSet: Received characterSet=%s(%d)\n", characterset_to_str(characterset), characterset);
+ value->characterset = characterset;
+ }
+
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message(pri, " NameSet: '%s', characterSet=%s(%d) i=%d len=%d\n", value->name, characterset_to_str(value->characterset), value->characterset, i, len);
+
+ return i;
+ }
+ while(0);
+
+ return -1;
+}
+
+static int rose_name_decode(struct pri *pri, unsigned char *data, int len, struct nameelements_name *value)
+{
+ int i = 0;
+ int size = 0;
+ struct rose_component *comp = NULL;
+ unsigned char *vdata = data;
+
+ value->name[0] = '\0';
+ value->characterset = CHARACTER_SET_UNKNOWN;
+ value->namepres = -1;
do {
GET_COMPONENT(comp, i, vdata, len);
- CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
- if(comp->len > 20 && comp->len != ASN1_LEN_INDEF) {
- pri_message(pri, "!! Oversized NumberDigits component (%d)\n", comp->len);
+
+ switch(comp->type) {
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] namePresentationAllowedSimple */
+ size = rose_namedata_decode(pri, comp->data, comp->len, 1, (struct nameelements_namedata *)value);
+ if (size < 0)
+ return -1;
+ i += (size + 2);
+ value->characterset = CHARACTER_SET_ISO8859_1;
+ value->namepres = 1;
+ break;
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] namePresentationAllowedExtended */
+ size = rose_nameset_decode(pri, comp->data, comp->len, 1, (struct nameelements_nameset *)value);
+ if (size < 0)
+ return -1;
+ i += (size + 2);
+ value->namepres = 1;
+ break;
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] namePresentationRestrictedSimple */
+ size = rose_namedata_decode(pri, comp->data, comp->len, 1, (struct nameelements_namedata *)value);
+ if (size < 0)
+ return -1;
+ i += (size + 2);
+ value->characterset = CHARACTER_SET_ISO8859_1;
+ value->namepres = 0;
+ break;
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] namePresentationRestrictedExtended */
+ size = rose_nameset_decode(pri, comp->data, comp->len, 1, (struct nameelements_nameset *)value);
+ if (size < 0)
+ return -1;
+ i += (size + 2);
+ value->namepres = 0;
+ break;
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_4): /* [4] nameNotAvailable */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_7): /* [7] namePresentationRestrictedNull */
+ i += (comp->len + 2);
+ value->name[0] = '\0';
+ value->characterset = CHARACTER_SET_UNKNOWN;
+ value->namepres = 0;
+ break;
+ default:
+ pri_message(pri, "!! Unknown Name component received 0x%x\n", comp->type);
return -1;
}
- if (comp->len == ASN1_LEN_INDEF) {
- datalen = strlen((char *)comp->data);
- res = datalen + 2;
+
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message(pri, " Name: '%s' i=%d len=%d\n", value->name, i, len);
+ return i;
+ }
+ while (0);
+
+ return -1;
+}
+
+static int rose_number_digits_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct addressingdataelements_presentednumberunscreened *value)
+{
+ int i = 0;
+ struct rose_component *comp = NULL;
+ unsigned char *vdata = data;
+ int res = 0;
+
+ do {
+ if (!implicit) {
+ GET_COMPONENT(comp, i, vdata, len);
+ CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with NumberDigits ROSE component type 0x%x\n");
+
+ data = comp->data;
+ if (comp->len == ASN1_LEN_INDEF) {
+ len = strlen((char *)comp->data);
+ res = len + 2 + 2;
+ } else {
+ len = comp->len;
+ res = len + 2;
+ }
} else
- res = datalen = comp->len;
-
- memcpy(value->partyaddress, comp->data, datalen);
- value->partyaddress[datalen] = '\0';
-
- return res + 2;
+ res = len;
+
+ if (len > sizeof(value->partyaddress)-1) {
+ pri_message(pri, "!! Oversized NumberDigits component (%d)\n", len);
+ return -1;
+ }
+
+ memcpy(value->partyaddress, data, len);
+ value->partyaddress[len] = '\0';
+
+ return res;
}
while(0);
-
+
return -1;
}
-static int rose_public_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
+static int rose_public_party_number_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct addressingdataelements_presentednumberunscreened *value)
{
int i = 0;
struct rose_component *comp = NULL;
@@ -450,13 +781,19 @@
return -1;
do {
+ if (!implicit) {
+ GET_COMPONENT(comp, i, vdata, len);
+ CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Don't know what to do if PublicPartyNumber is of type 0x%x\n");
+ SUB_COMPONENT(comp, i);
+ }
+
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
ASN1_GET_INTEGER(comp, ton);
NEXT_COMPONENT(comp, i);
ton = typeofnumber_for_q931(pri, ton);
- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
+ res = rose_number_digits_decode(pri, &vdata[i], len-i, 0, value);
if (res < 0)
return -1;
value->ton = ton;
@@ -467,7 +804,47 @@
return -1;
}
-static int rose_private_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
+static int rose_public_party_number_encode(struct pri *pri, unsigned char *dst, int implicit, unsigned char ton, char *num)
+{
+ int i = 0, compsp = 0;
+ struct rose_component *comp, *compstk[10];
+ int numsize;
+
+ numsize = strlen(num);
+ if (numsize > 20 ) {
+ pri_message(pri, "!! Encoding of oversized PublicPartyNumber component failed (%d)\n", numsize);
+ return -1;
+ }
+
+ if (!implicit) {
+ /* constructor component (0x30,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), dst, i);
+ ASN1_PUSH(compstk, compsp, comp);
+ } else
+ comp = (struct rose_component *)dst;
+
+ /* publicTypeOfNumber (0x0a,0x01,ton)*/
+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, dst, i, ton);
+
+ /* publicNumberDigits */
+
+ /* tag component NumericString (0x12,len) */
+ ASN1_ADD_SIMPLE(comp, ASN1_NUMERICSTRING, dst, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ /* NumericString */
+ memcpy(comp->data, num, numsize);
+ i += numsize;
+
+ ASN1_FIXUP(compstk, compsp, dst, i);
+
+ if (!implicit)
+ ASN1_FIXUP(compstk, compsp, dst, i);
+
+ return i;
+}
+
+static int rose_private_party_number_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct addressingdataelements_presentednumberunscreened *value)
{
int i = 0;
struct rose_component *comp = NULL;
@@ -476,18 +853,24 @@
int res = 0;
if (len < 2)
- return -1;
+ return -1;
do {
+ if (!implicit) {
+ GET_COMPONENT(comp, i, vdata, len);
+ CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Don't know what to do if PrivatePartyNumber is of type 0x%x\n");
+ SUB_COMPONENT(comp, i);
+ }
+
GET_COMPONENT(comp, i, vdata, len);
CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PrivatePartyNumber ROSE component type 0x%x\n");
ASN1_GET_INTEGER(comp, ton);
NEXT_COMPONENT(comp, i);
ton = typeofnumber_for_q931(pri, ton);
- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
+ res = rose_number_digits_decode(pri, &vdata[i], len-i, 0, value);
if (res < 0)
- return -1;
+ return -1;
value->ton = ton;
return res + 3;
@@ -496,7 +879,7 @@
return -1;
}
-static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
+static int rose_address_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
{
int i = 0;
struct rose_component *comp = NULL;
@@ -506,65 +889,59 @@
do {
GET_COMPONENT(comp, i, vdata, len);
+ /* PartyNumber */
switch(comp->type) {
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] unknownPartyNumber */
- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber, IMPLICIT NumberDigits */
+ res = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
if (res < 0)
return -1;
value->npi = PRI_NPI_UNKNOWN;
value->ton = PRI_TON_UNKNOWN;
break;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber */
- res = asn1_copy_string(value->partyaddress, sizeof(value->partyaddress), comp);
- if (res < 0)
- return -1;
- value->npi = PRI_NPI_UNKNOWN;
- value->ton = PRI_TON_UNKNOWN;
- break;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber */
- res = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber, IMPLICIT PublicPartyNumber */
+ res = rose_public_party_number_decode(pri, comp->data, comp->len, 1, value);
if (res < 0)
return -1;
value->npi = PRI_NPI_E163_E164;
break;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] nsapEncodedNumber */
- pri_message(pri, "!! NsapEncodedNumber isn't handled\n");
- return -1;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] dataPartyNumber */
- if(rose_number_digits_decode(pri, call, comp->data, comp->len, value))
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_3): /* [3] dataPartyNumber, IMPLICIT NumberDigits */
+ res = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
+ if (res < 0)
return -1;
value->npi = PRI_NPI_X121 /* ??? */;
value->ton = PRI_TON_UNKNOWN /* ??? */;
pri_message(pri, "!! dataPartyNumber isn't handled\n");
return -1;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] telexPartyNumber */
- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_4): /* [4] telexPartyNumber, IMPLICIT NumberDigits */
+ res = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
if (res < 0)
return -1;
value->npi = PRI_NPI_F69 /* ??? */;
value->ton = PRI_TON_UNKNOWN /* ??? */;
pri_message(pri, "!! telexPartyNumber isn't handled\n");
return -1;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */
- res = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] privatePartyNumber, IMPLICIT PrivatePartyNumber */
+ res = rose_private_party_number_decode(pri, comp->data, comp->len, 1, value);
if (res < 0)
- return -1;
+ return -1;
value->npi = PRI_NPI_PRIVATE;
break;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */
- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_8): /* [8] nationalStandardPartyNumber, IMPLICIT NumberDigits */
+ res = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
if (res < 0)
return -1;
value->npi = PRI_NPI_NATIONAL;
value->ton = PRI_TON_NATIONAL;
break;
default:
- pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type);
+ pri_message(pri, "!! Unknown PartyNumber component received 0x%X\n", comp->type);
return -1;
}
ASN1_FIXUP_LEN(comp, res);
NEXT_COMPONENT(comp, i);
- if(i < len)
+
+ /* PartySubaddress OPTIONAL */
+ if (i < len)
pri_message(pri, "!! not all information is handled from Address component\n");
return res + 2;
}
@@ -573,14 +950,176 @@
return -1;
}
-static int rose_presented_number_unscreened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
+static int rose_party_number_encode(struct pri *pri, unsigned char *dst, unsigned char ton, char *num)
+{
+ int i = 0, compsp = 0;
+ struct rose_component *comp, *compstk[10];
+ int numsize, size;
+
+ numsize = strlen(num);
+ if (numsize > 20 ) {
+ pri_message(pri, "!! Encoding of oversized PartyNumber component failed (%d)\n", numsize);
+ return -1;
+ }
+
+#if 0
+ /* tag component unknownPartyNumber (0x80,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), dst, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ /* unknownPartyNumber, implicid NumberDigits */
+ memcpy(comp->data, num, numsize);
+ i += numsize;
+
+ ASN1_FIXUP(compstk, compsp, dst, i);
+#endif
+
+ /* tag component publicPartyNumber (0xa1,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), dst, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ /* publicPartyNumber, implicid PublicPartyNumber */
+ size = rose_public_party_number_encode(pri, comp->data, 1, ton, num);
+ if (size < 0)
+ return -1;
+ i += size;
+
+ ASN1_FIXUP(compstk, compsp, dst, i);
+
+ return i;
+}
+
+static int rose_party_number_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
{
int i = 0;
int size = 0;
struct rose_component *comp = NULL;
unsigned char *vdata = data;
+ do {
+ GET_COMPONENT(comp, i, vdata, len);
+
+ switch(comp->type) {
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] IMPLICIT NumberDigits -- default: unknownPartyNumber */
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message(pri, " PartyNumber: UnknownPartyNumber len=%d\n", len);
+ size = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
+ if (size < 0)
+ return -1;
+ value->npi = PRI_NPI_UNKNOWN;
+ value->ton = PRI_TON_UNKNOWN;
+ break;
+
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT PublicPartyNumber */
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message(pri, " PartyNumber: PublicPartyNumber len=%d\n", len);
+ size = rose_public_party_number_decode(pri, comp->data, comp->len, 1, value);
+ if (size < 0)
+ return -1;
+ value->npi = PRI_NPI_E163_E164;
+ break;
+
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_3): /* [3] IMPLICIT NumberDigits -- not used: dataPartyNumber */
+ pri_message(pri, "!! PartyNumber: dataPartyNumber is reserved!\n");
+ size = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
+ if (size < 0)
+ return -1;
+ value->npi = PRI_NPI_X121 /* ??? */;
+ value->ton = PRI_TON_UNKNOWN /* ??? */;
+ break;
+
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_4): /* [4] IMPLICIT NumberDigits -- not used: telexPartyNumber */
+ pri_message(pri, "!! PartyNumber: telexPartyNumber is reserved!\n");
+ size = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
+ if (size < 0)
+ return -1;
+ value->npi = PRI_NPI_F69 /* ??? */;
+ value->ton = PRI_TON_UNKNOWN /* ??? */;
+ break;
+
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT PrivatePartyNumber */
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message(pri, " PartyNumber: PrivatePartyNumber len=%d\n", len);
+ size = rose_private_party_number_decode(pri, comp->data, comp->len, 1, value);
+ if (size < 0)
+ return -1;
+ value->npi = PRI_NPI_PRIVATE;
+ break;
+
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_8): /* [8] IMPLICIT NumberDigits -- not used: nationalStandatdPartyNumber */
+ pri_message(pri, "!! PartyNumber: nationalStandardPartyNumber is reserved!\n");
+ size = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
+ if (size < 0)
+ return -1;
+ value->npi = PRI_NPI_NATIONAL;
+ value->ton = PRI_TON_NATIONAL;
+ break;
+
+ default:
+ pri_message(pri, "Invalid PartyNumber component 0x%X\n", comp->type);
+ return -1;
+ }
+ ASN1_FIXUP_LEN(comp, size);
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message(pri, " PartyNumber: '%s' size=%d len=%d\n", value->partyaddress, size, len);
+ return size;
+ }
+ while (0);
+
+ return -1;
+}
+
+static int rose_presented_number_unscreened_encode(struct pri *pri, unsigned char *dst, unsigned char presentation, unsigned char ton, char *num)
+{
+ int i = 0, compsp = 0;
+ struct rose_component *comp, *compstk[10];
+ int numsize, size;
+
+ numsize = strlen(num);
+ if (numsize > 20 ) {
+ pri_message(pri, "!! Encoding of oversized PresentedNumberUnscreened component failed (%d)\n", numsize);
+ return -1;
+ }
+
+ switch (presentation & PRES_RESTRICTION) {
+ case PRES_ALLOWED:
+ /* tag component [0] presentationAllowedAddress (0xa0,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), dst, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ /* PartyNumber */
+ size = rose_party_number_encode(pri, comp->data, ton, num);
+ if (size < 0)
+ return -1;
+ i += size;
+ ASN1_FIXUP(compstk, compsp, dst, i);
+ break;
+ case PRES_RESTRICTED:
+ /* tag component [1] presentationRestricted (0x81,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), dst, i);
+ break;
+ case PRES_UNAVAILABLE:
+ /* tag component [2] numberNotAvailableDueToInterworking (0x82,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), dst, i);
+ ASN1_FIXUP(compstk, compsp, dst, i);
+ break;
+ default:
+ pri_message(pri, "!! Undefined presentation value for PresentedNumberUnscreened: 0x%x\n", presentation);
+ return -1;
+ }
+
+ return i;
+}
+
[... 3080 lines stripped ...]
More information about the libpri-commits
mailing list