From cd9d536d92b9ba4f6c010ca9decade5a4e5dc04a Mon Sep 17 00:00:00 2001
From: Richard Fuchs <rfuchs@sipwise.com>
Date: Mon, 2 Dec 2013 10:15:25 -0500
Subject: [PATCH] return type of decoded inap arg

---
 include/libtcap.h |  3 ++-
 src/tcap.c        | 35 ++++++++++++++++++-----------------
 tests/basic.c     |  5 +++--
 3 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/include/libtcap.h b/include/libtcap.h
index c55ae06..ee2d32f 100644
--- a/include/libtcap.h
+++ b/include/libtcap.h
@@ -4,10 +4,11 @@
 
 #include "TCMessage.h"
 #include "Invoke.h"
+#include "constr_TYPE.h"
 
 
 TCMessage_t *tcap_decode(const char *buf, size_t len);
-void *inap_decode(Invoke_t *invoke);
+void *inap_decode(Invoke_t *invoke, asn_TYPE_descriptor_t **);
 
 
 #endif
diff --git a/src/tcap.c b/src/tcap.c
index 417fd3c..5b05eca 100644
--- a/src/tcap.c
+++ b/src/tcap.c
@@ -13,11 +13,20 @@
 
 
 
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
+
 #define INVOKE_OPCODE_INITIALDP				0
 #define INVOKE_OPCODE_CONNECT				20
 #define INVOKE_OPCODE_FURNISHCHARGINGINFORMATION	34
 
 
+static asn_TYPE_descriptor_t *opcode_type_map[] = {
+	[INVOKE_OPCODE_INITIALDP]			= &asn_DEF_InitialDPArg,
+	[INVOKE_OPCODE_CONNECT]				= &asn_DEF_ConnectArg,
+	[INVOKE_OPCODE_FURNISHCHARGINGINFORMATION]	= &asn_DEF_FurnishChargingInformationArg,
+};
+
+
 
 TCMessage_t *tcap_decode(const char *buf, size_t len) {
 	TCMessage_t *ret = NULL;
@@ -32,12 +41,12 @@ TCMessage_t *tcap_decode(const char *buf, size_t len) {
 	return NULL;
 }
 
-void *inap_decode(Invoke_t *invoke) {
+void *inap_decode(Invoke_t *invoke, asn_TYPE_descriptor_t **type) {
 	long opcode;
 	int rv;
 	void *arg = 0;
 
-	if (!invoke || !invoke->parameter)
+	if (!invoke || !invoke->parameter || !type)
 		goto nothing;
 
 	if (invoke->opCode.present != OPERATION_PR_localValue)
@@ -46,28 +55,20 @@ void *inap_decode(Invoke_t *invoke) {
 	if (asn_INTEGER2long(&invoke->opCode.choice.localValue, &opcode))
 		goto nothing;
 
-	switch (opcode) {
-		case INVOKE_OPCODE_INITIALDP:
-			rv = ANY_to_type(invoke->parameter, &asn_DEF_InitialDPArg, &arg);
-			break;
-
-		case INVOKE_OPCODE_CONNECT:
-			rv = ANY_to_type(invoke->parameter, &asn_DEF_ConnectArg, &arg);
-			break;
+	if (opcode >= ARRAY_SIZE(opcode_type_map))
+		goto nothing;
 
-		case INVOKE_OPCODE_FURNISHCHARGINGINFORMATION:
-			rv = ANY_to_type(invoke->parameter, &asn_DEF_FurnishChargingInformationArg, &arg);
-			break;
+	*type = opcode_type_map[opcode];
 
-		default:
-			goto nothing;
-	}
+	rv = ANY_to_type(invoke->parameter, *type, &arg);
 
 	if (!rv)
 		return arg;
 
-	/* free struct */
+	if (arg)
+		(*type)->free_struct(*type, arg, 0);
 
 nothing:
+	*type = NULL;
 	return NULL;
 }
diff --git a/tests/basic.c b/tests/basic.c
index 6f017f0..868fdff 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -15,6 +15,7 @@ int main() {
 	Component_t *component;
 	int i;
 	void *arg;
+	asn_TYPE_descriptor_t *type;
 
 	tcm = tcap_decode(tcap, tcap_len);
 
@@ -65,8 +66,8 @@ int main() {
 
 				case Component_PR_invoke:
 					printf("invoke\n");
-					arg = inap_decode(&component->choice.invoke);
-					printf("arg: %p\n", arg);
+					arg = inap_decode(&component->choice.invoke, &type);
+					printf("arg: type %s -> %p\n", type ? type->name : "n/a", arg);
 					break;
 
 				case Component_PR_returnResultLast: