[Asterisk-Users] Several H323 bugfixes - working SIP <-> H.323 translator

Marian Durkovic md at bts.sk
Thu Mar 18 08:35:04 MST 2004


Hi all,

  in an effort to create a SIP <-> H.323 translator we've found and fixed
several problems in H.323 channel. These inlcude:

for SIP->H.323 calls

- no ringback tone 
- ringback not related to H.323 events
- one-way audio with Cisco CallManager
- incorrect Caller ID

for H.323->SIP calls

- not able to establish call with Cisco IOS 12.3(4)T
- ringback not related to SIP events
- no support for 183 Call Progress
- incorrect Caller ID


   Please find the patches against aterisk 0.7.2 release below.


	M.


--------------------------------------------------------------------------
----                                                                  ----
----   Marian Durkovic                       network  manager         ----
----                                                                  ----
----   Slovak Technical University           Tel: +421 2 524 51 301   ----
----   Computer Centre, Nam. Slobody 17      Fax: +421 2 524 94 351   ----
----   812 43 Bratislava, Slovak Republic    E-mail/sip: md at bts.sk    ----
----                                                                  ----
--------------------------------------------------------------------------
-------------- next part --------------
--- chan_h323.h.072	Tue Jan 13 09:46:46 2004
+++ chan_h323.h		Thu Mar 18 16:03:11 2004
@@ -84,6 +84,7 @@
 	function*/
 typedef struct call_options {
 	char		   *callerid;
+	char		   *callername;
 	int				noFastStart;
 	int				noH245Tunnelling;
 	int				noSilenceSuppression;
@@ -101,6 +102,7 @@
 	const char *call_dest_alias;
 	const char *call_source_e164;
 	const char *call_dest_e164;
+	const char *call_source_name;
 	const char *sourceIp;
 } call_details_t;
 
@@ -134,6 +136,11 @@
 typedef void (*start_logchan_cb)(unsigned int, const char *, int);
 start_logchan_cb	on_start_logical_channel; 
 
+/* This is a callback prototype function, called when openh323
+   OnAlerting is invoked */
+typedef void (*chan_ringing_cb)(unsigned);
+chan_ringing_cb		on_chan_ringing;
+
 /* This is a callback protoype function, called when the openh323
    OnConnectionEstablished is inovked */
 typedef void (*con_established_cb)(unsigned);
@@ -167,6 +174,7 @@
  								on_connection_cb,
  								start_logchan_cb,
  								clear_con_cb,
+								chan_ringing_cb,
  								con_established_cb,
  								send_digit_cb);
 
@@ -189,6 +197,8 @@
 	/* H323 create and destroy sessions */
 	int h323_make_call(char *host, call_details_t *cd, call_options_t);
 	int h323_clear_call(const char *);
+	int h323_send_alerting(const char *token);
+	int h323_send_progress(const char *token);
 	int h323_answering_call(const char *token, int);
 	int h323_soft_hangup(const char *data);
 	
-------------- next part --------------
--- chan_h323.c.072	Tue Jan 13 10:24:26 2004
+++ chan_h323.c		Thu Mar 18 16:09:40 2004
@@ -388,7 +389,7 @@
 	int res;
 	struct oh323_pvt *p = c->pvt->pvt;
 	char called_addr[256];
-	char *tmp;
+	char *tmp, *cid, *cidname, oldcid[256];
 
 	strtok_r(dest, "/", &(tmp));
 
@@ -419,15 +420,47 @@
 
 	/* Copy callerid, if there is any */
 	if (c->callerid) {
-		char *tmp = strchr(c->callerid, '"');
-		if (!tmp) {
-			p->calloptions.callerid = malloc(80); // evil
-			// sprintf(p->calloptions.callerid, "\"%s\"", c->callerid);
-			sprintf(p->calloptions.callerid, "\"\" <%s>", c->callerid);
-		} else {
-			p->calloptions.callerid = strdup(c->callerid);
-		}	
-	 }
+                memset(oldcid, 0, sizeof(oldcid));
+                memcpy(oldcid, c->callerid, strlen(c->callerid));
+                oldcid[sizeof(oldcid)-1] = '\0';
+                ast_callerid_parse(oldcid, &cidname, &cid);
+                if (p->calloptions.callerid) {
+                        free(p->calloptions.callerid);
+                        p->calloptions.callerid = NULL;
+                }
+                if (p->calloptions.callername) {
+                        free(p->calloptions.callername);
+                        p->calloptions.callername = NULL;
+                }
+                p->calloptions.callerid = (char*)malloc(256);
+                if (p->calloptions.callerid == NULL) {
+                        ast_log(LOG_ERROR, "Not enough memory.\n");
+                        return(-1);
+                }
+                memset(p->calloptions.callerid, 0, 256);
+                if ((cid != NULL)&&(strlen(cid) > 0))
+                        strncpy(p->calloptions.callerid, cid, 255);
+
+                p->calloptions.callername = (char*)malloc(256);
+                if (p->calloptions.callername == NULL) {
+                        ast_log(LOG_ERROR, "Not enough memory.\n");
+                        return(-1);
+                }
+                memset(p->calloptions.callername, 0, 256);
+                if ((cidname != NULL)&&(strlen(cidname) > 0))
+                        strncpy(p->calloptions.callername, cidname, 255);
+
+        } else {
+                if (p->calloptions.callerid) {
+                        free(p->calloptions.callerid);
+                        p->calloptions.callerid = NULL;
+                }
+                if (p->calloptions.callername) {
+                        free(p->calloptions.callername);
+                        p->calloptions.callername = NULL;
+                }
+        }
+
 
 	res = h323_make_call(called_addr, &(p->cd), p->calloptions);
 
@@ -436,7 +469,6 @@
 		return -1;
 	}
 
-	ast_setstate(c, AST_STATE_RINGING);
 	return 0;
 }
 
@@ -592,27 +624,33 @@
 	
 	switch(condition) {
 	case AST_CONTROL_RINGING:
-		if (c->_state == AST_STATE_RING) {
-		//	transmit_response(p, "180 Ringing", &p->initreq);
+		if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
+			h323_send_alerting(p->cd.call_token);
 			break;
 		}
-		return 0;
+		return -1;    
+	case AST_CONTROL_PROGRESS:
+		if (c->_state != AST_STATE_UP) {
+			h323_send_progress(p->cd.call_token);
+			break;
+		}
+		return -1;
 	case AST_CONTROL_BUSY:
 		if (c->_state != AST_STATE_UP) {
-		//	transmit_response(p, "600 Busy everywhere", &p->initreq);
+			h323_answering_call(p->cd.call_token, 1);
 			p->alreadygone = 1;
-			ast_softhangup(c, AST_SOFTHANGUP_DEV);
+			ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
 			break;
 		}
-		return 0;
+		return -1;
 	case AST_CONTROL_CONGESTION:
 		if (c->_state != AST_STATE_UP) {
-		//	transmit_response(p, "486 Busy here", &p->initreq);
+			h323_answering_call(p->cd.call_token, 1);
 			p->alreadygone = 1;
-			ast_softhangup(c, AST_SOFTHANGUP_DEV);
+			ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
 			break;
 		}
-		return 0;
+		return -1;
 	case -1:
 		return -1;
 	default:
@@ -985,11 +1023,12 @@
 	p->cd.call_dest_alias = cd.call_dest_alias;
 	p->cd.call_source_e164 = cd.call_source_e164;
 	p->cd.call_dest_e164 = cd.call_dest_e164;
+	p->cd.call_source_name = cd.call_source_name;
 
 	if (h323debug) {
 		ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
 		ast_verbose(VERBOSE_PREFIX_3 "	   Call token:  [%s]\n", p->cd.call_token);
-		ast_verbose(VERBOSE_PREFIX_3 "	   Calling party name:  [%s]\n", p->cd.call_source_aliases);
+		ast_verbose(VERBOSE_PREFIX_3 "	   Calling party name:  [%s]\n", p->cd.call_source_name);
 		ast_verbose(VERBOSE_PREFIX_3 "	   Calling party number:  [%s]\n", p->cd.call_source_e164);
 		ast_verbose(VERBOSE_PREFIX_3 "	   Called  party name:  [%s]\n", p->cd.call_dest_alias);
 		ast_verbose(VERBOSE_PREFIX_3 "	   Called  party number:  [%s]\n", p->cd.call_dest_e164);
@@ -1013,7 +1052,7 @@
 		}
 
 
-		sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164);
+		sprintf(p->callerid, "%s <%s>", p->cd.call_source_name, p->cd.call_source_e164);
 
 	} else { 
 		/* Either this call is not from the Gatekeeper 
@@ -1024,7 +1063,7 @@
 
 
 		if (!user) {
-			sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164); 
+			sprintf(p->callerid, "%s <%s>", p->cd.call_source_name, p->cd.call_source_e164); 
 			if (strlen(p->cd.call_dest_e164)) {
 				strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1);
 			} else {
@@ -1064,7 +1103,7 @@
 			if (strlen(user->callerid)) 
 				strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1);
 			else
-				sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164); 
+				sprintf(p->callerid, "%s <%s>", p->cd.call_source_name, p->cd.call_source_e164); 
 
 			if (strlen(p->cd.call_dest_e164)) {
 				strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1);
@@ -1162,8 +1201,38 @@
 	c = p->owner;	
 
 	ast_setstate(c, AST_STATE_UP);
+	ast_queue_control(c, AST_CONTROL_ANSWER, 0);
+
 	return;
 }
+/**
+  *     Call-back function to signal asterisk that the channel is ringing
+
+  * Returns nothing
+  */
+
+void chan_ringing(unsigned call_reference)
+{
+        struct ast_channel *c = NULL;
+        struct oh323_pvt *p = NULL;
+
+        p = find_call(call_reference);
+
+        if (!p)
+                ast_log(LOG_ERROR, "Something is wrong: ringing\n");
+
+
+        if (!p->owner) {
+                ast_log(LOG_ERROR, "Channel has no owner\n");
+                return;
+        }
+        c = p->owner;
+        ast_setstate(c, AST_STATE_RINGING);
+        ast_queue_control(c, AST_CONTROL_RINGING, 0);
+
+        return;
+}
+
 
 /**
   * Call-back function to cleanup communication
@@ -1793,6 +1862,7 @@
 	 			       create_connection, 
 				       setup_rtp_connection, 
 				       cleanup_connection, 
+				       chan_ringing,
 				       connection_made, 
 				       send_digit);	
 	
-------------- next part --------------
--- ast_h323.h.072	Tue Jan 13 04:06:06 2004
+++ ast_h323.h		Thu Mar 18 16:00:46 2004
@@ -198,7 +198,7 @@
 
 	public:
 
-	int MakeCall(const PString &, PString &, unsigned int *, unsigned int, char *);
+	int MakeCall(const PString &, PString &, unsigned int *, unsigned int, char *, char *);
 	BOOL ClearCall(const PString &);
 
 	void OnClosedLogicalChannel(H323Connection &, const H323Channel &);
@@ -252,6 +252,45 @@
 	WORD			   sessionId;
 	BOOL			   bridging;			// Used to help determine which IP to use
 };
+
+class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel {
+
+        PCLASSINFO(MyH323_ExternalRTPChannel, H323_ExternalRTPChannel);
+
+        public:
+    MyH323_ExternalRTPChannel(
+      MyH323Connection & connection,        /// Connection to endpoint for channel
+      const H323Capability & capability,  /// Capability channel is using
+      Directions direction,               /// Direction of channel
+      unsigned sessionID                  /// Session ID for channel
+    );
+    MyH323_ExternalRTPChannel(
+      MyH323Connection & connection,        /// Connection to endpoint for channel
+      const H323Capability & capability,  /// Capability channel is using
+      Directions direction,               /// Direction of channel
+      unsigned sessionID,                 /// Session ID for channel
+      const H323TransportAddress & data,  /// Data address
+      const H323TransportAddress & control/// Control address
+    );
+    /**Create a new channel.
+     */
+    MyH323_ExternalRTPChannel(
+      MyH323Connection & connection,        /// Connection to endpoint for channel
+      const H323Capability & capability,  /// Capability channel is using
+      Directions direction,               /// Direction of channel
+      unsigned sessionID,                 /// Session ID for channel
+      const PIPSocket::Address & ip,      /// IP address of media server
+      WORD dataPort                       /// Data port (control is dataPort+1)
+    ); 
+
+        BOOL OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param);
+
+        PIPSocket::Address externalIpAddress;   // IP address of media server
+        PIPSocket::Address remoteIpAddress;             // IP Address of remote
+        WORD                       externalPort;                // local media s
+        WORD                       remotePort;
+
+}; 
 
 /**
  * The MyProcess is a necessary descendant PProcess class so that the H323EndPoint 
-------------- next part --------------
--- ast_h323.cpp.072	Tue Jan 13 09:31:13 2004
+++ ast_h323.cpp	Thu Mar 18 16:12:58 2004
@@ -219,7 +219,7 @@
   *					port = 1720.
   */
 int MyH323EndPoint::MakeCall(const PString & dest, PString & token, 
-							  			unsigned int *callReference, unsigned int port, char *callerid)
+							  			unsigned int *callReference, unsigned int port, char *callerid, char *callername)
 {
 	PString fullAddress;
 	MyH323Connection * connection;
@@ -243,8 +243,15 @@
 	
 	*callReference = connection->GetCallReference();
 	
-	if (callerid)
-		connection->SetLocalPartyName(PString(callerid));
+	if (callername) {
+                localAliasNames.RemoveAll();
+		connection->SetLocalPartyName(PString(callername));
+	        if (callerid)
+                  localAliasNames.AppendString(PString(callerid));
+        } else if (callerid) {
+                localAliasNames.RemoveAll();
+                connection->SetLocalPartyName(PString(callerid));
+        }
 
 	connection->Unlock(); 	
 
@@ -447,6 +454,8 @@
 	if (noH245Tunnelling)
 		options |= H323Connection::H245TunnelingOptionDisable;
 
+	SetAudioJitterDelay(10, 50);
+
 	return new MyH323Connection(*this, callReference, options);
 }
 
