Skip to content

Commit

Permalink
fix H.460.18/.19 on multi-homed servers
Browse files Browse the repository at this point in the history
  • Loading branch information
willamowius committed Mar 12, 2021
1 parent 838ada5 commit c53df9f
Show file tree
Hide file tree
Showing 10 changed files with 345 additions and 77 deletions.
201 changes: 157 additions & 44 deletions ProxyChannel.cxx

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions ProxyChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// ProxyChannel.h
//
// Copyright (c) Citron Network Inc. 2001-2003
// Copyright (c) 2002-2020, Jan Willamowius
// Copyright (c) 2002-2021, Jan Willamowius
//
// This work is published under the GNU Public License version 2 (GPLv2)
// see file COPYING for details.
Expand Down Expand Up @@ -71,8 +71,8 @@ const WORD DEFAULT_PACKET_BUFFER_SIZE = 2048;

void PrintQ931(int, const char *, const char *, const Q931 *, const H225_H323_UserInformation *);

ssize_t UDPSendWithSourceIP(int fd, void * data, size_t len, const IPAndPortAddress & toAddress);
ssize_t UDPSendWithSourceIP(int fd, void * data, size_t len, const PIPSocket::Address & ip, WORD port);
ssize_t UDPSendWithSourceIP(int fd, void * data, size_t len, const IPAndPortAddress & toAddress, PIPSocket::Address * gkIP);
ssize_t UDPSendWithSourceIP(int fd, void * data, size_t len, const PIPSocket::Address & ip, WORD port, PIPSocket::Address * gkIP);


class ProxySocket : public USocket {
Expand Down Expand Up @@ -705,7 +705,7 @@ class H46019Session
static bool IsKeepAlive(unsigned len, bool isRTCP) { return isRTCP ? true : (len == 12); }

void HandlePacket(DWORD receivedMultiplexID, const IPAndPortAddress & fromAddress, void * data, unsigned len, bool isRTCP);
static void Send(DWORD sendMultiplexID, const IPAndPortAddress & toAddress, int ossocket, void * data, unsigned len, bool bufferHasRoomForID = false);
static void Send(DWORD sendMultiplexID, const IPAndPortAddress & toAddress, int ossocket, void * data, unsigned len, bool bufferHasRoomForID, PIPSocket::Address * gkIP);

public:
bool m_deleted; // logically deleted, but still in list so other threads can leave methods
Expand Down
10 changes: 7 additions & 3 deletions RasSrv.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// RAS Server for GNU Gatekeeper
//
// Copyright (c) 2000-2020, Jan Willamowius
// Copyright (c) 2000-2021, Jan Willamowius
// Copyright (c) Citron Network Inc. 2001-2003
//
// This work is published under the GNU Public License version 2 (GPLv2)
Expand All @@ -13,7 +13,9 @@
//////////////////////////////////////////////////////////////////

#include "config.h"
#include <malloc.h>
#ifdef __GNU_LIBRARY__
#include <malloc.h> // for malloc_trim()
#endif
#include <ptlib.h>
#include <ptlib/sockets.h>
#include <ptclib/enum.h>
Expand Down Expand Up @@ -2650,7 +2652,9 @@ bool RegistrationRequestPDU::Process()
PTRACE(3, "RAS\tRRQ rejected by unknown reason from " << rx_addr);
return BuildRRJ(H225_RegistrationRejectReason::e_undefinedReason);
}
ep->SetRasServerIP(m_msg->m_localAddr); // remember which of our IPs the endpoint has sent the RRQ to (needed for H.460.18 SCI)
// remember which of our IPs the endpoint has sent the RRQ to (to keep all later signaling to this IP)
ep->SetRasServerIP(m_msg->m_localAddr); // JWX
PTRACE(0, "JW set rasserverip for " << m_msg->m_peerAddr << " to " << m_msg->m_localAddr);

#ifdef HAS_H46017
if (usesH46017) {
Expand Down
48 changes: 43 additions & 5 deletions RasTbl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// bookkeeping for RAS-Server in H.323 gatekeeper
//
// Copyright (c) 2000-2020, Jan Willamowius
// Copyright (c) 2000-2021, Jan Willamowius
//
// This work is published under the GNU Public License version 2 (GPLv2)
// see file COPYING for details.
Expand Down Expand Up @@ -136,6 +136,8 @@ EndpointRec::EndpointRec(
if (permanent)
m_timeToLive = 0;

SetInvalid(m_rasServerIP);

LoadEndpointConfig();
}

Expand Down Expand Up @@ -2621,7 +2623,7 @@ void H46019KeepAlive::SendKeepAlive(GkTimer * t)
ka_ptr = (char*)&multiplexedRtpKeepAlive;
ka_size = sizeof(multiplexedRtpKeepAlive);
}
size_t sent = UDPSendWithSourceIP(ossocket, ka_ptr, ka_size, dest);
size_t sent = UDPSendWithSourceIP(ossocket, ka_ptr, ka_size, dest, gkIPptr); // JWX
if (sent != ka_size) {
PTRACE(1, "Error sending RTP keepAlive " << timer);
SNMP_TRAP(10, SNMPError, Network, "Sending multiplexed RTP keepAlive failed");
Expand Down Expand Up @@ -2657,7 +2659,7 @@ void H46019KeepAlive::SendKeepAlive(GkTimer * t)
ka_ptr = (char*)&multiplexedRtcpKeepAlive;
ka_size = sizeof(multiplexedRtcpKeepAlive);
}
size_t sent = UDPSendWithSourceIP(ossocket, ka_ptr, ka_size, dest);
size_t sent = UDPSendWithSourceIP(ossocket, ka_ptr, ka_size, dest, gkIPptr); // JWX
if (sent != ka_size) {
PTRACE(1, "Error sending RTCP keepAlive " << timer);
SNMP_TRAP(10, SNMPError, Network, "Sending multiplexed RTCP keepAlive failed");
Expand Down Expand Up @@ -5080,7 +5082,7 @@ int CallRec::GetH46019Direction() const
return dir;
}

