5#ifndef RESIP_FIXED_POINT
9#ifdef USE_MAXMIND_GEOIP
31#define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
57 return lhs.mDistance < rhs.mDistance;
70 mRUriRegularExpressionData(config.getConfigData(
"GeoProximityRequestUriFilter",
"")),
71 mRUriRegularExpression(0),
72 mDefaultDistance(config.getConfigUnsignedLong(
"GeoProximityDefaultDistance", 0)),
73 mLoadBalanceEqualDistantTargets(config.getConfigBool(
"LoadBalanceEqualDistantTargets", true))
79 std::regex_constants::syntax_option_type
flags = std::regex_constants::ECMAScript | std::regex_constants::nosubs;
87 catch(std::regex_error&)
90 ErrLog( <<
"GeoProximityRequestUriFilter rule has invalid match expression: "
100#ifdef USE_MAXMIND_GEOIP
102 Data geoIPv4Database = config.
getConfigData(
"GeoProximityIPv4CityDatabaseFile",
"GeoLiteCity.dat",
false);
103 if(!geoIPv4Database.
empty())
105 mGeoIPv4 = (GeoIP*)GeoIP_open(geoIPv4Database.
c_str(), GEOIP_MEMORY_CACHE);
108 char* dbInfo = GeoIP_database_info((GeoIP*)
mGeoIPv4);
109 InfoLog(<<
"GeoProximityTargetSorter: IPv4 db info: " << dbInfo);
112 int i = GeoIP_database_edition((GeoIP*)
mGeoIPv4);
114 if(i != GEOIP_CITY_EDITION_REV0 &&
115 i != GEOIP_CITY_EDITION_REV1 &&
116 i != GEOIP_CITYCONFIDENCE_EDITION &&
117 i != GEOIP_CITYCONFIDENCEDIST_EDITION )
120 ErrLog(<<
"GeoProximityTargetSorter: IPv4 GeoIP database is not of the correct type, IPv4 geo lookups will not take place.");
127 ErrLog(<<
"GeoProximityTargetSorter: Failed to open IPv4 GeoIP database, IPv4 geo lookups will not take place: " << geoIPv4Database);
132 InfoLog(<<
"GeoProximityTargetSorter: No IPv4 GeoIP database specified, IPv4 geo lookups will not take place.");
136 Data geoIPv6Database = config.
getConfigData(
"GeoProximityIPv6CityDatabaseFile",
"GeoLiteCityv6.dat",
false);
137 if(!geoIPv6Database.
empty())
139 mGeoIPv6 = (GeoIP*)GeoIP_open(geoIPv6Database.
c_str(), GEOIP_MEMORY_CACHE);
142 char* dbInfo = GeoIP_database_info((GeoIP*)
mGeoIPv6);
143 InfoLog(<<
"GeoProximityTargetSorter: IPv6 db info: " << dbInfo);
146 int i = GeoIP_database_edition((GeoIP*)
mGeoIPv6);
148 if(i != GEOIP_CITY_EDITION_REV1_V6 &&
149 i != GEOIP_CITY_EDITION_REV0_V6 )
152 ErrLog(<<
"GeoProximityTargetSorter: IPv6 GeoIP database is not of the correct type, IPv6 geo lookups will not take place.");
159 ErrLog(<<
"GeoProximityTargetSorter: Failed to open IPv6 GeoIP database, IPv6 geo lookups will not take place: " << geoIPv6Database);
164 InfoLog(<<
"GeoProximityTargetSorter: No IPv6 GeoIP database specified, IPv6 geo lookups will not take place.");
180#ifdef USE_MAXMIND_GEOIP
241 double clientLatitude;
242 double clientLongitude;
246 <<
", clientLatitude=" << clientLatitude <<
", clientLongitude=" << clientLongitude);
248 std::vector<GeoProximityTargetContainer> flatTargetList;
251 std::list<std::list<resip::Data> >::iterator outer = targetCollection.begin();
252 std::list<resip::Data>::iterator inner;
254 for(; outer!=targetCollection.end(); outer++, outerCounter++)
256 inner=outer->begin();
257 for(; inner != outer->end(); inner++)
268 DebugLog(<<
"GeoProximityTargetSorter: TransactionQueueCollection[" << outerCounter <<
"]: Target=" << rec.
mContact
270 <<
", DistanceFromClient=" << distance);
274 DebugLog(<<
"GeoProximityTargetSorter: TransactionQueueCollection[" << outerCounter <<
"]: Target=" << rec.
mContact
275 <<
", DistanceFromClient=" << distance);
283 WarningLog(<<
"GeoProximityTargetSorter: TransactionQueueCollection[" << outerCounter <<
"]: TID=" << *inner <<
" - Couldn't find target");
291 mt19937 randomgen(rd());
293 shuffle(flatTargetList.begin(), flatTargetList.end(), randomgen);
298 if(clientLatitude != 0 && clientLongitude != 0)
304 targetCollection.clear();
305 std::vector<GeoProximityTargetContainer>::iterator it = flatTargetList.begin();
307 for(; it != flatTargetList.end(); it++, outerCounter++)
309 std::list<resip::Data> queue;
310 queue.push_back(it->getTarget()->tid());
311 targetCollection.push_back(queue);
313 DebugLog(<<
"GeoProximityTargetSorter: Sorted TransactionQueueCollection[" << outerCounter <<
"]: Target=" << it->getTarget()->rec().mContact
314 <<
", DistanceFromClient=" << it->getDistance());
332 if(request.
exists(h_Contacts) && request.
header(h_Contacts).size() >= 1)
382 geoIPLookup(contactAddress, &latitude, &longitude);
390 if(clientLatitude == 0 && clientLongitude == 0)
394 double targetLatitude;
395 double targetLongitude;
397 if(targetLatitude == 0 && targetLongitude == 0)
402 return calculateDistance(clientLatitude, clientLongitude, targetLatitude, targetLongitude);
415 pb.
data(token, anchor);
424 pb.
data(token, anchor);
429 DebugLog(<<
"GeoProximityTargetSorter: parseGeoLocationParameter - invalid parameter format: " << parameter);
432static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
440 double hLat = sin(dLat * 0.5);
441 double hLong = sin(dLong * 0.5);
454#ifdef USE_MAXMIND_GEOIP
455 GeoIPRecord *gir = 0;
461 gir = GeoIP_record_by_ipnum_v6((GeoIP*)
mGeoIPv6,
reinterpret_cast<const sockaddr_in6&
>(address.
getSockaddr()).sin6_addr);
468 gir = GeoIP_record_by_ipnum((GeoIP*)
mGeoIPv4, ntohl(
reinterpret_cast<const sockaddr_in&
>(address.
getSockaddr()).sin_addr.s_addr));
474 Data countryData(
Data::Share, gir->country_code ? gir->country_code :
"");
477 if(latitude) *latitude = gir->latitude;
478 if(longitude) *longitude = gir->longitude;
479 if(country) *country = countryData;
480 if(region) *region = regionData;
481 if(city) *city = cityData;
483 DebugLog(<<
"GeoProximityTargetSorter::geoIPLookup: Tuple=" << address
484 <<
", Country=" << countryData
485 <<
", Region=" << regionData
486 <<
", City=" << cityData
487 <<
", Lat/Long=" << gir->latitude <<
"/" << gir->longitude);
489 GeoIPRecord_delete(gir);
494 DebugLog(<<
"GeoProximityTargetSorter::geoIPLookup: no geo location information found for Tuple=" << address);
static const double EARTH_RADIUS
static ExtensionParameter p_geolocation("x-repro-geolocation")
static const double DEG_TO_RAD
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
static const struct nv flags[]
GeoProximityTargetContainer(double distance, Target *target)
static bool instanceCompare(const GeoProximityTargetContainer &lhs, const GeoProximityTargetContainer &rhs)
~GeoProximityTargetContainer()
static bool geoIPLookup(const resip::Tuple &address, double *latitude, double *longitude, resip::Data *country=0, resip::Data *region=0, resip::Data *city=0)
bool mLoadBalanceEqualDistantTargets
virtual ~GeoProximityTargetSorter()
virtual processor_action_t process(RequestContext &)
void parseGeoLocationParameter(const resip::Data ¶meter, double &latitude, double &longitude)
resip::Data mRUriRegularExpressionData
unsigned long mDefaultDistance
void getClientGeoLocation(const resip::SipMessage &request, double &latitude, double &longitude)
double getTargetDistance(const Target &target, double clientLatitude, double clientLongitude)
double calculateDistance(double latitude1, double longitude1, double latitude2, double longitude2)
void getTargetGeoLocation(const Target &target, double &latitude, double &longitude)
static resip::KeyValueStore::Key mGeoTargetSortingDoneKey
GeoProximityTargetSorter(ProxyConfig &config)
std::regex * mRUriRegularExpression
static resip::KeyValueStore::Key allocateRequestKeyValueStoreKey()
resip::SipMessage & getOriginalRequest()
Returns the SipMessage associated with the server transaction.
ResponseContext & getResponseContext()
resip::KeyValueStore & getKeyValueStore()
const TransactionMap & getCandidateTransactionMap() const
Self-explanatory.
bool hasTerminatedTransactions() const
bool hasCandidateTransactions() const
std::list< std::list< resip::Data > > mTransactionQueueCollection
Target * getTarget(const resip::Data &serial) const
Self-explanatory.
bool hasActiveTransactions() const
bool isCandidate(const resip::Data &tid) const
virtual const resip::ContactInstanceRecord & rec() const
resip::Data getConfigData(const resip::Data &name, const resip::Data &defaultValue, bool useDefaultIfEmpty=false) const
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
const char * c_str() const
Returns a null-terminated string representing.
@ Share
The Data instance will use the buffer in a read-only mode.
bool empty() const noexcept
Checks whether the Data is empty.
static Data from(const T &x)
Converts from arbitrary other type to Data.
double convertDouble() const
Takes the contents of the Data and converts them to a double precision floating point value.
static Tuple getClientPublicAddress(const SipMessage &request)
Look at Via headers, and find the first public IP address closest to the sending client.
void setBoolValue(Key key, bool value)
const bool & getBoolValue(Key key) const
bool exists(const Param< NameAddr > ¶mType) const
const Data & param(const ExtensionParameter ¶m) const
Const accessor for non-natively-supported parameter types.
Provides string-parsing functionality with protection from buffer overflow.
CurrentPosition skipToChar(char c)
CurrentPosition position() const
CurrentPosition skipToOneOf(const char *cs)
CurrentPosition skipChar()
void data(Data &data, const char *start) const
make the passed in data share memory with the buffer (uses Data::Share)
Represents a SIP message.
bool isRequest() const
Returns true if message is a request, false otherwise.
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
bool exists(const HeaderBase &headerType) const
Returns true if the given header field is present, false otherwise.
static const char * COMMA
Represents a network address.
IpVersion ipVersion() const
Returns V4 or V6 as appropriate.
bool isPrivateAddress() const
TransportType getType() const
const sockaddr & getSockaddr() const
Retrieve a const binary representation of the socket address for this tuple.
This Class is used to implement a primitive form of RPC using loose XML formatting.
dcm! – add UnusedChecking(_enum) below;
RequestLineType h_RequestLine