@@ -478,7 +487,7 @@
 {
 	/* The call will be answered later with "AnsweringCall()" function.
 	 */ 
-	return H323Connection::AnswerCallAlertWithMedia;
+	return H323Connection::AnswerCallDeferred;
 }
 
 BOOL  MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
@@ -487,6 +496,7 @@
 	if (h323debug) {
 		cout << "	-- Ringing phone for \"" << username << "\"" << endl;
 	}
+	on_chan_ringing(GetCallReference());
 	return TRUE;
 }
 
@@ -499,6 +509,7 @@
 	
 	call_details_t cd;
 	PString sourceE164;
+	PString sourceName;
 	PString destE164;
 	PString sourceAliases;	
 	PString destAliases;
@@ -511,6 +522,8 @@
 			
 	sourceE164 = "";
 	setupPDU.GetSourceE164(sourceE164);
+	sourceName = "";
+	sourceName=setupPDU.GetQ931().GetDisplayName();
 	destE164 = "";
 	setupPDU.GetDestinationE164(destE164);
 
@@ -538,6 +551,7 @@
 	cd.call_source_e164		= (const char *)sourceE164;
 	cd.call_dest_e164		= (const char *)destE164;
 	cd.sourceIp				= (const char *)sourceIp;
+	cd.call_source_name		= (const char *)sourceName;
 	
 	/* Notify Asterisk of the request */
 	int res = on_incoming_call(cd); 
