Index: channels/chan_h323.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_h323.c,v
retrieving revision 1.9
diff -u -r1.9 chan_h323.c
--- channels/chan_h323.c	21 Oct 2003 08:52:51 -0000	1.9
+++ channels/chan_h323.c	10 Nov 2003 15:26:06 -0000
@@ -46,6 +46,7 @@
 #include <asterisk/callerid.h>
 #include <asterisk/cli.h>
 #include <asterisk/dsp.h>
+#include <asterisk/translate.h>
 #include <sys/socket.h>
 #include <net/if.h>
 #include <errno.h>
@@ -59,6 +60,13 @@
 
 #include "h323/chan_h323.h"
 
+/* from rtp.c to translate RTP's payload type to Asterisk's frame subcode */
+struct rtpPayloadType {
+	int isAstFormat; // whether the following code is an AST_FORMAT
+	int code;
+};
+    
+
 /** String variables required by ASTERISK */
 static char *type	= "H323";
 static char *desc	= "The NuFone Network's Open H.323 Channel Driver";
@@ -494,20 +502,32 @@
 	return 0;
 }
 
-static struct ast_frame *oh323_rtp_read(struct oh323_pvt *p)
+/* Pass channel struct too to allow RTCP handling */
+static struct ast_frame *oh323_rtp_read(struct ast_channel *c, struct oh323_pvt *p)
 {
 	/* Retrieve audio/etc from channel.  Assumes p->lock is already held. */
 	struct ast_frame *f;
 	static struct ast_frame null_frame = { AST_FRAME_NULL, };
 
-      /* Only apply it for the first packet, we just need the correct ip/port */
-      if(p->nat)
-      {
-              ast_rtp_setnat(p->rtp,p->nat);
-              p->nat = 0;
-      }
+	/* Only apply it for the first packet, we just need the correct ip/port */
+	if(p->nat)
+	{
+		ast_rtp_setnat(p->rtp,p->nat);
+		p->nat = 0;
+	}
+
+	/* Fetch frame from indicated stream */
+	switch(c->fdno) {
+		case 0: /* RTP stream */
+			f = ast_rtp_read(p->rtp);
+			break;
+		case 1:	/* RTCP stream */
+			f = ast_rtcp_read(p->rtp);
+			break;
+		default:	/* Unknown */
+			f = &null_frame;
+	}
 
-	f = ast_rtp_read(p->rtp);
 	/* Don't send RFC2833 if we're not supposed to */
 	if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & H323_DTMF_RFC2833))
 		return &null_frame;
@@ -515,20 +535,20 @@
 		/* We already hold the channel lock */
 		if (f->frametype == AST_FRAME_VOICE) {
 			if (f->subclass != p->owner->nativeformats) {
+				/* Must be handled on opening logical channel */
 				ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
 				p->owner->nativeformats = f->subclass;
 				ast_set_read_format(p->owner, p->owner->readformat);
-				ast_set_write_format(p->owner, p->owner->writeformat);
+				/* Don't set write format because it will be set up when channel started */
+//				ast_set_write_format(p->owner, p->owner->writeformat);
 			}
 		
 			/* Do in-band DTMF detection */
 			if (p->dtmfmode & H323_DTMF_INBAND) {
-                   f = ast_dsp_process(p->owner,p->vad,f,0);
-				   if (f->frametype == AST_FRAME_DTMF)
+				f = ast_dsp_process(p->owner,p->vad,f,0);
+				if (f->frametype == AST_FRAME_DTMF)
 					ast_log(LOG_DEBUG, "Got in-band digit %c.\n", f->subclass);
-            }
-			
-			
+			}
 		}
 	}
 	return f;
@@ -540,7 +560,8 @@
 	struct ast_frame *fr;
 	struct oh323_pvt *p = c->pvt->pvt;
 	ast_mutex_lock(&p->lock);
-	fr = oh323_rtp_read(p);
+	/* Pass channel structure to handle other streams than just RTP */
+	fr = oh323_rtp_read(c, p);
 	ast_mutex_unlock(&p->lock);
 	return fr;
 }
