To Jan Willamowius And Michal Zigmuntowicz Gentleman, May we all ask you to implement this patch to 2.0.7 This is really necessary for all GNUGK users, especially for a VoIP terminators and traders. Thank you in advance, Oleg -----Original Message----- From: openh323gk-users-admin@lists.sourceforge.net [mailto:openh323gk-users-admin@lists.sourceforge.net] On Behalf Of Ian.Campbell@band-x.com Sent: Tuesday, December 16, 2003 1:23 PM To: openh323gk-users@lists.sourceforge.net; openh323gk-developer@lists.sourceforge.net Cc: Justin.Wells@band-x.com Subject: Re: Re: Rewriting E164 numbers after GW selection Hello All, I have finally got round to implementing per gateway E164 number rewriting as discussed in this thread in early November. Attached is a patch providing it for version 2.0.6. The code provides triple stage rewriting: per gw input E164 rewriting -> standard E164 rewriting -> (endpoint selection) -> per gw output E164 rewriting This is configured in a new configuration section as follows: [RasSrv::GWRewriteE164] foo=out=1223=2323 foo=out=13=4444 foo=in=777=8888 bar=in=777=9999 And so on. The first element in the line is the GW that the rule is being applied to the second the direction (whether it is applied before the standard rewriting and the endpoint selection or after) and finally the rule itself in the same as the standard rewriting ([RasSrv::RewriteE164]). All this allows much more sophisticated control of what is sent to the endpoint for example an authentication prefix and per endpoint routing policies to be constructed. The code has been tested by me, but should probably be considered alpha quality for now. Jan et al. is there anything I need to do (beyond applying this to the 2.2 CVS archive) to get this included in a future release? Regards, Ian Campbell Band-X Ltd. diff -r -U 3 openh323gk/ProxyChannel.cxx openh323gk.gwrewrite/ProxyChannel.cxx --- openh323gk/ProxyChannel.cxx 2003-09-24 10:19:44.000000000 +0000 +++ openh323gk.gwrewrite/ProxyChannel.cxx 2003-12-15 16:55:05.000000000 +0000 @@ -393,6 +393,8 @@ ProxySocket::Result CallSignalSocket::ReceiveData() { + PString in_rewrite_id,out_rewrite_id; + if (!ReadTPKT()) return NoData; @@ -424,7 +426,7 @@ } m_crv = (m_lastQ931->GetCallReference() | 0x8000u); m_setupUUIE = new H225_H323_UserInformation(signal); - changed = OnSetup(body); + changed = OnSetup(body,in_rewrite_id,out_rewrite_id); break; case H225_H323_UU_PDU_h323_message_body::e_callProceeding: changed = OnCallProceeding(body); @@ -492,11 +494,28 @@ if (m_lastQ931->HasIE(Q931::CalledPartyNumberIE)) { unsigned plan, type; PString calledNumber; + + // Do per GW inbound rewrite before global rewrite + if (m_lastQ931->GetCalledPartyNumber(calledNumber, &plan, &type) && + Toolkit::Instance()->GWRewritePString(in_rewrite_id,true,calledNumber)) { + m_lastQ931->SetCalledPartyNumber(calledNumber, plan, type); + changed = true; + } + + // Normal rewrite if (m_lastQ931->GetCalledPartyNumber(calledNumber, &plan, &type) && Toolkit::Instance()->RewritePString(calledNumber)) { m_lastQ931->SetCalledPartyNumber(calledNumber, plan, type); changed = true; } + + // Do per GW outbound rewrite after global rewrite + if (m_lastQ931->GetCalledPartyNumber(calledNumber, &plan, &type) && + Toolkit::Instance()->GWRewritePString(out_rewrite_id,false,calledNumber)) { + m_lastQ931->SetCalledPartyNumber(calledNumber, plan, type); + changed = true; + } + } if (m_lastQ931->HasIE(Q931::DisplayIE)) { @@ -687,6 +706,9 @@ TCPProxySocket *CallSignalSocket::ForwardCall() { + + PString in_rewrite_id,out_rewrite_id; + // disconnect from forwarder SendReleaseComplete(H225_ReleaseCompleteReason::e_facilityCallDeflection); Close(); @@ -744,7 +766,7 @@ ret->m_h245handler = 0; CallSignalSocket *result = 0; - if (ret->OnSetup(SetupUUIE)) { + if (ret->OnSetup(SetupUUIE,in_rewrite_id,out_rewrite_id)) { SetUUIE(*Setup, suuie); Setup->Encode(ret->buffer); PrintQ931(5, "Forward Setup to " + ret->remote->Name(), Setup, &suuie); @@ -774,7 +796,7 @@ return result; } -bool CallSignalSocket::OnSetup(H225_Setup_UUIE & Setup) +bool CallSignalSocket::OnSetup(H225_Setup_UUIE & Setup, PString &in_rewrite_id, PString &out_rewrite_id) { const time_t setupTime = time(NULL); @@ -791,8 +813,26 @@ H323SetAliasAddress(destination, Setup.m_destinationAddress[0]); } } - if (Setup.HasOptionalField(H225_Setup_UUIE::e_destinationAddress)) + if (Setup.HasOptionalField(H225_Setup_UUIE::e_destinationAddress)) { + + // Do inbound per GWRewrite if we can before global rewrite + if (Setup.HasOptionalField(H225_Setup_UUIE::e_sourceAddress) == true) { + PString source; + PStringArray tokenised_source; + source = AsString(Setup.m_sourceAddress); + + // Chop up source to get the h323_ID or dialedDigits + tokenised_source = source.Tokenise(PString(":")); + + if (tokenised_source.GetSize() == 2) { + Toolkit::Instance()->GWRewriteE164(tokenised_source[0],true,Setup.m_destinat ionAddress); + in_rewrite_id = tokenised_source[0]; + } + } + + // Normal rewrite Toolkit::Instance()->RewriteE164(Setup.m_destinationAddress); + } #if PTRACING PString callid; @@ -815,10 +855,11 @@ GkClient *gkClient = RasThread->GetGkClient(); Address fromIP; GetPeerAddress(fromIP); + if (m_call) { #ifdef HAS_ACCT if( m_call->GetCalledStationId().IsEmpty() ) - if( Setup.HasOptionalField(H225_Setup_UUIE::e_destinationAddress) + if( Setup.HasOptionalField(H225_Setup_UUIE::e_destinationAddress) && (Setup.m_destinationAddress.GetSize() > 0) ) { const PString calledPartyNumber = GetBestAliasAddressString( @@ -830,10 +871,10 @@ if( !calledPartyNumber.IsEmpty() ) m_call->SetCalledStationId(calledPartyNumber); } - + #endif m_call->SetSetupTime(setupTime); - + if (m_call->IsSocketAttached()) { PTRACE(2, "Q931\tWarning: socket already attached for callid " << callid); return false; @@ -866,7 +907,7 @@ */ { ReadLock cfgLock(ConfigReloadMutex); - + GkAuthenticatorList* authList = RasThread->GetAuthList(); if( authList ) { @@ -877,7 +918,7 @@ PTRACE(3,"GKAUTH\tH.225 Setup authentication failed: "<<reason); return false; } - + if( limit > 0 ) m_call->SetDurationLimit( limit ); } @@ -901,14 +942,16 @@ } #endif } + } else { bool fromParent; if (!RasThread->AcceptUnregisteredCalls(fromIP, fromParent)) { PTRACE(3, "Q931\tNo CallRec found in CallTable for callid " << callid); return false; } - if (fromParent) + if (fromParent) { gkClient->RewriteE164(*m_lastQ931, Setup, false); + } endptr called; PString destinationString; @@ -934,14 +977,14 @@ // workaround for bandwidth, as OpenH323 library :p CallRec *call = new CallRec(Setup.m_callIdentifier, Setup.m_conferenceID, destinationString, sourceString, 100000, h245Routed); call->SetCalled(called, m_crv); - - call->SetSetupTime(setupTime); - + + call->SetSetupTime(setupTime); + long durationLimit = -1; - + { ReadLock cfgLock(ConfigReloadMutex); - + GkAuthenticatorList* authList = RasThread->GetAuthList(); if( authList ) { @@ -955,7 +998,7 @@ } #ifdef HAS_ACCT - if( Setup.HasOptionalField(H225_Setup_UUIE::e_destinationAddress) + if( Setup.HasOptionalField(H225_Setup_UUIE::e_destinationAddress) && (Setup.m_destinationAddress.GetSize() > 0) ) { const PString calledPartyNumber = GetBestAliasAddressString( Setup.m_destinationAddress, @@ -966,7 +1009,7 @@ if( !calledPartyNumber.IsEmpty() ) call->SetCalledStationId(calledPartyNumber); } - + GkAcctLoggers* acct = Toolkit::Instance()->GetAcctList(); if( acct != NULL ) if( call->GetAcctEventsLogged() & GkAcctLogger::AcctStart ) @@ -988,7 +1031,7 @@ } #endif } - + if( durationLimit > 0 ) call->SetDurationLimit( durationLimit ); @@ -1000,6 +1043,26 @@ } } + // Do outbound per GW rewrite + if (Setup.HasOptionalField(H225_Setup_UUIE::e_destinationAddress)) { + endptr rewriteEndPointOut = m_call->GetCalledParty(); + if (rewriteEndPointOut != NULL) { + PString source; + PStringArray tokenised_source; + + source = AsString(rewriteEndPointOut->GetAliases()[0]); + + // Chop up source to get the h323_ID or dialedDigits + tokenised_source = source.Tokenise(PString(":")); + + if (tokenised_source.GetSize() == 2) { + Toolkit::Instance()->GWRewriteE164(tokenised_source[0],false,Setup.m_destina tionAddress); + out_rewrite_id = tokenised_source[0]; + } + + } + } + const H225_TransportAddress *addr = m_call->GetCalledAddress(); if (!addr || !GetIPAndPortFromTransportAddr(*addr, peerAddr, peerPort)) { CallTable::Instance()->RemoveCall(m_call); @@ -1067,7 +1130,7 @@ { if (m_call) // hmm... it should not be null m_call->SetConnected(); - + #ifndef NDEBUG if (!Connect.HasOptionalField(H225_Connect_UUIE::e_callIdentifier)) { PTRACE(1, "Q931\tConnect_UUIE doesn't contain CallIdentifier!"); diff -r -U 3 openh323gk/ProxyChannel.h openh323gk.gwrewrite/ProxyChannel.h --- openh323gk/ProxyChannel.h 2003-04-10 02:39:55.000000000 +0000 +++ openh323gk.gwrewrite/ProxyChannel.h 2003-12-15 16:46:50.000000000 +0000 @@ -94,7 +94,7 @@ LogicalChannel *FindLogicalChannel(WORD); RTPLogicalChannel *FindRTPLogicalChannelBySessionID(WORD); - + private: // override from class H245Handler virtual bool HandleRequest(H245_RequestMessage &); @@ -152,7 +152,7 @@ TCPProxySocket *InternalConnectTo(); TCPProxySocket *ForwardCall(); - bool OnSetup(H225_Setup_UUIE &); + bool OnSetup(H225_Setup_UUIE &, PString &in_rewrite_id, PString &out_rewrite_id); bool OnCallProceeding(H225_CallProceeding_UUIE &); bool OnConnect(H225_Connect_UUIE &); bool OnAlerting(H225_Alerting_UUIE &); diff -r -U 3 openh323gk/RasSrv.cxx openh323gk.gwrewrite/RasSrv.cxx --- openh323gk/RasSrv.cxx 2003-09-24 10:19:44.000000000 +0000 +++ openh323gk.gwrewrite/RasSrv.cxx 2003-12-16 12:27:21.000000000 +0000 @@ -20,7 +20,7 @@ // ////////////////////////////////////////////////////////////////// -#if (_MSC_VER >= 1200) +#if (_MSC_VER >= 1200) #pragma warning( disable : 4800 ) // one performance warning off #pragma warning( disable : 4786 ) // warning about too long debug symbol off #define snprintf _snprintf @@ -361,7 +361,7 @@ } } } - + #if HAS_WAITARQ BOOL H323RasSrv::RouteToAlias(PString TargetAlias, PString SourceEpId, PString CallRef) { @@ -374,7 +374,7 @@ return wArqList->RouteReject(SourceEpId, CallRef); } #endif - + int NeighborList::SendLRQ(int seqNum, const H225_AdmissionRequest & obj_arq, const endptr & e) { int nbCount = 0; @@ -396,7 +396,7 @@ } } } - + eIter = List.end(); for(Iter = List.begin(); Iter != eIter; ++Iter) { if (Iter->SendLRQ(seqNum, obj_arq, RasSrv, e)) @@ -428,7 +428,7 @@ } } } - + eIter = List.end(); for(Iter = List.begin(); Iter != eIter; ++Iter) { if (Iter->ForwardLRQ(ip, obj_lrq, RasSrv)) @@ -470,7 +470,7 @@ : PThread(10000, NoAutoDeleteThread), requestSeqNum(0) { GKHome = _GKHome; - + GKRasPort = GkConfig()->GetInteger("UnicastRasPort", GK_DEF_UNICAST_RAS_PORT); EndpointTable = RegistrationTable::Instance(); //initialisation is done in LoadConfig @@ -492,7 +492,7 @@ #if HAS_WAITARQ wArqList = new WaitingARQlist(); #endif - + LoadConfig(); arqPendingList = new NBPendingList(this, GkConfig()->GetInteger(LRQFeaturesSection, "NeighborTimeout", 2)); @@ -536,7 +536,7 @@ #if HAS_WAITARQ delete wArqList ; #endif - + } void H323RasSrv::SetRoutedMode(bool routedSignaling, bool routedH245) @@ -638,7 +638,7 @@ const PStringArray tokens = altgks[idx].Tokenise(":", FALSE); if (tokens.GetSize() < 4) { PTRACE(1,"GK\tFormat error in AlternateGKs"); - continue; + continue; } H225_AlternateGK & A = altGKs[idx]; @@ -679,19 +679,19 @@ delete destAnalysisList; destAnalysisList = new GkDestAnalysisList(GkConfig()); EndpointTable->Initialize(*destAnalysisList); - + #if defined(HAS_LDAP) // shall use LDAP - + // initialize LDAP GkLDAP::Instance()->Initialize(*GkConfig()); - + #endif // HAS_LDAP #if defined(HAS_WAITARQ) // supports VirtualQueues // (re) load config wArqList->LoadConfig(); #endif - + // add neighbors delete NeighborsGK; NeighborsGK = new NeighborList(this, GkConfig()); @@ -729,7 +729,7 @@ delete GkStatusThread; GkStatusThread = 0; } - + PTRACE(1, "GK\tRasSrv closed"); } @@ -854,7 +854,7 @@ unsigned rsn = H225_GatekeeperRejectReason::e_securityDenial; if ((redirectGK != e_noRedirect) || !authList->Check(obj_gr, rsn)) { - obj_rpl.SetTag(H225_RasMessage::e_gatekeeperReject); + obj_rpl.SetTag(H225_RasMessage::e_gatekeeperReject); H225_GatekeeperReject & obj_grj = obj_rpl; obj_grj.m_protocolIdentifier = obj_gr.m_protocolIdentifier; if (redirectGK != e_noRedirect) { @@ -872,7 +872,7 @@ (const unsigned char *) obj_grj.m_rejectReason.GetTagName() ); } else { - obj_rpl.SetTag(H225_RasMessage::e_gatekeeperConfirm); + obj_rpl.SetTag(H225_RasMessage::e_gatekeeperConfirm); H225_GatekeeperConfirm & obj_gcf = obj_rpl; obj_gcf.m_requestSeqNum = obj_gr.m_requestSeqNum; @@ -900,11 +900,11 @@ } */ SelectH235Capability( obj_gr, obj_gcf ); - + //if (bShellSendReply)cw need to forward GRQ? // ForwardRasMsg(obj_grq); - msg = PString(PString::Printf, "GCF|%s|%s|%s;\r\n", + msg = PString(PString::Printf, "GCF|%s|%s|%s;\r\n", inet_ntoa(rx_addr), (const unsigned char *) aliasListString, (const unsigned char *) AsString(obj_gr.m_endpointType) ); @@ -912,13 +912,13 @@ PTRACE(2, msg); GkStatusThread->SignalStatus(msg); - + return bShellSendReply; } void H323RasSrv::BuildRCF(H225_RasMessage & obj_ras, const H225_RegistrationRequest & rrq, const endptr & ep, const PIPSocket::Address & rx_addr) { - obj_ras.SetTag(H225_RasMessage::e_registrationConfirm); + obj_ras.SetTag(H225_RasMessage::e_registrationConfirm); H225_RegistrationConfirm & rcf = obj_ras; rcf.m_requestSeqNum = rrq.m_requestSeqNum; rcf.m_protocolIdentifier = rrq.m_protocolIdentifier; @@ -990,7 +990,7 @@ if (bShellSendReply) BuildRCF(obj_rpl, obj_rr, ep, rx_addr); // forward lightweights, too - if (bShellForwardRequest) + if (bShellForwardRequest) ForwardRasMsg(obj_rrq); ep->Update(obj_rrq); @@ -1040,7 +1040,7 @@ rejectReason = H225_RegistrationRejectReason::e_securityDenial; } } - + if (!bReject) { unsigned rsn = H225_RegistrationRejectReason::e_securityDenial; if (!authList->Check(obj_rr, rsn)) { @@ -1065,7 +1065,7 @@ } else { bReject = TRUE; rejectReason = H225_RegistrationRejectReason::e_duplicateAlias; - } + } } // reject the empty string @@ -1089,7 +1089,7 @@ rejectReason = H225_RegistrationRejectReason::e_invalidAlias; break; /* only while debugging - default: + default: bReject = TRUE; rejectReason.SetTag(H225_RegistrationRejectReason::e_invalidAlias); break; @@ -1112,9 +1112,9 @@ else ep->SetNAT(false); if (bShellSendReply) { - // + // // OK, now send RCF - // + // BuildRCF(obj_rpl, obj_rr, ep, rx_addr); H225_RegistrationConfirm & rcf = obj_rpl; rcf.IncludeOptionalField(H225_RegistrationConfirm::e_terminalAlias); @@ -1148,7 +1148,7 @@ // Note that the terminalAlias is not optional here as we pass the auto generated alias if not were provided from // the endpoint itself - PString msg(PString::Printf, "RCF|%s|%s|%s|%s;\r\n", + PString msg(PString::Printf, "RCF|%s|%s|%s|%s;\r\n", (const unsigned char *) AsDotString(ep->GetCallSignalAddress()), (const unsigned char *) AsString(ep->GetAliases()), (const unsigned char *) AsString(obj_rr.m_terminalType), @@ -1167,7 +1167,7 @@ // // final rejection handling // - obj_rpl.SetTag(H225_RasMessage::e_registrationReject); + obj_rpl.SetTag(H225_RasMessage::e_registrationReject); H225_RegistrationReject & rrj = obj_rpl; rrj.m_requestSeqNum = obj_rr.m_requestSeqNum; @@ -1185,8 +1185,8 @@ aliasListString = AsString(obj_rr.m_terminalAlias); else aliasListString = " "; - - PString msg(PString::Printf, "RRJ|%s|%s|%s|%s;\r\n", + + PString msg(PString::Printf, "RRJ|%s|%s|%s|%s;\r\n", inet_ntoa(rx_addr), (const unsigned char *) aliasListString, (const unsigned char *) AsString(obj_rr.m_terminalType), @@ -1284,18 +1284,18 @@ BOOL H323RasSrv::DoARQ(const PIPSocket::Address & rx_addr, const H225_RasMessage & obj_arq) { H225_RasMessage obj_rpl; - const H225_AdmissionRequest & obj_rr = obj_arq; - + const H225_AdmissionRequest & obj_rr = obj_arq; + // find the caller const endptr RequestingEP = EndpointTable->FindByEndpointId(obj_rr.m_endpointIdentifier); if (!RequestingEP) { // TODO: signal error on status thread return false; }; - + BOOL ShallSendReply = OnARQ(rx_addr, obj_arq, obj_rpl); - if (ShallSendReply) { + if (ShallSendReply) { const H225_TransportAddress_ipAddress & ip = RequestingEP->GetRasAddress(); PIPSocket::Address ipaddress(ip.m_ip[0], ip.m_ip[1], ip.m_ip[2], ip.m_ip[3]); PTRACE(1, "GK\tDoARQ sendReply " << ipaddress << " " << ip.m_port ); @@ -1304,14 +1304,14 @@ return true; } - + /* Admission Request */ BOOL H323RasSrv::OnARQ(const PIPSocket::Address & rx_addr, const H225_RasMessage & obj_arq, H225_RasMessage & obj_rpl) -{ +{ PTRACE(1, "GK\tARQ Received"); const H225_AdmissionRequest & obj_rr = obj_arq; - + BOOL bReject = FALSE; long callDurationLimit = -1; unsigned rejectReason = 0; @@ -1321,15 +1321,32 @@ const endptr RequestingEP = EndpointTable->FindByEndpointId(obj_rr.m_endpointIdentifier); endptr CalledEP(0); - + if (CallTbl->Size() >= callLimit && !obj_rr.m_answerCall) { bReject = TRUE; rejectReason = H225_AdmissionRejectReason::e_resourceUnavailable; PTRACE(1, "GK\tWarning: Exceed call limit!!"); } else if (RequestingEP) { // Is the ARQ from a registered endpoint? bool bHasDestInfo = (obj_rr.HasOptionalField(H225_AdmissionRequest::e_destinationInfo) && obj_rr.m_destinationInfo.GetSize() >= 1); - if (bHasDestInfo) // apply rewriting rules + // apply rewriting rules + if (bHasDestInfo) { + + PString source; + PStringArray tokenised_source; + + // Do inbound per GW rewriting first + source = AsString(RequestingEP->GetAliases()[0]); + + // Chop up source to get the h323_ID or dialedDigits + tokenised_source = source.Tokenise(PString(":")); + + if (tokenised_source.GetSize() == 2) { + Toolkit::Instance()->GWRewriteE164(tokenised_source[0],true,obj_rr.m_destina tionInfo[0]); + } + + // Normal rewriting Toolkit::Instance()->RewriteE164(obj_rr.m_destinationInfo[0]); + } if (!authList->Check(obj_rr,rsn,callDurationLimit)) { bReject = TRUE; @@ -1344,7 +1361,7 @@ PString alias = H323GetAliasAddressString (obj_rr.m_destinationInfo[0]); if (wArqList->IsDestinationVirtualQueue(alias)) { PString src = (RequestingEP) ? AsDotString(RequestingEP->GetCallSignalAddress()) : PString(" "); - PString msg(PString::Printf, "RouteRequest|%s|%s|%u|%s|%s;\r\n", + PString msg(PString::Printf, "RouteRequest|%s|%s|%u|%s|%s;\r\n", (const unsigned char *) src, (const unsigned char *) RequestingEP->GetEndpointIdentifier().GetValue(), (unsigned) obj_rr.m_callReferenceValue, @@ -1372,7 +1389,7 @@ if (!CalledEP && bHasDestInfo) { #if WITH_DEST_ANALYSIS_LIST CalledEP = EndpointTable->getMsgDestination(obj_rr, rsn); - if (!CalledEP && + if (!CalledEP && rsn == H225_AdmissionRejectReason::e_incompleteAddress) { bReject = TRUE; rejectReason = rsn; @@ -1402,12 +1419,29 @@ } } if (bReject) { - obj_rpl.SetTag(H225_RasMessage::e_admissionReject); - H225_AdmissionReject & arj = obj_rpl; + obj_rpl.SetTag(H225_RasMessage::e_admissionReject); + H225_AdmissionReject & arj = obj_rpl; arj.m_rejectReason.SetTag(rejectReason); if (rejectReason == H225_AdmissionRejectReason::e_resourceUnavailable) SetAltGKInfo(arj); } + + // Per GW outbound + if (CalledEP && (RequestingEP != CalledEP)) { + PString source; + PStringArray tokenised_source; + + source = AsString(CalledEP->GetAliases()[0]); + + // Chop up source to get the h323_ID or dialedDigits + tokenised_source = source.Tokenise(PString(":")); + + if (tokenised_source.GetSize() == 2) { + Toolkit::Instance()->GWRewriteE164(tokenised_source[0],false,obj_rr.m_destin ationInfo[0]); + } + + } + ProcessARQ(rx_addr, RequestingEP, CalledEP, obj_rr, obj_rpl, bReject); if( callDurationLimit > 0 ) { callptr pExistingCallRec = (obj_rr.HasOptionalField(H225_AdmissionRequest::e_callIdentifier)) ? @@ -1451,16 +1485,16 @@ #ifdef ARJREASON_ROUTECALLTOSCN // - // call from one GW to itself? + // call from one GW to itself? // generate ARJ-reason: 'routeCallToSCN' // - if(!bReject && + if(!bReject && Toolkit::AsBool(GkConfig()->GetString("RasSrv::ARQFeatures", "ArjReasonRouteCallToSCN", "1"))) { // are the endpoints the same (GWs of course)? - if( (CalledEP) && (RequestingEP) && (CalledEP == RequestingEP) && + if( (CalledEP) && (RequestingEP) && (CalledEP == RequestingEP) && (!obj_arq.m_answerCall) // only first ARQ may be rejected with with 'routeCallToSCN' - ) + ) { // we have to extract the SCN from the destination. only EP-1 will be rejected this way if ( obj_arq.m_destinationInfo.GetSize() >= 1 ) { @@ -1471,14 +1505,14 @@ // set defaults PPN.m_publicTypeOfNumber.SetTag(H225_PublicTypeOfNumber::e_unknown); PPN.m_publicNumberDigits = ""; - + // there can be diffent information in the destination info switch(obj_arq.m_destinationInfo[0].GetTag()) { - case H225_AliasAddress::e_dialedDigits: + case H225_AliasAddress::e_dialedDigits: // normal number, extract only the digits PPN.m_publicNumberDigits = AsString(obj_arq.m_destinationInfo[0], FALSE); break; - case H225_AliasAddress::e_partyNumber: + case H225_AliasAddress::e_partyNumber: // ready-to-use party number PN = obj_arq.m_destinationInfo[0]; break; @@ -1486,7 +1520,7 @@ PTRACE(1,"Unsupported AliasAdress for ARQ reason 'routeCallToSCN': " << obj_arq.m_destinationInfo[0]); } - + // set the ARJ reason bReject = TRUE; rejectReason = H225_AdmissionRejectReason::e_routeCallToSCN; @@ -1494,7 +1528,7 @@ APN.SetSize(1); APN[0] = PN; } - else { + else { // missing destination info. is this possible at this point? } } @@ -1533,7 +1567,7 @@ } // - // Bandwidth + // Bandwidth // and GkManager admission // int BWRequest = 1280; @@ -1565,7 +1599,7 @@ arj.m_rejectReason.SetTag(rejectReason); arj.m_requestSeqNum = obj_arq.m_requestSeqNum; SetCryptoTokens(obj_arq, arj); - PString msg(PString::Printf, "ARJ|%s|%s|%s|%s|%s;\r\n", + PString msg(PString::Printf, "ARJ|%s|%s|%s|%s|%s;\r\n", (const unsigned char *) srcInfoString, (const unsigned char *) destinationInfoString, (const unsigned char *) AsString(obj_arq.m_srcInfo), @@ -1573,7 +1607,7 @@ (const unsigned char *) arj.m_rejectReason.GetTagName() ); PTRACE(2, msg); GkStatusThread->SignalStatus(msg); - + if (CalledEP && CalledEP->IsFromParent()) { H225_RasMessage drq_ras; drq_ras.SetTag(H225_RasMessage::e_disengageRequest); @@ -1599,8 +1633,8 @@ // else this may be a duplicate ARQ, ignore! PTRACE(3, "GK\tACF: found existing call no " << pExistingCallRec->GetCallNumber()); } else { - // the call is not in the table - CallRec *pCallRec = new CallRec(obj_arq.m_callIdentifier, obj_arq.m_conferenceID, + // the call is not in the table + CallRec *pCallRec = new CallRec(obj_arq.m_callIdentifier, obj_arq.m_conferenceID, destinationInfoString, AsString(obj_arq.m_srcInfo), BWRequest, GKRoutedH245); pCallRec->SetCalled(CalledEP, obj_arq.m_callReferenceValue); @@ -1611,7 +1645,7 @@ pCallRec->SetConnected(); CallTbl->Insert(pCallRec); } - + if ( GKRoutedSignaling ) { acf.m_callModel.SetTag( H225_CallModel::e_gatekeeperRouted ); acf.m_destCallSignalAddress = GetCallSignalAddress(rx_addr); @@ -1657,7 +1691,7 @@ if (destinationInfoString.IsEmpty()) destinationInfoString = "unknown destination alias"; // always signal ACF - PString msg(PString::Printf, "ACF|%s|%s|%u|%s|%s|%s;\r\n", + PString msg(PString::Printf, "ACF|%s|%s|%u|%s|%s|%s;\r\n", (const unsigned char *) srcInfoString, (const unsigned char *) RequestingEP->GetEndpointIdentifier().GetValue(), (unsigned) obj_arq.m_callReferenceValue, @@ -1729,25 +1763,25 @@ PString msg; if (bReject) { - obj_rpl.SetTag(H225_RasMessage::e_disengageReject); + obj_rpl.SetTag(H225_RasMessage::e_disengageReject); H225_DisengageReject & drj = obj_rpl; drj.m_requestSeqNum = obj_rr.m_requestSeqNum; drj.m_rejectReason.SetTag(rsn); SetCryptoTokens(obj_rr, drj); - msg = PString(PString::Printf, "DRJ|%s|%s|%u|%s;\r\n", + msg = PString(PString::Printf, "DRJ|%s|%s|%u|%s;\r\n", inet_ntoa(rx_addr), (const unsigned char *) obj_rr.m_endpointIdentifier.GetValue(), (unsigned) obj_rr.m_callReferenceValue, (const unsigned char *) drj.m_rejectReason.GetTagName()); } else { - obj_rpl.SetTag(H225_RasMessage::e_disengageConfirm); + obj_rpl.SetTag(H225_RasMessage::e_disengageConfirm); H225_DisengageConfirm & dcf = obj_rpl; - dcf.m_requestSeqNum = obj_rr.m_requestSeqNum; + dcf.m_requestSeqNum = obj_rr.m_requestSeqNum; SetCryptoTokens(obj_rr, dcf); // always signal DCF - msg = PString(PString::Printf, "DCF|%s|%s|%u|%s;\r\n", + msg = PString(PString::Printf, "DCF|%s|%s|%u|%s;\r\n", inet_ntoa(rx_addr), (const unsigned char *) obj_rr.m_endpointIdentifier.GetValue(), (unsigned) obj_rr.m_callReferenceValue, @@ -1765,7 +1799,7 @@ /* Unregistration Request */ BOOL H323RasSrv::OnURQ(const PIPSocket::Address & rx_addr, const H225_RasMessage &obj_urq, H225_RasMessage &obj_rpl) -{ +{ PTRACE(1, "GK\tURQ Received"); const H225_UnregistrationRequest & obj_rr = obj_urq; @@ -1804,18 +1838,18 @@ CopyNonStandardData(obj_rr, ucf); SetCryptoTokens(obj_rr, ucf); - msg = PString(PString::Printf, "UCF|%s|%s;", + msg = PString(PString::Printf, "UCF|%s|%s;", inet_ntoa(rx_addr), (const unsigned char *) endpointIdentifierString) ; } else { - // Return URJ + // Return URJ obj_rpl.SetTag(H225_RasMessage::e_unregistrationReject); H225_UnregistrationReject & urj = obj_rpl; urj.m_requestSeqNum = obj_rr.m_requestSeqNum; urj.m_rejectReason.SetTag(H225_UnregRejectReason::e_notCurrentlyRegistered); CopyNonStandardData(obj_rr, urj); - msg = PString(PString::Printf, "URJ|%s|%s|%s;", + msg = PString(PString::Printf, "URJ|%s|%s|%s;", inet_ntoa(rx_addr), (const unsigned char *) endpointIdentifierString, (const unsigned char *) urj.m_rejectReason.GetTagName() ); @@ -1824,7 +1858,7 @@ PTRACE(2, msg); GkStatusThread->SignalStatus(msg + "\r\n"); - if (bShellForwardRequest) + if (bShellForwardRequest) ForwardRasMsg(obj_urq); return bShellSendReply; @@ -1833,7 +1867,7 @@ /* Bandwidth Request */ BOOL H323RasSrv::OnBRQ(const PIPSocket::Address & rx_addr, const H225_RasMessage & obj_rr, H225_RasMessage & obj_rpl) -{ +{ PTRACE(1, "GK\tBRQ Received"); const H225_BandwidthRequest & obj_brq = obj_rr; @@ -1868,7 +1902,7 @@ if (bReject) { brj.m_rejectReason.SetTag(rsn); CopyNonStandardData(obj_brq, brj); - msg = PString(PString::Printf, "BRJ|%s|%s|%u|%s;\r\n", + msg = PString(PString::Printf, "BRJ|%s|%s|%u|%s;\r\n", inet_ntoa(rx_addr), (const unsigned char *)obj_brq.m_endpointIdentifier.GetValue(), bandwidth, @@ -1880,7 +1914,7 @@ bcf.m_requestSeqNum = obj_brq.m_requestSeqNum; bcf.m_bandWidth = bandwidth; CopyNonStandardData(obj_brq, bcf); - msg = PString(PString::Printf, "BCF|%s|%s|%u;\r\n", + msg = PString(PString::Printf, "BCF|%s|%s|%u;\r\n", inet_ntoa(rx_addr), (const unsigned char *)obj_brq.m_endpointIdentifier.GetValue(), bandwidth); @@ -1898,11 +1932,33 @@ PTRACE(1, "GK\tLRQ Received"); PString msg; - endptr WantedEndPoint; + endptr WantedEndPoint,rewriteEndPoint; const H225_LocationRequest & obj_lrq = obj_rr; - if (obj_lrq.m_destinationInfo.GetSize() > 0) + if (obj_lrq.m_destinationInfo.GetSize() > 0) { + + // per GW rewrite first + rewriteEndPoint = EndpointTable->FindByEndpointId(obj_lrq.m_endpointIdentifier); + if (rewriteEndPoint) { + + PString source; + PStringArray tokenised_source; + + source = AsString(rewriteEndPoint->GetAliases()[0]); + + // Chop up source to get the h323_ID or dialedDigits + tokenised_source = source.Tokenise(PString(":")); + + if (tokenised_source.GetSize() == 2) { + Toolkit::Instance()->GWRewriteE164(tokenised_source[0],true,obj_lrq.m_destin ationInfo[0]); + } + + } + + // Normal rewrite Toolkit::Instance()->RewriteE164(obj_lrq.m_destinationInfo[0]); + } + unsigned rsn = H225_LocationRejectReason::e_securityDenial; PIPSocket::Address ipaddr; @@ -1938,7 +1994,7 @@ lcf.m_rasAddress = GetRasAddress(rx_addr); } - msg = PString(PString::Printf, "LCF|%s|%s|%s|%s;\r\n", + msg = PString(PString::Printf, "LCF|%s|%s|%s|%s;\r\n", inet_ntoa(rx_addr), (const unsigned char *) WantedEndPoint->GetEndpointIdentifier().GetValue(), (const unsigned char *) AsString(obj_lrq.m_destinationInfo), @@ -1958,7 +2014,7 @@ lrj.m_rejectReason.SetTag(rsn); CopyNonStandardData(obj_lrq, lrj); - msg = PString(PString::Printf, "LRJ|%s|%s|%s|%s;\r\n", + msg = PString(PString::Printf, "LRJ|%s|%s|%s|%s;\r\n", inet_ntoa(rx_addr), (const unsigned char *) AsString(obj_lrq.m_destinationInfo), (const unsigned char *) sourceInfoString, @@ -2003,7 +2059,7 @@ /* Information Request Response */ BOOL H323RasSrv::OnIRR(const PIPSocket::Address & rx_addr, const H225_RasMessage &obj_rr, H225_RasMessage &obj_rpl) -{ +{ PTRACE(1, "GK\tIRR Received"); const H225_InfoRequestResponse & obj_irr = obj_rr; @@ -2029,7 +2085,7 @@ /* Resource Availability Indicate */ BOOL H323RasSrv::OnRAI(const PIPSocket::Address & rx_addr, const H225_RasMessage &obj_rr, H225_RasMessage &obj_rpl) -{ +{ PTRACE(1, "GK\tRAI Received"); const H225_ResourcesAvailableIndicate & obj_rai = obj_rr; @@ -2040,7 +2096,7 @@ rac.m_requestSeqNum = obj_rai.m_requestSeqNum; rac.m_protocolIdentifier = obj_rai.m_protocolIdentifier; CopyNonStandardData(obj_rai, rac); - + return TRUE; } @@ -2050,13 +2106,13 @@ PTRACE(1, "GK\tSCI Received"); return FALSE; } - + BOOL H323RasSrv::OnSCR(const PIPSocket::Address & rx_addr, const H225_RasMessage & obj_rr, H225_RasMessage & obj_rpl) { PTRACE(1, "GK\tSCR Received"); return FALSE; } - + BOOL H323RasSrv::OnIgnored(const PIPSocket::Address &, const H225_RasMessage & obj_rr, H225_RasMessage &) { PTRACE(2, "GK\t" << obj_rr.GetTagName() << " received and safely ignored"); @@ -2079,7 +2135,7 @@ #if HAS_WAITARQ wArqList->CheckWaitingARQ(); #endif - + return !IsTerminated(); } @@ -2137,7 +2193,7 @@ PTRACE(1, "GK\tRasThread " << getpid() << " started"); - PString err_msg("ERROR: Request received by gatekeeper: "); + PString err_msg("ERROR: Request received by gatekeeper: "); PTRACE(2, "GK\tEntering connection handling loop"); // queueSize is useless for UDPSocket @@ -2150,9 +2206,9 @@ gkClient = new GkClient(this); loadLock.Signal(); // OK, the thread is ready - while (listener.IsOpen()) { + while (listener.IsOpen()) { PIPSocket::Address rx_addr; - H225_RasMessage obj_req; + H225_RasMessage obj_req; H225_RasMessage obj_rpl; // large mutex! only allow the reloadhandler be executed @@ -2184,7 +2240,7 @@ PTRACE(3, "GK\n" << setprecision(2) << obj_req); else PTRACE(2, "GK\tReceived " << obj_req.GetTagName()); -#endif +#endif if (obj_req.GetTag() <= H225_RasMessage::e_serviceControlResponse) { if ((this->*rasHandler[obj_req.GetTag()])(rx_addr, obj_req, obj_rpl)) @@ -2201,14 +2257,14 @@ PTRACE(1, "GK\tRasThread terminated!"); } -void H323RasSrv::SelectH235Capability( +void H323RasSrv::SelectH235Capability( const H225_GatekeeperRequest& grq, H225_GatekeeperConfirm& gcf ) { if( authList == NULL ) return; - + // if GRQ does not contain a list of authentication mechanisms simply return if( !(grq.HasOptionalField(H225_GatekeeperRequest::e_authenticationCapability) && grq.HasOptionalField(H225_GatekeeperRequest::e_algorithmOIDs) @@ -2220,12 +2276,12 @@ H225_ArrayOf_PASN_ObjectId algorithmOIDs; authList->GetH235Capabilities(mechanisms,algorithmOIDs); - + // And now match H.235 capabilities found with those from GRQ - // to find the one to be returned in GCF + // to find the one to be returned in GCF for( int i = 0; i < grq.m_authenticationCapability.GetSize(); i++ ) - for( int j = 0; j < mechanisms.GetSize(); j++ ) - if( grq.m_authenticationCapability[i].GetTag() + for( int j = 0; j < mechanisms.GetSize(); j++ ) + if( grq.m_authenticationCapability[i].GetTag() == mechanisms[j].GetTag() ) for( int l = 0; l < algorithmOIDs.GetSize(); l++ ) for( int k = 0; k < grq.m_algorithmOIDs.GetSize(); k++ ) @@ -2234,7 +2290,7 @@ GkAuthenticator* authenticator = authList ? authList->GetHead() : NULL; while( authenticator ) { - if( authenticator->IsH235Capable() + if( authenticator->IsH235Capable() && authenticator->IsH235Capability( mechanisms[j], algorithmOIDs[l] ) ) @@ -2243,7 +2299,7 @@ gcf.m_authenticationMode = mechanisms[j]; gcf.IncludeOptionalField(H225_GatekeeperConfirm::e_algorithmOID); gcf.m_algorithmOID = algorithmOIDs[l]; - + PTRACE(4,"GK\tGCF will select authentication mechanism: " <<mechanisms[j]<<" and algorithm OID: "<<algorithmOIDs[l] ); @@ -2251,7 +2307,7 @@ } authenticator = authenticator->GetNext(); } - + PTRACE(5,"GK\tAuthentication mechanism: " <<mechanisms[j]<<" and algorithm OID: " <<algorithmOIDs[l]<<" dropped" diff -r -U 3 openh323gk/Toolkit.cxx openh323gk.gwrewrite/Toolkit.cxx --- openh323gk/Toolkit.cxx 2003-06-19 15:37:59.000000000 +0000 +++ openh323gk.gwrewrite/Toolkit.cxx 2003-12-16 12:22:48.000000000 +0000 @@ -276,9 +276,9 @@ break; } } - - // - // Do the rewrite. + + // + // Do the rewrite. // @param #t# will be written to #s# // if (do_rewrite) { @@ -286,10 +286,220 @@ s = t; changed = true; } - + return changed; } +// class Toolkit::GWRewriteTool + +static const char *GWRewriteSection = "RasSrv::GWRewriteE164"; + +Toolkit::GWRewriteTool::~GWRewriteTool() { + for (PINDEX i = 0; i < m_GWRewrite.GetSize(); ++i) { + delete &(m_GWRewrite.GetDataAt(i)); + } + m_GWRewrite.RemoveAll(); +} + +bool Toolkit::GWRewriteTool::RewritePString(PString gw, bool direction, PString &data) { + + GWRewriteEntry *gw_entry; + std::vector<std::pair<PString,PString> >::iterator rule_iterator; + PString key,value; + bool inverted; + int striplen; + + // First lookup the GW in the dictionary + gw_entry = m_GWRewrite.GetAt(gw); + + if (gw_entry == NULL) { + return false; + } + + // True is "in" direction + if (direction == true) { + for (rule_iterator = gw_entry->m_entry_data.first.begin(); rule_iterator != gw_entry->m_entry_data.first.end(); ++rule_iterator) { + key = (*rule_iterator).first; + inverted = false; + + // Inverted match sense + if (key.GetLength() !=0 && key[0] == '!') { + inverted = true; + key = key.Mid(1); + } + + // Attempt match + if ((strncmp(data, key, key.GetLength()) == 0) ^ inverted) { + + // Start rewrite + value = (*rule_iterator).second; + striplen = (inverted) ? 0 : key.GetLength(); + value += data.Mid(striplen); + + // Log + PTRACE(2, "\tGWRewriteTool::RewritePString: " << data << " to " << value); + + // Finish rewrite + data = value; + + break; + } + + } + + } + else { + for (rule_iterator = gw_entry->m_entry_data.second.begin(); rule_iterator != gw_entry->m_entry_data.second.end(); ++rule_iterator) { + key = (*rule_iterator).first; + inverted = false; + + // Inverted match sense + if (key.GetLength() !=0 && key[0] == '!') { + inverted = true; + key = key.Mid(1); + } + + // Attempt match + if ((strncmp(data, key, key.GetLength()) == 0) ^ inverted) { + + // Start rewrite + value = (*rule_iterator).second; + striplen = (inverted) ? 0 : key.GetLength(); + value += data.Mid(striplen); + + // Log + PTRACE(2, "\tGWRewriteTool::RewritePString: " << data << " to " << value); + + // Finish rewrite + data = value; + + break; + } + + } + + } + + + return true; + +} + +void Toolkit::GWRewriteTool::PrintData() { + + std::vector<std::pair<PString,PString> >::iterator rule_iterator; + + PTRACE(2, "GK\tLoaded per GW rewrite data:"); + + if (m_GWRewrite.GetSize() == 0) { + PTRACE(2, "GK\tNo per GW data loaded"); + return; + } + + for (PINDEX i = 0; i < m_GWRewrite.GetSize(); ++i) { + + // In + for (rule_iterator = m_GWRewrite.GetDataAt(i).m_entry_data.first.begin(); rule_iterator != m_GWRewrite.GetDataAt(i).m_entry_data.first.end(); ++rule_iterator) { + PTRACE(3, "GK\t" << m_GWRewrite.GetKeyAt(i) << " (in): " << (*rule_iterator).first << " = " << (*rule_iterator).second); + } + + // Out + for (rule_iterator = m_GWRewrite.GetDataAt(i).m_entry_data.second.begin(); rule_iterator != m_GWRewrite.GetDataAt(i).m_entry_data.second.end(); ++rule_iterator) { + PTRACE(3, "GK\t" << m_GWRewrite.GetKeyAt(i) << " (out): " << (*rule_iterator).first << " = " << (*rule_iterator).second); + } + + } + + PTRACE(2, "GK\tLoaded " << m_GWRewrite.GetSize() << " GW entries with rewrite info"); + +} + + +void Toolkit::GWRewriteTool::LoadConfig(PConfig *config) { + + PINDEX gw_size, i, j, lines_size; + PString key, cfg_value; + PStringArray lines, tokenised_line; + GWRewriteEntry *gw_entry; + std::map<PString,PString> in_strings, out_strings; + std::vector<std::pair<PString,PString> > sorted_in_strings, sorted_out_strings; + std::map<PString,PString>::reverse_iterator strings_iterator; + std::pair<PString,PString> rule; + + PStringToString cfgs(config->GetAllKeyValues(GWRewriteSection)); + + // Clear old config + for (PINDEX i = 0; i < m_GWRewrite.GetSize(); ++i) { + delete &(m_GWRewrite.GetDataAt(i)); + } + m_GWRewrite.RemoveAll(); + + gw_size = cfgs.GetSize(); + if (gw_size > 0) { + for (i = 0; i < gw_size; ++i) { + + // Get the config keys + key = cfgs.GetKeyAt(i); + cfg_value = cfgs[key]; + + in_strings.clear(); + out_strings.clear(); + sorted_in_strings.clear(); + sorted_out_strings.clear(); + + // Split the config data into seperate lines + lines = cfg_value.Tokenise(PString("\n")); + + lines_size = lines.GetSize(); + + for (j = 0; j < lines_size; ++j) { + + // Split the config line into three strings, direction, from string, to string + tokenised_line = lines[j].Tokenise(PString("=")); + + if (tokenised_line.GetSize() < 3) { + continue; + } + + // Put into appropriate std::map + + if (tokenised_line[0] == "in") { + in_strings[tokenised_line[1]] = tokenised_line[2]; + + } + if (tokenised_line[0] == "out") { + out_strings[tokenised_line[1]] = tokenised_line[2]; + } + + } + + // Put the map contents into reverse sorted vectors + for (strings_iterator = in_strings.rbegin(); strings_iterator != in_strings.rend(); ++strings_iterator) { + rule = *strings_iterator; + sorted_in_strings.push_back(rule); + } + for (strings_iterator = out_strings.rbegin(); strings_iterator != out_strings.rend(); ++strings_iterator) { + rule = *strings_iterator; + sorted_out_strings.push_back(rule); + } + + + // Create the entry + gw_entry = new GWRewriteEntry(); + gw_entry->m_entry_data.first = sorted_in_strings; + gw_entry->m_entry_data.second = sorted_out_strings; + + + // Add to PDictionary hash table + m_GWRewrite.Insert(key,gw_entry); + + } + } + + PrintData(); +} + + Toolkit::Toolkit() : m_Config(0), m_ConfigDirty(false) #ifdef HAS_ACCT , m_acctList(NULL) @@ -307,7 +517,7 @@ callptr dummycall; m_acctList->LogAcctEvent( GkAcctLogger::AcctOff, dummycall ); } - delete m_acctList; + delete m_acctList; } catch( ... ) { PTRACE(0,"GKACCT\tException caught during Accounting-Off event logging"); } @@ -333,7 +543,7 @@ } PConfig* Toolkit::SetConfig(const PFilePath &fp, const PString §ion) -{ +{ m_ConfigFilePath = fp; m_ConfigDefaultSection = section; @@ -401,11 +611,12 @@ m_RouteTable.InitTable(); m_ProxyCriterion.LoadConfig(m_Config); m_Rewrite.LoadConfig(m_Config); + m_GWRewrite.LoadConfig(m_Config); #ifdef HAS_ACCT const BOOL nasStart = (m_acctList == NULL); - try { - delete m_acctList; + try { + delete m_acctList; } catch( ... ) { PTRACE(0,"GKACCT\tException caught during accounting modules cleanup"); } @@ -420,7 +631,7 @@ PTRACE(0,"GKACCT\tException caught during Accounting-On event logging"); } #endif - return m_Config; + return m_Config; } BOOL Toolkit::MatchRegex(const PString &str, const PString ®exStr) @@ -441,16 +652,16 @@ bool Toolkit::RewriteE164(H225_AliasAddress &alias) -{ - if (alias.GetTag() != H225_AliasAddress::e_dialedDigits) +{ + if (alias.GetTag() != H225_AliasAddress::e_dialedDigits) return FALSE; - + PString E164 = H323GetAliasAddressString(alias); bool changed = RewritePString(E164); if (changed) H323SetAliasAddress(E164, alias); - + return changed; } @@ -462,8 +673,42 @@ return changed; } -const PString -Toolkit::GKName() + +bool Toolkit::GWRewriteE164(PString gw, bool direction, +H225_AliasAddress &alias) { + + PString E164; + bool changed; + + if (alias.GetTag() != H225_AliasAddress::e_dialedDigits) { + return false; + } + + E164 = H323GetAliasAddressString(alias); + changed = GWRewritePString(gw,direction,E164); + + if (changed) { + H323SetAliasAddress(E164, alias); + } + + return changed; +} + +bool Toolkit::GWRewriteE164(PString gw, bool direction, H225_ArrayOf_AliasAddress &aliases) { + + bool changed; + PINDEX n; + + changed = false; + for (n = 0; n < aliases.GetSize(); ++n) { + changed |= GWRewriteE164(gw,direction,aliases[n]); + } + + return changed; +} + + +const PString +Toolkit::GKName() { return GkConfig()->GetString("Name", "OpenH323GK"); //use default section (MM 06.11.01) } @@ -477,8 +722,8 @@ static const int INT_PTHREADS = 0; #endif -const PString -Toolkit::GKVersion() +const PString +Toolkit::GKVersion() { return PString(PString::Printf, "Gatekeeper(%s) Version(%s) Ext(pthreads=%d) Build(%s, %s) Sys(%s %s %s)\r\n", @@ -495,12 +740,12 @@ int -Toolkit::GetInternalExtensionCode( const unsigned &country, - const unsigned &extension, - const unsigned &manufacturer) const +Toolkit::GetInternalExtensionCode( const unsigned &country, + const unsigned &extension, + const unsigned &manufacturer) const { switch(country) { - case t35cOpenOrg: + case t35cOpenOrg: switch(manufacturer) { case t35mOpenOrg: switch(extension) { @@ -514,7 +759,7 @@ } -bool Toolkit::AsBool(const PString & str) +bool Toolkit::AsBool(const PString & str) { if (str.IsEmpty()) return false; diff -r -U 3 openh323gk/Toolkit.h openh323gk.gwrewrite/Toolkit.h --- openh323gk/Toolkit.h 2003-06-19 15:37:59.000000000 +0000 +++ openh323gk.gwrewrite/Toolkit.h 2003-12-15 11:40:50.000000000 +0000 @@ -15,6 +15,7 @@ #ifndef _toolkit_h__ #define _toolkit_h__ +#include <vector> #include <ptlib.h> #include <ptlib/sockets.h> #include "h225.h" @@ -124,16 +125,46 @@ bool RewritePString(PString & s) { return m_Rewrite.RewritePString(s); } + // Class to allow correct use of STL inside PDictionary type + class GWRewriteEntry : public PObject { + PCLASSINFO(GWRewriteEntry, PObject); + public: + std::pair<std::vector<std::pair<PString,PString> >,std::vector<std::pair<PString,PString> > > m_entry_data; + }; + + + // per GW RewriteTool + class GWRewriteTool { + public: + + GWRewriteTool() { + m_GWRewrite.AllowDeleteObjects(false); + } + ~GWRewriteTool(); + void LoadConfig(PConfig *); + void PrintData(); + bool RewritePString(PString gw, bool direction, PString &data); + + private: + PDictionary<PString, GWRewriteEntry> m_GWRewrite; + + }; + + // Equivalent functions to RewriteE164 group + bool GWRewriteE164(PString gw, bool direction, H225_AliasAddress &alias); + bool GWRewriteE164(PString gw, bool direction, H225_ArrayOf_AliasAddress &aliases); + bool GWRewritePString(PString gw, bool direction, PString &data) { return m_GWRewrite.RewritePString(gw,direction,data); } + // accessors - /** Accessor and 'Factory' to the static Toolkit. + /** Accessor and 'Factory' to the static Toolkit. * If you want to use your own Toolkit class you have to - * overwrite this method and ensure that your version is + * overwrite this method and ensure that your version is * called first -- before any other call to #Toolkit::Instance#. - * Example: + * Example: * <pre> * class MyToolkit: public Toolkit { - * public: + * public: * static Toolkit& Instance() { * if (m_Instance == NULL) m_Instance = new MyToolkit(); * return m_Instance; @@ -145,16 +176,16 @@ * </pre> */ - /** Accessor and 'Factory' for the global (static) configuration. - * With this we are able to implement out own Config-Loader - * in the same way as #Instance()#. And we can use #Config()# + /** Accessor and 'Factory' for the global (static) configuration. + * With this we are able to implement out own Config-Loader + * in the same way as #Instance()#. And we can use #Config()# * in the constructor of #Toolkit# (and its descentants). */ - PConfig* Config(); - PConfig* Config(const char *); + PConfig* Config(); + PConfig* Config(const char *); /** Sets the config that the toolkit uses to a given config. - * A prior loaded Config is discarded. + * A prior loaded Config is discarded. */ PConfig* SetConfig(const PFilePath &fp, const PString §ion); @@ -179,7 +210,7 @@ */ static BOOL MatchRegex(const PString &str, const PString ®exStr); - /** returns the #BOOL# that #str# represents. + /** returns the #BOOL# that #str# represents. * Case insensitive, "t...", "y...", "a...", "1" are #TRUE#, all other values are #FALSE#. */ static bool AsBool(const PString & str); @@ -199,10 +230,10 @@ enum { t35cOpenOrg = 255, /// country code for the "Open Source Organisation" Country t35mOpenOrg = 4242, /// manufacurers code for the "Open Source Organisation" - t35eFailoverRAS = 255 /// Defined HERE! + t35eFailoverRAS = 255 /// Defined HERE! }; - /** If the triple #(country,extension,manufacturer)# represents an - * extension known to the GnuGK this method returns its 'internal extension code' + /** If the triple #(country,extension,manufacturer)# represents an + * extension known to the GnuGK this method returns its 'internal extension code' # #iecXXX' or #iecUnknow# otherwise. * * Overwriting methods should use a simlilar scheme and call @@ -215,10 +246,10 @@ * </code> * This results in 'cascading' calls until a iec!=iecUnkown is returned. */ - virtual int GetInternalExtensionCode(const unsigned &country, - const unsigned &extension, + virtual int GetInternalExtensionCode(const unsigned &country, + const unsigned &extension, const unsigned &manufacturer) const; - + int GetInternalExtensionCode(const H225_H221NonStandard& data) const { return GetInternalExtensionCode(data.m_t35CountryCode, @@ -249,6 +280,11 @@ RouteTable m_RouteTable; ProxyCriterion m_ProxyCriterion; + /* GW Based RewriteTool */ + GWRewriteTool m_GWRewrite; + + + #ifdef HAS_ACCT GkAcctLoggers* m_acctList; #endif @@ -258,7 +294,7 @@ inline unsigned long -Toolkit::HashCStr(const unsigned char *name) +Toolkit::HashCStr(const unsigned char *name) { register unsigned long h = 0, g; while (*name) { ------------------------------------------------------- This SF.net email is sponsored by: SF.net Giveback Program. Does SourceForge.net help you be more productive? Does it help you create better code? SHARE THE LOVE, and help us help YOU! Click Here: http://sourceforge.net/donate/ _______________________________________________ List: Openh323gk-users@lists.sourceforge.net Archive: http://sourceforge.net/mailarchive/forum.php?forum_id=8549 Homepage: http://www.gnugk.org/ ------------------------------------------------------- This SF.net email is sponsored by: Perforce Software. Perforce is the Fast Software Configuration Management System offering advanced branching capabilities and atomic changes on 50+ platforms. Free Eval! http://www.perforce.com/perforce/loadprog.html _______________________________________________ List: Openh323gk-users@lists.sourceforge.net Archive: http://sourceforge.net/mailarchive/forum.php?forum_id=8549 Homepage: http://www.gnugk.org/