ast_h323.cpp

来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· C++ 代码 · 共 1,533 行 · 第 1/3 页

CPP
1,533
字号
#define _GNU_SOURCE/* * ast_h323.cpp * * OpenH323 Channel Driver for ASTERISK PBX. *			By  Jeremy McNamara *			For The NuFone Network *  * chan_h323 has been derived from code created by *               Michael Manousos and Mark Spencer * * This file is part of the chan_h323 driver for Asterisk * * chan_h323 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version.  * * chan_h323 is distributed WITHOUT ANY WARRANTY; without even  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  * PURPOSE. See the GNU General Public License for more details.  * * 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 7221 2005-11-29 18:24:39Z kpfleming $ */#include <arpa/inet.h>#include <list>#include <string>#include <algorithm>#include <ptlib.h>#include <h323.h>#include <h323pdu.h>#include <mediafmt.h>#include <lid.h>#ifdef __cplusplusextern "C" {#endif#include "asterisk/logger.h"#include "asterisk/channel.h"#ifdef __cplusplus}#endif#include "chan_h323.h"#include "ast_h323.h"/* PWlib Required Components  */#define MAJOR_VERSION 1#define MINOR_VERSION 0#define BUILD_TYPE    ReleaseCode#define BUILD_NUMBER  0/** Counter for the number of connections */int channelsOpen;/* DTMF Mode */int mode = H323_DTMF_RFC2833;/** * We assume that only one endPoint should exist. * The application cannot run the h323_end_point_create() more than once * FIXME: Singleton this, for safety */MyH323EndPoint *endPoint = NULL;/** PWLib entry point */MyProcess *localProcess = NULL;class PAsteriskLog : public PObject, public iostream {	PCLASSINFO(PAsteriskLog, PObject);	public:	PAsteriskLog() : iostream(cout.rdbuf()) { init(&buffer); }	~PAsteriskLog() { flush(); }	private:	PAsteriskLog(const PAsteriskLog &) : iostream(cout.rdbuf()) { }	PAsteriskLog & operator=(const PAsteriskLog &) { return *this; }	class Buffer : public streambuf {		public:		virtual int overflow(int=EOF);		virtual int underflow();		virtual int sync();		PString string;	} buffer;	friend class Buffer;};static PAsteriskLog *logstream = NULL;int PAsteriskLog::Buffer::overflow(int c){	if (pptr() >= epptr()) {		int ppos = pptr() - pbase();		char *newptr = string.GetPointer(string.GetSize() + 2000);		setp(newptr, newptr + string.GetSize() - 1);		pbump(ppos);	}	if (c != EOF) {		*pptr() = (char)c;		pbump(1);	}	return 0;}int PAsteriskLog::Buffer::underflow(){	return EOF;}int PAsteriskLog::Buffer::sync(){	char *str = strdup(string);	char *s, *s1;	char c;	/* Pass each line with different ast_verbose() call */	for (s = str; s && *s; s = s1) {		s1 = strchr(s, '\n');		if (!s1)			s1 = s + strlen(s);		else			s1++;		c = *s1;		*s1 = '\0';		ast_verbose("%s", s);		*s1 = c;	}	free(str);	string = PString();	char *base = string.GetPointer(2000);	setp(base, base + string.GetSize() - 1);	return 0;}#define cout (*logstream)MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",             MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER){	/* Fix missed one in PWLib */	PX_firstTimeStart = FALSE;	Resume();}void MyProcess::Main(){	cout << "  == Creating H.323 Endpoint" << endl;	endPoint = new MyH323EndPoint();	/* Due to a bug in the H.323 recomendation/stack we should request a sane	   amount of bandwidth from the GK - this function is ignored if not using a GK 	   We are requesting 128 (64k in each direction), which is the worst case codec. */        endPoint->SetInitialBandwidth(1280);	PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);	PTrace::SetStream(logstream);}void PAssertFunc(const char *msg){	ast_log(LOG_ERROR, "%s\n", msg);	/* XXX: Probably we need to crash here */}H323_REGISTER_CAPABILITY(H323_G7231Capability, OPAL_G7231);H323_REGISTER_CAPABILITY(AST_G729Capability,  OPAL_G729);H323_REGISTER_CAPABILITY(AST_G729ACapability, OPAL_G729A);H323_G7231Capability::H323_G7231Capability(BOOL annexA_)  : H323AudioCapability(7, 4){  	annexA = annexA_;}PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const{  	Comparison result = H323AudioCapability::Compare(obj);  	if (result != EqualTo) {    		return result;	}  	PINDEX otherAnnexA = ((const H323_G7231Capability &)obj).annexA;  	if (annexA < otherAnnexA) {    		return LessThan;	}  	if (annexA > otherAnnexA) {    		return GreaterThan;	}	return EqualTo;}PObject * H323_G7231Capability::Clone() const{ 	 return new H323_G7231Capability(*this);}PString H323_G7231Capability::GetFormatName() const{  	return OPAL_G7231;}unsigned H323_G7231Capability::GetSubType() const{  	return H245_AudioCapability::e_g7231;}BOOL H323_G7231Capability::OnSendingPDU(H245_AudioCapability & cap,                                          unsigned packetSize) const{  	cap.SetTag(H245_AudioCapability::e_g7231);  	H245_AudioCapability_g7231 & g7231 = cap;  	g7231.m_maxAl_sduAudioFrames = packetSize;  	g7231.m_silenceSuppression = annexA;  	return TRUE;}BOOL H323_G7231Capability::OnReceivedPDU(const H245_AudioCapability & cap,                                           unsigned & packetSize){	if (cap.GetTag() != H245_AudioCapability::e_g7231) {    		return FALSE;	}  	const H245_AudioCapability_g7231 & g7231 = cap;  	packetSize = g7231.m_maxAl_sduAudioFrames;  	annexA = g7231.m_silenceSuppression;  	return TRUE;}H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) const{  	return NULL;}AST_G729Capability::AST_G729Capability()  : H323AudioCapability(24, 2){}PObject * AST_G729Capability::Clone() const{  	return new AST_G729Capability(*this);}unsigned AST_G729Capability::GetSubType() const{  	return H245_AudioCapability::e_g729;}PString AST_G729Capability::GetFormatName() const{  	return OPAL_G729;}H323Codec * AST_G729Capability::CreateCodec(H323Codec::Direction direction) const{  	return NULL;}AST_G729ACapability::AST_G729ACapability()  : H323AudioCapability(24, 6){}PObject * AST_G729ACapability::Clone() const{  	return new AST_G729ACapability(*this);}unsigned AST_G729ACapability::GetSubType() const{  	return H245_AudioCapability::e_g729AnnexA;}PString AST_G729ACapability::GetFormatName() const{  	return OPAL_G729A;}H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) const{  	return NULL;}/** MyH323EndPoint   */MyH323EndPoint::MyH323EndPoint()		: H323EndPoint(){	// Capabilities will be negotiated on per-connection basis	capabilities.RemoveAll();}/** The fullAddress parameter is used directly in the MakeCall method so  * the General form for the fullAddress argument is :  * [alias@][transport$]host[:port]  * default values:	alias = the same value as host.  *					transport = ip.  *					port = 1720.  */int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int *callReference, call_options_t *opts){	PString fullAddress;	MyH323Connection * connection;	/* Determine whether we are using a gatekeeper or not. */	if (GetGatekeeper()) {		fullAddress = dest;		if (h323debug) {			cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;		}	} else {		fullAddress = dest; 		if (h323debug) {			cout << " -- Making call to " << fullAddress << " without gatekeeper." << endl;		}	}	if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token, opts))) {		if (h323debug) {			cout << "Error making call to \"" << fullAddress << '"' << endl;		}		return 1;	}	*callReference = connection->GetCallReference();		if (opts->cid_num) {		connection->ast_cid_num = PString(opts->cid_num);	}	if (opts->cid_name) {		connection->ast_cid_name = PString(opts->cid_name);		connection->SetLocalPartyName(connection->ast_cid_name);	}	connection->dtmfCodec = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec;	if (h323debug) {		cout << "\t-- " << GetLocalUserName() << " is calling host " << fullAddress << endl;		cout << "\t-- Call token is " << (const char *)token << endl;		cout << "\t-- Call reference is " << *callReference << endl;		cout << "\t-- DTMF Payload is " << connection->dtmfCodec << endl;	}	connection->Unlock(); 		return 0;}void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const{  	H323EndPoint::SetEndpointTypeInfo(info);	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];  	protocol.SetTag(H225_SupportedProtocols::e_voice);  	PINDEX as=SupportedPrefixes.GetSize();  	((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);  	for (PINDEX p=0; p<as; p++) {		H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix, H225_AliasAddress::e_dialedDigits);  	}}void MyH323EndPoint::SetGateway(void){	terminalType = e_GatewayOnly;}BOOL MyH323EndPoint::ClearCall(const PString & token, H323Connection::CallEndReason reason){	if (h323debug) {		cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause " << reason << endl;	}	return H323EndPoint::ClearCall(token, reason);}BOOL MyH323EndPoint::ClearCall(const PString & token){	if (h323debug) {		cout << "\t-- ClearCall: Request to clear call with token " << token << endl;	}	return H323EndPoint::ClearCall(token, H323Connection::EndedByLocalUser);}void MyH323EndPoint::SendUserTone(const PString &token, char tone){	H323Connection *connection = NULL;			connection = FindConnectionWithLock(token);	if (connection != NULL) {		connection->SendUserInputTone(tone, 500);		connection->Unlock();	}}void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel){	channelsOpen--;	if (h323debug) {		cout << "\t\tchannelsOpen = " << channelsOpen << endl;	}	H323EndPoint::OnClosedLogicalChannel(connection, channel);}BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection, 		const PString & forwardParty, 		const H323SignalPDU & pdu) { 	if (h323debug) {	 	cout << "\t-- Call Forwarded to " << forwardParty << endl; 	}	return FALSE; } BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection, 		const PString & forwardParty, 		const H323SignalPDU & pdu){ 	if (h323debug) { 		cout << "\t-- Forwarding call to " << forwardParty << endl; 	}	return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);}void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken){	if (h323debug) {		cout << "\t=-= In OnConnectionEstablished for call " << connection.GetCallReference() << endl;		cout << "\t\t-- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;	}	on_connection_established(connection.GetCallReference(), (const char *)connection.GetCallToken());}/** OnConnectionCleared callback function is called upon the dropping of an established  * H323 connection.   */void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken){	PString remoteName = connection.GetRemotePartyName();	switch (connection.GetCallEndReason()) {		case H323Connection::EndedByCallForwarded:			if (h323debug) {				cout << "-- " << remoteName << " has forwarded the call" << endl;			}			break;		case H323Connection::EndedByRemoteUser:			if (h323debug) {				cout << "-- " << remoteName << " has cleared the call" << endl;			}			break;		case H323Connection::EndedByCallerAbort:			if (h323debug) {				cout << "-- " << remoteName << " has stopped calling" << endl;			}			break;		case H323Connection::EndedByRefusal:			if (h323debug) {				cout << "-- " << remoteName << " did not accept your call" << endl;			}			break;		case H323Connection::EndedByRemoteBusy:			if (h323debug) {				cout << "-- " << remoteName << " was busy" << endl;			}			break;		case H323Connection::EndedByRemoteCongestion:			if (h323debug) {				cout << "-- Congested link to " << remoteName << endl;			}			break;		case H323Connection::EndedByNoAnswer:			if (h323debug) {				cout << "-- " << remoteName << " did not answer your call" << endl;			}			break;		case H323Connection::EndedByTransportFail:			if (h323debug) {				cout << "-- Call with " << remoteName << " ended abnormally" << endl;			}			break;		case H323Connection::EndedByCapabilityExchange:			if (h323debug) {				cout << "-- Could not find common codec with " << remoteName << endl;			}			break;		case H323Connection::EndedByNoAccept:			if (h323debug) {				cout << "-- Did not accept incoming call from " << remoteName << endl;			}			break;		case H323Connection::EndedByAnswerDenied:			if (h323debug) {				cout << "-- Refused incoming call from " << remoteName << endl;			}			break;		case H323Connection::EndedByNoUser:			if (h323debug) {				cout << "-- Remote endpoint could not find user: " << remoteName << endl;			}			break;		case H323Connection::EndedByNoBandwidth:			if (h323debug) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?