@@ -549,6 +570,7 @@
 {
 	struct oh323_pvt *p = c->pvt->pvt;
 	int res = 0;
+	int need_frfree = 0;	/* Does ast_frfree() call required? */
 	if (frame->frametype != AST_FRAME_VOICE) {
 		if (frame->frametype == AST_FRAME_IMAGE)
 			return 0;
@@ -558,9 +580,44 @@
 		}
 	} else {
 		if (!(frame->subclass & c->nativeformats)) {
-			ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
-				frame->subclass, c->nativeformats, c->readformat, c->writeformat);
-			return -1;
+			if(!(frame->subclass & c->writeformat)) { /* Someone sent frame with old format */
+				ast_log(LOG_WARNING, "Asked to transmit frame type %s from %s by '%s', while native formats is %s (read/write = %s/%s)\n",
+					ast_getformatname(frame->subclass), frame->src, c->name, ast_getformatname(c->nativeformats), ast_getformatname(c->readformat), ast_getformatname(c->writeformat));
+				return -1;
+			} else {
+				/* Frame goes from RTP is not in our native
+				 * format - try to translate it... Or we must
+				 * just drop it?
+				 */
+
+				/* Sometimes translation table isn't set
+				 * correctly but writeformat is invalid,
+				 * so force required translation allocation
+				 */
+				ast_set_write_format(c, c->nativeformats);
+				ast_set_write_format(c, frame->subclass);
+
+				/* Translate it on-the-fly */
+				if (c->pvt->writetrans) {
+					struct ast_frame *frame1;
+					ast_log(LOG_WARNING, "Asked to transmit frame type %s from %s by '%s', while native formats is %s (read/write = %s/%s) - 2 TRANSLATE\n",
+						ast_getformatname(frame->subclass), frame->src, c->name, ast_getformatname(c->nativeformats), ast_getformatname(c->readformat), ast_getformatname(c->writeformat));
+					/* Allocate new frame with translated context.
+					 * Don't free frame because it will be freed on
+					 * upper layer (RTP).
+					 */
+					frame1 = ast_translate(c->pvt->writetrans, frame, 0);
+					
+					/* Substitute passed frame with translated and
+					 *  mark it for freeing before return */
+					frame = frame1;
+					need_frfree = 1;
+				} else {
+					ast_log(LOG_WARNING, "Asked to transmit frame type %s from %s by '%s', while native formats is %s (read/write = %s/%s)\n",
+						ast_getformatname(frame->subclass), frame->src, c->name, ast_getformatname(c->nativeformats), ast_getformatname(c->readformat), ast_getformatname(c->writeformat));
+					return -1;
+				}
+			}
 		}
 	}
 	if (p) {
@@ -570,6 +627,9 @@
 		}
 		ast_mutex_unlock(&p->lock);
 	}
+	/* Free translated frame */
+	if(need_frfree)
+		ast_frfree(frame);
 	return res;
 }
 
@@ -640,7 +700,13 @@
 			ch->nativeformats = capability;
 		fmt = ast_best_codec(ch->nativeformats);
 		ch->type = type;
+
+		/* RTP stream */
 		ch->fds[0] = ast_rtp_fd(i->rtp);
+
+		/* RTCP stream */
+		ch->fds[1] = ast_rtcp_fd(i->rtp);
+
 		ast_setstate(ch, state);
 		
 		if (state == AST_STATE_RING)
@@ -931,14 +997,14 @@
 
 	info->addr = inet_ntoa(us.sin_addr);
 	info->port = ntohs(us.sin_port);
-
-#if 0
-	printf("  us: %s:%d\n", inet_ntoa(us.sin_addr), ntohs(us.sin_port));
-	printf("them: %s:%d\n", inet_ntoa(them.sin_addr), ntohs(them.sin_port));
+
+#if 0
+	printf("  us: %s:%d\n", inet_ntoa(us.sin_addr), ntohs(us.sin_port));
+	printf("them: %s:%d\n", inet_ntoa(them.sin_addr), ntohs(them.sin_port));
 
 	printf("info: %s:%d\n", info->addr, info->port);	
-#endif
-
+#endif
+
 	return info;
 }
 
@@ -998,8 +1064,8 @@
 			strncpy(p->context, alias->context, sizeof(p->context)-1);
 		}
 
