aboutsummaryrefslogtreecommitdiffstats
path: root/channels/h323
diff options
context:
space:
mode:
Diffstat (limited to 'channels/h323')
-rwxr-xr-xchannels/h323/ast_h323.cpp253
-rwxr-xr-xchannels/h323/ast_h323.h15
-rwxr-xr-xchannels/h323/chan_h323.h59
3 files changed, 267 insertions, 60 deletions
diff --git a/channels/h323/ast_h323.cpp b/channels/h323/ast_h323.cpp
index 6abfff932..616b7381b 100755
--- a/channels/h323/ast_h323.cpp
+++ b/channels/h323/ast_h323.cpp
@@ -156,7 +156,7 @@ H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) co
}
AST_G729Capability::AST_G729Capability()
- : H323AudioCapability(24, 6)
+ : H323AudioCapability(24, 2)
{
}
@@ -213,7 +213,7 @@ H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) con
* transport = ip.
* port = 1720.
*/
-int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int *callReference, char *cid_name, char *cid_num)
+int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int *callReference, call_options_t *opts)
{
PString fullAddress;
MyH323Connection * connection;
@@ -237,20 +237,23 @@ int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int
return 1;
}
*callReference = connection->GetCallReference();
- if (cid_name) {
+ if (opts->cid_name) {
localAliasNames.RemoveAll();
- connection->SetLocalPartyName(PString(cid_name));
- if (cid_num) {
- localAliasNames.AppendString(PString(cid_num));
+ connection->SetLocalPartyName(PString(opts->cid_name));
+ if (opts->cid_num) {
+ localAliasNames.AppendString(PString(opts->cid_num));
}
- } else if (cid_num) {
+ } else if (opts->cid_num) {
localAliasNames.RemoveAll();
- connection->SetLocalPartyName(PString(cid_num));
+ connection->SetLocalPartyName(PString(opts->cid_num));
}
+ 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;
@@ -259,6 +262,12 @@ int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int
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];
@@ -280,12 +289,20 @@ H323Capabilities MyH323EndPoint::GetCapabilities(void)
return capabilities;
}
+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);
+ return ClearCall(token, H323Connection::EndedByLocalUser);
}
void MyH323EndPoint::SendUserTone(const PString &token, char tone)
@@ -506,29 +523,99 @@ MyH323Connection::~MyH323Connection()
return;
}
+BOOL MyH323Connection::OnReceivedProgress(const H323SignalPDU &pdu)
+{
+ BOOL isInband;
+ unsigned pi;
+
+ if (!H323Connection::OnReceivedProgress(pdu)) {
+ return FALSE;
+ }
+
+ if (!pdu.GetQ931().GetProgressIndicator(pi))
+ pi = 0;
+ if (h323debug) {
+ cout << "\t- Progress Indicator: " << pi << endl;
+ }
+
+ switch(pi) {
+ case Q931::ProgressNotEndToEndISDN:
+ case Q931::ProgressInbandInformationAvailable:
+ isInband = TRUE;
+ break;
+ default:
+ isInband = FALSE;
+ }
+ on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
+
+ return TRUE;
+}
+
H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
- const H323SignalPDU & /*setupPDU*/,
+ const H323SignalPDU & setupPDU,
H323SignalPDU & /*connectPDU*/)
{
+ unsigned pi;
- if (h323debug) {
+ if (h323debug) {
cout << "\t=-= In OnAnswerCall for call " << GetCallReference() << endl;
}
+
+ if (!setupPDU.GetQ931().GetProgressIndicator(pi)) {
+ pi = 0;
+ }
+ if (h323debug) {
+ cout << "\t\t- Progress Indicator: " << pi << endl;
+ }
+ if (progressAlert) {
+ pi = progressAlert;
+ } else if (pi == Q931::ProgressOriginNotISDN) {
+ pi = Q931::ProgressInbandInformationAvailable;
+ }
+ if (pi) {
+ alertingPDU->GetQ931().SetProgressIndicator(pi);
+ }
+ if (h323debug) {
+ cout << "\t\t- Inserting PI of " << pi << " into ALERTING message" << endl;
+ }
+
if (!on_answer_call(GetCallReference(), (const char *)GetCallToken())) {
return H323Connection::AnswerCallDenied;
}
/* The call will be answered later with "AnsweringCall()" function.
*/
- return H323Connection::AnswerCallDeferred;
+ return H323Connection::AnswerCallDeferredWithMedia;
}
-BOOL MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
+BOOL MyH323Connection::OnAlerting(const H323SignalPDU & alertingPDU, const PString & username)
{
if (h323debug) {
cout << "\t=-= In OnAlerting for call " << GetCallReference()
<< ": sessionId=" << sessionId << endl;
cout << "\t-- Ringing phone for \"" << username << "\"" << endl;
- }
+ }
+
+ if (on_progress) {
+ BOOL isInband;
+ unsigned alertingPI;
+
+ if (!alertingPDU.GetQ931().GetProgressIndicator(alertingPI)) {
+ alertingPI = 0;
+ }
+ if (h323debug) {
+ cout << "\t\t- Progress Indicator: " << alertingPI << endl;
+ }
+
+ switch(alertingPI) {
+ case Q931::ProgressNotEndToEndISDN:
+ case Q931::ProgressInbandInformationAvailable:
+ isInband = TRUE;
+ break;
+ default:
+ isInband = FALSE;
+ }
+ on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
+ }
on_chan_ringing(GetCallReference(), (const char *)GetCallToken() );
return TRUE;
}
@@ -588,7 +675,7 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
cd.sourceIp = strdup((const char *)Ip.AsString());
/* Notify Asterisk of the request */
- int res = on_incoming_call(cd);
+ call_options_t *res = on_incoming_call(cd);
if (!res) {
if (h323debug) {
@@ -596,6 +683,12 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
}
return FALSE;
}
+
+ progressSetup = res->progress_setup;
+ progressAlert = res->progress_alert;
+ dtmfCodec = (RTP_DataFrame::PayloadTypes)res->dtmfcodec;
+
+
return H323Connection::OnReceivedSignalSetup(setupPDU);
}
@@ -646,6 +739,10 @@ BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
}
return FALSE;
}
+
+ if (progressSetup) {
+ setupPDU.GetQ931().SetProgressIndicator(progressSetup);
+ }
return H323Connection::OnSendSignalSetup(setupPDU);
}
@@ -711,6 +808,50 @@ void MyH323Connection::OnUserInputString(const PString &value)
}
}
+void MyH323Connection::OnSendCapabilitySet(H245_TerminalCapabilitySet & pdu)
+{
+ PINDEX i;
+
+ H323Connection::OnSendCapabilitySet(pdu);
+
+ H245_ArrayOf_CapabilityTableEntry & tables = pdu.m_capabilityTable;
+ for(i = 0; i < tables.GetSize(); i++)
+ {
+ H245_CapabilityTableEntry & entry = tables[i];
+ if (entry.HasOptionalField(H245_CapabilityTableEntry::e_capability)) {
+ H245_Capability & cap = entry.m_capability;
+ if (cap.GetTag() == H245_Capability::e_receiveRTPAudioTelephonyEventCapability) {
+ H245_AudioTelephonyEventCapability & atec = cap;
+ atec.m_dynamicRTPPayloadType = dtmfCodec;
+ on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)dtmfCodec);
+ if (h323debug) {
+ cout << "\t-- Transmitting RFC2833 on payload " <<
+ atec.m_dynamicRTPPayloadType << endl;
+ }
+ }
+ }
+ }
+}
+
+BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
+ const H245_MultiplexCapability * muxCap,
+ H245_TerminalCapabilitySetReject & reject)
+{
+ if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
+ return FALSE;
+ }
+
+ const H323Capability * cap = remoteCaps.FindCapability(H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833]);
+ if (cap != NULL) {
+ RTP_DataFrame::PayloadTypes pt = ((H323_UserInputCapability*)cap)->GetPayloadType();
+ on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt);
+ if (h323debug) {
+ cout << "\t-- Inbound RFC2833 on payload " << pt << endl;
+ }
+ }
+ return TRUE;
+}
+
H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
H323Channel::Directions dir,
unsigned sessionID,
@@ -783,7 +924,7 @@ BOOL MyH323_ExternalRTPChannel::Start(void)
}
/* Collect the remote information */
- GetRemoteAddress(remoteIpAddr, remotePort);
+ H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddr, remotePort);
if (h323debug) {
cout << "\t\tExternal RTP Session Starting" << endl;
@@ -800,6 +941,28 @@ BOOL MyH323_ExternalRTPChannel::Start(void)
return TRUE;
}
+BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
+{
+ PIPSocket::Address remoteIpAddress;
+ WORD remotePort;
+
+ if (h323debug) {
+ cout << " MyH323_ExternalRTPChannel::OnReceivedAckPDU" << endl;
+ }
+
+ if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) {
+ GetRemoteAddress(remoteIpAddress, remotePort);
+ if (h323debug) {
+ cout << " -- remoteIpAddress: " << remoteIpAddress << endl;
+ cout << " -- remotePort: " << remotePort << endl;
+ }
+ on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(),
+ remotePort, (const char *)connection.GetCallToken());
+ return TRUE;
+ }
+ return FALSE;
+}
+
/** IMPLEMENTATION OF C FUNCTIONS */
/**
@@ -859,7 +1022,9 @@ void h323_callback_register(setup_incoming_cb ifunc,
chan_ringing_cb rfunc,
con_established_cb efunc,
send_digit_cb dfunc,
- answer_call_cb acfunc)
+ answer_call_cb acfunc,
+ progress_cb pgfunc,
+ rfc2833_cb dtmffunc)
{
on_incoming_call = ifunc;
on_outgoing_call = sfunc;
@@ -870,6 +1035,8 @@ void h323_callback_register(setup_incoming_cb ifunc,
on_connection_established = efunc;
on_send_digit = dfunc;
on_answer_call = acfunc;
+ on_progress = pgfunc;
+ on_set_rfc2833_payload = dtmffunc;
}
/**
@@ -879,8 +1046,9 @@ int h323_set_capability(int cap, int dtmfMode)
{
H323Capabilities oldcaps;
PStringArray codecs;
- int g711Frames = 30;
+ int g711Frames = 20;
// int gsmFrames = 4;
+ PINDEX lastcap = -1; /* last common capability index */
if (!h323_end_point_exist()) {
cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
@@ -894,12 +1062,6 @@ int h323_set_capability(int cap, int dtmfMode)
}
endPoint->RemoveCapabilities(codecs);
- mode = dtmfMode;
- if (dtmfMode == H323_DTMF_INBAND) {
- endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
- } else {
- endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
- }
#if 0
if (cap & AST_FORMAT_SPEEX) {
/* Not real sure if Asterisk acutally supports all
@@ -916,32 +1078,45 @@ int h323_set_capability(int cap, int dtmfMode)
if (cap & AST_FORMAT_G729A) {
AST_G729ACapability *g729aCap;
AST_G729Capability *g729Cap;
- endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
- endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
+ lastcap = endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
+ lastcap = endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
}
if (cap & AST_FORMAT_G723_1) {
H323_G7231Capability *g7231Cap;
- endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
+ lastcap = endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
}
#if 0
if (cap & AST_FORMAT_GSM) {
H323_GSM0610Capability *gsmCap;
- endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
+ lastcap = endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
gsmCap->SetTxFramesInPacket(gsmFrames);
}
#endif
if (cap & AST_FORMAT_ULAW) {
H323_G711Capability *g711uCap;
- endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
+ lastcap = 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));
+ lastcap = endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
g711aCap->SetTxFramesInPacket(g711Frames);
- }
+ }
+
+ lastcap++;
+ lastcap = endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
+
+ lastcap++;
+ mode = dtmfMode;
+ if (dtmfMode == H323_DTMF_INBAND) {
+ endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
+ endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
+ } else {
+ endPoint->SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
+ endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
+ }
if (h323debug) {
cout << "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
@@ -1086,7 +1261,7 @@ void h323_send_tone(const char *call_token, char tone)
/** Make a call to the remote endpoint.
*/
-int h323_make_call(char *dest, call_details_t *cd, call_options_t call_options)
+int h323_make_call(char *dest, call_details_t *cd, call_options_t *call_options)
{
int res;
PString token;
@@ -1096,17 +1271,23 @@ int h323_make_call(char *dest, call_details_t *cd, call_options_t call_options)
return 1;
}
- res = endPoint->MakeCall(host, token, &cd->call_reference, call_options.cid_name, call_options.cid_num);
+ res = endPoint->MakeCall(host, token, &cd->call_reference, call_options);
memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
return res;
};
-int h323_clear_call(const char *call_token)
+int h323_clear_call(const char *call_token, int cause)
{
+ H225_ReleaseCompleteReason dummy;
+ H323Connection::CallEndReason r = H323Connection::NumCallEndReasons;
+
if (!h323_end_point_exist()) {
return 1;
}
- endPoint->ClearCall(PString(call_token));
+
+ r = H323TranslateToCallEndReason((Q931::CauseValues)(cause), dummy);
+
+ endPoint->ClearCall(PString(call_token), r);
return 0;
};
@@ -1184,7 +1365,7 @@ int h323_soft_hangup(const char *data)
{
PString token(data);
BOOL result;
-
+ cout << "Soft hangup" << endl;
result = endPoint->ClearCall(token);
return result;
}
diff --git a/channels/h323/ast_h323.h b/channels/h323/ast_h323.h
index f9a454b6f..906acd65d 100755
--- a/channels/h323/ast_h323.h
+++ b/channels/h323/ast_h323.h
@@ -128,7 +128,8 @@ class MyH323EndPoint : public H323EndPoint {
PCLASSINFO(MyH323EndPoint, H323EndPoint);
public:
- int MakeCall(const PString &, PString &, unsigned int *, char *, char *);
+ int MakeCall(const PString &, PString &, unsigned int *, call_options_t *opts);
+ BOOL ClearCall(const PString &, H323Connection::CallEndReason reason);
BOOL ClearCall(const PString &);
void OnClosedLogicalChannel(H323Connection &, const H323Channel &);
@@ -170,6 +171,10 @@ class MyH323Connection : public H323Connection {
void SendUserInputTone(char, unsigned);
void OnUserInputTone(char, unsigned, unsigned, unsigned);
void OnUserInputString(const PString &value);
+ BOOL OnReceivedProgress(const H323SignalPDU &);
+ void OnSendCapabilitySet(H245_TerminalCapabilitySet &);
+ BOOL OnReceivedCapabilitySet(const H323Capabilities &, const H245_MultiplexCapability *,
+ H245_TerminalCapabilitySetReject &);
PString sourceAliases;
PString destAliases;
@@ -178,6 +183,11 @@ class MyH323Connection : public H323Connection {
WORD sessionId;
BOOL bridging;
+
+ unsigned progressSetup;
+ unsigned progressAlert;
+
+ RTP_DataFrame::PayloadTypes dtmfCodec;
};
class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel {
@@ -192,9 +202,10 @@ class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel {
unsigned sessionID);
~MyH323_ExternalRTPChannel();
-
+
/* Overrides */
BOOL Start(void);
+ BOOL OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param);
protected:
BYTE payloadCode;
diff --git a/channels/h323/chan_h323.h b/channels/h323/chan_h323.h
index 0005b421c..995b81896 100755
--- a/channels/h323/chan_h323.h
+++ b/channels/h323/chan_h323.h
@@ -28,7 +28,20 @@
#include <arpa/inet.h>
-static struct sockaddr_in bindaddr;
+/** call_option struct holds various bits
+ * of information for each call */
+typedef struct call_options {
+ char *cid_num;
+ char *cid_name;
+ int noFastStart;
+ int noH245Tunneling;
+ int noSilenceSuppression;
+ unsigned int port;
+ int progress_setup;
+ int progress_alert;
+ int progress_audio;
+ int dtmfcodec;
+} call_options_t;
/* structure to hold the valid asterisk users */
struct oh323_user {
@@ -38,13 +51,11 @@ struct oh323_user {
char callerid[80];
char accountcode[20];
int amaflags;
- int noFastStart;
- int noH245Tunneling;
- int noSilenceSuppression;
int bridge;
int nat;
int dtmfmode;
int host;
+ call_options_t options;
struct ast_ha *ha;
struct sockaddr_in addr;
struct oh323_user *next;
@@ -56,15 +67,13 @@ struct oh323_peer {
char name[80];
char mailbox[80];
int capability;
- int noFastStart;
- int noH245Tunneling;
- int noSilenceSuppression;
int bridge;
int nat;
int dtmfmode;
int delme;
struct sockaddr_in addr;
struct ast_ha *ha;
+ call_options_t options;
struct oh323_peer *next;
};
@@ -79,17 +88,6 @@ struct oh323_alias {
struct oh323_alias *next;
};
-/** call_option struct holds various bits
- of information for each call */
-typedef struct call_options {
- char *cid_num;
- char *cid_name;
- int noFastStart;
- int noH245Tunneling;
- int noSilenceSuppression;
- unsigned int port;
-} call_options_t;
-
/** call_details struct call detail records
to asterisk for processing and used for matching up
asterisk channels to acutal h.323 connections */
@@ -124,9 +122,14 @@ extern on_rtp_cb on_external_rtp_create;
typedef void (*start_rtp_cb)(unsigned int, const char *, int, const char *);
extern start_rtp_cb on_start_rtp_channel;
+/* This is a callback that happens when call progress is
+ * made, and handles inband progress */
+typedef int (*progress_cb)(unsigned, const char *, int);
+extern progress_cb on_progress;
+
/* This is a callback prototype function, called upon
an incoming call happens. */
-typedef int (*setup_incoming_cb)(call_details_t);
+typedef call_options_t *(*setup_incoming_cb)(call_details_t);
extern setup_incoming_cb on_incoming_call;
/* This is a callback prototype function, called upon
@@ -154,12 +157,22 @@ extern clear_con_cb on_connection_cleared;
typedef int (*answer_call_cb)(unsigned, const char *);
extern answer_call_cb on_answer_call;
+/* This is a callback prototype function, called when
+ we know which RTP payload type RFC2833 will be
+ transmitted */
+typedef void (*rfc2833_cb)(unsigned, const char *, int);
+extern rfc2833_cb on_set_rfc2833_payload;
+
/* debug flag */
extern int h323debug;
#define H323_DTMF_RFC2833 (1 << 0)
#define H323_DTMF_INBAND (1 << 1)
+#ifndef BOOL
+#define BOOL int
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -180,7 +193,9 @@ extern "C" {
chan_ringing_cb,
con_established_cb,
send_digit_cb,
- answer_call_cb);
+ answer_call_cb,
+ progress_cb,
+ rfc2833_cb);
int h323_set_capability(int, int);
int h323_set_alias(struct oh323_alias *);
int h323_set_gk(int, char *, char *);
@@ -196,8 +211,8 @@ extern "C" {
void h323_send_tone(const char *call_token, char tone);
/* H323 create and destroy sessions */
- int h323_make_call(char *dest, call_details_t *cd, call_options_t);
- int h323_clear_call(const char *);
+ int h323_make_call(char *dest, call_details_t *cd, call_options_t *);
+ int h323_clear_call(const char *, int cause);
/* H.323 alerting and progress */
int h323_send_alerting(const char *token);