XRootD
Loading...
Searching...
No Matches
ProxyPrefixFile.cc
Go to the documentation of this file.
1//------------------------------------------------------------------------------
2// Copyright (c) 2011-2017 by European Organization for Nuclear Research (CERN)
3// Author: Elvin Sindrilaru <esindril@cern.ch>
4//------------------------------------------------------------------------------
5// This file is part of the XRootD software suite.
6//
7// XRootD is free software: you can redistribute it and/or modify
8// it under the terms of the GNU Lesser General Public License as published by
9// the Free Software Foundation, either version 3 of the License, or
10// (at your option) any later version.
11//
12// XRootD is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU Lesser General Public License
18// along with XRootD. If not, see <http://www.gnu.org/licenses/>.
19//
20// In applying this licence, CERN does not waive the privileges and immunities
21// granted to it by virtue of its status as an Intergovernmental Organization
22// or submit itself to any jurisdiction.
23//------------------------------------------------------------------------------
24
25#include "ProxyPrefixFile.hh"
26#include <iostream>
27#include <cstdio>
28#include <cstdlib>
29#include <algorithm>
30#include <cctype>
31#include "XrdCl/XrdClLog.hh"
32#include <sys/socket.h>
33#include <netdb.h>
34
35namespace xrdcl_proxy
36{
37//------------------------------------------------------------------------------
38// Constructor
39//------------------------------------------------------------------------------
41 mIsOpen(false),
42 pFile(0)
43{}
44
45//------------------------------------------------------------------------------
46// Destructor
47//------------------------------------------------------------------------------
49{
50 if (pFile) {
51 delete pFile;
52 }
53}
54
55//------------------------------------------------------------------------------
56// Open
57//------------------------------------------------------------------------------
59ProxyPrefixFile::Open(const std::string& url,
60 OpenFlags::Flags flags,
61 Access::Mode mode,
62 ResponseHandler* handler,
63 uint16_t timeout)
64{
65 XRootDStatus st;
66
67 if (mIsOpen) {
69 return st;
70 }
71
72 pFile = new XrdCl::File(false);
73 std::string open_url = ConstructFinalUrl(url);
74 st = pFile->Open(open_url, flags, mode, handler, timeout);
75
76 if (st.IsOK()) {
77 mIsOpen = true;
78 }
79
80 return st;
81}
82
83//------------------------------------------------------------------------------
84// Get proxy prefix Url
85//------------------------------------------------------------------------------
86std::string
87ProxyPrefixFile::GetPrefixUrl() const
88{
89 std::string url_prefix = (getenv("XROOT_PROXY") ? getenv("XROOT_PROXY") : "");
90
91 // Try out also the lower-case one
92 if (url_prefix.empty()) {
93 url_prefix = (getenv("xroot_proxy") ? getenv("xroot_proxy") : "");
94 }
95
96 return url_prefix;
97}
98
99//------------------------------------------------------------------------------
100// Trim whitespaces from both ends for a string
101//------------------------------------------------------------------------------
102std::string
103ProxyPrefixFile::trim(const std::string& in) const
104{
105 std::string::const_iterator wsfront, wsback;
106 std::string::const_reverse_iterator rwsback;
107 wsfront = in.begin();
108 rwsback = in.rbegin();
109
110 while (*wsfront == ' ') {
111 ++wsfront;
112 }
113
114 while (*rwsback == ' ') {
115 ++rwsback;
116 }
117
118 wsback = rwsback.base();
119 return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback));
120 /* TODO: To be used when C++11 is available
121 auto wsfront = std::find_if_not(in.begin(), in.end(),
122 [](int c) -> bool {return std::isspace(c);});
123 auto wsback = std::find_if_not(in.rbegin(), in.rend(),
124 [](int c) -> bool {return std::isspace(c);}).base();
125 return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback));
126 */
127}
128
129//------------------------------------------------------------------------------
130// Get list of domains which are NOT to be prefixed
131//------------------------------------------------------------------------------
132std::list<std::string>
133ProxyPrefixFile::GetExclDomains() const
134{
135 std::string excl_domains = (getenv("XROOT_PROXY_EXCL_DOMAINS") ?
136 getenv("XROOT_PROXY_EXCL_DOMAINS") : "");
137
138 if (excl_domains.empty()) {
139 return std::list<std::string>();
140 }
141
142 char delim = ',';
143 std::string item;
144 std::list<std::string> lst;
145 std::stringstream ss(excl_domains);
146
147 while (getline(ss, item, delim)) {
148 lst.push_back(trim(item));
149 }
150
151 return lst;
152}
153
154//------------------------------------------------------------------------------
155// Construct final Url
156//------------------------------------------------------------------------------
157std::string
158ProxyPrefixFile::ConstructFinalUrl(const std::string& orig_surl) const
159{
160 std::string final_surl = orig_surl;
161 std::string url_prefix = GetPrefixUrl();
163 log->Debug(1, "url=%s, prefix_url=%s", orig_surl.c_str(), url_prefix.c_str());
164
165 if (!url_prefix.empty()) {
166 bool exclude = false;
167 std::list<std::string> lst_excl = GetExclDomains();
168 XrdCl::URL orig_url(orig_surl);
169 std::string orig_host = orig_url.GetHostId();
170 // Remove port if present
171 size_t pos = orig_host.find(':');
172
173 if (pos != std::string::npos) {
174 orig_host = orig_host.substr(0, pos);
175 }
176
177 orig_host = GetFqdn(orig_host);
178
179 for (std::list<std::string>::iterator it_excl = lst_excl.begin();
180 it_excl != lst_excl.end(); ++it_excl) {
181 if (url_prefix.size() < it_excl->size()) {
182 continue;
183 }
184
185 if (std::equal(it_excl->rbegin(), it_excl->rend(), orig_host.rbegin())) {
186 exclude = true;
187 break;
188 }
189 }
190
191 if (!exclude) {
192 final_surl.insert(0, url_prefix);
193 }
194 }
195
196 log->Debug(1, "final_url=%s", final_surl.c_str());
197 return final_surl;
198}
199
200//------------------------------------------------------------------------------
201// Get FQDN for specified host
202//------------------------------------------------------------------------------
203std::string
204ProxyPrefixFile::GetFqdn(const std::string& hostname) const
205{
207 std::string fqdn = hostname;
208 struct addrinfo hints, *info;
209 int gai_result;
210 memset(&hints, 0, sizeof hints);
211 hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6*/
212 hints.ai_socktype = SOCK_STREAM;
213 hints.ai_flags = AI_CANONNAME;
214
215 if ((gai_result = getaddrinfo(hostname.c_str(), NULL, &hints, &info)) != 0) {
216 log->Error(1, "getaddrinfo: %s", gai_strerror(gai_result));
217 return fqdn;
218 }
219
220 if (info) {
221 fqdn = info->ai_canonname;
222 }
223
224 freeaddrinfo(info);
225 return fqdn;
226}
227
228} // namespace xrdcl_proxy
void getline(uchar *buff, int blen)
static Log * GetLog()
Get default log.
A file.
Definition XrdClFile.hh:46
XRootDStatus Open(const std::string &url, OpenFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
Definition XrdClFile.cc:99
Handle diagnostics.
Definition XrdClLog.hh:101
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition XrdClLog.cc:231
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
Definition XrdClLog.cc:282
Handle an async response.
URL representation.
Definition XrdClURL.hh:31
virtual XRootDStatus Open(const std::string &url, OpenFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout) override
Open.
virtual ~ProxyPrefixFile() override
Destructor.
const uint16_t stError
An error occurred that could potentially be retried.
const uint16_t errInvalidOp
Flags
Open flags, may be or'd when appropriate.
bool IsOK() const
We're fine.