-
-		sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164);
+		/* Asterisk prefers user name to be quoted */
+		sprintf(p->callerid, "\"%s\" <%s>", p->cd.call_source_aliases, p->cd.call_source_e164);
 
 	} else { 
 		/* Either this call is not from the Gatekeeper 
@@ -1010,7 +1076,8 @@
 
 
 		if (!user) {
-			sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164); 
+			/* Asterisk prefers user name to be quoted */
+			sprintf(p->callerid, "\"%s\" <%s>", p->cd.call_source_aliases, p->cd.call_source_e164); 
 			if (strlen(p->cd.call_dest_e164)) {
 				strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1);
 			} else {
@@ -1107,10 +1174,11 @@
   *
   * Returns nothing 
   */
-void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort)
+void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, int direction, int payloadType)
 {
 	struct oh323_pvt *p = NULL;
 	struct sockaddr_in them;
+	struct rtpPayloadType payload;
 
 	/* Find the call or allocate a private structure if call not found */
 	p = find_call(call_reference);
@@ -1123,11 +1191,50 @@
 	them.sin_family = AF_INET;
 	them.sin_addr.s_addr = inet_addr(remoteIp); // only works for IPv4
 	them.sin_port = htons(remotePort);
+
+	/* Find RTP payload <=> asterisk's subcode association */
+	payload = ast_rtp_lookup_pt(p->rtp, payloadType);
+
+	ast_log(LOG_DEBUG, "Setting up %sbound RTP connection for %s:%d with payload %s (RTP code %d)\n", (direction ? "out" : "in"), inet_ntoa(them.sin_addr), remotePort, ast_getformatname(payload.code), payloadType);
+
+	/* Set channel's native codec and prepare translation table
+	 * for given direction and currently used format
+	 */
+	if (p->owner) {
+		if (payload.isAstFormat) {
+			p->owner->nativeformats = payload.code;
+			if(direction)
+				ast_set_write_format(p->owner, p->owner->writeformat);
+			else
+				ast_set_read_format(p->owner, p->owner->readformat);
+		}
+	}
+
 	ast_rtp_set_peer(p->rtp, &them);
 
 	return;
 }
 
+/* Not used for now - set RTP peer's address */
+void setup_rtp_peer(unsigned call_reference, const char *remoteIp, int remotePort)
+{
+	struct oh323_pvt *p = NULL;
+	struct sockaddr_in them;
+
+	/* Find the call or allocate a private structure if call not found */
+	p = find_call(call_reference);
+
+	if (!p) {
+		ast_log(LOG_ERROR, "Something is wrong: rtp\n");
+		return;
+	}
+
+	them.sin_family = AF_INET;
+	them.sin_addr.s_addr = inet_addr(remoteIp); // only works for IPv4
+	them.sin_port = htons(remotePort);
+	ast_rtp_set_peer(p->rtp, &them);
+}
+
 /**  
   *	Call-back function to signal asterisk that the channel has been answered 
   * Returns nothing
@@ -1226,13 +1333,15 @@
 		}
 		ast_mutex_unlock(&iflock);
 
-		pthread_testcancel();
-
 		/* Wait for sched or io */
 		res = ast_sched_wait(sched);
 		if ((res < 0) || (res > 1000))
 			res = 1000;
 		res = ast_io_wait(io, res);
+
+		/* Check for thread cancellation */
+		pthread_testcancel();
+
 		ast_mutex_lock(&monlock);
 		if (res >= 0) 
 			ast_sched_runq(sched);
@@ -1382,7 +1491,7 @@
 	struct oh323_alias *alias = NULL;
 	struct hostent *hp;
 	char *cat;
-    char *utype;
+	char *utype;
 	
 	cfg = ast_load(config);
 
@@ -1394,6 +1503,10 @@
 	
 	h323debug=0;
 	dtmfmode = H323_DTMF_RFC2833;
+	/* Fill global variables with pre-determined values */
+	noFastStart = 0;
+	noH245Tunnelling = 0;
+	noSilenceSuppression = 0;
 
 	memset(&bindaddr, 0, sizeof(bindaddr));
 
@@ -1464,6 +1577,13 @@
 				ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
 				dtmfmode = H323_DTMF_RFC2833;
 			}
+		/* Setup global parameters */
+		} else if (!strcasecmp(v->name, "noFastStart")) {
+			noFastStart = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "noH245Tunneling")) {
+			noH245Tunnelling = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "noSilenceSuppression")) {
+			noSilenceSuppression = ast_true(v->value);
 		}
 		v = v->next;	
 	}
@@ -1676,7 +1796,7 @@
 	ast_rtp_get_us(rtp, &us);
 
 	printf("peer is now: %s:%d\n", inet_ntoa(them.sin_addr), htons(them.sin_port));
-	printf("Us is: %s\n", inet_ntoa(us.sin_addr));
+	printf("Us is: %s:%d\n", inet_ntoa(us.sin_addr), htons(us.sin_port));
 		
 
 	h323_native_bridge(p->cd.call_token, inet_ntoa(them.sin_addr), mode);