@@ -683,7 +697,7 @@
 		cout << "		-- SessionID: " << sessionID << endl;
 		cout << "		-- Direction: " << dir << endl;
 	}
-	return new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
+	return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
 }
 
 /** This callback function is invoked once upon creation of each
@@ -717,6 +731,49 @@
 }
 
 
+MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
+                                                 const H323Capability & capability,
+                                                 Directions direction,
+                                                 unsigned id)
+: 
+H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id)
+{   
+} 
+
+MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection, const H323Capability & capability,
+                                                 Directions direction,
+                                                 unsigned id,
+                                                 const H323TransportAddress & data,
+                                                 const H323TransportAddress & control) : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id, data, control)
+{
+} 
+
+MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
+                                                 const H323Capability & capability,
+                                                 Directions direction,
+                                                 unsigned id,
+                                                 const PIPSocket::Address & ip,
+                                                 WORD dataPort)
+  : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id, ip, dataPort)
+{
+}
+
+BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
+{    
+	H323_ExternalRTPChannel::OnReceivedAckPDU(param);
+
+ 	H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddress, remotePort); 
+
+	if (h323debug) {
+		cout << "		-- remoteIpAddress: " << remoteIpAddress << endl;
+		cout << "		-- remotePort: " << remotePort << endl;
+	}
+	/* Notify Asterisk of remote RTP information */
+	on_start_logical_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort);
+
+	return TRUE;	
+} 
+
 /** IMPLEMENTATION OF C FUNCTIONS */
 
 /**
@@ -772,6 +829,7 @@
  			    on_connection_cb   	confunc,
 			    start_logchan_cb   	lfunc,
  			    clear_con_cb	clfunc,
+			    chan_ringing_cb     rfunc,
  			    con_established_cb 	efunc,
  			    send_digit_cb	dfunc)
 {
@@ -780,6 +838,7 @@
 	on_create_connection = confunc;
 	on_start_logical_channel = lfunc;
 	on_connection_cleared = clfunc;
+	on_chan_ringing = rfunc;
 	on_connection_established = efunc;
 	on_send_digit = dfunc;
 }
@@ -1011,7 +1070,7 @@
 	
 	PString dest(host);
 
-	res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid);
+	res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid, call_options.callername);
 	memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
 	
 	return res;
@@ -1026,6 +1085,47 @@
         endPoint->ClearCall(PString(call_token));
 	return 0;
 };
+
+/* Send Alerting PDU to H.323 caller */
+
+int h323_send_alerting(const char *token)
+{
+        const PString currentToken(token);
+        H323Connection * connection;
+
+        connection = endPoint->FindConnectionWithLock(currentToken);
+
+        if (connection == NULL) {
+                cout << "No connection found for " << token << endl;
+                return -1;
+        }
+
+        connection->AnsweringCall(H323Connection::AnswerCallPending);
+        connection->Unlock();
+
+        return 0; 
+
+}
+
+/* Send Progress PDU to H.323 caller */
+
+int h323_send_progress(const char *token)
+{
+        const PString currentToken(token);
+        H323Connection * connection;
+
+        connection = endPoint->FindConnectionWithLock(currentToken);
+
+        if (connection == NULL) {
+                cout << "No connection found for " << token << endl;
+                return -1;
+        }
+
+        connection->AnsweringCall(H323Connection::AnswerCallDeferredWithMedia);
+        connection->Unlock();
+
+        return 0;  
+}
 
 /** This function tells the h.323 stack to either 
     answer or deny an incoming call  */


More information about the asterisk-users mailing list