[libss7-commits] mattf: branch mattf/bug13495 r217 - /team/mattf/bug13495/

SVN commits to the libss7 project libss7-commits at lists.digium.com
Wed Oct 15 16:59:19 CDT 2008


Author: mattf
Date: Wed Oct 15 16:59:19 2008
New Revision: 217

URL: http://svn.digium.com/view/libss7?view=rev&rev=217
Log:
Put in libss7-20080930-full.patch from bug #13495

Modified:
    team/mattf/bug13495/isup.c
    team/mattf/bug13495/isup.h
    team/mattf/bug13495/libss7.h
    team/mattf/bug13495/ss7.c
    team/mattf/bug13495/ss7_internal.h
    team/mattf/bug13495/ss7linktest.c

Modified: team/mattf/bug13495/isup.c
URL: http://svn.digium.com/view/libss7/team/mattf/bug13495/isup.c?view=diff&rev=217&r1=216&r2=217
==============================================================================
--- team/mattf/bug13495/isup.c (original)
+++ team/mattf/bug13495/isup.c Wed Oct 15 16:59:19 2008
@@ -31,6 +31,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <time.h>
 #include "libss7.h"
 #include "isup.h"
 #include "ss7_internal.h"
@@ -58,13 +59,21 @@
 	FUNC_SEND(*transmit);
 };
 
+struct isup_timer_param {
+	struct ss7 *ss7;
+	struct isup_call *c;
+	int timer;
+};
+
 static int iam_params[] = {ISUP_PARM_NATURE_OF_CONNECTION_IND, ISUP_PARM_FORWARD_CALL_IND, ISUP_PARM_CALLING_PARTY_CAT,
-	ISUP_PARM_TRANSMISSION_MEDIUM_REQS, ISUP_PARM_CALLED_PARTY_NUM, ISUP_PARM_CALLING_PARTY_NUM, -1};
+	ISUP_PARM_TRANSMISSION_MEDIUM_REQS, ISUP_PARM_CALLED_PARTY_NUM, ISUP_PARM_CALLING_PARTY_NUM, ISUP_PARM_REDIRECTING_NUMBER,
+	ISUP_PARM_REDIRECTION_INFO, ISUP_PARM_REDIRECT_COUNTER, ISUP_PARM_ORIGINAL_CALLED_NUM, -1};
 
 static int ansi_iam_params[] = {ISUP_PARM_NATURE_OF_CONNECTION_IND, ISUP_PARM_FORWARD_CALL_IND, ISUP_PARM_CALLING_PARTY_CAT,
 	ISUP_PARM_USER_SERVICE_INFO, ISUP_PARM_CALLED_PARTY_NUM, ISUP_PARM_CALLING_PARTY_NUM, ISUP_PARM_CHARGE_NUMBER, 
 	ISUP_PARM_ORIG_LINE_INFO, ISUP_PARM_GENERIC_ADDR, ISUP_PARM_GENERIC_DIGITS, ISUP_PARM_GENERIC_NAME, ISUP_PARM_JIP, 
-	ISUP_PARM_LOCAL_SERVICE_PROVIDER_IDENTIFICATION, -1};
+	ISUP_PARM_LOCAL_SERVICE_PROVIDER_IDENTIFICATION, ISUP_PARM_REDIRECTION_INFO, ISUP_PARM_REDIRECTING_NUMBER, ISUP_PARM_REDIRECT_COUNTER,
+	ISUP_PARM_ORIGINAL_CALLED_NUM, -1};
 
 
 static int acm_params[] = {ISUP_PARM_BACKWARD_CALL_IND, -1};
@@ -88,6 +97,14 @@
 static int cicgroup_params[] = { ISUP_PARM_CIRCUIT_GROUP_SUPERVISION_IND, ISUP_PARM_RANGE_AND_STATUS, -1};
 
 static int cqr_params[] = { ISUP_PARM_RANGE_AND_STATUS, ISUP_PARM_CIRCUIT_STATE_IND, -1};
+
+static int susres_params[] = { ISUP_PARM_SUSRES_IND, ISUP_PARM_CALL_REF, -1};
+
+static int inr_params[] = { ISUP_PARM_INR_IND, -1};
+
+static int inf_params[] = { ISUP_PARM_INF_IND, ISUP_PARM_CALLING_PARTY_NUM, ISUP_PARM_CALLING_PARTY_CAT, -1};
+
+static int sam_params[] = { ISUP_PARM_SUBSEQUENT_NUMBER, -1};
 
 static int empty_params[] = { -1};
 
@@ -126,10 +143,20 @@
 	{ISUP_CQR, 0, 2, 0, cqr_params},
 	{ISUP_FAA, 1, 0, 1, faa_params},
 	{ISUP_FAR, 1, 0, 1, far_params},
-	{ISUP_CFN, 0, 1, 0, rel_params}
+	{ISUP_CFN, 0, 1, 0, rel_params},
+	{ISUP_SUS, 1, 0, 1, susres_params},
+	{ISUP_RES, 1, 0, 1, susres_params},
+	{ISUP_INR, 1, 0, 0, inr_params},
+	{ISUP_INF, 1, 0, 2, inf_params},
+	{ISUP_SAM, 0, 1, 0, sam_params}
 };
 
 static int isup_send_message(struct ss7 *ss7, struct isup_call *c, int messagetype, int parms[]);
+
+static int isup_start_timer(struct ss7 *ss7, struct isup_call *c, int timer);
+static void isup_stop_all_timers(struct ss7 *ss7, struct isup_call *c);
+static int isup_timer2str(int timer, char *res);
+static void isup_stop_timer(struct ss7 *ss7, struct isup_call *c, int timer);
 
 static char * message2str(unsigned char message)
 {
@@ -188,6 +215,16 @@
 			return "CVR";
 		case ISUP_CFN:
 			return "CFN";
+		case ISUP_SUS:
+			return "SUS";
+		case ISUP_RES:
+			return "RES";
+		case ISUP_INR:
+			return "INR";
+		case ISUP_INF:
+			return "INF";
+		case ISUP_SAM:
+			return "SAM";
 		default:
 			return "Unknown";
 	}
@@ -846,15 +883,9 @@
 
 	statuslen = (numcics / 8) + !!(numcics % 8);
 
