summaryrefslogtreecommitdiff
path: root/channels/h323/ast_h323.cpp
diff options
context:
space:
mode:
authorJeremy McNamara <jj@nufone.net>2004-12-15 23:24:13 +0000
committerJeremy McNamara <jj@nufone.net>2004-12-15 23:24:13 +0000
commit4082e265d68f602718e78239a35fb3f4e825c5d0 (patch)
treec6ab11cf50a0edeab333525773145b9f6fd9ab7e /channels/h323/ast_h323.cpp
parentf08b28975bbc06aa7218d5ff117052d554544889 (diff)
Major fixes: Fixed deadlock issue, added support for inband call progress and correct Progress Indicator messages, added configurable RTP payload to send RFC2833 DTMF and correct sending of RFC2833 User Input capability, fixed hostname parsing on peers, preliminary support for correct Q.931 cause codes and fixed bindaddr compile warning
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4466 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/h323/ast_h323.cpp')
-rwxr-xr-xchannels/h323/ast_h323.cpp253
1 files changed, 217 insertions, 36 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;
}