📄 ast_h323.cxx
字号:
#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif/* * 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.cxx 129046 2008-07-08 16:41:31Z bbryant $ */#include <arpa/inet.h>#include <list>#include <string>#include <algorithm>#include <ptlib.h>#include <h323.h>#include <h323pdu.h>#include <h323neg.h>#include <mediafmt.h>#include <lid.h>#ifdef H323_H450#include "h4501.h"#include "h4504.h"#include "h45011.h"#include "h450pdu.h"#endif#ifdef __cplusplusextern "C" {#endif#include "asterisk/compat.h"#include "asterisk/logger.h"#include "asterisk/channel.h"#include "asterisk/astobj.h"#ifdef __cplusplus}#endif#include "chan_h323.h"#include "ast_h323.h"#include "cisco-h225.h"#include "caps_h323.h"#include <ptbuildopts.h>#if PWLIB_MAJOR * 10000 + PWLIB_MINOR * 100 + PWLIB_BUILD >= 1 * 10000 + 12 * 100 + 0#define SKIP_PWLIB_PIPE_BUG_WORKAROUND 1#endif/* 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 */static int channelsOpen;/** * 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 */static MyH323EndPoint *endPoint = NULL;/** PWLib entry point */static MyProcess *localProcess = NULL;#ifndef SKIP_PWLIB_PIPE_BUG_WORKAROUNDstatic int _timerChangePipe[2];#endifstatic unsigned traceOptions = PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine;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;}static ostream &my_endl(ostream &os){ if (logstream) { PTrace::SetOptions(traceOptions); return PTrace::End(os); } return endl(os);}#define cout \ (logstream ? (PTrace::ClearOptions((unsigned)-1), PTrace::Begin(0, __FILE__, __LINE__)) : std::cout)#define endl my_endl/* Special class designed to call cleanup code on module destruction */class MyH323_Shutdown { public: MyH323_Shutdown() { }; ~MyH323_Shutdown() { h323_end_process(); };};MyProcess::MyProcess(): PProcess("The NuFone Networks", "H.323 Channel Driver for Asterisk", MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER){ /* Call shutdown when module being unload or asterisk has been stopped */ static MyH323_Shutdown x; /* Fix missed one in PWLib */ PX_firstTimeStart = FALSE; Resume();}MyProcess::~MyProcess(){#ifndef SKIP_PWLIB_PIPE_BUG_WORKAROUND _timerChangePipe[0] = timerChangePipe[0]; _timerChangePipe[1] = timerChangePipe[1];#endif}void MyProcess::Main(){ PTrace::Initialise(PTrace::GetLevel(), NULL, traceOptions); PTrace::SetStream(logstream); cout << " == Creating H.323 Endpoint" << endl; if (endPoint) { cout << " == ENDPOINT ALREADY CREATED" << endl; return; } 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);}void PAssertFunc(const char *msg){ ast_log(LOG_ERROR, "%s\n", msg); /* XXX: Probably we need to crash here */}/** MyH323EndPoint */MyH323EndPoint::MyH323EndPoint() : H323EndPoint(){ /* Capabilities will be negotiated on per-connection basis */ capabilities.RemoveAll(); /* Reset call setup timeout to some more reasonable value than 1 minute */ signallingChannelCallTimeout = PTimeInterval(0, 0, 10); /* 10 minutes */}/** 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::MyMakeCall(const PString & dest, PString & token, void *_callReference, void *_opts){ PString fullAddress; MyH323Connection * connection; H323Transport *transport = NULL; unsigned int *callReference = (unsigned int *)_callReference; call_options_t *opts = (call_options_t *)_opts; /* 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; } /* Use bindaddr for outgoing calls too if we don't use gatekeeper */ if (listeners.GetSize() > 0) { H323TransportAddress taddr = listeners[0].GetTransportAddress(); PIPSocket::Address addr; WORD port; if (taddr.GetIpAndPort(addr, port)) { /* Create own transport for specific addresses only */ if (addr) { if (h323debug) cout << "Using " << addr << " for outbound call" << endl; transport = new MyH323TransportTCP(*this, addr); if (!transport) cout << "Unable to create transport for outgoing call" << endl; } } else cout << "Unable to get address and port" << endl; } } if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token, opts, transport))) { if (h323debug) { cout << "Error making call to \"" << fullAddress << '"' << endl; } return 1; } *callReference = connection->GetCallReference(); 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;#ifdef PTRACING cout << "\t-- DTMF Payload is " << connection->dtmfCodec << endl;#endif } 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) {#ifdef PTRACING cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause " << reason << endl;#else cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause [" << (int)reason << "]" << endl;#endif } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -