[asterisk-commits] may: trunk r369613 - in /trunk: ./ addons/ addons/ooh323c/src/ configs/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 4 16:42:09 CDT 2012


Author: may
Date: Wed Jul  4 16:42:05 2012
New Revision: 369613

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=369613
Log:
Added direct media support to ooh323 channel driver
options are documented in config sample
sample config rename to proper name - ooh323.conf

To change media address ooh323 send empty TCS if there was 
completed TCS exchange or send facility forwardedelements 
with new fast start proposal if not.
Then close transmit logical channels and renew TCS exchange.

If new fast start proposal is received then ooh323 stack call back
channel driver routine to change rtp address in the rtp instance.
If empty TCS is received then close transmit logical channels and
renew TCS exchange

Review: https://reviewboard.asterisk.org/r/1607/


Added:
    trunk/configs/ooh323.conf.sample   (with props)
Removed:
    trunk/configs/chan_ooh323.conf.sample
Modified:
    trunk/CHANGES
    trunk/addons/chan_ooh323.c
    trunk/addons/ooh323c/src/ooCalls.h
    trunk/addons/ooh323c/src/ooCmdChannel.c
    trunk/addons/ooh323c/src/ooLogChan.c
    trunk/addons/ooh323c/src/ooLogChan.h
    trunk/addons/ooh323c/src/ooStackCmds.c
    trunk/addons/ooh323c/src/ooStackCmds.h
    trunk/addons/ooh323c/src/ooh245.c
    trunk/addons/ooh323c/src/ooh245.h
    trunk/addons/ooh323c/src/ooh323.c
    trunk/addons/ooh323c/src/ooh323ep.c
    trunk/addons/ooh323c/src/ooq931.c
    trunk/addons/ooh323c/src/ooq931.h
    trunk/addons/ooh323cDriver.c

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Wed Jul  4 16:42:05 2012
@@ -288,6 +288,11 @@
  * IPv6 addresses are now supported when using FastAGI (agi://).  Hostnames
    are resolved and each address is attempted in turn until one succeeds or
    all fail.
+
+chan_ooh323
+-----------
+ * Direct media functionality has been added.
+   Options in config are:  directmedia (directrtp) and directrtpsetup (earlydirect)
 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 1.8 to Asterisk 10 -------------------

Modified: trunk/addons/chan_ooh323.c
URL: http://svnview.digium.com/svn/asterisk/trunk/addons/chan_ooh323.c?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/addons/chan_ooh323.c (original)
+++ trunk/addons/chan_ooh323.c Wed Jul  4 16:42:05 2012
@@ -89,6 +89,8 @@
 static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
 static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, 
           struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active);
+static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *result);
+void setup_rtp_remote(ooCallData *call, const char *remoteIp, int remotePort);
 
 static struct ast_udptl *ooh323_get_udptl_peer(struct ast_channel *chan);
 static int ooh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl);
@@ -126,6 +128,7 @@
 	.get_rtp_info = ooh323_get_rtp_peer,
 	.get_vrtp_info = ooh323_get_vrtp_peer,
 	.update_peer = ooh323_set_rtp_peer,
+	.get_codec = ooh323_get_codec,
 };
 
 static struct ast_udptl_protocol ooh323_udptl = {
@@ -141,7 +144,9 @@
 /* H.323 channel private structure */
 static struct ooh323_pvt {
 	ast_mutex_t lock;		/* Channel private lock */
+	ast_cond_t rtpcond;		/* RTP condition */
 	struct ast_rtp_instance *rtp;
+	struct ast_sockaddr redirip;	/* redir ip */
 	struct ast_rtp_instance *vrtp; /* Placeholder for now */
 
 	int t38support;			/* T.38 mode - disable, transparent, faxgw */
@@ -193,6 +198,8 @@
 	int amaflags;
 	int progsent;			/* progress is sent */
 	int alertsent;			/* alerting is sent */
+	int directrtp;			/* direct rtp */
+	int earlydirect;		/* early direct rtp */
 	int g729onlyA;			/* G.729 only A */
 	struct ast_dsp *vad;
 	struct OOH323Regex *rtpmask;	/* rtp ip regexp */
@@ -228,6 +235,8 @@
 	int		rtdrcount, rtdrinterval;
 	int		nat;
 	int		faststart, h245tunneling;
+	int		directrtp;
+	int		earlydirect;
 	int		g729onlyA;
 	struct ooh323_user *next;
 };
@@ -259,6 +268,8 @@
 	int	    rtdrcount,rtdrinterval;
 	int	    nat;
 	int	    faststart, h245tunneling;
+	int	    directrtp;
+	int	    earlydirect;
 	int	    g729onlyA;
 	struct ooh323_peer *next;
 };
@@ -318,6 +329,8 @@
 static int  gTunneling = 1;
 static int  gBeMaster = 0;
 static int  gMediaWaitForConnect = 0;
+static int  gDirectRTP = 0;
+static int  gEarlyDirect = 0;
 static int  gTOS = 0;
 static int  gRTPTimeout = 60;
 static int  g729onlyA = 0;
@@ -655,6 +668,8 @@
 		p->nat = peer->nat;
 		p->faststart = peer->faststart;
 		p->h245tunneling = peer->h245tunneling;
+		p->directrtp = peer->directrtp;
+		p->earlydirect = peer->earlydirect;
 		if (peer->rtpmask && peer->rtpmaskstr[0]) {
 			p->rtpmask = peer->rtpmask;
 			ast_copy_string(p->rtpmaskstr, peer->rtpmaskstr, sizeof(p->rtpmaskstr));
@@ -689,6 +704,8 @@
 		p->rtdrcount = gRTDRCount;
 		p->faststart = gFastStart;
 		p->h245tunneling = gTunneling;
+		p->directrtp = gDirectRTP;
+		p->earlydirect = gEarlyDirect;
 
 		memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref));
 		p->username = strdup(dest);
@@ -726,7 +743,14 @@
 
       		ast_mutex_unlock(&p->lock);
       		ast_mutex_lock(&ooh323c_cmd_lock);
+		ast_cond_init(&p->rtpcond, NULL);
       		ooMakeCall(data, p->callToken, AST_MAX_EXTENSION, NULL);
