diff options
Diffstat (limited to 'channels/h323')
-rwxr-xr-x | channels/h323/ast_h323.cpp | 253 | ||||
-rwxr-xr-x | channels/h323/ast_h323.h | 15 | ||||
-rwxr-xr-x | channels/h323/chan_h323.h | 59 |
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); |