void CallRec::AddRTPKeepAlive(unsigned flcn, const IPAndPortAddress & keepAliveRTPAddr, unsigned keepAliveInterval, DWORD multiplexID)
void CallRec::AddRTPKeepAlive(unsigned flcn, const IPAndPortAddress & keepAliveRTPAddr, unsigned keepAliveInterval, DWORD multiplexID, PIPSocket::Address gkIP)
{
H46019KeepAlive ka;
ka.type = RTP;
Expand All @@ -5089,6 +5091,12 @@ void CallRec::AddRTPKeepAlive(unsigned flcn, const IPAndPortAddress & keepAliveR
ka.interval = keepAliveInterval;
ka.multiplexID = multiplexID;
m_RTPkeepalives[flcn] = ka;
ka.gkIP = gkIP;
if (gkIP.IsValid()) {
ka.gkIPptr = &gkIP;
} else {
ka.gkIPptr = NULL;
}
}

void CallRec::SetRTPKeepAlivePayloadType(unsigned flcn, BYTE payloadType)
Expand All @@ -5114,7 +5122,7 @@ void CallRec::StartRTPKeepAlive(unsigned flcn, int RTPOSSocket)
}
}

void CallRec::AddRTCPKeepAlive(unsigned flcn, const H245_UnicastAddress & keepAliveRTCPAddr, unsigned keepAliveInterval, DWORD multiplexID)
void CallRec::AddRTCPKeepAlive(unsigned flcn, const H245_UnicastAddress & keepAliveRTCPAddr, unsigned keepAliveInterval, DWORD multiplexID, PIPSocket::Address gkIP)
{
H46019KeepAlive ka;
ka.type = RTCP;
Expand All @@ -5123,6 +5131,12 @@ void CallRec::AddRTCPKeepAlive(unsigned flcn, const H245_UnicastAddress & keepAl
ka.interval = keepAliveInterval;
ka.multiplexID = multiplexID;
m_RTCPkeepalives[flcn] = ka;
ka.gkIP = gkIP;
if (gkIP.IsValid()) {
ka.gkIPptr = &gkIP;
} else {
ka.gkIPptr = NULL;
}
}

void CallRec::StartRTCPKeepAlive(unsigned flcn, int RTCPOSSocket)
Expand Down Expand Up @@ -5199,6 +5213,30 @@ void CallRec::AbortLogicalChannel(short session)
}
}

// which gatekeeper IP to use for sending to endpoint IP
void CallRec::SetEndpointIPMapping(PIPSocket::Address epIP, PIPSocket::Address gkIP)
{
PWaitAndSignal lock(m_endpointIPMappingMutex);

std::map<PIPSocket::Address, PIPSocket::Address>::iterator it = m_endpointIPMapping.find(epIP);
if (it == m_endpointIPMapping.end()) {
PTRACE(0, "JW add mapping " << AsString(epIP) << " <=> " << AsString(gkIP));
m_endpointIPMapping[epIP] = gkIP;
}
}

bool CallRec::GetEndpointIPMapping(PIPSocket::Address epIP, PIPSocket::Address & gkIP) const
{
PWaitAndSignal lock(m_endpointIPMappingMutex);

std::map<PIPSocket::Address, PIPSocket::Address>::const_iterator it = m_endpointIPMapping.find(epIP);
if (it != m_endpointIPMapping.end()) {
gkIP = it->second;
return true;
}
return false;
}

