📄 ast_h323.cxx
字号:
}#endif } } }}void MyH323Connection::OnSetLocalCapabilities(){ if (on_setcapabilities) on_setcapabilities(GetCallReference(), (const char *)callToken);}BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps, const H245_MultiplexCapability * muxCap, H245_TerminalCapabilitySetReject & reject){ struct __codec__ { unsigned int asterisk_codec; unsigned int h245_cap; const char *oid; }; static const struct __codec__ codecs[] = { { AST_FORMAT_G723_1, H245_AudioCapability::e_g7231 }, { AST_FORMAT_GSM, H245_AudioCapability::e_gsmFullRate }, { AST_FORMAT_ULAW, H245_AudioCapability::e_g711Ulaw64k }, { AST_FORMAT_ALAW, H245_AudioCapability::e_g711Alaw64k }, { AST_FORMAT_G729A, H245_AudioCapability::e_g729AnnexA }, { AST_FORMAT_G729A, H245_AudioCapability::e_g729 },#ifdef AST_FORMAT_MODEM { AST_FORMAT_MODEM, H245_DataApplicationCapability_application::e_t38fax },#endif { 0 } };#if 0 static const struct __codec__ vcodecs[] = {#ifdef HAVE_H261 { AST_FORMAT_H261, H245_VideoCapability::e_h261VideoCapability },#endif#ifdef HAVE_H263 { AST_FORMAT_H263, H245_VideoCapability::e_h263VideoCapability },#endif#ifdef HAVE_H264 { AST_FORMAT_H264, H245_VideoCapability::e_genericVideoCapability, "0.0.8.241.0.0.1" },#endif { 0 } };#endif struct ast_codec_pref prefs; 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 ((dtmfMode == H323_DTMF_RFC2833) && (sendUserInputMode == SendUserInputAsTone)) sendUserInputMode = SendUserInputAsInlineRFC2833;#ifdef PTRACING if (h323debug) { cout << "\t-- Inbound RFC2833 on payload " << pt << endl; }#endif } memset(&prefs, 0, sizeof(prefs)); int peer_capabilities = 0; for (int i = 0; i < remoteCapabilities.GetSize(); ++i) { unsigned int subType = remoteCapabilities[i].GetSubType(); if (h323debug) { cout << "Peer capability is " << remoteCapabilities[i] << endl; } switch(remoteCapabilities[i].GetMainType()) { case H323Capability::e_Audio: for (int x = 0; codecs[x].asterisk_codec > 0; ++x) { if (subType == codecs[x].h245_cap) { int ast_codec = codecs[x].asterisk_codec; int ms = 0; if (!(peer_capabilities & ast_codec)) { struct ast_format_list format; ast_codec_pref_append(&prefs, ast_codec); format = ast_codec_pref_getsize(&prefs, ast_codec); if ((ast_codec == AST_FORMAT_ALAW) || (ast_codec == AST_FORMAT_ULAW)) { ms = remoteCapabilities[i].GetTxFramesInPacket(); if (ms > 60) ms = format.cur_ms; } else ms = remoteCapabilities[i].GetTxFramesInPacket() * format.inc_ms; ast_codec_pref_setsize(&prefs, ast_codec, ms); } if (h323debug) { cout << "Found peer capability " << remoteCapabilities[i] << ", Asterisk code is " << ast_codec << ", frame size (in ms) is " << ms << endl; } peer_capabilities |= ast_codec; } } break;#if 0 case H323Capability::e_Video: for (int x = 0; vcodecs[x].asterisk_codec > 0; ++x) { if (subType == vcodecs[x].h245_cap) { H245_CapabilityIdentifier *cap = NULL; H245_GenericCapability y; if (vcodecs[x].oid) { cap = new H245_CapabilityIdentifier(H245_CapabilityIdentifier::e_standard); PASN_ObjectId &object_id = *cap; object_id = vcodecs[x].oid; y.m_capabilityIdentifier = *cap; } if ((subType != H245_VideoCapability::e_genericVideoCapability) || (vcodecs[x].oid && ((const H323GenericVideoCapability &)remoteCapabilities[i]).IsGenericMatch((const H245_GenericCapability)y))) { if (h323debug) { cout << "Found peer video capability " << remoteCapabilities[i] << ", Asterisk code is " << vcodecs[x].asterisk_codec << endl; } peer_capabilities |= vcodecs[x].asterisk_codec; } if (cap) delete(cap); } } break;#endif default: break; } } if (h323debug) { char caps_str[1024], caps2_str[1024]; ast_codec_pref_string(&prefs, caps2_str, sizeof(caps2_str)); cout << "Peer capabilities = " << ast_getformatname_multiple(caps_str, sizeof(caps_str), peer_capabilities) << ", ordered list is " << caps2_str << endl; }#if 0 redir_capabilities &= peer_capabilities;#endif if (on_setpeercapabilities) on_setpeercapabilities(GetCallReference(), (const char *)callToken, peer_capabilities, &prefs); return TRUE;}H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability, H323Channel::Directions dir, unsigned sessionID, const H245_H2250LogicalChannelParameters * /*param*/, RTP_QOS * /*param*/ ){ /* Do not open tx channel when transmitter has been paused by empty TCS */ if ((dir == H323Channel::IsTransmitter) && transmitterSidePaused) return NULL; return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID);}/** This callback function is invoked once upon creation of each * channel for an H323 session */BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel){ /* Increase the count of channels we have open */ channelsOpen++; if (h323debug) { cout << "\t-- Started logical channel: " << ((channel.GetDirection() == H323Channel::IsTransmitter) ? "sending " : ((channel.GetDirection() == H323Channel::IsReceiver) ? "receiving " : " ")) << (const char *)(channel.GetCapability()).GetFormatName() << endl; cout << "\t\t-- channelsOpen = " << channelsOpen << endl; } return connectionState != ShuttingDownConnection;}void MyH323Connection::SetCapabilities(int cap, int dtmf_mode, void *_prefs, int pref_codec){ PINDEX lastcap = -1; /* last common capability index */ int alreadysent = 0; int codec; int x, y; char caps_str[1024]; struct ast_codec_pref *prefs = (struct ast_codec_pref *)_prefs; struct ast_format_list format; int frames_per_packet; int max_frames_per_packet; localCapabilities.RemoveAll(); if (h323debug) { cout << "Setting capabilities to " << ast_getformatname_multiple(caps_str, sizeof(caps_str), cap) << endl; ast_codec_pref_string(prefs, caps_str, sizeof(caps_str)); cout << "Capabilities in preference order is " << caps_str << endl; } /* Add audio codecs in preference order first, then audio codecs without preference as allowed by mask */ for (y = 0, x = -1; x < 32 + 32; ++x) { if (x < 0) codec = pref_codec; else if (y || (!(codec = ast_codec_pref_index(prefs, x)))) { if (!y) y = 1; else if (y == AST_FORMAT_MAX_AUDIO) break; else y <<= 1; codec = y; } if (!(cap & codec) || (alreadysent & codec) || !(codec & AST_FORMAT_AUDIO_MASK)) continue; alreadysent |= codec; format = ast_codec_pref_getsize(prefs, codec); frames_per_packet = (format.inc_ms ? format.cur_ms / format.inc_ms : format.cur_ms); max_frames_per_packet = (format.inc_ms ? format.max_ms / format.inc_ms : 0); switch(codec) {#if 0 case AST_FORMAT_SPEEX: /* Not real sure if Asterisk acutally supports all of the various different bit rates so add them all and figure it out later*/ lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow2AudioCapability()); lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow3AudioCapability()); lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow4AudioCapability()); lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow5AudioCapability()); lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow6AudioCapability()); break;#endif case AST_FORMAT_G729A: AST_G729ACapability *g729aCap; AST_G729Capability *g729Cap; lastcap = localCapabilities.SetCapability(0, 0, g729aCap = new AST_G729ACapability(frames_per_packet)); lastcap = localCapabilities.SetCapability(0, 0, g729Cap = new AST_G729Capability(frames_per_packet)); if (max_frames_per_packet) { g729aCap->SetTxFramesInPacket(max_frames_per_packet); g729Cap->SetTxFramesInPacket(max_frames_per_packet); } break; case AST_FORMAT_G723_1: AST_G7231Capability *g7231Cap; lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new AST_G7231Capability(frames_per_packet, TRUE)); if (max_frames_per_packet) g7231Cap->SetTxFramesInPacket(max_frames_per_packet); lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new AST_G7231Capability(frames_per_packet, FALSE)); if (max_frames_per_packet) g7231Cap->SetTxFramesInPacket(max_frames_per_packet); break; case AST_FORMAT_GSM: AST_GSM0610Capability *gsmCap; lastcap = localCapabilities.SetCapability(0, 0, gsmCap = new AST_GSM0610Capability(frames_per_packet)); if (max_frames_per_packet) gsmCap->SetTxFramesInPacket(max_frames_per_packet); break; case AST_FORMAT_ULAW: AST_G711Capability *g711uCap; lastcap = localCapabilities.SetCapability(0, 0, g711uCap = new AST_G711Capability(format.cur_ms, H323_G711Capability::muLaw)); if (format.max_ms) g711uCap->SetTxFramesInPacket(format.max_ms); break; case AST_FORMAT_ALAW: AST_G711Capability *g711aCap; lastcap = localCapabilities.SetCapability(0, 0, g711aCap = new AST_G711Capability(format.cur_ms, H323_G711Capability::ALaw)); if (format.max_ms) g711aCap->SetTxFramesInPacket(format.max_ms); break; default: alreadysent &= ~codec; break; } } lastcap++; lastcap = localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245)); lastcap++; dtmfMode = dtmf_mode; if (dtmf_mode == H323_DTMF_INBAND) { localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::BasicString)); sendUserInputMode = SendUserInputAsString; } else { lastcap = localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833)); /* Cisco sends DTMF only through h245-alphanumeric or h245-signal, no support for RFC2833 */ lastcap = localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245)); sendUserInputMode = SendUserInputAsTone; /* RFC2833 transmission handled at Asterisk level */ } if (h323debug) { cout << "Allowed Codecs:\n\t" << setprecision(2) << localCapabilities << endl; }}BOOL MyH323Connection::StartControlChannel(const H225_TransportAddress & h245Address){ // Check that it is an IP address, all we support at the moment if (h245Address.GetTag() != H225_TransportAddress::e_ipAddress#if P_HAS_IPV6 && h245Address.GetTag() != H225_TransportAddress::e_ip6Address#endif ) { PTRACE(1, "H225\tConnect of H245 failed: Unsupported transport"); return FALSE; } // Already have the H245 channel up. if (controlChannel != NULL) return TRUE; PIPSocket::Address addr; WORD port; GetSignallingChannel()->GetLocalAddress().GetIpAndPort(addr, port); if (addr) { if (h323debug) cout << "Using " << addr << " for outbound H.245 transport" << endl; controlChannel = new MyH323TransportTCP(endpoint, addr); } else controlChannel = new H323TransportTCP(endpoint); if (!controlChannel->SetRemoteAddress(h245Address)) { PTRACE(1, "H225\tCould not extract H245 address"); delete controlChannel; controlChannel = NULL; return FALSE; } if (!controlChannel->Connect()) { PTRACE(1, "H225\tConnect of H245 failed: " << controlChannel->GetErrorText()); delete controlChannel; controlChannel = NULL; return FALSE; } controlChannel->StartControlChannel(*this); return TRUE;}/* MyH323_ExternalRTPChannel */MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection, const H323Capability & capability, Directions direction, unsigned id) : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id){ struct rtp_info *info; /* Determine the Local (A side) IP Address and port */ info = on_external_rtp_create(connection.GetCallReference(), (const char *)connection.GetCallToken()); if (!info) { cout << "\tERROR: on_external_rtp_create failure" << endl; return; } else { localIpAddr = info->addr; localPort = info->port; /* tell the H.323 stack */ SetExternalAddress(H323TransportAddress(localIpAddr, localPort), H323TransportAddress(localIpAddr, localPort + 1)); /* clean up allocated memory */ free(info); } /* Get the payload code */ OpalMediaFormat format(capability.GetFormatName(), FALSE); payloadCode = format.GetPayloadType();}MyH323_ExternalRTPChannel::~MyH323_ExternalRTPChannel(){ if (h323debug) { cout << "\tExternalRTPChannel Destroyed" << endl; }}BOOL MyH323_ExternalRTPChannel::Start(void){ /* Call ancestor first */ if (!H323_ExternalRTPChannel::Start()) { return FALSE; } if (h323debug) { cout << "\t\tExternal RTP Session Starting" << endl; cout << "\t\tRTP channel id " << sessionID << " parameters:" << endl; } /* Collect the remote information */ H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddr, remotePort); if (h323debug) { cout << "\t\t-- remoteIpAddress: " << remoteIpAddr << endl; cout << "\t\t-- remotePort: " << remotePort << endl; cout << "\t\t-- ExternalIpAddress: " << localIpAddr << endl; cout << "\t\t-- ExternalPort: " << localPort << endl; } /* Notify Asterisk of remote RTP information */ on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(), remotePort, (const char *)connection.GetCallToken(), (int)payloadCode); return TRUE;}BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param){ if (h323debug) { cout << " MyH323_ExternalRTPChannel::OnReceivedAckPDU" << endl; } if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) { GetRemoteAddress(remoteIpAddr, remotePort); if (h323debug) { cout << " -- remoteIpAddress: " << remoteIpAddr << endl; cout << " -- remotePort: " << remotePort << endl; } on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(), remotePort, (const char *)connection.GetCallToken(), (int)payloadCode); return TRUE; } return FALSE;}/** IMPLEMENTATION O
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -