[Asterisk-Dev] Zombie channel doesn't free

Miroslaw KLABA totoro at ovh.net
Sat May 3 09:41:10 MST 2003


Hello,

I have a problem with zombie channels. I've maid a try to transfer calls on chan_h323 and
it's nearly done. I miss just why the zombie calls doesn't hangup.

I use ast_chan_masquerade to make the transfer and it works well. But a ZOMBIE is created
from the channel previously used and evezn if I hangup each side of the call, the ZOMBIE
doesn't free.

-When I have a call, it's like this:

*CLI> show channels
        Channel  (Context    Extension    Pri )   State Appl.         Data           
      H323/miro  (                        1   )      Up Bridged Call  H323/ip$10.48.200.101:2244/17768
H323/ip$10.48.200.101:2244/17768  (remote     s            5   )      Up Dial          H323/miro|15   
2 active channel(s)

-When the transfer is done:

*CLI> show channels
        Channel  (Context    Extension    Pri )   State Appl.         Data           
H323/miro<ZOMBIE>  (                        1   ) Ringing (None)        (None)         
      H323/oles  (                        1   )      Up Bridged Call  H323/ip$10.48.200.101:2244/17768
H323/ip$10.48.200.101:2244/17768  (remote     s            5   )      Up Dial          H323/miro|15   
3 active channel(s)

-And when both parties are hanged up:

*CLI> show channels
        Channel  (Context    Extension    Pri )   State Appl.         Data           
H323/miro<ZOMBIE>  (                        1   ) Ringing (None)        (None)         
1 active channel(s)

The channels is still here but the phone that transfered the call has cleared the call so there's
nobody at the other end.

How can I free it?

Thanks
Miro

PS: I attach the patch against asterisk-0.4.0 but it's not yet usable because of the
zombie problem and some cleanup...

PS2: Tell me also if there's something wrong in the code...
-------------- next part --------------
diff -ur /temp/asterisk/asterisk-0.4.0/channels/h323/ast_h323.cpp h323/ast_h323.cpp
--- /temp/asterisk/asterisk-0.4.0/channels/h323/ast_h323.cpp	Tue Apr  8 20:22:39 2003
+++ h323/ast_h323.cpp	Sat May  3 18:05:34 2003
@@ -242,6 +242,81 @@
 	return capabilities;
 }
 
+H323Connection * MyH323EndPoint::SetupTransfer(const PString & token, const PString & callIdentity, const PString & remoteParty, PString & newToken, void * userData)
+{
+	PString fullAddress;
+	PString alias;
+	H323TransportAddress address;
+	
+	H323Connection *newH323Con;
+	H323Connection *oldH323Con; 
+
+	PINDEX at = remoteParty.FindLast('@');
+	if (remoteParty.GetLength() == at+1)
+		fullAddress = remoteParty.Left(at);
+	else
+		fullAddress = remoteParty;
+	    
+	if (h323debug) {
+		cout << "	-- Setup transfer of	" << callIdentity << ":" << endl;
+		cout << "	-- Call from	" << token << endl;
+		cout << "	-- Call to	" << fullAddress << endl;
+		cout << "	-- NewToken	" << newToken << endl;
+	}
+
+
+
+	
+	if (GetGatekeeper() != NULL) {
+		if (h323debug)
+			cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
+	} else {
+		if (h323debug)
+			cout << " -- Making call to " << fullAddress << "." << endl;
+	}
+	
+	// Making call to remoteParty
+	if (!H323EndPoint::MakeCall(fullAddress, newToken)) {
+		if (h323debug)
+			cout << "Error making call to \"" << fullAddress << '"' << endl;
+		return NULL;
+	}
+	
+	newH323Con = FindConnectionWithLock(newToken);
+	oldH323Con = FindConnectionWithLock(token);
+
+	if (newH323Con != NULL && oldH323Con != NULL) {
+		unsigned int new_call_reference = newH323Con->GetCallReference();
+		unsigned int old_call_reference = oldH323Con->GetCallReference();
+		if (h323debug) {
+			cout << " -- New call reference " << new_call_reference << endl;
+			cout << " -- Old call reference " << old_call_reference << endl;
+			cout << " -- NewToken " << newToken << endl;
+		}
+		newH323Con->Unlock();
+		oldH323Con->Unlock();
+		// Setup transfer then
+		if (setup_transfer(old_call_reference, new_call_reference, fullAddress)) {
+			if (h323debug)
+				cout << "	-- Transfer succeded" << endl;
+			return newH323Con;
+		} else {
+			if (h323debug)
+				cout << "	-- Transfer failed " << endl;
+			return NULL;
+		}
+	} else {
+		//Clean all mess
+		if (newH323Con != NULL)
+			newH323Con->Unlock();
+		if (oldH323Con != NULL)
+			oldH323Con->Unlock();
+		if (h323debug)
+			cout << "Error making call to \"" << fullAddress << '"' << endl;
+		return NULL;
+	}
+}
+
 BOOL MyH323EndPoint::ClearCall(const PString & token)
 {
 	if (h323debug)
@@ -268,6 +343,20 @@
 	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);