-	if (messagetype == ISUP_GRA) {
-		for (i = 0; i < statuslen; i++) {
-			parm[1 + i] = 0;
-		}
-	} else {
-		for (i = 0; i < numcics; i++) {
-			if (c->status[i])
-				parm[1 + (i/8)] |= (1 << (i % 8));
-		}
+	for (i = 0; i < numcics; i++) {
+		if (c->status[i])
+			parm[1 + (i/8)] |= (1 << (i % 8));
 	}
 
 	return statuslen + 1;
@@ -896,13 +927,20 @@
 {
 	int oddeven, datalen;
 
-	if (!c->calling_party_num[0])
+	if (!c->calling_party_num[0] && c->presentation_ind != SS7_PRESENTATION_ADDR_NOT_AVAILABLE)
 		return 0;
 
-	isup_put_number(&parm[2], c->calling_party_num, &datalen, &oddeven);
+	if (c->calling_party_num[0] && c->presentation_ind != SS7_PRESENTATION_ADDR_NOT_AVAILABLE)
+		isup_put_number(&parm[2], c->calling_party_num, &datalen, &oddeven);
+	else {
+		datalen = 0;
+		oddeven = 0;
+		c->calling_nai = 0;
+	}
 
 	parm[0] = (oddeven << 7) | c->calling_nai;      /* Nature of Address Indicator */
-	parm[1] = (1 << 4) |                            /* Assume E.164 ISDN numbering plan, calling number complete */
+	 /* Assume E.164 ISDN numbering plan, calling number complete */
+	parm[1] = ((c->presentation_ind == SS7_PRESENTATION_ADDR_NOT_AVAILABLE) ? 0 : (1 << 4)) |
 		((c->presentation_ind & 0x3) << 2) |
 		(c->screening_ind & 0x3);
 
@@ -1394,7 +1432,7 @@
 
 	switch ((parm[1] >> 4) & 0xf) {
 		case 0:
-			orig_redir_reas = "Unknown/not available";
+			redir_reas = "Unknown/not available";
 			break;
 		case 1:
 			redir_reas = "User busy";
@@ -1426,11 +1464,21 @@
 
 static FUNC_RECV(redirection_info_receive)
 {
+	c->redirect_info = 1;
+	c->redirect_info_ind = parm[0] & 0x7;
+	c->redirect_info_orig_reas = (parm[0] >> 4) & 0xf;
+	c->redirect_info_counter = parm[1] & 0x7;
+	c->redirect_info_reas = (parm[1] >> 4) & 0xf;
 	return 2;
 }
 
 static FUNC_SEND(redirection_info_transmit)
 {
+	if (!c->redirect_info)
+		return 0;
+
+	parm[0] = (c->redirect_info_ind & 0x7) | ((c->redirect_info_orig_reas << 4) & 0xf0);
+	parm[1] = (c->redirect_info_counter & 0x7) | ((c->redirect_info_reas << 4) & 0xf0); 
 	return 2;
 }
 
@@ -1607,7 +1655,19 @@
 
 static FUNC_SEND(original_called_num_transmit)
 {
-	return len;
+	int oddeven, datalen;
+
+	if (!c->orig_called_num[0])
+		return 0;
+
+	isup_put_number(&parm[2], c->orig_called_num, &datalen, &oddeven);
+
+	parm[0] = (oddeven << 7) | c->orig_called_nai;      /* Nature of Address Indicator */
+	parm[1] = (1 << 4) |                            /* Assume E.164 ISDN numbering plan, calling number complete */
+		((c->orig_called_pres_ind & 0x3) << 2) |
+		(c->orig_called_screening_ind & 0x3);
+
+	return datalen + 2;
 }
 
 static FUNC_DUMP(echo_control_info_dump)
@@ -1955,8 +2015,110 @@
 
 static FUNC_SEND(redirecting_number_transmit)
 {
-	return 0;	
+	int oddeven, datalen;
+
+	if (!c->redirecting_num[0])
+		return 0;
+
+	isup_put_number(&parm[2], c->redirecting_num, &datalen, &oddeven);
+	parm[0] = (oddeven << 7) | c->redirecting_num_nai;      /* Nature of Address Indicator */
+	parm[1] = (1 << 4) |                            /* Assume E.164 ISDN numbering plan, calling number complete */
+		((c->redirecting_num_presentation_ind & 0x3) << 2) |
+		(c->redirecting_num_screening_ind & 0x3);
+
+	return datalen + 2;
 }	
+
+static FUNC_DUMP(redirect_counter_dump)
+{
+	ss7_message(ss7, "\t\t\tRedirect count: %i\n", parm[0] & 0x1f);
+	return 1;
+}
+
+static FUNC_RECV(redirect_counter_receive)
+{
+	c->redirect_counter = parm[0] & 0x1f;
+	return 1;
+}
+
+static FUNC_SEND(redirect_counter_transmit)
+{
+	if (!c->redirect_counter)
+		return 0;
+
+	parm[0] = c->redirect_counter & 0x1f;
+	return 1;
+}
+
+static FUNC_DUMP(susres_ind_dump)
+{
+	ss7_message(ss7, "\t\t\tSUS/RES indicator: %s (%i)\n", (parm[0] & 1) ? "network initiated" : "ISDN subscriber initiated", parm[0] & 1);
+	return 1;
+}
+
+static FUNC_RECV(susres_ind_receive)
+{
+	c->susres_ind = parm[0] & 1;
+	return 1;
+}
+
+static FUNC_SEND(susres_ind_transmit)
+{
+	parm[0] = c->susres_ind & 1;
+	return 1;
+}
+
+static FUNC_DUMP(inr_ind_dump)
+{
+	ss7_message(ss7, "\t\t\tCalling party address %srequested\n", (parm[0] & 0x1) ? "" : "not ");
+	ss7_message(ss7, "\t\t\tHolding %srequested\n", (parm[0] & 0x2) ? "" : "not ");
+	ss7_message(ss7, "\t\t\tCalling party category %srequested\n", (parm[0] & 0x8) ? "" : "not ");
+	ss7_message(ss7, "\t\t\tCharge information %srequested\n", (parm[0] & 0x10) ? "" : "not ");
+	ss7_message(ss7, "\t\t\tMalicous call identification %srequested\n", (parm[0] & 0x80) ? "" : "not ");
+	return 2;
+}
+
+static FUNC_RECV(inr_ind_receive)
+{
+	c->inr_ind[0] = parm[0];
+	c->inr_ind[1] = parm[1];
+	return 2;
+}
+
+static FUNC_SEND(inr_ind_transmit)
+{
+	parm[0] = c->inr_ind[0];
+	parm[1] = c->inr_ind[1];
+	return 2;
+}
+
+static FUNC_DUMP(inf_ind_dump)
+{
+	ss7_message(ss7, "\t\t\tCalling party address: %s\n",
+		(parm[0] & 0x2) ? ((parm[0] & 0x1) ? "included" : "spare" ) : ((parm[0] & 0x1) ? "not available" : "not included") );
+	ss7_message(ss7, "\t\t\tHold: %sprovided\n", (parm[0] & 0x4) ? "" : "not ");
+	ss7_message(ss7, "\t\t\tCalling party's category %sincluded\n", (parm[0] & 0x20) ? "" : "not ");
+	ss7_message(ss7, "\t\t\tCharge information %sincluded\n", (parm[0] & 0x40) ? "" : "not ");
+	ss7_message(ss7, "\t\t\t%s\n", (parm[0] & 0x80) ? "Unsolicated" : "Solicated");
+
+	return 2;
+}
+
+static FUNC_RECV(inf_ind_receive)
+{
+	c->inf_ind[0] = parm[0];
+	c->inf_ind[1] = parm[1];
+	if((parm[0] & 0x3) == 0x1)
+		c->presentation_ind = SS7_PRESENTATION_ADDR_NOT_AVAILABLE;
+	return 2;	
+}
+
+static FUNC_SEND(inf_ind_transmit)
+{
+	parm[0] = c->inf_ind[0];
+	parm[1] = c->inf_ind[1];
+	return 2;
+}
 
 static FUNC_DUMP(access_transport_dump)
 {
@@ -1972,6 +2134,35 @@
 	return len;	
 }	
 
+static FUNC_DUMP(subs_num_dump)
+{
+	int oddeven = (parm[0] >> 7) & 0x1;
+	char numbuf[64];
+
+	isup_get_number(numbuf, &parm[1], len - 1, oddeven);
+	ss7_message(ss7, "\t\t\tSubsequent signals: %s\n", numbuf);
+	
+	return len;
+}
+
+static FUNC_RECV(subs_num_receive)
+{
+	int oddeven = (parm[0] >> 7) & 0x1;
+
+	isup_get_number(c->called_party_num, &parm[1], len - 1, oddeven);
+
+	return len;
+}
+
+static FUNC_SEND(subs_num_transmit)
+{
+	int oddeven, datalen;
+
+	isup_put_number(&parm[1], c->called_party_num, &datalen, &oddeven);
+	parm[0] = (oddeven << 7);
+
+	return datalen + 1;
+}
 
 static struct parm_func parms[] = {
 	{ISUP_PARM_NATURE_OF_CONNECTION_IND, "Nature of Connection Indicator", nature_of_connection_ind_dump, nature_of_connection_ind_receive, nature_of_connection_ind_transmit },
@@ -2018,6 +2209,11 @@
 	{ISUP_PARM_FACILITY_IND, "Facility Indicator", facility_ind_dump, facility_ind_receive, facility_ind_transmit},
 	{ISUP_PARM_REDIRECTING_NUMBER, "Redirecting Number", redirecting_number_dump, redirecting_number_receive, redirecting_number_transmit},
 	{ISUP_PARM_ACCESS_DELIVERY_INFO, "Access Delivery Information", },
+	{ISUP_PARM_REDIRECT_COUNTER, "Redirect Counter", redirect_counter_dump, redirect_counter_receive, redirect_counter_transmit},
+	{ISUP_PARM_SUSRES_IND, "SUS/RES Indicator", susres_ind_dump, susres_ind_receive, susres_ind_transmit},
+	{ISUP_PARM_INR_IND, "Information Request Indicators", inr_ind_dump, inr_ind_receive, inr_ind_transmit},
+	{ISUP_PARM_INF_IND, "Information Indicators", inf_ind_dump, inf_ind_receive, inf_ind_transmit},
+	{ISUP_PARM_SUBSEQUENT_NUMBER, "Subsequent Number", subs_num_dump, subs_num_receive, subs_num_transmit}
 };
 
 static char * param2str(int parm)
@@ -2033,7 +2229,12 @@
 
 static void init_isup_call(struct isup_call *c)
 {
+	int x;
+	for(x = 0; x < ISUP_MAX_TIMERS; x++)
+		c->timer[x] = -1;
 	c->oli_ani2 = -1;
+	c->range = 0;
+	c->got_sent_msg = 0;
 }
 
 static struct isup_call * __isup_new_call(struct ss7 *ss7, int nolink)
@@ -2079,7 +2280,6 @@
 			snprintf(c->called_party_num, sizeof(c->called_party_num), "%s", called);
 		c->called_nai = called_nai;
 	}
-
 }
 
 void isup_set_oli(struct isup_call *c, int oli_ani2)
@@ -2089,11 +2289,45 @@
 
 void isup_set_calling(struct isup_call *c, const char *calling, unsigned char calling_nai, unsigned char presentation_ind, unsigned char screening_ind)
 {
-	if (calling && calling[0]) {
-		strncpy(c->calling_party_num, calling, sizeof(c->calling_party_num));
+	if ((calling && calling[0]) || presentation_ind == SS7_PRESENTATION_ADDR_NOT_AVAILABLE) {
+		if(calling)
+			strncpy(c->calling_party_num, calling, sizeof(c->calling_party_num));
 		c->calling_nai = calling_nai;
 		c->presentation_ind = presentation_ind;
 		c->screening_ind = screening_ind;
+	}
+}
+
+void isup_set_redirecting_number(struct isup_call *c, const char *redirecting_number, unsigned char redirecting_num_nai, unsigned char redirecting_num_presentation_ind, unsigned char redirecting_num_screening_ind)
+{
+	if (redirecting_number && redirecting_number[0]) {
+		strncpy(c->redirecting_num, redirecting_number, sizeof(c->redirecting_num));
+		c->redirecting_num_nai = redirecting_num_nai;
+		c->redirecting_num_presentation_ind = redirecting_num_presentation_ind;
+		c->redirecting_num_screening_ind = redirecting_num_screening_ind;
+	}
+}
+
+void isup_set_redirectiong_info(struct isup_call *c, unsigned char redirect_info_ind, unsigned char redirect_info_orig_reas,
+	unsigned char redirect_info_counter, unsigned char redirect_info_reas)
+{
+	c->redirect_info = 1;
+	c->redirect_info_ind = redirect_info_ind;
+	c->redirect_info_orig_reas = redirect_info_orig_reas;
+	c->redirect_info_counter = redirect_info_counter;
+	c->redirect_info_reas = redirect_info_reas;
+}
+
+void isup_set_redirect_counter(struct isup_call *c, unsigned char redirect_counter) {
+	c->redirect_counter = redirect_counter;
+}
+
+void isup_set_orig_called_num(struct isup_call *c, const char *orig_called_num, unsigned char orig_called_nai, unsigned char orig_called_pres_ind, unsigned char orig_called_screening_ind) {
+	if(orig_called_num && orig_called_num[0]) {
+		strncpy(c->orig_called_num, orig_called_num, sizeof(c->orig_called_num));
+		c->orig_called_nai = orig_called_nai;
+		c->orig_called_pres_ind = orig_called_pres_ind;
+		c->orig_called_screening_ind = orig_called_screening_ind;
 	}
 }
 
@@ -2194,9 +2428,12 @@
 	return winner;
 }
 
-static void isup_free_call(struct ss7 *ss7, struct isup_call *c)
+void isup_free_call(struct ss7 *ss7, struct isup_call *c)
 {
 	struct isup_call *cur, *prev = NULL, *winner = NULL;
+	
+	if (!ss7 || !c)
+		return;
 
 	cur = ss7->calls;
 	while (cur) {
@@ -2213,9 +2450,12 @@
 			ss7->calls = winner->next;
 		else
 			prev->next = winner->next;
-	}
-
-	free(c);
+
+		isup_stop_all_timers(ss7, c);
+		free(c);
+	} else
+		ss7_error(ss7, "Requested free an unlinked call!!!\n");
+
 
 	return;
 }
@@ -2579,6 +2819,33 @@
 	return 0;
 }
 
+/* Checking we whether got more 1 bits back in the status */
+static int isup_check_status(unsigned char *sent_status, unsigned char *got_status, int range)
+{
+	int i;
+	for (i = 0; i <= range; i++)
+		if (got_status[i] > sent_status[i])
+			return 1;
+
+	return 0;
+}
+
+static int isup_handle_unexpected (struct ss7 *ss7, struct isup_call *c, unsigned int opc) {
+	int res;
+
+	if (c->got_sent_msg & (ISUP_CALL_CONNECTED)) {
+		ss7_message(ss7, "ignoring... \n");
+	} else {
+		ss7_message(ss7, "reseting the cic\n");
+		res = ss7_hangup(ss7, c->cic, opc, 16, SS7_HANGUP_SEND_RSC);
+		if(res == SS7_CIC_IDLE)
+			isup_rsc(ss7, c);
+		else if (res == SS7_CIC_NOT_EXISTS)
+			isup_free_call(ss7, c);
+	}
+		return 0;
+}
+
 int isup_receive(struct ss7 *ss7, struct mtp2 *link, struct routing_label *rl, unsigned char *buf, int len)
 {
 	unsigned short cic;
@@ -2630,30 +2897,7 @@
 		}
 	}
 
-	/* Make sure we don't hijack a call associated isup_call for non call
-	 * associated messages */
-	switch (mh->type) {
-		/* All of these messages are ones where a persistent call is associated with them and
-		should not generate a new, unlinked call, or free a call (unless explicitly done, link in RLC) */
-		case ISUP_IAM:
-		case ISUP_ANM:
-		case ISUP_ACM:
-		case ISUP_CPG:
-		case ISUP_COT:
-		case ISUP_CON:
-		case ISUP_REL:
-		case ISUP_RLC:
-		case ISUP_RSC:
-		case ISUP_FAA:
-		case ISUP_FAR:
-			c = isup_find_call(ss7, rl, cic);
-			break;
-		default:
-			c = __isup_new_call(ss7, 1);
-			c->dpc = rl->opc;
-			c->cic = cic;
-			break;
-	}
+	c = isup_find_call(ss7, rl, cic);
 
 	if (!c) {
 		ss7_error(ss7, "Huh? No call!!!???\n");
@@ -2714,58 +2958,71 @@
 
 	switch (mh->type) {
 		case ISUP_IAM:
+			return isup_event_iam(ss7, c, opc);
+		case ISUP_SAM:
+			if(c->got_sent_msg != ISUP_GOT_IAM) {
+				ss7_message(ss7, "Got unexpected SAM  on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
 
-			e->e = ISUP_EVENT_IAM;
-			e->iam.cic = c->cic;
-			e->iam.transcap = c->transcap;
-			e->iam.cot_check_required = c->cot_check_required;
-			strncpy(e->iam.called_party_num, c->called_party_num, sizeof(e->iam.called_party_num));
-			e->iam.called_nai = c->called_nai;
-			strncpy(e->iam.calling_party_num, c->calling_party_num, sizeof(e->iam.calling_party_num));
-			e->iam.calling_nai = c->calling_nai;
-			e->iam.presentation_ind = c->presentation_ind;
-			e->iam.screening_ind = c->screening_ind;
-			strncpy(e->iam.charge_number, c->charge_number, sizeof(e->iam.charge_number));
-			e->iam.charge_nai = c->charge_nai;
-			e->iam.charge_num_plan = c->charge_num_plan;
-			e->iam.oli_ani2 = c->oli_ani2;
-			e->iam.gen_add_nai = c->gen_add_nai;
-			e->iam.gen_add_num_plan = c->gen_add_num_plan;
-			strncpy(e->iam.gen_add_number, c->gen_add_number, sizeof(e->iam.gen_add_number));
-			e->iam.gen_add_pres_ind = c->gen_add_pres_ind;
-			e->iam.gen_add_type = c->gen_add_type;
-			strncpy(e->iam.gen_dig_number, c->gen_dig_number, sizeof(e->iam.gen_dig_number));
-			e->iam.gen_dig_type = c->gen_dig_type;
-			e->iam.gen_dig_scheme = c->gen_dig_scheme;
-			strncpy(e->iam.jip_number, c->jip_number, sizeof(e->iam.jip_number));
-			strncpy(e->iam.generic_name, c->generic_name, sizeof(e->iam.generic_name));
-			e->iam.generic_name_typeofname = c->generic_name_typeofname;
-			e->iam.generic_name_avail = c->generic_name_avail;
-			e->iam.generic_name_presentation = c->generic_name_presentation;
-			e->iam.lspi_type = c->lspi_type;
-			e->iam.lspi_scheme = c->lspi_scheme;
-			e->iam.lspi_context = c->lspi_context;
-			strncpy(e->iam.lspi_ident, c->lspi_ident, sizeof(e->iam.lspi_ident));
-			strncpy(e->iam.orig_called_num, c->orig_called_num, sizeof(e->iam.orig_called_num));
-			e->iam.orig_called_nai = c->orig_called_nai;
-			e->iam.orig_called_pres_ind = c->orig_called_pres_ind;
-			e->iam.orig_called_screening_ind = c->orig_called_screening_ind;
-			strncpy(e->iam.redirecting_num, c->redirecting_num, sizeof(e->iam.redirecting_num));
-			e->iam.redirecting_num_nai = c->redirecting_num_nai;
-			e->iam.redirecting_num_presentation_ind = c->redirecting_num_presentation_ind;
-			e->iam.redirecting_num_screening_ind = c->redirecting_num_screening_ind;
-			e->iam.calling_party_cat = c->calling_party_cat;
-			e->iam.call = c;
-			e->iam.opc = opc; /* keep OPC information */
+			e->e = ISUP_EVENT_SAM;
+			e->sam.cic = c->cic;
+			e->sam.call = c;
+			e->sam.opc = opc; /* keep OPC information */
+			strncpy(e->sam.called_party_num, c->called_party_num, sizeof(e->sam.called_party_num));
+			e->sam.called_nai = c->called_nai;
+			e->sam.got_sent_msg = c->got_sent_msg;
+			e->sam.cot_check_passed = c->cot_check_passed;
+			isup_start_timer(ss7, c, ISUP_TIMER_T35);
 			return 0;
+		case ISUP_INF:
+			if(!(c->got_sent_msg & ISUP_SENT_INR) && !(c->inf_ind[0] & 0x80)) {
+				ss7_message(ss7, "Got solicated INF but we didn't send INR on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+			if ((ss7->flags & SS7_INR_IF_NO_CALLING) && 
+				!c->calling_party_num[0] && 
+				c->presentation_ind != SS7_PRESENTATION_ADDR_NOT_AVAILABLE) {
+				isup_rel(ss7, c, 16);
+				return 0;
+			}
+
+			if(c->inf_ind[0] & 0x80) {
+				/* unsolicated */
+				if(!isup_free_call_if_clear(ss7, c))
+					ss7_call_null(ss7, c);
+				return 0;
+			} else {
+				isup_stop_timer(ss7, c, ISUP_TIMER_T33);
+				c->got_sent_msg &= ~ISUP_SENT_INR;
+				return isup_event_iam(ss7, c, opc);
+			}
+		case ISUP_INR:
+			if(!(c->got_sent_msg & ISUP_SENT_IAM)) {
+				ss7_message(ss7, "Got INF but no outgoing call on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
+			int inf_parm0 = 0x20; /* Calling party category included, solicated */
+			if(!c->calling_party_num[0])
+				inf_parm0 |= 0x1; /* Calling party address not available */
+			else
+				inf_parm0 |= 0x3; /* Calling party address included */
+			isup_inf(ss7, c, inf_parm0, 0);
+			if(!isup_free_call_if_clear(ss7, c))
+				ss7_call_null(ss7, c);
+			return(0);
 		case ISUP_CQM:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2774,11 +3031,12 @@
 			e->cqm.startcic = cic;
 			e->cqm.endcic = cic + c->range;
 			e->cqm.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c); /* Won't need this again */
+			e->cqm.call = c;
 			return 0;
 		case ISUP_GRS:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2786,12 +3044,23 @@
 			e->e = ISUP_EVENT_GRS;
 			e->grs.startcic = cic;
 			e->grs.endcic = cic + c->range;
-			isup_free_call(ss7, c); /* Won't need this again */
+			e->grs.call = c;
 			e->grs.opc = opc; /* keep OPC information */
 			return 0;
 		case ISUP_GRA:
+			if(!(c->got_sent_msg & ISUP_SENT_GRS)) {
+				ss7_message(ss7, "Got GRA but we didn't send GRS on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+			/* checking the answer */
+			if(c->range != c->sent_grs_endcic - c->cic) {
+				ss7_message(ss7, "Got GRA doesn't match with the sent GRS on CIC %d DPC %d\n", c->cic, opc);
+				return 0;
+			}
+	
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2802,41 +3071,61 @@
 			for (i = 0; i < (c->range + 1); i++)
 				e->gra.status[i] = c->status[i];
 			e->gra.opc = opc; /* keep OPC information */
-
-			isup_free_call(ss7, c); /* Won't need this again */
+			e->gra.call = c;
+			e->gra.sent_endcic = c->sent_grs_endcic;
+			e->gra.got_sent_msg = c->got_sent_msg;
+			c->got_sent_msg &= ~ISUP_SENT_GRS;
 			return 0;
 		case ISUP_RSC:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
-
+			isup_stop_all_timers(ss7, c);
 			e->e = ISUP_EVENT_RSC;
 			e->rsc.cic = cic;
 			e->rsc.call = c;
 			e->rsc.opc = opc; /* keep OPC information */
+			e->rsc.got_sent_msg = c->got_sent_msg;
+			c->got_sent_msg = 0;
 			return 0;
 		case ISUP_REL:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
 
+			isup_stop_timer(ss7, c, ISUP_TIMER_T7);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T2);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T6);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T35);
+			c->got_sent_msg &= ~(ISUP_CALL_CONNECTED | ISUP_SENT_IAM | ISUP_GOT_IAM | ISUP_GOT_CCR | ISUP_SENT_INR);
 			e->e = ISUP_EVENT_REL;
 			e->rel.cic = c->cic;
 			e->rel.call = c;
 			e->rel.cause = c->cause;
 			e->rel.opc = opc; /* keep OPC information */
+			e->rel.got_sent_msg = c->got_sent_msg;
 			return 0;
 		case ISUP_ACM:
+			if (!(c->got_sent_msg & ISUP_SENT_IAM)) {
+				ss7_message(ss7, "Got ACM but we didn't send IAM on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
 
+			isup_stop_timer(ss7, c, ISUP_TIMER_T7);
+			c->got_sent_msg |= ISUP_GOT_ACM;
 			e->e = ISUP_EVENT_ACM;
 			e->acm.cic = c->cic;
 			e->acm.call_ref_ident = c->call_ref_ident;
@@ -2844,34 +3133,58 @@
 			e->acm.call = c;
 			e->acm.opc = opc; /* keep OPC information */
 			e->acm.called_party_status_ind = c->called_party_status_ind;
+			e->acm.got_sent_msg = c->got_sent_msg;
 			return 0;
 		case ISUP_CON:
+			if (!(c->got_sent_msg & ISUP_SENT_IAM)) {
+				ss7_message(ss7, "Got CON but we didn't send IAM on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
 
+			isup_stop_timer(ss7, c, ISUP_TIMER_T7);
+			c->got_sent_msg |= ISUP_GOT_CON;
 			e->e = ISUP_EVENT_CON;
 			e->con.cic = c->cic;
 			e->con.call = c;
 			e->con.opc = opc; /* keep OPC information */
+			e->con.got_sent_msg = c->got_sent_msg;
 			return 0;
 		case ISUP_ANM:
+			if (!(c->got_sent_msg & ISUP_SENT_IAM)) {
+				ss7_message(ss7, "Got ANM but we didn't send IAM on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
 
+			c->got_sent_msg |= ISUP_GOT_ANM;
 			e->e = ISUP_EVENT_ANM;
 			e->anm.cic = c->cic;
 			e->anm.call = c;
 			e->anm.opc = opc; /* keep OPC information */
+			e->anm.got_sent_msg = c->got_sent_msg;
 			return 0;
 		case ISUP_RLC:
+			if (!(c->got_sent_msg & (ISUP_SENT_REL | ISUP_SENT_RSC))) {
+				ss7_message(ss7, "Got RLC but we didn't send REL/RSC on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2879,11 +3192,24 @@
 			e->e = ISUP_EVENT_RLC;
 			e->rlc.cic = c->cic;
 			e->rlc.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c);
+			e->rlc.call = c;
+			e->rlc.got_sent_msg = c->got_sent_msg;
+			c->got_sent_msg &= ~(ISUP_SENT_REL | ISUP_SENT_RSC);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T1);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T5);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T16);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T17);
 			return 0;
 		case ISUP_COT:
+			/* Got we CCR or CCR in IAM ?*/
+			if (!(c->got_sent_msg & ISUP_GOT_CCR)) {
+				ss7_message(ss7, "Got COT but we didn't got CCR previously on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2893,33 +3219,39 @@
 			e->cot.passed = c->cot_check_passed;
 			e->cot.call = c;
 			e->cot.opc = opc; /* keep OPC information */
+			e->cot.got_sent_msg = c->got_sent_msg;
+			c->got_sent_msg &= ~ISUP_GOT_CCR;
 			return 0;
 		case ISUP_CCR:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
-
+			c->got_sent_msg |= ISUP_GOT_CCR;
 			e->e = ISUP_EVENT_CCR;
 			e->ccr.cic = c->cic;
 			e->ccr.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c);
+			e->ccr.call = c;
+			e->ccr.got_sent_msg = c->got_sent_msg;
 			return 0;
 		case ISUP_CVT:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
 
 			e->e = ISUP_EVENT_CVT;
 			e->cvt.cic = c->cic;
-			isup_free_call(ss7, c);
+			e->cvt.call = c;
 			return 0;
 		case ISUP_BLO:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2927,11 +3259,13 @@
 			e->e = ISUP_EVENT_BLO;
 			e->blo.cic = c->cic;
 			e->blo.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c);
+			e->blo.call = c;
+			e->blo.got_sent_msg = c->got_sent_msg;
 			return 0;
 		case ISUP_UBL:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2939,23 +3273,35 @@
 			e->e = ISUP_EVENT_UBL;
 			e->ubl.cic = c->cic;
 			e->ubl.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c);
+			e->ubl.call = c;
 			return 0;
 		case ISUP_BLA:
+			if(!(c->got_sent_msg & ISUP_SENT_BLO)) {
+				ss7_message(ss7, "Got BLA but we didn't send BLO on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
+
+			isup_stop_timer(ss7, c, ISUP_TIMER_T12);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T13);
 
 			e->e = ISUP_EVENT_BLA;
 			e->bla.cic = c->cic;
 			e->bla.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c);
+			e->bla.call = c;
+			e->bla.got_sent_msg = c->got_sent_msg;
+			c->got_sent_msg &= ~ISUP_SENT_BLO;			
 			return 0;
 		case ISUP_LPA:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2963,23 +3309,35 @@
 			e->e = ISUP_EVENT_LPA;
 			e->lpa.cic = c->cic;
 			e->lpa.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c);
+			e->lpa.call = c;
 			return 0;
 		case ISUP_UBA:
+			if(!(c->got_sent_msg & ISUP_SENT_UBL)) {
+				ss7_message(ss7, "Got UBA but we didn't send UBL on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
+
+			isup_stop_timer(ss7, c, ISUP_TIMER_T14);
+			isup_stop_timer(ss7, c, ISUP_TIMER_T15);
+
 
 			e->e = ISUP_EVENT_UBA;
 			e->uba.cic = c->cic;
 			e->uba.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c);
+			e->uba.call = c;
+			e->uba.got_sent_msg = c->got_sent_msg;
+			c->got_sent_msg &= ~ISUP_SENT_UBL;
 			return 0;
 		case ISUP_CGB:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -2992,12 +3350,12 @@
 			for (i = 0; i < (c->range + 1); i++)
 				e->cgb.status[i] = c->status[i];
 			e->cgb.opc = opc; /* keep OPC information */
-
-			isup_free_call(ss7, c);
+			e->cgb.call = c;
 			return 0;
 		case ISUP_CGU:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -3010,24 +3368,32 @@
 			for (i = 0; i < (c->range + 1); i++)
 				e->cgu.status[i] = c->status[i];
 			e->cgu.opc = opc; /* keep OPC information */
-
-			isup_free_call(ss7, c);
+			e->cgu.call = c;
 			return 0;
 		case ISUP_CPG:
+			if (!(c->got_sent_msg & ISUP_SENT_IAM)) {
+				ss7_message(ss7, "Got CPG but we didn't send IAM on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
 
-			e->e = ISUP_EVENT_CPG;
+			e->e |= ISUP_EVENT_CPG;
 			e->cpg.cic = c->cic;
 			e->cpg.opc = opc; /* keep OPC information */
 			e->cpg.event = c->event_info;
+			e->cpg.call = c;
+			e->cpg.got_sent_msg = c->got_sent_msg;
 			return 0;
 		case ISUP_UCIC:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -3035,11 +3401,12 @@
 			e->e = ISUP_EVENT_UCIC;
 			e->ucic.cic = c->cic;
 			e->ucic.opc = opc; /* keep OPC information */
-			isup_free_call(ss7, c);
+			e->ucic.call = c;
 			return 0;
 		case ISUP_FAA:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -3054,6 +3421,7 @@
 		case ISUP_FAR:
 			e = ss7_next_empty_event(ss7);
 			if (!e) {
+				ss7_call_null(ss7, c);
 				isup_free_call(ss7, c);
 				return -1;
 			}
@@ -3065,29 +3433,216 @@
 			e->ucic.opc = opc; /* keep OPC information */
 			e->far.call = c;
 			return 0;
+		case ISUP_CGBA:
+			if(!(c->got_sent_msg & ISUP_SENT_CGB)) {
+				ss7_message(ss7, "Got CGBA but we didn't send CGB on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+			/* checking the answer */
+			if(c->range != c->sent_cgb_endcic - c->cic || c->cicgroupsupervisiontype != c->sent_cgb_type ||
+				isup_check_status(c->sent_cgb_status, c->status, c->range)) {
+				ss7_message(ss7, "Got CGBA doesn't match with the sent CGB on CIC %d DPC %d\n", c->cic, opc);
+				return 0;
+			}
+			e = ss7_next_empty_event(ss7);
+			if (!e) {
+				ss7_call_null(ss7, c);
+				isup_free_call(ss7, c);
+				return -1;
+			}
+			
+			e->e = ISUP_EVENT_CGBA;
+			e->cgba.startcic = c->cic;
+			e->cgba.endcic = c->cic + c->range;
+			e->cgba.sent_endcic = c->sent_cgb_endcic;
+			e->cgba.type = c->cicgroupsupervisiontype;
+			e->cgba.sent_type = c->sent_cgb_type;
+			for (i = 0; i < (c->range + 1); i++) {
+				e->cgba.status[i] = c->status[i];
+				e->cgba.sent_status[i] = c->sent_cgb_status[i];
+			}
+			e->cgba.got_sent_msg = c->got_sent_msg;
+			e->cgba.opc = opc;
+			e->cgba.call = c;
+			isup_clear_callflags(ss7, c, ISUP_SENT_CGB);
+			return 0;
+		case ISUP_CGUA:
+			if(!(c->got_sent_msg & ISUP_SENT_CGU)) {
+				ss7_message(ss7, "Got CGUA but we didn't send CGU on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+			/* checking the answer */
+			if(c->range != c->sent_cgu_endcic - c->cic || c->cicgroupsupervisiontype != c->sent_cgu_type ||
+				isup_check_status(c->sent_cgu_status, c->status, c->range)) {
+				ss7_message(ss7, "Got CGUA doesn't match with the sent CGU on CIC %d DPC %d\n", c->cic, opc);
+				return 0;
+			}
+
+			e = ss7_next_empty_event(ss7);
+			if (!e) {
+				ss7_call_null(ss7, c);
+				isup_free_call(ss7, c);
+				return -1;
+			}
+			
+			e->e = ISUP_EVENT_CGUA;
+			e->cgua.startcic = c->cic;
+			e->cgua.endcic = c->cic + c->range;
+			e->cgua.sent_endcic = c->sent_cgu_endcic;
+			e->cgua.type = c->cicgroupsupervisiontype;
+			e->cgua.sent_type = c->sent_cgu_type;
+			for (i = 0; i < (c->range + 1); i++) {
+				e->cgua.status[i] = c->status[i];
+				e->cgua.sent_status[i] = c->sent_cgu_status[i];
+			}
+			e->cgua.got_sent_msg = c->got_sent_msg;
+			e->cgua.opc = opc;
+			e->cgua.call = c;
+			isup_clear_callflags(ss7, c, ISUP_SENT_CGU);
+			return 0;
+		case ISUP_SUS:
+			if(!(c->got_sent_msg & (ISUP_GOT_IAM | ISUP_SENT_IAM))) {
+				ss7_message(ss7, "Got SUS but no call on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+			e = ss7_next_empty_event(ss7);
+			if (!e) {
+				ss7_call_null(ss7, c);
+				isup_free_call(ss7, c);
+				return -1;
+			}
+
+			if(c->susres_ind)
+				isup_start_timer(ss7, c, ISUP_TIMER_T6); /* network */
+			else
+				isup_start_timer(ss7, c, ISUP_TIMER_T2);
+
+			e->e = ISUP_EVENT_SUS;
+			e->susres.cic = c->cic;
+			e->susres.opc = opc; /* keep OPC information */
+			e->susres.call = c;
+			e->susres.susres_ind = c->susres_ind;
+			e->susres.got_sent_msg = c->got_sent_msg;
+			return 0;
+		case ISUP_RES:
+			if(!(c->got_sent_msg & (ISUP_GOT_IAM | ISUP_SENT_IAM))) {
+				ss7_message(ss7, "Got RES but no call on CIC %d PC %d ", c->cic, opc);
+				return isup_handle_unexpected(ss7, c, opc);
+			}
+			e = ss7_next_empty_event(ss7);
+			if (!e) {
+				ss7_call_null(ss7, c);
+				isup_free_call(ss7, c);
+				return -1;
+			}
+
+			if(c->susres_ind)
+				isup_stop_timer(ss7, c, ISUP_TIMER_T6); /* network */
+			else
+				isup_stop_timer(ss7, c, ISUP_TIMER_T2);
+
+			e->e = ISUP_EVENT_RES;
+			e->susres.cic = c->cic;
+			e->susres.opc = opc; /* keep OPC information */
+			e->susres.call = c;
+			e->susres.susres_ind = c->susres_ind;
+			e->susres.got_sent_msg = c->got_sent_msg;
+			return 0;
+		return 0;
 		default:
-			isup_free_call(ss7, c);
+			if(!isup_free_call_if_clear(ss7, c))
+				ss7_call_null(ss7, c);
 			return 0;
 	}
 }
 
-static int isup_send_cicgroupmessage(struct ss7 *ss7, int messagetype, int begincic, int endcic, unsigned int dpc, unsigned char status[], int type)
-{
-	struct isup_call call;
-	int i;
-
-	for (i = 0; (i + begincic) <= endcic; i++)
-		call.status[i] = status[i];
-
-	call.cic = begincic;
-	call.range = endcic - begincic;
-	call.cicgroupsupervisiontype = type;
-	call.dpc = dpc;
-
-	if (call.range > 31)
+int isup_event_iam(struct ss7 *ss7, struct isup_call *c, int opc) {
+	ss7_event *e;
+
+	/* Checking dual seizure */
+	if(c->got_sent_msg == ISUP_SENT_IAM) {
+		if ((ss7->pc > opc) ? (~c->cic & 1) : (c->cic & 1)) {
+			ss7_message(ss7, "Dual seizure on CIC %d DPC %d we are the controlling, ignore IAM\n", c->cic, opc);
+			return 0;
+		} else {
+			ss7_message(ss7, "Dual seizure on CIC %d DPC %d they are the controlling, hangup our call\n", c->cic, opc);
+			c->got_sent_msg = ISUP_GOT_IAM;
+			ss7_hangup(ss7, c->cic, opc, SS7_CAUSE_TRY_AGAIN, SS7_HANGUP_REEVENT_IAM);
+			return 0;
+		}
+	}
+
+	c->got_sent_msg |= ISUP_GOT_IAM;
+
+	if ((ss7->flags & SS7_INR_IF_NO_CALLING) && 
+		!c->calling_party_num[0] && c->presentation_ind != SS7_PRESENTATION_ADDR_NOT_AVAILABLE) {
+		c->dpc = opc;
+		isup_inr(ss7, c, 0x1, 0); /* Calling party address requested */
+		return 0;
+	}
+
+	e = ss7_next_empty_event(ss7);
+	if (!e) {
+		ss7_call_null(ss7, c);
+		isup_free_call(ss7, c);
 		return -1;
-
-	return isup_send_message(ss7, &call, messagetype, cicgroup_params);
+	}
+
+	if (c->cot_check_required)
+		c->got_sent_msg |= ISUP_GOT_CCR;
+
+	e->e = ISUP_EVENT_IAM;
+	e->iam.got_sent_msg = c->got_sent_msg;
+	e->iam.cic = c->cic;
+	e->iam.transcap = c->transcap;
+	e->iam.cot_check_required = c->cot_check_required;
+	c->cot_check_passed = 0;
+	strncpy(e->iam.called_party_num, c->called_party_num, sizeof(e->iam.called_party_num));
+	e->iam.called_nai = c->called_nai;
+	strncpy(e->iam.calling_party_num, c->calling_party_num, sizeof(e->iam.calling_party_num));
+	e->iam.calling_nai = c->calling_nai;
+	e->iam.presentation_ind = c->presentation_ind;
+	e->iam.screening_ind = c->screening_ind;
+	strncpy(e->iam.charge_number, c->charge_number, sizeof(e->iam.charge_number));
+	e->iam.charge_nai = c->charge_nai;
+	e->iam.charge_num_plan = c->charge_num_plan;
+	e->iam.oli_ani2 = c->oli_ani2;
+	e->iam.gen_add_nai = c->gen_add_nai;
+	e->iam.gen_add_num_plan = c->gen_add_num_plan;
+	strncpy(e->iam.gen_add_number, c->gen_add_number, sizeof(e->iam.gen_add_number));
+	e->iam.gen_add_pres_ind = c->gen_add_pres_ind;
+	e->iam.gen_add_type = c->gen_add_type;
+	strncpy(e->iam.gen_dig_number, c->gen_dig_number, sizeof(e->iam.gen_dig_number));
+	e->iam.gen_dig_type = c->gen_dig_type;
+	e->iam.gen_dig_scheme = c->gen_dig_scheme;
+	strncpy(e->iam.jip_number, c->jip_number, sizeof(e->iam.jip_number));
+	strncpy(e->iam.generic_name, c->generic_name, sizeof(e->iam.generic_name));
+	e->iam.generic_name_typeofname = c->generic_name_typeofname;
+	e->iam.generic_name_avail = c->generic_name_avail;
+	e->iam.generic_name_presentation = c->generic_name_presentation;
+	e->iam.lspi_type = c->lspi_type;
+	e->iam.lspi_scheme = c->lspi_scheme;
+	e->iam.lspi_context = c->lspi_context;
+	strncpy(e->iam.lspi_ident, c->lspi_ident, sizeof(e->iam.lspi_ident));
+	strncpy(e->iam.orig_called_num, c->orig_called_num, sizeof(e->iam.orig_called_num));
+	e->iam.orig_called_nai = c->orig_called_nai;
+	e->iam.orig_called_pres_ind = c->orig_called_pres_ind;
+	e->iam.orig_called_screening_ind = c->orig_called_screening_ind;
+	strncpy(e->iam.redirecting_num, c->redirecting_num, sizeof(e->iam.redirecting_num));
+	e->iam.redirecting_num_nai = c->redirecting_num_nai;
+	e->iam.redirecting_num_presentation_ind = c->redirecting_num_presentation_ind;
+	e->iam.redirecting_num_screening_ind = c->redirecting_num_screening_ind;
+	e->iam.calling_party_cat = c->calling_party_cat;
+	e->iam.redirect_counter = c->redirect_counter;
+	e->iam.redirect_info = c->redirect_info;
+	e->iam.redirect_info_ind = c->redirect_info_ind;
+	e->iam.redirect_info_orig_reas = c->redirect_info_orig_reas;
+	e->iam.redirect_info_counter = c->redirect_info_counter;
+	e->iam.redirect_info_reas = c->redirect_info_reas;
+	e->iam.call = c;
+	e->iam.opc = opc; /* keep OPC information */

[... 1445 lines stripped ...]



More information about the libss7-commits mailing list