50 int gIPHold = 8 * 60 * 60;
68 std::function<time_t()> gNow;
69 inline time_t Now() {
return gNow ? gNow() : time(nullptr); }
85 explicit netInfo(
const char *
id) : netID(id) {}
95 netInfo *Info =
nullptr;
97 ~THandle() {
if (Info) Info->refs--; }
98 THandle(
const THandle&) =
delete;
99 THandle& operator=(
const THandle&) =
delete;
109 netInfo *LookupTarget(
const char *netID,
int port)
111 static std::map<std::string, std::unique_ptr<netInfo>, std::less<>> niMap;
118 if (
auto it = niMap.find(netID); it == niMap.end())
119 {
auto newInfo = std::make_unique<netInfo>(netID);
121 niMap.try_emplace(niP->netID, std::move(newInfo));
122 }
else niP = it->second.get();
134 if (niP->expTime > nowT || niP->refs != 1)
139 if (
const char *eTxt = niP->netAddr.
Set(netID, port); eTxt)
140 {
if (niP->expTime == 0)
143 if (gLog) gLog->
Emsg(
"RedirIP",
"Unable to init NetInfo for",
151 if (gLog) gLog->
Emsg(
"RedirIP",
"Unable to refresh NetInfo for",
154 }
else niP->expTime = nowT + gIPHold;
191 gNow = std::move(nowFn);
201 std::string &outTarget, std::string &errMsg)
205 std::string pluginReply;
206 uint16_t hostPort = 0;
211 if (port > UINT16_MAX)
212 {
if (gLog) gLog->
Emsg(
"RedirPI",
"Redirect port out of range -",
213 std::to_string(port).c_str());
224 T.Info = LookupTarget(host.c_str(), port);
227 hostPort =
static_cast<uint16_t
>(port);
228 pluginReply = gPlugin->
Redirect(host.c_str(), hostPort, cgi.c_str(),
229 T.Info->netAddr, clientAddr);
240 if (!
ParseURL(trg, urlHead, host, urlPort, urlTail))
241 {
if (gLog) gLog->
Emsg(
"RedirPI",
"Invalid redirect URL -", trg);
249 T.Info = LookupTarget(host.c_str(), -1);
253 pluginReply = gPlugin->
RedirectURL(urlHead.c_str(), host.c_str(),
254 urlPort.c_str(), urlTail.c_str(),
255 rdrOpts, T.Info->netAddr,
261 if (pluginReply.front() ==
'!') { errMsg.assign(pluginReply, 1);
266 if (port >= 0) port = hostPort;
267 outTarget = std::move(pluginReply);
276 std::string &host, std::string &port,
277 std::string &urlTail)
279 const char *hBeg = strstr(url,
"://");
280 if (!hBeg)
return false;
282 urlHead.assign(url, hBeg - url);
286 if (
const char *tail = strstr(hBeg,
"/"); !tail)
287 {urlTail.clear(); host = hBeg;}
288 else {
if (tail - hBeg < 3)
return false;
289 host.assign(hBeg, tail - hBeg);
295 if (
size_t colon = host.find(
':'); colon != std::string::npos)
296 {port.assign(host, colon + 1, std::string::npos);
static XrdSysError eDest(0,"crypto_")
void splitHostCgi(std::string_view target, std::string &host, std::string &cgi)
XrdSys::RAtomic< unsigned int > RAtomic_uint
const char * Set(const char *hSpec, int pNum=PortInSpec)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
static Outcome Redirect(const char *trg, int &port, XrdNetAddrInfo &clientAddr, std::string &outTarget, std::string &errMsg)
static void Init(XrdXrootdRedirPI *pi, XrdSysError *eDest, int ipHold)
static bool ParseURL(const char *url, std::string &urlHead, std::string &host, std::string &port, std::string &urlTail)
static void SetClockForTesting(std::function< time_t()> nowFn)
virtual std::string RedirectURL(const char *urlHead, const char *Target, const char *port, const char *urlTail, int &rdrOpts, XrdNetAddrInfo &TNetInfo, XrdNetAddrInfo &CNetInfo)
virtual std::string Redirect(const char *Target, uint16_t &port, const char *TCgi, XrdNetAddrInfo &TNetInfo, XrdNetAddrInfo &CNetInfo)=0