+}
+
 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
 {
 	if (h323debug)
@@ -298,6 +387,8 @@
 
 	switch (connection.GetCallEndReason()) {
 		case H323Connection::EndedByCallForwarded :
+			if (h323debug)
+				cout << " -- " << remoteName << " has forwarded the call" << endl;
 			break;
 		case H323Connection::EndedByRemoteUser :
 			if (h323debug)
@@ -535,6 +626,13 @@
 	return H323Connection::OnSendSignalSetup(setupPDU);
 }
 
+BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
+{
+	if (h323debug)
+		cout << "	-- Received Facility message... " << endl;
+	return H323Connection::OnReceivedFacility(pdu);
+}
+
 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
 {
 	if (h323debug)
diff -ur /temp/asterisk/asterisk-0.4.0/channels/h323/ast_h323.h h323/ast_h323.h
--- /temp/asterisk/asterisk-0.4.0/channels/h323/ast_h323.h	Mon Mar 31 09:13:36 2003
+++ h323/ast_h323.h	Thu May  1 16:05:22 2003
@@ -62,6 +62,8 @@
 /*! SpeeX Free Compression */
 #define AST_FORMAT_SPEEX	(1 << 9)
 
+class MyH323EndPoint;
+class MyH323Connection;
 
 /**This class describes the G.723.1 codec capability.
  */
@@ -103,10 +105,13 @@
 	public:
 
 	int MakeCall(const PString &, PString &, unsigned int *, unsigned int);
+	H323Connection * SetupTransfer(const PString &, const PString &, const PString &, PString &, void *);
 	BOOL ClearCall(const PString &);
 //	BOOL OnIncomingCall( H323Connection & connection, const H323SignalPDU &, H323SignalPDU &);
 
 	void OnClosedLogicalChannel(H323Connection &, const H323Channel &);
+	BOOL OnConnectionForwarded(H323Connection &, const PString &, const H323SignalPDU &);
+	BOOL ForwardConnection(H323Connection &, const PString &, const H323SignalPDU &);
 	void OnConnectionEstablished(H323Connection &, const PString &);
 	void OnConnectionCleared(H323Connection &, const PString &);
 	H323Connection * CreateConnection(unsigned, void *);
@@ -119,7 +124,6 @@
     void SetGateway(void);
 };
 
-  
 class MyH323Connection : public H323Connection {
 
 	PCLASSINFO(MyH323Connection, H323Connection);
@@ -134,6 +138,7 @@
 	BOOL OnAlerting(const H323SignalPDU &, const PString &);
 	BOOL OnReceivedSignalSetup(const H323SignalPDU &);
 	void OnReceivedReleaseComplete(const H323SignalPDU &);
+	BOOL OnReceivedFacility(const H323SignalPDU &);
 	BOOL OnSendSignalSetup(H323SignalPDU &);
 	BOOL OnStartLogicalChannel(H323Channel &);
 	BOOL OnClosingLogicalChannel(H323Channel &);
diff -ur /temp/asterisk/asterisk-0.4.0/channels/h323/chan_h323.c h323/chan_h323.c
--- /temp/asterisk/asterisk-0.4.0/channels/h323/chan_h323.c	Fri Apr 11 06:12:41 2003
+++ h323/chan_h323.c	Sat May  3 18:01:23 2003
@@ -45,6 +45,7 @@
 #include <asterisk/callerid.h>
 #include <asterisk/cli.h>
 #include <asterisk/dsp.h>
+#include <asterisk/musiconhold.h>
 #include <sys/socket.h>
 #include <net/if.h>
 #include <errno.h>
@@ -404,7 +405,7 @@
 	res = h323_make_call(called_addr, &(p->cd), p->call_opt);
 
 	if (res) {
-		printf("h323_make_call failed\n");
+		ast_log(LOG_DEBUG, "h323_make_call failed(%s)\n", c->name);
 		return -1;
 	}
 
@@ -463,6 +464,15 @@
 			ast_log(LOG_DEBUG, "ClearCall failed.\n");
 		p->needdestroy = 1;
 	}
+	
+	/* Update usage counter */
+	ast_pthread_mutex_lock(&usecnt_lock);
+	usecnt--;
+	if (usecnt < 0)
+		ast_log(LOG_WARNING, "Usecnt < 0???\n");
+	ast_pthread_mutex_unlock(&usecnt_lock);
+	ast_update_use_count();
+
 
 	
 	ast_pthread_mutex_unlock(&p->lock);
@@ -1028,6 +1038,82 @@
 #endif
 
 /**
+ * Call-back function that transfers the call
+ *
+ *
+ */
+int setup_transfer(unsigned call_reference, unsigned new_call_reference, const char * fullAddress)
+{
+	/* Find the call with token */
+	struct oh323_pvt *p1, *p2;
+	struct ast_channel *c;
+
+	p1=find_call(call_reference);
+
+	if (!p1) {
+		ast_log(LOG_WARNING, "No such call %d\n", call_reference);
+		return 0;
+	}
+
+	p2=oh323_alloc(new_call_reference);
+        if (!p2) {
+		ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
+		return 0;
+	}
+
+	/* Assign a default capability */
+	p2->capability = capability;
+	p2->outgoing = 1;
+
+	if (p2->dtmfmode) {
+		if (p2->dtmfmode & H323_DTMF_RFC2833)
+			p2->nonCodecCapability |= AST_RTP_DTMF;
+		else
+			p2->nonCodecCapability &= ~AST_RTP_DTMF;
+	}
+			
+	/* Clear the call token */
+	if ((p2->cd).call_token == NULL)
+		(p2->cd).call_token = (char *)malloc(128);
+
+	memset((char *)(p2->cd).call_token, 0, 128);
+	
+	if (p2->cd.call_token == NULL) {
+		ast_log(LOG_ERROR, "Not enough memory.\n");
+		return -1;
+	}
+
+	p2->cd.call_token = fullAddress;
+	c = oh323_new(p2, AST_STATE_DOWN, p2->cd.call_token);
+	if (!c){
+		ast_log(LOG_WARNING, "Couldn't create channel. This is bad\n");
+//		oh323_destroy(p2);
+		return 0;
+	}
+
+	if (!p1->owner || !p2->owner) {
+		ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
+		oh323_destroy(p2);
+		return 0;
+	}
+
+	if (p1->owner->bridge){
+		ast_moh_stop(p1->owner->bridge);
+		ast_moh_stop(p2->owner);
+		ast_moh_stop(p1->owner);
+		if (ast_channel_masquerade(p1->owner, p2->owner)) {
+			ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", p1->owner->name, p2->owner->name);
+			return 0;
+		}
+		ast_setstate(c, AST_STATE_RINGING);
+	} else {
+		ast_log(LOG_WARNING, "Transfer attempted with call bridged yet\n");
+		return 0;
+	}
+	return 1;
+}
+
+/**
   * Call-back function that gets called for each rtp channel opened 
   *
   * Returns nothing 
@@ -1123,6 +1209,13 @@
 	}
 	
 	p->alreadygone = 1;
+	
+#if 0
+	if (p->owner->masq) {
+		ast_queue_hangup(p->owner->masq,1);
+		p->owner->masq = NULL;
+	}
+#endif
 
 	/* Send hangup */	
 	if (p->owner)
@@ -1667,6 +1760,11 @@
 		ast_log(LOG_WARNING, "Unable to lock the interface list\n");
 		return -1;
 	}
+
+	delete_users();
+	delete_aliases();
+	prune_peers();
+				
 		
 	if (!ast_pthread_mutex_lock(&iflock)) {
 		/* destroy all the interfaces and free their memory */
@@ -1685,6 +1783,17 @@
 	}
 	h323_gk_urq();
 	h323_end_process();
+	
+	/* unregister rtp */
+	ast_rtp_proto_unregister(&oh323_rtp);
+	
+	/* unregister commands */
+	ast_cli_unregister(&cli_debug);
+	ast_cli_unregister(&cli_no_debug);
+	ast_cli_unregister(&cli_trace);
+	ast_cli_unregister(&cli_no_trace);
+	ast_cli_unregister(&cli_show_codecs);
+	ast_cli_unregister(&cli_gk_cycle);
 
 	/* unregister channel type */
 	ast_channel_unregister(type);
diff -ur /temp/asterisk/asterisk-0.4.0/channels/h323/chan_h323.h h323/chan_h323.h
--- /temp/asterisk/asterisk-0.4.0/channels/h323/chan_h323.h	Mon Mar 31 22:26:08 2003
+++ h323/chan_h323.h	Sat May  3 18:04:50 2003
@@ -153,7 +153,9 @@
 	void h323_end_point_create(void);
 	void h323_end_process(void);
 	int end_point_exist(void);
-    
+
+	int setup_transfer(unsigned, unsigned, const char *);
+
 	void h323_debug(int, unsigned);
 
 	/* callback function handler*/


More information about the asterisk-dev mailing list