+		ast_mutex_lock(&p->lock);
+		if (!p->rtp) {
+			ast_cond_wait(&p->rtpcond, &p->lock);
+		}
+		ast_mutex_unlock(&p->lock);
+		ast_cond_destroy(&p->rtpcond);
       		ast_mutex_unlock(&ooh323c_cmd_lock);
 	}
 
@@ -886,7 +910,7 @@
 	ast_mutex_unlock(&p->lock);
 
 	if (gH323Debug) {
-		ast_verb(0, "+++   ooh323_digit_begin %d\n", res);
+		ast_verb(0, "+++   ooh323_digit_begin, res = %d\n", res);
 	}
 	return res;
 }
@@ -915,7 +939,6 @@
 	if (gH323Debug) {
 		ast_verb(0, "+++   ooh323_digit_end, res = %d\n", res);
 	}
-
 	return res;
 }
 
@@ -1230,8 +1253,13 @@
 		return -1;
 	}
 
-	if (gH323Debug)
+	if (!ast_sockaddr_isnull(&p->redirip)) {
+		res = 0;
+	}
+
+	if (gH323Debug) {
 		ast_verb(0, "----- ooh323_indicate %d on call %s\n", condition, callToken);
+	}
 	 
    	ast_mutex_lock(&p->lock);
 	switch (condition) {
@@ -1383,8 +1411,9 @@
 
    	ast_mutex_unlock(&p->lock);
 
-	if (gH323Debug)
-		ast_verb(0, "++++  ooh323_indicate %d on %s\n", condition, callToken);
+	if (gH323Debug) {
+		ast_verb(0, "++++  ooh323_indicate %d on %s is %d\n", condition, callToken, res);
+	}
 
    	free(callToken);
 	return res;
@@ -1604,7 +1633,7 @@
 	ast_mutex_lock(&p->lock);
 	if (!p->owner) {
 		ast_mutex_unlock(&p->lock);
-		ast_log(LOG_ERROR, "Channel has no owner\n");
+		ast_debug(1, "Channel has no owner\n");
 		return 0;
 	}
 	while (p->owner && ast_channel_trylock(p->owner)) {
@@ -1843,6 +1872,8 @@
 		p->nat = user->nat;
 		p->h245tunneling = user->h245tunneling;
 		p->faststart = user->faststart;
+		p->directrtp = user->directrtp;
+		p->earlydirect = user->earlydirect;
 
 		if (p->faststart)
          		OO_SETFLAG(call->flags, OO_M_FASTSTART);
@@ -1869,6 +1900,8 @@
 	} else {
 	 if (!OO_TESTFLAG(p->flags,H323_DISABLEGK)) {
 		p->username = strdup(call->remoteIP);
+		p->directrtp = gDirectRTP;
+		p->earlydirect = gEarlyDirect;
 	} else {
 	  ast_mutex_unlock(&p->lock);
 	  ast_log(LOG_ERROR, "Unacceptable ip %s\n", call->remoteIP);
@@ -1970,7 +2003,7 @@
 			ast_copy_string(call->rtpMaskStr, p->rtpmaskstr, sizeof(call->rtpMaskStr));
 		}
 
-		if (!configure_local_rtp(p, call)) {
+		if (!p->rtp && !configure_local_rtp(p, call)) {
 			ast_mutex_unlock(&p->lock);
 			return OO_FAILED;
 		}
@@ -2064,7 +2097,8 @@
       		ooh323c_set_capability_for_call(call, &p->prefs, p->cap,
                                      p->dtmfmode, p->dtmfcodec, p->t38support, p->g729onlyA);
 
-		/* configure_local_rtp(p, call); */
+		configure_local_rtp(p, call);
+		ast_cond_signal(&p->rtpcond);
 		ast_mutex_unlock(&p->lock);
 	}
 
@@ -2284,6 +2318,8 @@
 		user->t38support = gT38Support;
 		user->faststart = gFastStart;
 		user->h245tunneling = gTunneling;
+		user->directrtp = gDirectRTP;
+		user->earlydirect = gEarlyDirect;
 		user->g729onlyA = g729onlyA;
 		/* set default context */
 		ast_copy_string(user->context, gContext, sizeof(user->context));
@@ -2305,6 +2341,11 @@
 				user->faststart = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "h245tunneling")) {
 				user->h245tunneling = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "directrtp") || !strcasecmp(v->name, "directmedia")) {
+				user->directrtp = ast_true(v->value);
+				user->earlydirect = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "earlydirect") || !strcasecmp(v->name, "directrtpsetup")) {
+				user->earlydirect = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "g729onlyA")) {
 				user->g729onlyA = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "nat")) {
@@ -2427,6 +2468,8 @@
 		peer->t38support = gT38Support;
 		peer->faststart = gFastStart;
 		peer->h245tunneling = gTunneling;
+		peer->directrtp = gDirectRTP;
+		peer->earlydirect = gEarlyDirect;
 		peer->g729onlyA = g729onlyA;
 		peer->port = 1720;
 		if (0 == friend_type) {
@@ -2482,6 +2525,11 @@
 				peer->faststart = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "h245tunneling")) {
 				peer->h245tunneling = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "directrtp") || !strcasecmp(v->name, "directmedia")) {
+				peer->directrtp = ast_true(v->value);
+				peer->earlydirect = ast_true(v->value);
+			} else if (!strcasecmp(v->name, "earlydirect") || !strcasecmp(v->name, "directrtpsetup")) {
+				peer->earlydirect = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "g729onlyA")) {
 				peer->g729onlyA = ast_true(v->value);
 			} else if (!strcasecmp(v->name, "nat")) {
@@ -2761,6 +2809,11 @@
 				ooH323EpEnableH245Tunneling();
 			else
 				ooH323EpDisableH245Tunneling();
+		} else if (!strcasecmp(v->name, "directrtp") || !strcasecmp(v->name, "directmedia")) {
+			gDirectRTP = ast_true(v->value);
+			gEarlyDirect = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "earlydirect") || !strcasecmp(v->name, "directrtpsetup")) {
+			gEarlyDirect = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "g729onlyA")) {
 			g729onlyA = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "roundtrip")) {
@@ -3022,6 +3075,8 @@
 		ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name);
 		ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", peer->faststart?"yes":"no",
 					peer->h245tunneling?"yes":"no");
+		ast_cli(a->fd, "%-15s%s\n", "DirectRTP", peer->directrtp ? "yes" : "no");
+		ast_cli(a->fd, "%-15s%s\n", "EarlyDirectRTP", peer->earlydirect ? "yes" : "no");
 		ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
 		print_codec_to_cli(a->fd, &peer->prefs);
 		ast_cli(a->fd, ")\n");
@@ -3179,6 +3234,8 @@
 		ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name);
 		ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", user->faststart?"yes":"no",
 					user->h245tunneling?"yes":"no");
+		ast_cli(a->fd, "%-15s%s\n", "DirectRTP", user->directrtp ? "yes" : "no");
+		ast_cli(a->fd, "%-15s%s\n", "EarlyDirectRTP", user->earlydirect ? "yes" : "no");
 		ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
 		print_codec_to_cli(a->fd, &user->prefs);
 		ast_cli(a->fd, ")\n");
@@ -3341,6 +3398,8 @@
 	ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no");
 	ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID);
 	ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", gMediaWaitForConnect?"yes":"no");
+	ast_cli(a->fd, "%-20s%s\n", "DirectRTP", gDirectRTP ? "yes" : "no");
+	ast_cli(a->fd, "%-20s%s\n", "EarlyDirectRTP", gEarlyDirect ? "yes" : "no");
 
 #if (0)
 		extern OOH323EndPoint gH323ep;
@@ -3556,7 +3615,8 @@
 		.onCallCleared = onCallCleared,
 		.openLogicalChannels = NULL,
 		.onReceivedDTMF = ooh323_onReceivedDigit,
-		.onModeChanged = onModeChanged
+		.onModeChanged = onModeChanged,
+		.onMediaChanged = (cb_OnMediaChanged) setup_rtp_remote,
 	};
 	if (!(gCap = ast_format_cap_alloc())) {
 		return 1; 
@@ -3736,8 +3796,6 @@
 		while (h323) {
 			h323_next = h323->next;
 
-			/* TODO: Need to add rtptimeout keepalive support */
-
 			if (h323->rtp && h323->rtptimeout && h323->lastrtptx &&
 				h323->lastrtptx + h323->rtptimeout < t) {
 				ast_rtp_instance_sendcng(h323->rtp, 0);
@@ -3745,7 +3803,7 @@
 			}
 
 			if (h323->rtp && h323->owner && h323->rtptimeout &&
-				h323->lastrtprx &&
+				h323->lastrtprx && ast_sockaddr_isnull(&h323->redirip) &&
 				h323->lastrtprx + h323->rtptimeout < t) {
 				if (!ast_channel_trylock(h323->owner)) {
 					ast_softhangup_nolock(h323->owner, AST_SOFTHANGUP_DEV);
@@ -4123,12 +4181,34 @@
 	return 0;
 }
 
+static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
+{
+	struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan);
+	if (gH323Debug) {
+		ast_verb(0, "+++ ooh323  get_codec, %s\n", ast_channel_name(chan));
+	}
+
+	if (p) {
+		ast_format_cap_append(result,  ast_format_cap_is_empty(ast_channel_nativeformats(chan)) ?
+				(ast_format_cap_is_empty(p->cap) ? NULL : p->cap) : ast_channel_nativeformats(chan));
+	}
+
+	if (gH323Debug) {
+		ast_verb(0, "--- ooh323  get_codec, %s\n", ast_channel_name(chan));
+	}
+}
+
 
 
 static enum ast_rtp_glue_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
 {
 	struct ooh323_pvt *p = NULL;
 	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
+	struct ast_sockaddr tmp;
+
+	if (gH323Debug) {
+		ast_verb(0, "+++ ooh323  get_rtp_peer \n");
+	}
 
 	if (!(p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan)))
 		return AST_RTP_GLUE_RESULT_FORBID;
@@ -4139,12 +4219,27 @@
 
 	*rtp = p->rtp ? ao2_ref(p->rtp, +1), p->rtp : NULL;
 
-	res = AST_RTP_GLUE_RESULT_LOCAL;
+	/* there must be checking of directmedia setting */
+
+	if ((ast_channel_state(chan) != AST_STATE_UP && !p->earlydirect) || !p->directrtp) {
+		res = AST_RTP_GLUE_RESULT_LOCAL;
+	} else {
+		res = AST_RTP_GLUE_RESULT_REMOTE;
+	}
 
 	if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) {
 		res = AST_RTP_GLUE_RESULT_FORBID;
 	}
 
+	ast_rtp_instance_get_remote_address(*rtp, &tmp);
+	if (gH323Debug) {
+		ast_verb(0, "ooh323_get_rtp_peer  %s -> %s:%d, %d\n", ast_channel_name(chan), ast_sockaddr_stringify_addr(&tmp),
+						ast_sockaddr_port(&tmp), res);
+	}
+	if (gH323Debug) {
+		ast_verb(0, "--- ooh323  get_rtp_peer, res = %d\n", (int) res);
+	}
+
 	return res;
 }
 
@@ -4161,7 +4256,10 @@
 	}
 
 	*rtp = p->vrtp ? ao2_ref(p->vrtp, +1), p->vrtp : NULL;
-	res = AST_RTP_GLUE_RESULT_LOCAL;
+
+	/* there must check of supporting video per call */
+
+	res = AST_RTP_GLUE_RESULT_FORBID;
 
 	return res;
 }
