[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