Index: channels/h323/ast_h323.cpp
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/h323/ast_h323.cpp,v
retrieving revision 1.25
diff -u -r1.25 ast_h323.cpp
--- channels/h323/ast_h323.cpp	22 Sep 2003 06:21:03 -0000	1.25
+++ channels/h323/ast_h323.cpp	10 Nov 2003 15:26:06 -0000
@@ -1,4 +1,4 @@
-/*
+/*
  * ast_h323.cpp
  *
  * OpenH323 Channel Driver for ASTERISK PBX.
@@ -22,7 +22,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
+ *
  * Version Info: $Id: ast_h323.cpp,v 1.25 2003/09/22 06:21:03 jeremy Exp $
  */
 #include "ast_h323.h"
@@ -41,10 +41,13 @@
 /* DTMF Mode */
 int mode = H323_DTMF_RFC2833;
 
+/* Make those variables accessible from chan_h323.c */
+extern "C" {
 /** Options for connections creation */
 BOOL	noFastStart;
 BOOL	noH245Tunnelling;
 BOOL	noSilenceSuppression;
+}
 
 /**
  * We assume that only one endPoint should exist.
@@ -59,6 +62,26 @@
 /** H.323 listener */
 H323ListenerTCP *tcpListener;
 
+/* Provide common methods to split out non-user parts of OpenH323 aliases */
+static void FormatAliases(PString & aliases)
+{
+	/* Convert complex strings */
+	//  FIXME: deal more than one source alias 
+	char *s;
+	const char *p = (const char *)aliases;
+	if ((s = strchr(p, '(')) != NULL)
+		*s = '\0';
+	else if ((s = strchr(p, '[')) != NULL)
+		*s = '\0';
+	else if ((s = strchr(p, ' ')) != NULL)
+		*s = '\0';
+	else if ((s = strchr(p, '\t')) != NULL)
+		*s = '\0';
+	/* Strip trailing spaces */
+	while((s > p) && (*--s == ' '))
+		*s = '\0';
+}
+
 MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",
              MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
 {
@@ -207,7 +230,7 @@
 	*callReference = connection->GetCallReference();
 	
 	if (callerid)
-		connection->SetLocalPartyName(PString(callerid));
+		connection->SetCID(callerid);	// Use our local function to setup H.323 caller ID correctly
 
 	connection->Unlock(); 	
 
@@ -221,7 +244,16 @@
 
 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
 {
+//  cout << " **** Terminal type: " << terminalType << endl;
   H323EndPoint::SetEndpointTypeInfo(info);
+//  cout << " **** INFO: " << info << endl;
+  /* Because H323EndPoint::SetEndpointTypeInfo() don't set correctly
+     endpoint type, force manual setting it */
+  if(terminalType == e_GatewayOnly)
+  {
+    info.RemoveOptionalField(H225_EndpointType::e_terminal);
+    info.IncludeOptionalField(H225_EndpointType::e_gateway);
+  }
   info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
   info.m_gateway.m_protocol.SetSize(1);
   H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
@@ -268,24 +300,24 @@
 		cout << "		channelsOpen = " << channelsOpen << endl;
 	H323EndPoint::OnClosedLogicalChannel(connection, channel);
 }
-
-BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
- 		const PString & forwardParty,
- 		const H323SignalPDU & pdu)
- {
- 	if (h323debug)
- 	cout << "       -- Call Forwarded to " << forwardParty << endl;
- 	return FALSE;
- }
- 
-BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
- 		const PString & forwardParty,
- 		const H323SignalPDU & pdu)
-{
- 	if (h323debug)
- 		cout << "       -- Forwarding call to " << forwardParty << endl;
- 	return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
-}
+
+BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
+	const PString & forwardParty,
+	const H323SignalPDU & pdu)
+{
+ 	if (h323debug)
+ 	cout << "       -- Call Forwarded to " << forwardParty << endl;
+ 	return FALSE;
+}
+
+BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
+		const PString & forwardParty,
+		const H323SignalPDU & pdu)
+{
+ 	if (h323debug)
+ 		cout << "       -- Forwarding call to " << forwardParty << endl;
+ 	return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
+}
 
 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
 {
@@ -303,14 +335,12 @@
 	
 	call_details_t cd;
 
+	/* Use common alias formatting routine */
+	FormatAliases(remoteName);
+
 	cd.call_reference = connection.GetCallReference();
 	cd.call_token = (const char *)connection.GetCallToken();
-	cd.call_source_aliases = (const char *)connection.GetRemotePartyName();
-	
-	/* Convert complex strings */
-	char *s;
-    if ((s = strchr(cd.call_source_aliases, ' ')) != NULL)
-		*s = '\0';
+	cd.call_source_aliases = (const char *)remoteName;
 
 	/* Invoke the PBX application registered callback */
 	on_connection_cleared(cd);
@@ -404,9 +434,12 @@
 	if (noH245Tunnelling)
 		options |= H323Connection::H245TunnelingOptionDisable;
 
+	/* Set silence detection mode - won't work for Asterisk's RTP but can be used in the negotiation process */
+	SetSilenceDetectionMode(noSilenceSuppression ? H323AudioCodec::NoSilenceDetection : H323AudioCodec::AdaptiveSilenceDetection);		
+
 	return new MyH323Connection(*this, callReference, options);
 }
-
+
 /* MyH323Connection */    
 MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
 										   unsigned callReference,
@@ -430,6 +463,37 @@
 	return;
 }
 
+/* Declare reference to standard Asterisk's callerid parser */
+extern "C" {
+	void ast_callerid_parse(const char *, char **, char **);
+}
+
+/*
+ * Setup H.323 caller ID to allow OpenH323 to set up Q.931's
+ * IE:DisplayName and IE:DisplayNumber fields correctly
+ */
+void MyH323Connection::SetCID(const char *callerid)
+{
+	char *name;
+	char *num;
+
+	ast_callerid_parse(callerid, &name, &num);
+
+	if (h323debug)
+		cout << "name=" << name << ", num=" << num << endl;
+
+	if ((name && *name) || (num && *num))
+	{
+		localAliasNames.RemoveAll();
+		if(name && *name) {
+			SetLocalPartyName(PString(name));
+//			localAliasNames.AppendString(name);
+		}
+		if(num && *num)
+			localAliasNames.AppendString(PString(num));
+	}
+}
+
 H323Connection::AnswerCallResponse	MyH323Connection::OnAnswerCall(const PString & caller,
 																   const H323SignalPDU & /*setupPDU*/,
 																   H323SignalPDU & /*connectPDU*/)
@@ -472,18 +536,9 @@
 	destE164 = "";
 	setupPDU.GetDestinationE164(destE164);
 
-	/* Convert complex strings */
-	//  FIXME: deal more than one source alias 
-	char *s; 
-    if ((s = strchr(sourceAliases, ' ')) != NULL)
-                *s = '\0';
-    if ((s = strchr(sourceAliases, '\t')) != NULL)
-                *s = '\0';
-	char *s1;
-    if ((s1 = strchr(destAliases, ' ')) != NULL)
-         *s1 = '\0';
-	if ((s1 = strchr(destAliases, '\t')) != NULL)
-         *s1 = '\0';
+	/* Use common alias formatting routine */
+	FormatAliases(sourceAliases);
+	FormatAliases(destAliases);
 
 	GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
 
@@ -524,18 +579,9 @@
 	destE164 = "";
 	setupPDU.GetDestinationE164(destE164);
 
-	/* Convert complex strings */
-	//  FIXME: deal more than one source alias 
-	char *s; 
-    if ((s = strchr(sourceAliases, ' ')) != NULL)
-                *s = '\0';
-    if ((s = strchr(sourceAliases, '\t')) != NULL)
-                *s = '\0';
-	char *s1;
-    if ((s1 = strchr(destAliases, ' ')) != NULL)
-         *s1 = '\0';
-	if ((s1 = strchr(destAliases, '\t')) != NULL)
-         *s1 = '\0';
+	/* Use common alias formatting routine */
+	FormatAliases(sourceAliases);
+	FormatAliases(destAliases);
 
 	cd.call_reference		= GetCallReference();
 	cd.call_token			= (const char *)GetCallToken();
@@ -619,27 +665,27 @@
 														     unsigned sessionID,
 														     const H245_H2250LogicalChannelParameters * /*param*/)
 {
-	struct rtp_info *info;
-	WORD port;
+	struct rtp_info *info;
+	WORD port;
 
 	/* Determine the Local (A side) IP Address and port */
 	info = on_create_connection(GetCallReference()); 
-	
-//	if (bridging) {
-//		externalIpAddress = PIPSocket::Address(info->addr);
-//	} else {
-        GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
-//	}
-
-//	externalIpAddress = PIPSocket::Address("192.168.1.50");
-
-	externalPort = info->port;
+	
+//	if (bridging) {
+//		externalIpAddress = PIPSocket::Address(info->addr);
+//	} else {
+        GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
+//	}
+
+//	externalIpAddress = PIPSocket::Address("192.168.1.50");
+
+	externalPort = info->port;
 	
 	if (h323debug) {
 		cout << "	=*= In CreateRealTimeLogicalChannel for call " << GetCallReference() << endl;
 		cout << "		-- externalIpAddress: " << externalIpAddress << endl;
 		cout << "		-- externalPort: " << externalPort << endl;
-		cout << "		-- SessionID: " << sessionID << endl;
+		cout << "		-- SessionID: " << sessionID << endl;
 		cout << "		-- Direction: " << dir << endl;
 	}
 	return new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
@@ -651,7 +697,8 @@
 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
 {    
 	if (h323debug) {
-		cout << "	 -- Started logical channel: ";	
+		/* Show H.323 channel number to make debugging more comfortable */
+		cout << "	 -- Started logical channel " << channel.GetNumber() << ": ";	
 		cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" ")); 
 		cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
 	}
@@ -661,7 +708,7 @@
 		cout <<  "		-- channelsOpen = " << channelsOpen << endl;
 	
 	H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
-    external.GetRemoteAddress(remoteIpAddress, remotePort); 
+	external.GetRemoteAddress(remoteIpAddress, remotePort); 
 
 	if (h323debug) {
 		cout << "		-- remoteIpAddress: " << remoteIpAddress << endl;
@@ -669,8 +716,40 @@
 		cout << "		-- ExternalIpAddress: " << externalIpAddress << endl;
 		cout << "		-- ExternalPort: " << externalPort << endl;
 	}
+
+	/* Try to determine negotiated RTP payload format to configure
+	 * RTP stack more quickly (not to wait at least one packet with
+	 * filled RTP payload
+	 */
+	RTP_DataFrame::PayloadTypes payloadType = channel.GetCapability().GetPayloadType();
+	if (payloadType == RTP_DataFrame::IllegalPayloadType) {
+		channel.GetCodec()->GetMediaFormat().GetPayloadType();
+	}
+	if (payloadType == RTP_DataFrame::IllegalPayloadType) {
+		OpalMediaFormat mediaFormat = channel.GetCodec()->GetMediaFormat();
+//		if (mediaFormat.GetPayloadType() < RTP_DataFrame::???)
+			payloadType = mediaFormat.GetPayloadType();
+	}
+	if (payloadType == RTP_DataFrame::IllegalPayloadType) {
+		OpalMediaFormat OMF((const char *)(channel.GetCapability()).GetFormatName(), 1);
+		if (OMF.IsValid())
+			payloadType = OMF.GetPayloadType();
+	}
+
+	/* Deduce direction of starting channel */
+	int direction;
+	if (channel.GetDirection()==H323Channel::IsTransmitter)
+		direction = 1;
+	else if (channel.GetDirection()==H323Channel::IsReceiver)
+		direction = 0;
+	else
+		direction = -1;
+
 	/* Notify Asterisk of remote RTP information */
-	on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort);
+	/* direction and payload arguments needs to
+	 * correctly setup RTP transport
+	 */
+	on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort, direction, (int)payloadType);
 
 	return TRUE;	
 }
@@ -751,30 +830,31 @@
 }
 	
 /** Installs the callback functions on behalf of the PBX application  */
-void h323_callback_register(setup_incoming_cb  ifunc,
-							setup_outbound_cb  sfunc,
-							on_connection_cb   confunc,
-							start_logchan_cb   lfunc,
- 							clear_con_cb	   clfunc,
- 							con_established_cb efunc,
- 							send_digit_cb	   dfunc)
+void h323_callback_register(setup_incoming_cb  ifunc,
+							setup_outbound_cb  sfunc,
+							on_connection_cb   confunc,
+							start_logchan_cb   lfunc,
+ 							clear_con_cb	   clfunc,
+ 							con_established_cb efunc,
+ 							send_digit_cb	   dfunc)
 {
 	on_incoming_call = ifunc;
-	on_outgoing_call = sfunc;
+	on_outgoing_call = sfunc;
 	on_create_connection = confunc;
 	on_start_logical_channel = lfunc;
 	on_connection_cleared = clfunc;
 	on_connection_established = efunc;
 	on_send_digit = dfunc;
 }
-
+
 /**
  * Add capability to the capability table of the end point. 
  */
 int h323_set_capability(int cap, int dtmfMode)
 {
 	int g711Frames = 30;
-    int gsmFrames  = 4;
+	int gsmFrames  = 4;
+	PINDEX last_cap = -1;	/* last common capability block index */
 
 	
 	if (!end_point_exist()) {
@@ -782,61 +862,75 @@
 		return 1;
 	}
 
-	mode = dtmfMode;
-	if (dtmfMode == H323_DTMF_INBAND)
-	    endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
-	else
-		endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
-	 
+	/* User input mode moved to the end of procedure */
+
 
 	/* Hardcode this for now (Someone tell me if T.38 works now 
 	   or provide me with some debug so we can make this work */
 
-//	endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
+//	last_cap = endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
 	
 	if (cap & AST_FORMAT_SPEEX) {
 		/* Not real sure if Asterisk acutally supports all
 		   of the various different bit rates so add them 
 		   all and figure it out later*/
 
-		endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
-		endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
-		endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
-		endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
-		endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
+		last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
+		last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
+		last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
+		last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
+		last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
 	}
 
 #if WANT_G729
 	if (cap & AST_FORMAT_G729A) {
 		H323_G729ACapability *g729aCap;
-		endPoint->SetCapability(0, 0, g729aCap = new H323_G729ACapability);
+		last_cap = endPoint->SetCapability(0, 0, g729aCap = new H323_G729ACapability);
 	}
 #endif
 	
 	if (cap & AST_FORMAT_G723_1) {
 		H323_G7231Capability *g7231Cap;
-		endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
+		last_cap = endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
 	} 
 
 	if (cap & AST_FORMAT_GSM) {
 		H323_GSM0610Capability *gsmCap;
-	    endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
-	    gsmCap->SetTxFramesInPacket(gsmFrames);
+		last_cap = endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
+		gsmCap->SetTxFramesInPacket(gsmFrames);
 	} 
 
 	if (cap & AST_FORMAT_ULAW) {
 
 		H323_G711Capability *g711uCap;
-	    endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
+		last_cap = endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
 		g711uCap->SetTxFramesInPacket(g711Frames);
 	} 
 
 	if (cap & AST_FORMAT_ALAW) {
 		H323_G711Capability *g711aCap;
-		endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
+		last_cap = endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
 		g711aCap->SetTxFramesInPacket(g711Frames);
 	} 
 
+	/* Add HookFlash capability - not used yet now */
+	last_cap++;
+	last_cap = endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
+
+	/* Add correct UserInputMode capability
+	 * This allows remote party to send UserInput with
+	 * correctly embedded into protocol
+	 */
+	last_cap++;
+	mode = dtmfMode;
+	if (dtmfMode == H323_DTMF_INBAND) {
+		endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
+		endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
+	} else {
+		endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
+		endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
+	}
+	 
 	return 0;
 }
 
@@ -1058,24 +1152,24 @@
 {
 	H323Channel *channel;
 	MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
-	PString mode(capability);
-	
-	if (!mode) {
-		return;
-	}
-
-	if (!connection){
-		cout << "ERROR: No connection found, this is bad\n";
-		return;
-	}
-
-	cout << "Native Bridge:  them [" << them << "]" << endl; 
-
-	channel = connection->FindChannel(connection->sessionId, TRUE);
-	connection->bridging = TRUE;
-	connection->CloseLogicalChannelNumber(channel->GetNumber());
-	connection->RequestModeChange(mode);	
-	connection->Unlock();
+	PString mode(capability);
+	
+	if (!mode) {
+		return;
+	}
+
+	if (!connection){
+		cout << "ERROR: No connection found, this is bad\n";
+		return;
+	}
+
+	cout << "Native Bridge:  them [" << them << "]" << endl; 
+
+	channel = connection->FindChannel(connection->sessionId, TRUE);
+	connection->bridging = TRUE;
+	connection->CloseLogicalChannelNumber(channel->GetNumber());
+	connection->RequestModeChange(mode);	
+	connection->Unlock();
 	return;
 
 }
Index: channels/h323/ast_h323.h
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/h323/ast_h323.h,v
retrieving revision 1.11
diff -u -r1.11 ast_h323.h
--- channels/h323/ast_h323.h	22 Sep 2003 23:19:27 -0000	1.11
+++ channels/h323/ast_h323.h	10 Nov 2003 15:26:06 -0000
@@ -147,6 +147,8 @@
 	void SendUserInputTone(char, unsigned);
 	void OnUserInputTone(char, unsigned, unsigned, unsigned);
 	void OnUserInputString(const PString &value);
+	/* Set up H.323 caller id */
+	void SetCID(const char *callerid);	
 
 	PString sourceAliases;
 	PString destAliases;
Index: channels/h323/chan_h323.h
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/h323/chan_h323.h,v
retrieving revision 1.11
diff -u -r1.11 chan_h323.h
--- channels/h323/chan_h323.h	22 Sep 2003 06:21:03 -0000	1.11
+++ channels/h323/chan_h323.h	10 Nov 2003 15:26:06 -0000
@@ -23,7 +23,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * Version Info: $Id: chan_h323.h,v 1.11 2003/09/22 06:21:03 jeremy Exp $
+ * Version Info: $Id: chan_h323.h,v 1.11 2003/09/22 06:21:03 jeremy Exp $
  */
 
 #include <arpa/inet.h>
@@ -84,7 +84,7 @@
 /** call_option struct is filled from the 
 	PBX application and passed through make_call 
 	function*/
-typedef struct call_options {
+typedef struct call_options {
 	char		   *callerid;
 	int				noFastStart;
 	int				noH245Tunnelling;
@@ -97,7 +97,7 @@
 	asterisk channels to acutal h.323 connections */
 typedef struct call_details {	
 	unsigned int call_reference;
-
+
 	const char *call_token;				
 	const char *call_source_aliases;
 	const char *call_dest_alias;
@@ -105,11 +105,11 @@
 	const char *call_dest_e164;
 	const char *sourceIp;
 } call_details_t;
-
-typedef struct rtp_info {
-	char *addr;
-	unsigned int port;
-} rtp_info_t;
+
+typedef struct rtp_info {
+	char *addr;
+	unsigned int port;
+} rtp_info_t;
 
 /* This is a callback prototype function, called pass
    DTMF down the RTP. */
@@ -130,10 +130,12 @@
    an outbound call. */
 typedef int (*setup_outbound_cb)(call_details_t);
 setup_outbound_cb	on_outgoing_call; 
-
+
 /* This is a callback prototype function, called when the openh323 
-   OnStartLogicalChannel is invoked. */
-typedef void (*start_logchan_cb)(unsigned int, const char *, int);
+   OnStartLogicalChannel is invoked.
+   2 more arguments - direction and payload type.
+*/
+typedef void (*start_logchan_cb)(unsigned int, const char *, int, int, int);
 start_logchan_cb	on_start_logical_channel; 
 
 /* This is a callback protoype function, called when the openh323
@@ -146,15 +148,30 @@
 typedef void (*clear_con_cb)(call_details_t);
 clear_con_cb		on_connection_cleared;
 
+/* This is a callback prototype function, called when the openh323 
+   OnReceivedAckPDU is invoked. */
+typedef void (*setup_rtp_cb)(unsigned int, const char *, int);
+setup_rtp_cb		on_setup_rtp_peer; 
+
 /* debug flag */
 int h323debug;
 
 #define H323_DTMF_RFC2833	(1 << 0)
 #define H323_DTMF_INBAND	(1 << 1)
 
+/* Required to declare global variables from chan_h323.c */
+#ifndef BOOL
+#define BOOL int
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif   
+
+	/* chan_h323 global parameters */
+	extern BOOL noFastStart;
+	extern BOOL noH245Tunnelling;
+	extern BOOL noSilenceSuppression;
     
 	void h323_gk_urq(void);
 	void h323_end_point_create(void);
@@ -164,14 +181,14 @@
 	void h323_debug(int, unsigned);
 
 	/* callback function handler*/
-	void h323_callback_register(setup_incoming_cb,
- 								setup_outbound_cb,
- 								on_connection_cb,
- 								start_logchan_cb,
- 								clear_con_cb,
- 								con_established_cb,
- 								send_digit_cb);
-
+	void h323_callback_register(setup_incoming_cb,
+ 								setup_outbound_cb,
+ 								on_connection_cb,
+ 								start_logchan_cb,
+ 								clear_con_cb,
+ 								con_established_cb,
+ 								send_digit_cb);
+
 
 	int h323_set_capability(int, int);
 	int h323_set_alias(struct oh323_alias *);
@@ -181,7 +198,7 @@
 
 	/* H323 listener related funcions */
 	int h323_start_listener(int, struct sockaddr_in);
-
+
 	void h323_native_bridge(const char *, char *, char *);
 
 	/* Send a DTMF tone to remote endpoint */