/*
bool CallRec::IsTimeout(
const time_t now,
Expand Down
18 changes: 14 additions & 4 deletions RasTbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// bookkeeping for RAS-Server in H.323 gatekeeper
//
// Copyright (c) 2000-2019, Jan Willamowius
// Copyright (c) 2000-2021, Jan Willamowius
//
// This work is published under the GNU Public License version 2 (GPLv2)
// see file COPYING for details.
Expand Down Expand Up @@ -117,7 +117,8 @@ class EndpointRec
H225_TransportAddress GetCallSignalAddress() const;
PIPSocket::Address GetIP() const;
// for multi-homed servers: the IP that the endpoint sent his RAS messages to (needed for H.460.18 SCI)
PIPSocket::Address GetRasServerIP() const { return m_rasServerIP; }
PIPSocket::Address GetRasServerIP() const { return m_rasServerIP; } // caller need to check for IsValid()
//bool GetRasServerIP(PIPSocket::Address & ip) const { ip = m_rasServerIP; return m_rasServerIP.IsValid(); } // JWX
H225_EndpointIdentifier GetEndpointIdentifier() const;
H225_ArrayOf_AliasAddress GetAliases() const;
H225_EndpointType GetEndpointType() const;
Expand Down Expand Up @@ -692,6 +693,8 @@ class H46019KeepAlive
int ossocket;
DWORD multiplexID;
BYTE payloadType;
PIPSocket::Address gkIP; // source IP
PIPSocket::Address * gkIPptr; // source IP pointer if valid
GkTimerManager::GkTimerHandle timer;
};
#endif
Expand Down Expand Up @@ -1438,10 +1441,10 @@ class CallRec {
PBYTEArray RetrieveSetup();
int GetH46019Direction() const;

void AddRTPKeepAlive(unsigned flcn, const IPAndPortAddress & keepAliveRTPAddr, unsigned keepAliveInterval, DWORD multiplexID);
void AddRTPKeepAlive(unsigned flcn, const IPAndPortAddress & keepAliveRTPAddr, unsigned keepAliveInterval, DWORD multiplexID, PIPSocket::Address gkIP);
void SetRTPKeepAlivePayloadType(unsigned flcn, BYTE payloadType);
void StartRTPKeepAlive(unsigned flcn, int RTPOSSocket);
void AddRTCPKeepAlive(unsigned flcn, const H245_UnicastAddress & keepAliveRTCPAddr, unsigned keepAliveInterval, DWORD multiplexID);
void AddRTCPKeepAlive(unsigned flcn, const H245_UnicastAddress & keepAliveRTCPAddr, unsigned keepAliveInterval, DWORD multiplexID, PIPSocket::Address gkIP);
void StartRTCPKeepAlive(unsigned flcn, int RTCPOSSocket);
void RemoveRTPKeepAlives(unsigned flcn);
void RemoveAllRTPKeepAlives();
Expand Down Expand Up @@ -1469,6 +1472,10 @@ class CallRec {
bool IsRTPInactive(short session) const;
void AbortLogicalChannel(short session);

// which gatekeeper IP to use for sending to endpoint IP
void SetEndpointIPMapping(PIPSocket::Address epIP, PIPSocket::Address gkIP);
bool GetEndpointIPMapping(PIPSocket::Address epIP, PIPSocket::Address & gkIP) const;

private:
void SendDRQ();
void InternalSetEP(endptr &, const endptr &);
Expand Down Expand Up @@ -1734,6 +1741,9 @@ class CallRec {
// Sorenson SInfo
PString m_sinfoIP;
vector<WORD> m_channelFlcnList; // list of all channel Flcn every _tried_ to open so we can close them on Reroute

std::map<PIPSocket::Address, PIPSocket::Address> m_endpointIPMapping;
PMutex m_endpointIPMappingMutex;
};

typedef CallRec::Ptr callptr;
Expand Down
1 change: 1 addition & 0 deletions changes.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Changes from 5.7 to 5.8
=======================
- BUGFIX(ProxyChannel.cxx) fix H.460.18/.19 on multi-homed servers
- BUGFIX(job.cxx) better endpointIDs on Windows when compiling without OpenSSL


Expand Down
7 changes: 6 additions & 1 deletion h323util.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// H.323 utility functions
//
// Copyright (c) 2000-2019, Jan Willamowius
// Copyright (c) 2000-2021, Jan Willamowius
//
// This work is published under the GNU Public License version 2 (GPLv2)
// see file COPYING for details.
Expand Down Expand Up @@ -731,6 +731,11 @@ bool IsPrivate(const PIPSocket::Address & ip)
return result;
}

void SetInvalid(PIPSocket::Address & ip)
{
ip = INADDR_ANY; // detected as !IsValid()
}

// is this IP part of this network
bool IsInNetwork(const PIPSocket::Address & ip, const NetworkAddress & net)
{
Expand Down
5 changes: 4 additions & 1 deletion h323util.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// H.323 utility functions
//
// Copyright (c) 2000-2019, Jan Willamowius
// Copyright (c) 2000-2021, Jan Willamowius
//
// This work is published under the GNU Public License version 2 (GPLv2)
// see file COPYING for details.
Expand Down Expand Up @@ -141,6 +141,9 @@ bool IsLoopback(const PIPSocket::Address & addr);

bool IsPrivate(const PIPSocket::Address & ip);

// set IP to an invalid state, check with IsValid()
void SetInvalid(PIPSocket::Address & ip);

// is this IP part of this network
bool IsInNetwork(const PIPSocket::Address & ip, const NetworkAddress & net);

Expand Down
Loading

0 comments on commit c53df9f

Please sign in to comment.