[svn-commits] trunk - r286 /trunk/
svn-commits at lists.digium.com
svn-commits at lists.digium.com
Thu Jan 5 14:50:52 CST 2006
Author: mattf
Date: Thu Jan 5 14:50:51 2006
New Revision: 286
URL: http://svn.digium.com/view/libpri?rev=286&view=rev
Log:
Lots of changes for APDU handling and debugging. Thanks PCadach (bug #5265)!
Modified:
trunk/pri_facility.c
trunk/pri_facility.h
trunk/pri_q931.h
trunk/q931.c
trunk/testprilib.c
Modified: trunk/pri_facility.c
URL: http://svn.digium.com/view/libpri/trunk/pri_facility.c?rev=286&r1=285&r2=286&view=diff
==============================================================================
--- trunk/pri_facility.c (original)
+++ trunk/pri_facility.c Thu Jan 5 14:50:51 2006
@@ -32,6 +32,132 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
+
+static char *asn1id2text(int id)
+{
+ static char data[32];
+ static char *strings[] = {
+ "none",
+ "Boolean",
+ "Integer",
+ "Bit String",
+ "Octet String",
+ "NULL",
+ "Object Identifier",
+ "Object Descriptor",
+ "External Reference",
+ "Real Number",
+ "Enumerated",
+ "Embedded PDV",
+ "UTF-8 String",
+ "Relative Object ID",
+ "Reserved (0e)",
+ "Reserved (0f)",
+ "Sequence",
+ "Set",
+ "Numeric String",
+ "Printable String",
+ "Tele-Text String",
+ "IA-5 String",
+ "UTC Time",
+ "Generalized Time",
+ };
+ if (id > 0 && id <= 0x18) {
+ return strings[id];
+ } else {
+ sprintf(data, "Unknown (%02x)", id);
+ return data;
+ }
+}
+
+static int asn1_dumprecursive(struct pri *pri, void *comp_ptr, int len, int level)
+{
+ unsigned char *vdata = (unsigned char *)comp_ptr;
+ struct rose_component *comp;
+ int i = 0;
+ int j, k, l;
+ int clen = 0;
+
+ while (len > 0) {
+ GET_COMPONENT(comp, i, vdata, len);
+ pri_message(pri, "%*s%02X %04X", 2 * level, "", comp->type, comp->len);
+ if ((comp->type == 0) && (comp->len == 0))
+ return clen + 2;
+ if ((comp->type & ASN1_PC_MASK) == ASN1_PRIMITIVE) {
+ for (j = 0; j < comp->len; ++j)
+ pri_message(pri, " %02X", comp->data[j]);
+ }
+ if ((comp->type & ASN1_CLAN_MASK) == ASN1_UNIVERSAL) {
+ switch (comp->type & ASN1_TYPE_MASK) {
+ case 0:
+ pri_message(pri, " (none)");
+ break;
+ case ASN1_BOOLEAN:
+ pri_message(pri, " (BOOLEAN: %d)", comp->data[0]);
+ break;
+ case ASN1_INTEGER:
+ for (k = l = 0; k < comp->len; ++k)
+ l = (l << 8) | comp->data[k];
+ pri_message(pri, " (INTEGER: %d)", l);
+ break;
+ case ASN1_BITSTRING:
+ pri_message(pri, " (BITSTRING:");
+ for (k = 0; k < comp->len; ++k)
+ pri_message(pri, " %02x", comp->data[k]);
+ pri_message(pri, ")");
+ break;
+ case ASN1_OCTETSTRING:
+ pri_message(pri, " (OCTETSTRING:");
+ for (k = 0; k < comp->len; ++k)
+ pri_message(pri, " %02x", comp->data[k]);
+ pri_message(pri, ")");
+ break;
+ case ASN1_NULL:
+ pri_message(pri, " (NULL)");
+ break;
+ case ASN1_OBJECTIDENTIFIER:
+ pri_message(pri, " (OBJECTIDENTIFIER:");
+ for (k = 0; k < comp->len; ++k)
+ pri_message(pri, " %02x", comp->data[k]);
+ pri_message(pri, ")");
+ break;
+ case ASN1_ENUMERATED:
+ for (k = l = 0; k < comp->len; ++k)
+ l = (l << 8) | comp->data[k];
+ pri_message(pri, " (ENUMERATED: %d)", l);
+ break;
+ case ASN1_SEQUENCE:
+ pri_message(pri, " (SEQUENCE)");
+ break;
+ default:
+ pri_message(pri, " (component %02x - %s)", comp->type, asn1id2text(comp->type & ASN1_TYPE_MASK));
+ break;
+ }
+ }
+ else if ((comp->type & ASN1_CLAN_MASK) == ASN1_CONTEXT_SPECIFIC) {
+ pri_message(pri, " (CONTEXT SPECIFIC [%d])", comp->type & ASN1_TYPE_MASK);
+ }
+ else {
+ pri_message(pri, " (component %02x)", comp->type);
+ }
+ pri_message(pri, "\n");
+ if ((comp->type & ASN1_PC_MASK) == ASN1_CONSTRUCTOR)
+ j = asn1_dumprecursive(pri, comp->data, (comp->len ? comp->len : INT_MAX), level+1);
+ else
+ j = comp->len;
+ j += 2;
+ len -= j;
+ vdata += j;
+ clen += j;
+ }
+ return clen;
+}
+
+int asn1_dump(struct pri *pri, void *comp, int len)
+{
+ return asn1_dumprecursive(pri, comp, len, 0);
+}
static unsigned char get_invokeid(struct pri *pri)
{
@@ -46,28 +172,44 @@
int pres;
};
+#define PRI_CHECKOVERFLOW(size) \
+ if (msgptr - message + (size) >= sizeof(message)) { \
+ *msgptr = '\0'; \
+ pri_message(pri, "%s", message); \
+ msgptr = message; \
+ }
+
static void dump_apdu(struct pri *pri, unsigned char *c, int len)
{
#define MAX_APDU_LENGTH 255
+ static char hexs[16] = "0123456789ABCDEF";
int i;
char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */
-
- if (len > MAX_APDU_LENGTH)
- return;
-
- snprintf(message, sizeof(message)-1, " [");
- for (i=0; i<len; i++)
- snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " %02x", c[i]);
- snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " ] - [");
+ char *msgptr;
+
+ msgptr = message;
+ *msgptr++ = ' ';
+ *msgptr++ = '[';
for (i=0; i<len; i++) {
- if (c[i] < 20 || c[i] >= 128)
- snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "°");
- else
- snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "%c", c[i]);
- }
- snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "]\n");
- pri_message(pri, message);
-}
+ PRI_CHECKOVERFLOW(3);
+ *msgptr++ = ' ';
+ *msgptr++ = hexs[(c[i] >> 4) & 0x0f];
+ *msgptr++ = hexs[(c[i]) & 0x0f];
+ }
+ PRI_CHECKOVERFLOW(6);
+ strcpy(msgptr, " ] - [");
+ msgptr += strlen(msgptr);
+ for (i=0; i<len; i++) {
+ PRI_CHECKOVERFLOW(1);
+ *msgptr++ = ((c[i] < ' ') || (c[i] > '~')) ? '.' : c[i];
+ }
+ PRI_CHECKOVERFLOW(2);
+ *msgptr++ = ']';
+ *msgptr++ = '\n';
+ *msgptr = '\0';
+ pri_message(pri, "%s", message);
+}
+#undef PRI_CHECKOVERFLOW
int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
{
@@ -564,9 +706,11 @@
unsigned char buffer[256];
int len = 253;
+#if 0 /* This is not required by specifications */
if (!strlen(call->callername)) {
return -1;
}
+#endif
buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
i++;
@@ -749,7 +893,7 @@
}
- /* Now the ADPu that contains the information that needs sent.
+ /* Now the APDU that contains the information that needs sent.
* We can reuse the buffer since the queue function doesn't
* need it. */
@@ -903,7 +1047,7 @@
res = pri_call_apdu_queue(c1, Q931_FACILITY, buffer, i, NULL, NULL);
if (res) {
- pri_message(pri, "Could not queue ADPU in facility message\n");
+ pri_message(pri, "Could not queue APDU in facility message\n");
return -1;
}
@@ -1110,7 +1254,7 @@
/* code below is untested */
res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
if (res) {
- pri_message(pri, "Could not queue ADPU in facility message\n");
+ pri_message(pri, "Could not queue APDU in facility message\n");
return -1;
}
@@ -1305,6 +1449,7 @@
return 0;
}
+#if 0
if (pri->localtype == PRI_NETWORK) {
switch (pri->switchtype) {
case PRI_SWITCH_NI2:
@@ -1324,6 +1469,10 @@
}
return 0;
}
+#else
+ if (pri->switchtype == PRI_SWITCH_NI2)
+ add_callername_facility_ies(pri, call, (pri->localtype == PRI_CPE));
+#endif
return 0;
}
Modified: trunk/pri_facility.h
URL: http://svn.digium.com/view/libpri/trunk/pri_facility.h?rev=286&r1=285&r2=286&view=diff
==============================================================================
--- trunk/pri_facility.h (original)
+++ trunk/pri_facility.h Thu Jan 5 14:50:51 2006
@@ -146,7 +146,7 @@
break; \
(component) = (struct rose_component*)&((ptr)[idx]); \
if ((idx)+(component)->len+2 > (length)) { \
- if ((component)->len != 128) \
+ if ((component)->len != ASN1_LEN_INDEF) \
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
}
/*
@@ -169,6 +169,7 @@
#define CHECK_COMPONENT(component, comptype, message) \
if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
pri_message(pri, (message), (component)->type); \
+ asn1_dump(pri, (component), (component)->len+2); \
break; \
}
@@ -249,7 +250,7 @@
/* starts a 2BCT */
extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
-/* Use this function to queue a facility-IE born ADPU onto a call
+/* Use this function to queue a facility-IE born APDU onto a call
* call is the call to use, messagetype is any one of the Q931 messages,
* apdu is the apdu data, apdu_len is the length of the apdu data */
extern int pri_call_apdu_queue(q931_call *call, int messagetype, void *apdu, int apdu_len, void (*function)(void *data), void *data);
@@ -257,7 +258,9 @@
/* Used by q931.c to cleanup the apdu queue upon destruction of a call */
extern int pri_call_apdu_queue_cleanup(q931_call *call);
-/* Adds the "standard" ADPUs to a call */
+/* Adds the "standard" APDUs to a call */
extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
+int asn1_dump(struct pri *pri, void *comp, int len);
+
#endif /* _PRI_FACILITY_H */
Modified: trunk/pri_q931.h
URL: http://svn.digium.com/view/libpri/trunk/pri_q931.h?rev=286&r1=285&r2=286&view=diff
==============================================================================
--- trunk/pri_q931.h (original)
+++ trunk/pri_q931.h Thu Jan 5 14:50:51 2006
@@ -243,6 +243,10 @@
/* EuroISDN */
#define Q931_SENDING_COMPLETE 0xa1
+
+/* Q.SIG specific */
+#define QSIG_IE_TRANSIT_COUNT 0x31
+
extern int q931_receive(struct pri *pri, q931_h *h, int len);
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
Modified: trunk/q931.c
URL: http://svn.digium.com/view/libpri/trunk/q931.c?rev=286&r1=285&r2=286&view=diff
==============================================================================
--- trunk/q931.c (original)
+++ trunk/q931.c Thu Jan 5 14:50:51 2006
@@ -1119,22 +1119,21 @@
int i = 0;
for (tmp = call->apdus; tmp; tmp = tmp->next) {
- if (tmp->message == msgtype)
- break;
- }
-
+ if ((tmp->message == msgtype) && !tmp->sent)
+ break;
+ }
+
if (!tmp) /* No APDU found */
return 0;
- if (tmp->apdu_len > 235) { /* TODO: find out how much sapce we can use */
- pri_message(pri, "Requested ADPU (%d bytes) is too long\n", tmp->apdu_len);
-
-
+ if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */
+ pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len);
return 0;
}
- memcpy(ie->data, tmp->apdu, tmp->apdu_len);
+ memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len);
i += tmp->apdu_len;
+ tmp->sent = 1;
return i + 2;
}
@@ -1434,57 +1433,71 @@
}
}
-static void dump_ie_data(unsigned char *c, int len)
-{
- char tmp[1024] = "";
- int x=0;
+#define CHECK_OVERFLOW(limit) \
+ if (tmpptr - tmp + limit >= sizeof(tmp)) { \
+ *tmpptr = '\0'; \
+ pri_message(pri, "%s", tmpptr = tmp); \
+ }
+
+static void dump_ie_data(struct pri *pri, unsigned char *c, int len)
+{
+ static char hexs[16] = "0123456789ABCDEF";
+ char tmp[1024], *tmpptr;
int lastascii = 0;
- while(len) {
+ tmpptr = tmp;
+ for (; len; --len, ++c) {
+ CHECK_OVERFLOW(7);
if (isprint(*c)) {
if (!lastascii) {
- if (*tmp) {
- tmp[x++] = ',';
- tmp[x++] = ' ';
+ if (tmpptr != tmp) {
+ *tmpptr++ = ',';
+ *tmpptr++ = ' ';
}
- tmp[x++] = '\'';
+ *tmpptr++ = '\'';
+ lastascii = 1;
}
- tmp[x++] = *c;
- lastascii = 1;
+ *tmpptr++ = *c;
} else {
if (lastascii) {
- tmp[x++] = '\'';
+ *tmpptr++ = '\'';
+ lastascii = 0;
}
- if (*tmp) {
- tmp[x++] = ',';
- tmp[x++] = ' ';
+ if (tmpptr != tmp) {
+ *tmpptr++ = ',';
+ *tmpptr++ = ' ';
}
- sprintf (tmp + x, "0x%02x", *c);
- x += 4;
- lastascii = 0;
- }
- c++;
- len--;
+ *tmpptr++ = '0';
+ *tmpptr++ = 'x';
+ *tmpptr++ = hexs[(*c >> 4) & 0x0f];
+ *tmpptr++ = hexs[(*c) & 0x0f];
+ }
}
if (lastascii)
- tmp[x++] = '\'';
- pri_message(NULL, tmp);
+ *tmpptr++ = '\'';
+ *tmpptr = '\0';
+ pri_message(pri, "%s", tmp);
}
static FUNC_DUMP(dump_facility)
{
pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
- dump_ie_data(ie->data, ie->len);
+ dump_ie_data(pri, ie->data, ie->len);
pri_message(NULL, " ]\n");
+ if (ie->len > 1) {
+ pri_message(pri, "PROTOCOL %02X\n", ie->data[0] & ASN1_TYPE_MASK);
+ asn1_dump(pri, &ie->data[1], ie->len - 1);
+ }
+
}
static FUNC_DUMP(dump_network_spec_fac)
{
pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
if (ie->data[0] == 0x00) {
- pri_message(pri, code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
+ pri_message(pri, "%s", code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
}
else
- dump_ie_data(ie->data, ie->len);
+ dump_ie_data(pri, ie->data, ie->len);
pri_message(pri, " ]\n");
}
@@ -1925,6 +1938,17 @@
pri_message(pri, "Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]);
}
+static FUNC_DUMP(dump_transit_count)
+{
+ /* Defined in ECMA-225 */
+ pri_message(pri, "%c Transit Count (len=%02d): ", prefix, len);
+ if (len < 3) {
+ pri_message(pri, "Invalid length\n");
+ return;
+ }
+ pri_message(pri, "Count=%d (0x%02x)\n", ie->data[0] & 0x1f, ie->data[0] & 0x1f);
+}
+
struct ie ies[] = {
/* Codeset 0 - Common */
@@ -1954,7 +1978,7 @@
{ 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
{ 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
{ 1, Q931_PACKET_SIZE, "Packet Size" },
- { 1, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
+ { 0, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
{ 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
{ 1, Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
{ 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
@@ -1979,6 +2003,8 @@
{ 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" },
{ 1, Q931_IE_UPDATE, "Update" },
{ 1, Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
+ /* Codeset 4 - Q.SIG specific */
+ { 1, QSIG_IE_TRANSIT_COUNT | Q931_CODESET(4), "Transit Count", dump_transit_count },
/* Codeset 6 - Network specific */
{ 1, Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information },
{ 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility },
@@ -2090,14 +2116,14 @@
int full_ie = Q931_FULL_IE(codeset, ie->ie);
int base_ie;
- pri_message(NULL, "%c [", prefix);
- pri_message(NULL, "%02x", ie->ie);
+ pri_message(pri, "%c [", prefix);
+ pri_message(pri, "%02x", ie->ie);
if (!(ie->ie & 0x80)) {
- pri_message(NULL, " %02x", ielen(ie)-2);
+ pri_message(pri, " %02x", ielen(ie)-2);
for (x = 0; x + 2 < ielen(ie); ++x)
- pri_message(NULL, " %02x", ie->data[x]);
- }
- pri_message(NULL, "]\n");
+ pri_message(pri, " %02x", ie->data[x]);
+ }
+ pri_message(pri, "]\n");
/* Special treatment for shifts */
if((full_ie & 0xf0) == Q931_LOCKING_SHIFT)
@@ -2114,7 +2140,7 @@
return;
}
- pri_error(pri, "!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));
+ pri_error(pri, "!! %c Unknown IE %d (cs%d, len = %d)\n", prefix, Q931_IE_IE(base_ie), Q931_IE_CODESET(base_ie), ielen(ie));
}
static q931_call *q931_getcall(struct pri *pri, int cr)
@@ -2377,7 +2403,6 @@
int offset=0;
int x;
int codeset;
- struct apdu_event *facevent = c->apdus;
memset(buf, 0, sizeof(buf));
len = sizeof(buf);
@@ -2386,24 +2411,7 @@
x=0;
codeset = 0;
while(ies[x] > -1) {
- if (ies[x] == Q931_IE_FACILITY) {
- res = 0;
- while (facevent) {
- if (!facevent->sent && (facevent->message == msgtype)) {
- int tmpres;
- tmpres = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
- if (tmpres < 0) {
- pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
- return -1;
- }
- res += tmpres;
- facevent->sent = 1;
- }
- facevent = facevent->next;
- }
- } else {
- res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
- }
+ res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len, &codeset);
if (res < 0) {
pri_error(pri, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
Modified: trunk/testprilib.c
URL: http://svn.digium.com/view/libpri/trunk/testprilib.c?rev=286&r1=285&r2=286&view=diff
==============================================================================
--- trunk/testprilib.c (original)
+++ trunk/testprilib.c Thu Jan 5 14:50:51 2006
@@ -147,7 +147,7 @@
}
}
-static void testmsg(char *s)
+static void testmsg(struct pri *pri, char *s)
{
char *c;
static int keeplast = 0;
@@ -173,7 +173,7 @@
keeplast = 0;
}
-static void testerr(char *s)
+static void testerr(struct pri *pri, char *s)
{
char *c;
static int keeplast = 0;
@@ -264,6 +264,7 @@
}
first = pri;
pri_set_debug(pri, DEBUG_LEVEL);
+ pri_facility_enable(pri);
if (pthread_create(&tmp, NULL, dchan, pri)) {
perror("thread(0)");
exit(1);
@@ -273,6 +274,7 @@
exit(1);
}
pri_set_debug(pri, DEBUG_LEVEL);
+ pri_facility_enable(pri);
if (pthread_create(&tmp, NULL, dchan, pri)) {
perror("thread(1)");
exit(1);
More information about the svn-commits
mailing list