diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index f34369d8f..a14191339 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -134,6 +135,76 @@ ref UDSRemoteStore::openConnection() } +TCPRemoteStore::TCPRemoteStore(std::string tcp_path, const Params & params) + : Store(params) + , LocalFSStore(params) + , RemoteStore(params) + , path(tcp_path) +{ +} + + +std::string TCPRemoteStore::getUri() +{ + return std::string("tcp://") + path; +} + + +ref TCPRemoteStore::openConnection() +{ + auto conn = make_ref(); + + size_t remoteColonOffset = path.find(':'); + if (remoteColonOffset == string::npos) + throw Error(format("invalid daemon address '%1%' (should be host:port)") % path); + + string remoteHost = path.substr(0,remoteColonOffset); + string remoteService = path.substr(remoteColonOffset+1); + + addrinfo addrHints; + addrinfo* addrResults_raw; + + memset(&addrHints,0,sizeof(addrHints)); + addrHints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED; + addrHints.ai_family = AF_UNSPEC; + addrHints.ai_socktype = SOCK_STREAM; + addrHints.ai_protocol = 0; + + int result = getaddrinfo(remoteHost.c_str(), remoteService.c_str(), &addrHints, &addrResults_raw); + if (result != 0) + throw Error(format("unable to lookup daemon address '%1%'") % path); + std::unique_ptr addrResults(addrResults_raw,freeaddrinfo); + + addrinfo* addrIter; + for (addrIter = addrResults.get(); addrIter; addrIter = addrIter->ai_next) { + AutoCloseFD remoteSocket = socket(addrIter->ai_family, addrIter->ai_socktype + #ifdef SOCK_CLOEXEC + | SOCK_CLOEXEC + #endif + , addrIter->ai_protocol); + if (!remoteSocket) + continue; + + if (::connect(remoteSocket.get(), addrIter->ai_addr, addrIter->ai_addrlen) == -1) + continue; + + conn->fd = std::move(remoteSocket); + break; + } + if (addrIter == 0) + throw Error(format("unable to connect to daemon at '%1%'") % path); + + conn->from.fd = conn->fd.get(); + conn->to.fd = conn->fd.get(); + + conn->startTime = std::chrono::steady_clock::now(); + + initConnection(*conn); + + return conn; +} + + void RemoteStore::initConnection(Connection & conn) { /* Send the magic greeting, check for the reply. */ @@ -804,14 +875,18 @@ std::exception_ptr RemoteStore::Connection::processStderr(Sink * sink, Source * return nullptr; } -static std::string uriScheme = "unix://"; +static std::string uriSchemeUnix = "unix://"; +static std::string uriSchemeTCP = "tcp://"; static RegisterStoreImplementation regStore([]( const std::string & uri, const Store::Params & params) -> std::shared_ptr { - if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0; - return std::make_shared(std::string(uri, uriScheme.size()), params); + if (std::string(uri, 0, uriSchemeUnix.size()) == uriSchemeUnix) + return std::make_shared(std::string(uri, uriSchemeUnix.size()), params); + if (std::string(uri, 0, uriSchemeTCP.size()) == uriSchemeTCP) + return std::make_shared(std::string(uri, uriSchemeTCP.size()), params); + return 0; }); } diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 1f375dd71..cfd0a7629 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -157,5 +157,26 @@ private: std::optional path; }; +class TCPRemoteStore : public LocalFSStore, public RemoteStore +{ +public: + + TCPRemoteStore(std::string path, const Params & params); + + std::string getUri() override; + + bool sameMachine() + { return false; } + +private: + + struct Connection : RemoteStore::Connection + { + AutoCloseFD fd; + }; + + ref openConnection() override; + std::string path; +}; }