XRootD
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 
35 namespace 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 //------------------------------------------------------------------------------
59 ProxyPrefixFile::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 //------------------------------------------------------------------------------
86 std::string
87 ProxyPrefixFile::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 //------------------------------------------------------------------------------
102 std::string
103 ProxyPrefixFile::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 //------------------------------------------------------------------------------
132 std::list<std::string>
133 ProxyPrefixFile::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 //------------------------------------------------------------------------------
157 std::string
158 ProxyPrefixFile::ConstructFinalUrl(const std::string& orig_surl) const
159 {
160  std::string final_surl = orig_surl;
161  std::string url_prefix = GetPrefixUrl();
162  XrdCl::Log* log = DefaultEnv::GetLog();
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 //------------------------------------------------------------------------------
203 std::string
204 ProxyPrefixFile::GetFqdn(const std::string& hostname) const
205 {
206  XrdCl::Log* log = DefaultEnv::GetLog();
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
XrdOucString File
void getline(uchar *buff, int blen)
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.
Definition: XrdClStatus.hh:32
const uint16_t errInvalidOp
Definition: XrdClStatus.hh:51
Mode
Access mode.
Flags
Open flags, may be or'd when appropriate.
bool IsOK() const
We're fine.
Definition: XrdClStatus.hh:124