1
0
Fork 0

added srv://

This commit is contained in:
Frank Celler 2016-03-08 10:51:25 +01:00
parent 40f410b4c8
commit 785a970dec
10 changed files with 371 additions and 28 deletions

4
.clang-format Normal file
View File

@ -0,0 +1,4 @@
BasedOnStyle: Google
DerivePointerAlignment: false
PointerAlignment: Left
Standard: Cpp11

View File

@ -5,11 +5,14 @@ v2.8.5 (2016-03-XX)
and #1770 (Display ACTUAL query time in aardvark's AQL editor) and #1770 (Display ACTUAL query time in aardvark's AQL editor)
* Windows: the unhandled exception handler now calls the windows logging * Windows: the unhandled exception handler now calls the windows logging
facilities directly without locks. facilities directly without locks.
This fixes lockups on crashes from the logging framework. This fixes lockups on crashes from the logging framework.
* improve nullptr handling in logger. * improve nullptr handling in logger.
* added new endpoint "srv://" for DNS service records
v2.8.4 (2016-03-01) v2.8.4 (2016-03-01)
------------------- -------------------

View File

@ -525,12 +525,12 @@ am__lib_libarango_a_SOURCES_DIST = lib/Basics/application-exit.cpp \
lib/Rest/EndpointList.cpp lib/Rest/Endpoint.cpp \ lib/Rest/EndpointList.cpp lib/Rest/Endpoint.cpp \
lib/Rest/EndpointIp.cpp lib/Rest/EndpointIpV4.cpp \ lib/Rest/EndpointIp.cpp lib/Rest/EndpointIpV4.cpp \
lib/Rest/EndpointIpV6.cpp lib/Rest/EndpointUnixDomain.cpp \ lib/Rest/EndpointIpV6.cpp lib/Rest/EndpointUnixDomain.cpp \
lib/Rest/HttpRequest.cpp lib/Rest/HttpResponse.cpp \ lib/Rest/EndpointSrv.cpp lib/Rest/HttpRequest.cpp \
lib/Rest/InitializeRest.cpp lib/Rest/SslInterface.cpp \ lib/Rest/HttpResponse.cpp lib/Rest/InitializeRest.cpp \
lib/Rest/Version.cpp lib/Utilities/DummyShell.cpp \ lib/Rest/SslInterface.cpp lib/Rest/Version.cpp \
lib/Utilities/LineEditor.cpp lib/Utilities/ScriptLoader.cpp \ lib/Utilities/DummyShell.cpp lib/Utilities/LineEditor.cpp \
lib/Utilities/ShellBase.cpp lib/Zip/ioapi.cpp \ lib/Utilities/ScriptLoader.cpp lib/Utilities/ShellBase.cpp \
lib/Zip/unzip.cpp lib/Zip/zip.cpp \ lib/Zip/ioapi.cpp lib/Zip/unzip.cpp lib/Zip/zip.cpp \
3rdParty/linenoise-ng/src/linenoise.cpp \ 3rdParty/linenoise-ng/src/linenoise.cpp \
3rdParty/linenoise-ng/src/ConvertUTF.cpp \ 3rdParty/linenoise-ng/src/ConvertUTF.cpp \
3rdParty/linenoise-ng/src/wcwidth.cpp \ 3rdParty/linenoise-ng/src/wcwidth.cpp \
@ -623,6 +623,7 @@ am_lib_libarango_a_OBJECTS = \
lib/Rest/lib_libarango_a-EndpointIpV4.$(OBJEXT) \ lib/Rest/lib_libarango_a-EndpointIpV4.$(OBJEXT) \
lib/Rest/lib_libarango_a-EndpointIpV6.$(OBJEXT) \ lib/Rest/lib_libarango_a-EndpointIpV6.$(OBJEXT) \
lib/Rest/lib_libarango_a-EndpointUnixDomain.$(OBJEXT) \ lib/Rest/lib_libarango_a-EndpointUnixDomain.$(OBJEXT) \
lib/Rest/lib_libarango_a-EndpointSrv.$(OBJEXT) \
lib/Rest/lib_libarango_a-HttpRequest.$(OBJEXT) \ lib/Rest/lib_libarango_a-HttpRequest.$(OBJEXT) \
lib/Rest/lib_libarango_a-HttpResponse.$(OBJEXT) \ lib/Rest/lib_libarango_a-HttpResponse.$(OBJEXT) \
lib/Rest/lib_libarango_a-InitializeRest.$(OBJEXT) \ lib/Rest/lib_libarango_a-InitializeRest.$(OBJEXT) \
@ -1363,12 +1364,13 @@ lib_libarango_a_SOURCES = lib/Basics/application-exit.cpp \
lib/Rest/EndpointList.cpp lib/Rest/Endpoint.cpp \ lib/Rest/EndpointList.cpp lib/Rest/Endpoint.cpp \
lib/Rest/EndpointIp.cpp lib/Rest/EndpointIpV4.cpp \ lib/Rest/EndpointIp.cpp lib/Rest/EndpointIpV4.cpp \
lib/Rest/EndpointIpV6.cpp lib/Rest/EndpointUnixDomain.cpp \ lib/Rest/EndpointIpV6.cpp lib/Rest/EndpointUnixDomain.cpp \
lib/Rest/HttpRequest.cpp lib/Rest/HttpResponse.cpp \ lib/Rest/EndpointSrv.cpp lib/Rest/HttpRequest.cpp \
lib/Rest/InitializeRest.cpp lib/Rest/SslInterface.cpp \ lib/Rest/HttpResponse.cpp lib/Rest/InitializeRest.cpp \
lib/Rest/Version.cpp lib/Utilities/DummyShell.cpp \ lib/Rest/SslInterface.cpp lib/Rest/Version.cpp \
lib/Utilities/LineEditor.cpp lib/Utilities/ScriptLoader.cpp \ lib/Utilities/DummyShell.cpp lib/Utilities/LineEditor.cpp \
lib/Utilities/ShellBase.cpp lib/Zip/ioapi.cpp \ lib/Utilities/ScriptLoader.cpp lib/Utilities/ShellBase.cpp \
lib/Zip/unzip.cpp lib/Zip/zip.cpp $(am__append_3) \ lib/Zip/ioapi.cpp lib/Zip/unzip.cpp lib/Zip/zip.cpp \
$(am__append_3) \
3rdParty/velocypack/src/AttributeTranslator.cpp \ 3rdParty/velocypack/src/AttributeTranslator.cpp \
3rdParty/velocypack/src/Builder.cpp \ 3rdParty/velocypack/src/Builder.cpp \
3rdParty/velocypack/src/Collection.cpp \ 3rdParty/velocypack/src/Collection.cpp \
@ -3246,6 +3248,8 @@ lib/Rest/lib_libarango_a-EndpointIpV6.$(OBJEXT): \
lib/Rest/$(am__dirstamp) lib/Rest/$(DEPDIR)/$(am__dirstamp) lib/Rest/$(am__dirstamp) lib/Rest/$(DEPDIR)/$(am__dirstamp)
lib/Rest/lib_libarango_a-EndpointUnixDomain.$(OBJEXT): \ lib/Rest/lib_libarango_a-EndpointUnixDomain.$(OBJEXT): \
lib/Rest/$(am__dirstamp) lib/Rest/$(DEPDIR)/$(am__dirstamp) lib/Rest/$(am__dirstamp) lib/Rest/$(DEPDIR)/$(am__dirstamp)
lib/Rest/lib_libarango_a-EndpointSrv.$(OBJEXT): \
lib/Rest/$(am__dirstamp) lib/Rest/$(DEPDIR)/$(am__dirstamp)
lib/Rest/lib_libarango_a-HttpRequest.$(OBJEXT): \ lib/Rest/lib_libarango_a-HttpRequest.$(OBJEXT): \
lib/Rest/$(am__dirstamp) lib/Rest/$(DEPDIR)/$(am__dirstamp) lib/Rest/$(am__dirstamp) lib/Rest/$(DEPDIR)/$(am__dirstamp)
lib/Rest/lib_libarango_a-HttpResponse.$(OBJEXT): \ lib/Rest/lib_libarango_a-HttpResponse.$(OBJEXT): \
@ -4166,6 +4170,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointIpV4.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointIpV4.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointIpV6.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointIpV6.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointList.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointList.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointSrv.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointUnixDomain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointUnixDomain.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-HttpRequest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-HttpRequest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-HttpResponse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/Rest/$(DEPDIR)/lib_libarango_a-HttpResponse.Po@am__quote@
@ -8258,6 +8263,20 @@ lib/Rest/lib_libarango_a-EndpointUnixDomain.obj: lib/Rest/EndpointUnixDomain.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libarango_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o lib/Rest/lib_libarango_a-EndpointUnixDomain.obj `if test -f 'lib/Rest/EndpointUnixDomain.cpp'; then $(CYGPATH_W) 'lib/Rest/EndpointUnixDomain.cpp'; else $(CYGPATH_W) '$(srcdir)/lib/Rest/EndpointUnixDomain.cpp'; fi` @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libarango_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o lib/Rest/lib_libarango_a-EndpointUnixDomain.obj `if test -f 'lib/Rest/EndpointUnixDomain.cpp'; then $(CYGPATH_W) 'lib/Rest/EndpointUnixDomain.cpp'; else $(CYGPATH_W) '$(srcdir)/lib/Rest/EndpointUnixDomain.cpp'; fi`
lib/Rest/lib_libarango_a-EndpointSrv.o: lib/Rest/EndpointSrv.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libarango_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT lib/Rest/lib_libarango_a-EndpointSrv.o -MD -MP -MF lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointSrv.Tpo -c -o lib/Rest/lib_libarango_a-EndpointSrv.o `test -f 'lib/Rest/EndpointSrv.cpp' || echo '$(srcdir)/'`lib/Rest/EndpointSrv.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointSrv.Tpo lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointSrv.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lib/Rest/EndpointSrv.cpp' object='lib/Rest/lib_libarango_a-EndpointSrv.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libarango_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o lib/Rest/lib_libarango_a-EndpointSrv.o `test -f 'lib/Rest/EndpointSrv.cpp' || echo '$(srcdir)/'`lib/Rest/EndpointSrv.cpp
lib/Rest/lib_libarango_a-EndpointSrv.obj: lib/Rest/EndpointSrv.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libarango_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT lib/Rest/lib_libarango_a-EndpointSrv.obj -MD -MP -MF lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointSrv.Tpo -c -o lib/Rest/lib_libarango_a-EndpointSrv.obj `if test -f 'lib/Rest/EndpointSrv.cpp'; then $(CYGPATH_W) 'lib/Rest/EndpointSrv.cpp'; else $(CYGPATH_W) '$(srcdir)/lib/Rest/EndpointSrv.cpp'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointSrv.Tpo lib/Rest/$(DEPDIR)/lib_libarango_a-EndpointSrv.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='lib/Rest/EndpointSrv.cpp' object='lib/Rest/lib_libarango_a-EndpointSrv.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libarango_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o lib/Rest/lib_libarango_a-EndpointSrv.obj `if test -f 'lib/Rest/EndpointSrv.cpp'; then $(CYGPATH_W) 'lib/Rest/EndpointSrv.cpp'; else $(CYGPATH_W) '$(srcdir)/lib/Rest/EndpointSrv.cpp'; fi`
lib/Rest/lib_libarango_a-HttpRequest.o: lib/Rest/HttpRequest.cpp lib/Rest/lib_libarango_a-HttpRequest.o: lib/Rest/HttpRequest.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libarango_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT lib/Rest/lib_libarango_a-HttpRequest.o -MD -MP -MF lib/Rest/$(DEPDIR)/lib_libarango_a-HttpRequest.Tpo -c -o lib/Rest/lib_libarango_a-HttpRequest.o `test -f 'lib/Rest/HttpRequest.cpp' || echo '$(srcdir)/'`lib/Rest/HttpRequest.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libarango_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT lib/Rest/lib_libarango_a-HttpRequest.o -MD -MP -MF lib/Rest/$(DEPDIR)/lib_libarango_a-HttpRequest.Tpo -c -o lib/Rest/lib_libarango_a-HttpRequest.o `test -f 'lib/Rest/HttpRequest.cpp' || echo '$(srcdir)/'`lib/Rest/HttpRequest.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) lib/Rest/$(DEPDIR)/lib_libarango_a-HttpRequest.Tpo lib/Rest/$(DEPDIR)/lib_libarango_a-HttpRequest.Po @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) lib/Rest/$(DEPDIR)/lib_libarango_a-HttpRequest.Tpo lib/Rest/$(DEPDIR)/lib_libarango_a-HttpRequest.Po

View File

@ -139,6 +139,7 @@ add_library(
Rest/EndpointIp.cpp Rest/EndpointIp.cpp
Rest/EndpointIpV4.cpp Rest/EndpointIpV4.cpp
Rest/EndpointIpV6.cpp Rest/EndpointIpV6.cpp
Rest/EndpointSrv.cpp
Rest/HttpRequest.cpp Rest/HttpRequest.cpp
Rest/HttpResponse.cpp Rest/HttpResponse.cpp
Rest/InitializeRest.cpp Rest/InitializeRest.cpp

View File

@ -80,6 +80,7 @@ lib_libarango_a_SOURCES = \
lib/Rest/EndpointIpV4.cpp \ lib/Rest/EndpointIpV4.cpp \
lib/Rest/EndpointIpV6.cpp \ lib/Rest/EndpointIpV6.cpp \
lib/Rest/EndpointUnixDomain.cpp \ lib/Rest/EndpointUnixDomain.cpp \
lib/Rest/EndpointSrv.cpp \
lib/Rest/HttpRequest.cpp \ lib/Rest/HttpRequest.cpp \
lib/Rest/HttpResponse.cpp \ lib/Rest/HttpResponse.cpp \
lib/Rest/InitializeRest.cpp \ lib/Rest/InitializeRest.cpp \

View File

@ -39,6 +39,7 @@
#endif #endif
#include "Rest/EndpointIpV4.h" #include "Rest/EndpointIpV4.h"
#include "Rest/EndpointIpV6.h" #include "Rest/EndpointIpV6.h"
#include "Rest/EndpointSrv.h"
using namespace std; using namespace std;
using namespace triagens::basics; using namespace triagens::basics;
@ -116,25 +117,19 @@ std::string Endpoint::getUnifiedForm (const std::string& specification) {
return ""; return "";
} }
#endif #endif
else if (StringUtils::isPrefix(copy, "srv://")) {
return copy;
}
else if (! StringUtils::isPrefix(copy, "ssl://") && else if (! StringUtils::isPrefix(copy, "ssl://") &&
! StringUtils::isPrefix(copy, "tcp://")) { ! StringUtils::isPrefix(copy, "tcp://")) {
// invalid type // invalid type
return ""; return "";
} }
size_t found;
/*
// turn "localhost" into "127.0.0.1"
// technically this is not always correct, but circumvents obvious problems
// when the configuration contains both "127.0.0.1" and "localhost" endpoints
found = copy.find("localhost");
if (found != string::npos && found >= 6 && found < 10) {
copy = copy.replace(found, strlen("localhost"), "127.0.0.1");
}
*/
// tcp/ip or ssl // tcp/ip or ssl
size_t found;
string temp = copy.substr(6, copy.length()); // strip tcp:// or ssl:// string temp = copy.substr(6, copy.length()); // strip tcp:// or ssl://
if (temp[0] == '[') { if (temp[0] == '[') {
// ipv6 // ipv6
found = temp.find("]:", 1); found = temp.find("]:", 1);
@ -144,6 +139,7 @@ std::string Endpoint::getUnifiedForm (const std::string& specification) {
} }
found = temp.find("]", 1); found = temp.find("]", 1);
if (found != string::npos && found > 2 && found + 1 == temp.size()) { if (found != string::npos && found > 2 && found + 1 == temp.size()) {
// hostname only (e.g. [address]) // hostname only (e.g. [address])
return copy + ":" + StringUtils::itoa(EndpointIp::_defaultPort); return copy + ":" + StringUtils::itoa(EndpointIp::_defaultPort);
@ -227,7 +223,6 @@ Endpoint* Endpoint::factory (const Endpoint::EndpointType type,
EncryptionType encryption = ENCRYPTION_NONE; EncryptionType encryption = ENCRYPTION_NONE;
string domainType = StringUtils::tolower(copy.substr(0, 7)); string domainType = StringUtils::tolower(copy.substr(0, 7));
if (StringUtils::isPrefix(domainType, "ssl://")) { if (StringUtils::isPrefix(domainType, "ssl://")) {
// ssl // ssl
encryption = ENCRYPTION_SSL; encryption = ENCRYPTION_SSL;
@ -246,6 +241,14 @@ Endpoint* Endpoint::factory (const Endpoint::EndpointType type,
} }
#endif #endif
else if (StringUtils::isPrefix(domainType, "srv://")) {
if (type != ENDPOINT_CLIENT) {
return nullptr;
}
return new EndpointSrv(specification.substr(6));
}
else if (! StringUtils::isPrefix(domainType, "tcp://")) { else if (! StringUtils::isPrefix(domainType, "tcp://")) {
// invalid type // invalid type
return nullptr; return nullptr;

View File

@ -88,7 +88,8 @@ namespace triagens {
DOMAIN_UNKNOWN = 0, DOMAIN_UNKNOWN = 0,
DOMAIN_UNIX, DOMAIN_UNIX,
DOMAIN_IPV4, DOMAIN_IPV4,
DOMAIN_IPV6 DOMAIN_IPV6,
DOMAIN_SRV
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -205,7 +206,7 @@ namespace triagens {
/// @brief return whether the endpoint is connected /// @brief return whether the endpoint is connected
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool isConnected () const { virtual bool isConnected () const {
return _connected; return _connected;
} }
@ -221,7 +222,7 @@ namespace triagens {
/// @brief get the domain type of an endpoint /// @brief get the domain type of an endpoint
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DomainType getDomainType () const { virtual DomainType getDomainType () const {
return _domainType; return _domainType;
} }

View File

@ -126,6 +126,7 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
#ifdef _WIN32 #ifdef _WIN32
char windowsErrorBuf[256]; char windowsErrorBuf[256];
#endif #endif
// set address and port // set address and port
char host[NI_MAXHOST]; char host[NI_MAXHOST];
char serv[NI_MAXSERV]; char serv[NI_MAXSERV];

257
lib/Rest/EndpointSrv.cpp Normal file
View File

@ -0,0 +1,257 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2016, ArangoDB GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "EndpointSrv.h"
#ifndef _WIN32
#define BIND_4_COMPAT 1 // LINUX
#define BIND_8_COMPAT 1 // MACOSX
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include "Basics/logging.h"
#include "Rest/EndpointIp.h"
using namespace triagens::basics;
using namespace triagens::rest;
#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
#else
#define MAXPACKET 1024
#endif
union QueryBuffer {
::HEADER header;
unsigned char buffer[MAXPACKET];
};
struct SrvRecord {
int priority;
int weight;
int port;
std::string name;
};
std::vector<SrvRecord> srvRecords(std::string specification) {
res_init();
char const* dname = specification.c_str();
int nclass = ns_c_in;
int type = ns_t_srv;
QueryBuffer answer;
int anslen = sizeof(answer);
int n = res_search(dname, nclass, type, answer.buffer, anslen);
std::vector<SrvRecord> services;
if (n != -1) {
HEADER* hp = &answer.header;
int qdcount = ntohs(hp->qdcount);
int ancount = ntohs(hp->ancount);
unsigned char* msg = answer.buffer;
unsigned char* eom = msg + n;
unsigned char* cp = msg + sizeof(HEADER);
unsigned char hostbuf[256];
while (0 < qdcount-- && cp < eom) {
n = dn_expand(msg, eom, cp, (char*)hostbuf, 256);
if (n < 0) {
LOG_WARNING("DNS record for '%s' is corrupt", specification.c_str());
return {};
}
cp += n + QFIXEDSZ;
}
// loop through the answer buffer and extract SRV records
while (0 < ancount-- && cp < eom) {
n = dn_expand(msg, eom, cp, (char*)hostbuf, 256);
if (n < 0) {
LOG_WARNING("DNS record for '%s' is corrupt", specification.c_str());
return {};
}
cp += n;
int type = _getshort(cp);
cp += 2;
int nclass = _getshort(cp);
cp += 2;
int ttl = _getlong(cp);
cp += 4;
int dlen = _getshort(cp);
cp += 2;
int priority = _getshort(cp);
cp += 2;
int weight = _getshort(cp);
cp += 2;
int port = _getshort(cp);
cp += 2;
n = dn_expand(msg, eom, cp, (char*)hostbuf, 256);
if (n < 0) {
LOG_WARNING("DNS record for '%s' is corrupt", specification.c_str());
break;
}
cp += n;
LOG_TRACE("DNS record for '%s': type %d, class %d, ttl %d, len %d, prio %d, "
" weight %d, port %d, host '%s'", specification.c_str(),
type, nclass, ttl, dlen, priority, weight, port, hostbuf);
if (type != T_SRV) {
continue;
}
SrvRecord srv;
srv.weight = weight;
srv.priority = priority;
srv.port = port;
srv.name = (char*)hostbuf;
services.push_back(srv);
}
} else {
LOG_WARNING("DNS record for '%s' not found", specification.c_str());
}
std::sort(services.begin(), services.end(),
[](SrvRecord const& lhs, SrvRecord const& rhs) {
if (lhs.priority != rhs.priority) {
return lhs.priority < rhs.priority;
}
return lhs.weight > rhs.weight;
});
return services;
}
#else
std::vector<SrvRecord> srvRecords(std::string specification) {
return {};
}
#endif
EndpointSrv::EndpointSrv(std::string const& specification)
: Endpoint(ENDPOINT_CLIENT, DOMAIN_SRV, ENCRYPTION_NONE, specification, 0) {
LOG_ERROR("%s", specification.c_str());
}
EndpointSrv::~EndpointSrv() {}
bool EndpointSrv::isConnected() const {
if (_endpoint != nullptr) {
return _endpoint->isConnected();
}
return false;
}
TRI_socket_t EndpointSrv::connect(double connectTimeout,
double requestTimeout) {
LOG_ERROR("connecting to ip endpoint '%s'", _specification.c_str());
auto services = srvRecords(_specification);
TRI_socket_t res;
for (auto service : services) {
std::string spec =
"tcp://" + service.name + ":" + StringUtils::itoa(service.port);
_endpoint.reset(Endpoint::clientFactory(spec));
res = _endpoint->connect(connectTimeout, requestTimeout);
if (_endpoint->isConnected()) {
return res;
}
}
TRI_invalidatesocket(&res);
return res;
}
void EndpointSrv::disconnect() {
if (_endpoint != nullptr) {
_endpoint->disconnect();
}
}
bool EndpointSrv::initIncoming(TRI_socket_t) { return false; }
int EndpointSrv::getDomain() const {
if (_endpoint != nullptr) {
return _endpoint->getDomain();
}
return -1;
}
int EndpointSrv::getPort() const {
if (_endpoint != nullptr) {
return _endpoint->getPort();
}
return -1;
}
std::string EndpointSrv::getHost() const {
if (_endpoint != nullptr) {
return _endpoint->getHost();
}
return "";
}
std::string EndpointSrv::getHostString() const {
if (_endpoint != nullptr) {
return _endpoint->getHostString();
}
return "";
}

53
lib/Rest/EndpointSrv.h Normal file
View File

@ -0,0 +1,53 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2016, ArangoDB GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_REST_ENDPOINT_SRV_H
#define ARANGODB_REST_ENDPOINT_SRV_H 1
#include "Rest/Endpoint.h"
namespace triagens {
namespace rest {
class EndpointSrv final : public Endpoint {
public:
explicit EndpointSrv(std::string const&);
~EndpointSrv();
public:
bool isConnected() const override;
TRI_socket_t connect(double, double) override;
void disconnect() override;
bool initIncoming(TRI_socket_t) override;
int getDomain() const override;
int getPort() const override;
std::string getHost() const override;
std::string getHostString() const override;
private:
std::unique_ptr<Endpoint> _endpoint;
};
}
}
#endif