@@ -4225,13 +4323,11 @@
 {
 	/* XXX Deal with Video */
 	struct ooh323_pvt *p;
-	struct ast_sockaddr tmp;
-
-	if (gH323Debug)
+	int changed = 0;
+	char *callToken = NULL;
+
+	if (gH323Debug) {
 		ast_verb(0, "---   ooh323_set_peer - %s\n", ast_channel_name(chan));
-
-	if (!rtp) {
-		return 0;
 	}
 
 	if (ooh323_convertAsteriskCapToH323Cap(ast_channel_writeformat(chan)) < 0) {
@@ -4243,14 +4339,47 @@
 		ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
 		return -1;
 	}
-	ast_rtp_instance_get_remote_address(rtp, &tmp);
-	ast_rtp_instance_get_local_address(rtp, &tmp);
+
+	ast_mutex_lock(&p->lock);
+
+	if (rtp) {
+		changed |= ast_rtp_instance_get_and_cmp_remote_address(rtp, &p->redirip);
+	} else if (!ast_sockaddr_isnull(&p->redirip)) {
+		changed = 1;
+		memset(&p->redirip, 0, sizeof(p->redirip));
+	}
+
+	callToken = (p->callToken ? strdup(p->callToken) : NULL);
+
+	if (!callToken) {
+		if (gH323Debug) {
+			ast_verb(0, "	set_rtp_peer - No callToken\n");
+		}
+		ast_mutex_unlock(&p->lock);
+		return -1;
+	}
+
+
+	if (changed) {
+		if (!ast_sockaddr_isnull(&p->redirip)) {
+			if (gH323Debug) {
+				ast_verb(0, "ooh323_set_rtp_peer  %s -> %s:%d\n", ast_channel_name(chan), ast_sockaddr_stringify_addr(&p->redirip),
+							ast_sockaddr_port(&p->redirip));
+			}
+			ooUpdateLogChannels(callToken, ast_sockaddr_stringify_addr(&p->redirip),
+							ast_sockaddr_port(&p->redirip));
+		} else {
+			if (gH323Debug) {
+				ast_verb(0, "ooh323_set_rtp_peer  return back to local\n");
+			}
+			ooUpdateLogChannels(callToken, "0.0.0.0" , 0);
+		}
+	}
+
+	ast_mutex_unlock(&p->lock);
+	free(callToken);
 	return 0;
 
-/* 	May 20101003 */
-/*	What we should to do here? */
-
-
 }
 
 
@@ -4258,7 +4387,8 @@
 
 int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
 {
-	char lhost[INET6_ADDRSTRLEN], *lport=NULL;
+	char lhost[INET6_ADDRSTRLEN];
+	unsigned lport = 0;
 	struct ast_sockaddr tmp;
 	ooMediaInfo mediaInfo;
 	int x;
@@ -4269,7 +4399,7 @@
 	if (gH323Debug)
 		ast_verb(0, "---   configure_local_rtp\n");
 
-
+	memset(&mediaInfo, 0, sizeof(mediaInfo));
 	if (ast_parse_arg(call->localIP, PARSE_ADDR, &tmp)) {
 		ast_sockaddr_copy(&tmp, &bindaddr);
 	}
@@ -4327,7 +4457,7 @@
 		/* figure out our local RTP port and tell the H.323 stack about it*/
 		ast_rtp_instance_get_local_address(p->rtp, &tmp);
 		ast_copy_string(lhost, ast_sockaddr_stringify_addr(&tmp), sizeof(lhost));
-		lport = ast_sockaddr_stringify_port(&tmp);
+		lport = ast_sockaddr_port(&tmp);
 
 		if (p->rtptimeout) {
 			ast_rtp_instance_set_timeout(p->rtp, p->rtptimeout);
@@ -4345,8 +4475,8 @@
 
 
 	ast_copy_string(mediaInfo.lMediaIP, lhost, sizeof(mediaInfo.lMediaIP));
-	mediaInfo.lMediaPort = atoi(lport);
-	mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
+	mediaInfo.lMediaPort = lport;
+	mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort + 1;
 	for (x = 0; ast_codec_pref_index(&p->prefs, x, &tmpfmt); x++) {
 		strcpy(mediaInfo.dir, "transmit");
 		mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(&tmpfmt);
@@ -4371,9 +4501,9 @@
 	if (p->udptl) {
 		ast_udptl_get_us(p->udptl, &tmp);
 		ast_copy_string(lhost, ast_sockaddr_stringify_addr(&tmp), sizeof(lhost));
-		lport = ast_sockaddr_stringify_port(&tmp);
+		lport = ast_sockaddr_port(&tmp);
 		ast_copy_string(mediaInfo.lMediaIP, lhost, sizeof(mediaInfo.lMediaIP));
-		mediaInfo.lMediaPort = atoi(lport);
+		mediaInfo.lMediaPort = lport;
 		mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
 		mediaInfo.cap = OO_T38;
 		strcpy(mediaInfo.dir, "transmit");
@@ -4388,30 +4518,73 @@
 	return 1;
 }
 
-void setup_rtp_connection(ooCallData *call, const char *remoteIp, 
-								  int remotePort)
+void setup_rtp_remote(ooCallData *call, const char *remoteIp, int remotePort)
 {
 	struct ooh323_pvt *p = NULL;
 	struct ast_sockaddr tmp;
 
-	if (gH323Debug)
-		ast_verb(0, "---   setup_rtp_connection %s:%d\n", remoteIp, remotePort);
+	if (gH323Debug) {
+		ast_verb(0, "---   setup_rtp_remote %s:%d\n", remoteIp, remotePort);
+	}
+	if (!remoteIp || !remoteIp[0] || !remotePort) {
+		if (gH323Debug) {
+			ast_verb(0, "+++ setup_rtp_remote no data\n");
+		}
+		return;
+	}
 
 	/* Find the call or allocate a private structure if call not found */
-	p = find_call(call); 
-
-	if (!p) {
+	p = find_call(call);
+
+	if (!p || !p->rtp) {
 		ast_log(LOG_ERROR, "Something is wrong: rtp\n");
 		return;
 	}
+
+	ast_mutex_lock(&p->lock);
 
 	ast_parse_arg(remoteIp, PARSE_ADDR, &tmp);
 	ast_sockaddr_set_port(&tmp, remotePort);
 	ast_rtp_instance_set_remote_address(p->rtp, &tmp);
 
-	if (p->writeformat.id == AST_FORMAT_G726_AAL2) 
+	ast_mutex_unlock(&p->lock);
+
+	if (gH323Debug) {
+		ast_verb(0, "+++   setup_rtp_remote\n");
+	}
+
+	return;
+}
+
+
+void setup_rtp_connection(ooCallData *call, const char *remoteIp, int remotePort)
+{
+	struct ooh323_pvt *p = NULL;
+	struct ast_sockaddr tmp;
+
+	if (gH323Debug)
+		ast_verb(0, "---   setup_rtp_connection %s:%d\n", remoteIp, remotePort);
+
+	/* Find the call or allocate a private structure if call not found */
+	p = find_call(call);
+
+	if (!p || !p->rtp) {
+		ast_log(LOG_ERROR, "Something is wrong: rtp\n");
+		return;
+	}
+
+	ast_mutex_lock(&p->lock);
+
+	ast_parse_arg(remoteIp, PARSE_ADDR, &tmp);
+	ast_sockaddr_set_port(&tmp, remotePort);
+	ast_rtp_instance_set_remote_address(p->rtp, &tmp);
+
+	if (p->writeformat.id == AST_FORMAT_G726_AAL2) {
                 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, 2,
 							"audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
+	}
+
+	ast_mutex_unlock(&p->lock);
 
 	if(gH323Debug)
 		ast_verb(0, "+++   setup_rtp_connection\n");
@@ -4531,9 +4704,10 @@
 		parameters.rate = AST_T38_RATE_14400;
 		ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
 	}
-	if (gH323Debug)
-		ast_debug(1, "Receiving UDPTL  %s:%s\n", ast_sockaddr_stringify_host(&them),
-							ast_sockaddr_stringify_port(&them));
+	if (gH323Debug) {
+		ast_debug(1, "Receiving UDPTL  %s:%d\n", ast_sockaddr_stringify_host(&them),
+							ast_sockaddr_port(&them));
+	}
 
 	ast_channel_unlock(p->owner);
 	ast_mutex_unlock(&p->lock);

Modified: trunk/addons/ooh323c/src/ooCalls.h
URL: http://svnview.digium.com/svn/asterisk/trunk/addons/ooh323c/src/ooCalls.h?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/addons/ooh323c/src/ooCalls.h (original)
+++ trunk/addons/ooh323c/src/ooCalls.h Wed Jul  4 16:42:05 2012
@@ -97,6 +97,8 @@
    int   cap;
    int   lMediaPort;
    int   lMediaCntrlPort;
+   int   lMediaRedirPort;
+   int   lMediaRedirCPort;
    char  lMediaIP[2+8*4+7];
    struct OOMediaInfo *next;
 } OOMediaInfo;
@@ -197,6 +199,7 @@
    ASN1UINT             statusDeterminationNumber;
    OOCapExchangeState   localTermCapState;
    OOCapExchangeState   remoteTermCapState;
+   OOBOOL		TCSPending;
    struct ooH323EpCapability* ourCaps;
    struct ooH323EpCapability* remoteCaps; /* TODO: once we start using jointCaps, get rid of remoteCaps*/
    struct ooH323EpCapability* jointCaps;
@@ -325,6 +328,9 @@
 typedef void (*cb_OnModeChanged)
    (struct OOH323CallData *call, int isT38Mode);
 
+typedef void (*cb_OnMediaChanged)
+   (struct OOH323CallData *call, char* remoteIP, int remotePort);
+
 /**
  * This structure holds all of the H.323 signaling callback function 
  * addresses.
@@ -342,6 +348,7 @@
    cb_OpenLogicalChannels openLogicalChannels;
    cb_OnReceivedDTMF onReceivedDTMF;
    cb_OnModeChanged onModeChanged;
+   cb_OnMediaChanged onMediaChanged;
 } OOH323CALLBACKS;
 
 /**

Modified: trunk/addons/ooh323c/src/ooCmdChannel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/addons/ooh323c/src/ooCmdChannel.c?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/addons/ooh323c/src/ooCmdChannel.c (original)
+++ trunk/addons/ooh323c/src/ooCmdChannel.c Wed Jul  4 16:42:05 2012
@@ -411,12 +411,26 @@
    		}
 		break;
 
+	    case OO_CMD_UPDLC:
+		OOTRACEINFO4("Processing UpdLC command %s, localIP is %s, port is %d\n",
+				(char *)cmd.param1, (char *)cmd.param2, *(int *)cmd.param3);
+		if (cmd.param2) {
+			ooUpdateAllLogicalChannels(call, (char *)cmd.param2, *(int *)cmd.param3);
+		}
+		break;
+
             default: OOTRACEERR1("ERROR:Unknown command\n");
          }
       }
-      if(cmd.param1) free(cmd.param1);
-      if(cmd.param2) free(cmd.param2);
-      if(cmd.param3) free(cmd.param3);
+      if (cmd.param1) {
+	ast_free(cmd.param1);
+      }
+      if (cmd.param2) {
+	ast_free(cmd.param2);
+      }
+      if (cmd.param3) {
+	ast_free(cmd.param3);
+      }
    }
 
 

Modified: trunk/addons/ooh323c/src/ooLogChan.c
URL: http://svnview.digium.com/svn/asterisk/trunk/addons/ooh323c/src/ooLogChan.c?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/addons/ooh323c/src/ooLogChan.c (original)
+++ trunk/addons/ooh323c/src/ooLogChan.c Wed Jul  4 16:42:05 2012
@@ -77,8 +77,9 @@
    {
       OOTRACEDBGC3("Using configured media info (%s, %s)\n", call->callType,
                    call->callToken);
-      pNewChannel->localRtpPort = pMediaInfo->lMediaPort;
-      pNewChannel->localRtcpPort = pMediaInfo->lMediaCntrlPort;
+      pNewChannel->localRtpPort = pMediaInfo->lMediaRedirPort ? pMediaInfo->lMediaRedirPort : pMediaInfo->lMediaPort;
+      /* check MediaRedirPort here because RedirCPort is ReditPort + 1 and can't be 0 ;) */
+      pNewChannel->localRtcpPort = pMediaInfo->lMediaRedirPort ? pMediaInfo->lMediaRedirCPort : pMediaInfo->lMediaCntrlPort;
       /* If user application has not specified a specific ip and is using 
          multihomed mode, substitute appropriate ip.
       */
@@ -86,6 +87,8 @@
          strcpy(pNewChannel->localIP, call->localIP);
       else
          strcpy(pNewChannel->localIP, pMediaInfo->lMediaIP);
+
+      OOTRACEDBGC5("Configured media info (%s, %s) %s:%d\n", call->callType, call->callToken, pNewChannel->localIP, pNewChannel->localRtcpPort);
    }
    else{
       OOTRACEDBGC3("Using default media info (%s, %s)\n", call->callType,
@@ -254,6 +257,26 @@
    return NULL;
 }
 
+
+OOLogicalChannel* ooGetReceiveLogicalChannel
+   (OOH323CallData *call)
+{
+   OOLogicalChannel * pChannel = NULL;
+   pChannel = call->logicalChans;
+   while (pChannel) {
+      OOTRACEINFO6("Listing logical channel %d cap %d state %d for (%s, %s)\n",
+		pChannel->channelNo, pChannel->chanCap->cap, pChannel->state,
+		call->callType, call->callToken);
+      if (!strcmp(pChannel->dir, "receive") && pChannel->state != OO_LOGICALCHAN_IDLE &&
+					       pChannel->state != OO_LOGICALCHAN_PROPOSEDFS) {
+         return pChannel;
+      } else {
+         pChannel = pChannel->next;
+      }
+   }
+   return NULL;
+}
+
 int ooClearAllLogicalChannels(OOH323CallData *call)
 {
    OOLogicalChannel * temp = NULL, *prev = NULL;
@@ -326,7 +349,7 @@
    ooRemoveLogicalChannel(call, channelNo);/* TODO: efficiency - This causes re-search of
                                                     of logical channel in the list. Can be
                                                     easily improved.*/
-   }  while ((pLogicalChannel = ooFindLogicalChannelByLogicalChannelNo(call,channelNo)));
+   } while ((pLogicalChannel = ooFindLogicalChannelByLogicalChannelNo(call, channelNo)));
    return OO_OK;
 }
 

Modified: trunk/addons/ooh323c/src/ooLogChan.h
URL: http://svnview.digium.com/svn/asterisk/trunk/addons/ooh323c/src/ooLogChan.h?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/addons/ooh323c/src/ooLogChan.h (original)
+++ trunk/addons/ooh323c/src/ooLogChan.h Wed Jul  4 16:42:05 2012
@@ -42,7 +42,8 @@
    OO_LOGICALCHAN_IDLE, 
    OO_LOGICALCHAN_PROPOSED, 
    OO_LOGICALCHAN_ESTABLISHED,
-   OO_LOGICALCHAN_PROPOSEDFS
+   OO_LOGICALCHAN_PROPOSEDFS,
+   OO_LOGICALCHAN_CLOSEPENDING
 } OOLogicalChannelState;
 
 /**
@@ -181,6 +182,7 @@
 (struct OOH323CallData* call, int sessionID, char *dir, H245DataType* dataType);
 
 EXTERN OOLogicalChannel* ooGetTransmitLogicalChannel(struct OOH323CallData *call);
+EXTERN OOLogicalChannel* ooGetReceiveLogicalChannel(struct OOH323CallData *call);
 
 /** 
  * @} 

Modified: trunk/addons/ooh323c/src/ooStackCmds.c
URL: http://svnview.digium.com/svn/asterisk/trunk/addons/ooh323c/src/ooStackCmds.c?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/addons/ooh323c/src/ooStackCmds.c (original)
+++ trunk/addons/ooh323c/src/ooStackCmds.c Wed Jul  4 16:42:05 2012
@@ -545,6 +545,68 @@
    return OO_STKCMD_SUCCESS;
 }
 
+OOStkCmdStat ooUpdateLogChannels(const char *callToken, const char* localIP, int port)
+{
+   OOStackCommand cmd;
+   OOH323CallData *call;
+
+   if (!callToken) {
+      return OO_STKCMD_INVALIDPARAM;
+   }
+
+   if (!(call = ooFindCallByToken(callToken))) {
+      return OO_STKCMD_INVALIDPARAM;
+   }
+
+   if (localIP == NULL) {
+      return OO_STKCMD_INVALIDPARAM;
+   }
+
+   if (call->CmdChan == 0) {
+      if (ooCreateCallCmdConnection(call) != OO_OK) {
+         return OO_STKCMD_CONNECTIONERR;
+      }
+   }
+
+   memset(&cmd, 0, sizeof(OOStackCommand));
+   cmd.type = OO_CMD_UPDLC;
+
+   cmd.param1 = ast_malloc(strlen(callToken) + 1);
+   cmd.param2 = ast_malloc(strlen(localIP) + 1);
+   cmd.param3 = ast_malloc(sizeof(int) + 1);
+   if (!cmd.param1 || !cmd.param2 || !cmd.param3) {
+      if (cmd.param1) {
+	ast_free(cmd.param1); /* Release memory */
+      }
+      if (cmd.param2) {
+	ast_free(cmd.param2);
+      }
+      if (cmd.param3) {
+	ast_free(cmd.param3);
+      }
+      return OO_STKCMD_MEMERR;
+   }
+   strcpy((char*)cmd.param1, callToken);
+   cmd.plen1 = strlen(callToken);
+   strcpy((char*)cmd.param2, localIP);
+   cmd.plen2 = strlen(localIP);
+   *((int *)cmd.param3) = port;
+   cmd.plen3 = sizeof(int) + 1;
+
+   if (ooWriteCallStackCommand(call, &cmd) != OO_OK) {
+      ast_free(cmd.param1);
+      ast_free(cmd.param2);
+      ast_free(cmd.param3);
+      return OO_STKCMD_WRITEERR;
+   }
+
+   ast_free(cmd.param1);
+   ast_free(cmd.param2);
+   ast_free(cmd.param3);
+
+   return OO_STKCMD_SUCCESS;
+}
+
 OOStkCmdStat ooRequestChangeMode(const char *callToken, int isT38Mode)
 {
    OOStackCommand cmd;
@@ -593,7 +655,6 @@
    return OO_STKCMD_SUCCESS;
 }
 
-
 const char* ooGetStkCmdStatusCodeTxt(OOStkCmdStat stat)
 {
    switch(stat)

Modified: trunk/addons/ooh323c/src/ooStackCmds.h
URL: http://svnview.digium.com/svn/asterisk/trunk/addons/ooh323c/src/ooStackCmds.h?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/addons/ooh323c/src/ooStackCmds.h (original)
+++ trunk/addons/ooh323c/src/ooStackCmds.h Wed Jul  4 16:42:05 2012
@@ -68,7 +68,8 @@
    OO_CMD_MANUALPROGRESS,    /*!< Send progress */
    OO_CMD_STOPMONITOR,       /*!< Stop the event monitor */
    OO_CMD_REQMODE,	     /*!< Request new mode */
-   OO_CMD_SETANI	     /*! <Set conncted info */
+   OO_CMD_SETANI,	     /*! <Set conncted info */
+   OO_CMD_UPDLC		     /*! <Update Logical channels */
    
 } OOStackCmdID;
 
@@ -178,6 +179,7 @@
 int ooGenerateOutgoingCallToken (char *callToken, size_t size);
 
 EXTERN OOStkCmdStat ooSetANI(const char *callToken, const char* ani);
+EXTERN OOStkCmdStat ooUpdateLogChannels(const char *callToken, const char* localIP, const int port);
 
 #ifdef __cplusplus
 }

Modified: trunk/addons/ooh323c/src/ooh245.c
URL: http://svnview.digium.com/svn/asterisk/trunk/addons/ooh323c/src/ooh245.c?view=diff&rev=369613&r1=369612&r2=369613
==============================================================================
--- trunk/addons/ooh323c/src/ooh245.c (original)
+++ trunk/addons/ooh323c/src/ooh245.c Wed Jul  4 16:42:05 2012
@@ -814,6 +814,51 @@
    }
 
    ooFreeH245Message(call,ph245msg);
+
+   return ret;
+}
+int ooSendEmptyTermCapMsg(OOH323CallData *call)
+{
+   int ret;
+   H245RequestMessage *request = NULL;
+   OOCTXT *pctxt = NULL;
+   H245TerminalCapabilitySet *termCap = NULL;
+   H245Message *ph245msg = NULL;
+
+   ret = ooCreateH245Message(call, &ph245msg,
+				T_H245MultimediaSystemControlMessage_request);
+
+   if (ret == OO_FAILED) {
+      OOTRACEERR3("Error:Failed to create H245 message for Terminal "
+                  "CapabilitySet (%s, %s)\n", call->callType, call->callToken);
+      return OO_FAILED;
+   }
+
+  /* Set request type as TerminalCapabilitySet */
+   request = ph245msg->h245Msg.u.request;
+   pctxt = call->msgctxt;
+   ph245msg->msgType = OOTerminalCapabilitySet;
+   memset(request, 0, sizeof(H245RequestMessage));
+
+   request->t = T_H245RequestMessage_terminalCapabilitySet;
+   request->u.terminalCapabilitySet = (H245TerminalCapabilitySet*)
+                  memAlloc(pctxt, sizeof(H245TerminalCapabilitySet));
+   termCap = request->u.terminalCapabilitySet;
+   memset(termCap, 0, sizeof(H245TerminalCapabilitySet));
+   termCap->m.multiplexCapabilityPresent = 0;
+   termCap->m.capabilityTablePresent = 0;
+   termCap->m.capabilityDescriptorsPresent = 0;
+   termCap->sequenceNumber = ++(call->localTermCapSeqNo);
+   termCap->protocolIdentifier = gh245ProtocolID; /* protocol id */
+
+   OOTRACEDBGA3("Built empty terminal capability set message (%s, %s)\n",
+                 call->callType, call->callToken);
+   ret = ooSendH245Msg(call, ph245msg);
+   if (ret != OO_OK) {
+      OOTRACEERR3("Error:Failed to enqueue empty TCS message to outbound queue. "
+                  "(%s, %s)\n", call->callType, call->callToken);
+   }
+   ooFreeH245Message(call, ph245msg);
 
    return ret;
 }
@@ -1668,11 +1713,11 @@
    }
 
    if (call->versionIP == 6) {
-	inet_pton(AF_INET6, call->localIP, iP6Address->network.data);
+	inet_pton(AF_INET6, pLogicalChannel->localIP, iP6Address->network.data);
    	iP6Address->network.numocts = 16;
    	iP6Address->tsapIdentifier = pLogicalChannel->localRtpPort;
    } else {
-	inet_pton(AF_INET, call->localIP, iPAddress->network.data);
+	inet_pton(AF_INET, pLogicalChannel->localIP, iPAddress->network.data);
    	iPAddress->network.numocts = 4;
    	iPAddress->tsapIdentifier = pLogicalChannel->localRtpPort;
    }
@@ -1692,7 +1737,7 @@
                memAlloc(pctxt, sizeof(H245UnicastAddress_iP6Address));
    	iP6Address1 = unicastAddrs1->u.iP6Address;
    	memset(iP6Address1, 0, sizeof(H245UnicastAddress_iP6Address));
-	inet_pton(AF_INET6, call->localIP, iP6Address1->network.data);
+	inet_pton(AF_INET6, pLogicalChannel->localIP, iP6Address1->network.data);
    	iP6Address1->network.numocts = 16;
    	iP6Address1->tsapIdentifier = pLogicalChannel->localRtcpPort;
    } else {
@@ -1702,7 +1747,7 @@
    	iPAddress1 = unicastAddrs1->u.iPAddress;
    	memset(iPAddress1, 0, sizeof(H245UnicastAddress_iPAddress));
 
-	inet_pton(AF_INET, call->localIP, iPAddress1->network.data);
+	inet_pton(AF_INET, pLogicalChannel->localIP, iPAddress1->network.data);
    	iPAddress1->network.numocts = 4;
    	iPAddress1->tsapIdentifier = pLogicalChannel->localRtcpPort;
    }
@@ -1723,7 +1768,7 @@
    {
       epCap->startReceiveChannel(call, pLogicalChannel);      
       OOTRACEINFO6("Receive channel of type %s started at %s:%d(%s, %s)\n", 
-                    ooGetCapTypeText(epCap->cap), call->localIP, 
+                    ooGetCapTypeText(epCap->cap), pLogicalChannel->localIP,
                     pLogicalChannel->localRtpPort, call->callType, 
                     call->callToken);
    }
@@ -2219,6 +2264,63 @@
    return OO_OK;
 }
 
+int ooUpdateAllLogicalChannels(OOH323CallData *call, char* localIP, int port)
+{
+   ooLogicalChannel *temp;
+   OOMediaInfo *pMediaInfo = NULL;
+   char *lIP = localIP;
+   OOBOOL eTCS = FALSE;
+
+   if (!lIP || !lIP[0]) {
+      lIP = call->localIP;
+   }
+
+/* close all log chans */
+
+   temp = call->logicalChans;
+   while (temp) {
+      if (temp->state == OO_LOGICALCHAN_ESTABLISHED) {
+          /* Sending closelogicalchannel only for outgoing channels */
+         if (!strcmp(temp->dir, "transmit")) {
+	    if (call->h245SessionState != OO_H245SESSION_IDLE) {
+              ooSendCloseLogicalChannel(call, temp);
+            } else {
+              ooClearLogicalChannel(call, temp->channelNo);
+            }
+         } else if (!eTCS && call->h245SessionState != OO_H245SESSION_IDLE) {
+            ooSendEmptyTermCapMsg(call);
+            eTCS = TRUE;
+         }
+      }
+      temp = temp->next;
+   }
+
+/* change media address for all caps */
+
+   if (call->mediaInfo) {
+      pMediaInfo = call->mediaInfo;
+      while (pMediaInfo) {
+         strcpy(pMediaInfo->lMediaIP, lIP);
+         pMediaInfo->lMediaRedirPort = port;
+         pMediaInfo->lMediaRedirCPort = port + 1;
+         pMediaInfo = pMediaInfo->next;
+      }
+   }
+
+   if (call->h245SessionState == OO_H245SESSION_IDLE) {
+      if (call->fsSent) {
+         ooSendFSUpdate(call);
+      }
+   } else {
+      call->TCSPending = TRUE;
+   }
+
+/* Restart TCS exchange proc - Paul Cadah do it in chan_h323_exts native bridge code */
+/* We must do it after all log channels are closed */
+
+   return OO_OK;
+}
+
 int ooSendCloseLogicalChannel(OOH323CallData *call, ooLogicalChannel *logicalChan)
 {
    int ret = OO_OK, error=0;
@@ -2271,17 +2373,11 @@
    ooFreeH245Message(call, ph245msg);
    
    /* Stop the media transmission */
-   OOTRACEINFO4("Closing logical channel %d (%s, %s)\n", 
-                clc->forwardLogicalChannelNumber, call->callType, 
-                call->callToken);
-   ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
-   if(ret != OO_OK)
-   {
-      OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
-         clc->forwardLogicalChannelNumber, call->callType, call->callToken);
-      return OO_FAILED;
-   }
-   if(error) return OO_FAILED;
+   /* Moved to OnReceivedClosedChannelAck */
+   logicalChan->state = OO_LOGICALCHAN_CLOSEPENDING;
+   if (error) {
+	return OO_FAILED;
+   }
    return ret;
 }
 
@@ -2459,17 +2555,18 @@
 
    ooFreeH245Message(call, ph245msg);
    
-   /* Send Close Logical Channel*/
-   ret = ooSendCloseLogicalChannel(call, lChannel);
-   if(ret != OO_OK)
-   {
+   /* Send Close Logical Channel if LogChan is established */
+   if (lChannel->state == OO_LOGICALCHAN_ESTABLISHED) {
+     ret = ooSendCloseLogicalChannel(call, lChannel);
+     if (ret != OO_OK) {
       OOTRACEERR3("ERROR:Failed to build CloseLgicalChannel message(%s, %s)\n",
                    call->callType, call->callToken);
       return OO_FAILED;
-   }
-
-   if(error) return OO_FAILED;
-
+     }
+   }
+   if (error) {
+	return OO_FAILED;
+   }
    return ret;
 }
 
@@ -2677,8 +2774,7 @@
       clc->forwardLogicalChannelNumber, call->callType, call->callToken);
    
    ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
-   if(ret != OO_OK)
-   {
+   if (ret != OO_OK) {
       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
          clc->forwardLogicalChannelNumber, call->callType, call->callToken);
       return OO_FAILED;
@@ -2728,6 +2824,16 @@
                                 H245CloseLogicalChannelAck* clcAck)
 {
    int ret = OO_OK;
+   /* Stop the media transmission */
+   OOTRACEINFO4("Closing logical channel %d (%s, %s)\n",
+                clcAck->forwardLogicalChannelNumber, call->callType,
+                call->callToken);
+   ret = ooClearLogicalChannel(call, clcAck->forwardLogicalChannelNumber);
+   if (ret != OO_OK) {
+      OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
+         clcAck->forwardLogicalChannelNumber, call->callType, call->callToken);
+      return OO_FAILED;
+   }
    return ret;
 }
 
@@ -2789,7 +2895,13 @@
                   call->callType, call->callToken);
                if (ooOnReceivedCloseLogicalChannel(call, 
                                                request->u.closeLogicalChannel) == OO_OK) {
+		if (call->TCSPending && !ooGetTransmitLogicalChannel(call)) {
+			call->TCSPending = FALSE;
+			call->localTermCapState = OO_LocalTermCapExchange_Idle;
+			ooSendTermCapMsg(call);
+		} else if (!call->TCSPending) {
 			ooCloseAllLogicalChannels(call, NULL);
+		}
 	       }
                break;
             case T_H245RequestMessage_requestChannelClose:
@@ -2979,8 +3091,13 @@
                }
                ooOnReceivedCloseChannelAck(call, 
                                            response->u.closeLogicalChannelAck);
-		if(!ooGetTransmitLogicalChannel(call))
+	       if (call->TCSPending && !ooGetReceiveLogicalChannel(call)) {
+			call->TCSPending = FALSE;
+			call->localTermCapState = OO_LocalTermCapExchange_Idle;
+			ooSendTermCapMsg(call);
+	       } else if (!ooGetTransmitLogicalChannel(call)) {
 			ooOpenLogicalChannels(call);
+	       }
                break;
             case T_H245ResponseMessage_requestChannelCloseAck:

[... 1550 lines stripped ...]



More information about the asterisk-commits mailing list