XRootD
XrdHttpTpcConfigure.cc
Go to the documentation of this file.
1 
2 #include "XrdHttpTpcTPC.hh"
3 
4 #include <dlfcn.h>
5 #include <fcntl.h>
6 
7 #include "XrdOuc/XrdOuca2x.hh"
8 #include "XrdOuc/XrdOucEnv.hh"
9 #include "XrdOuc/XrdOucStream.hh"
10 #include "XrdOuc/XrdOucPinPath.hh"
13 #include "XrdOuc/XrdOucTUtils.hh"
14 
15 using namespace TPC;
16 
17 
18 bool TPCHandler::Configure(const char *configfn, XrdOucEnv *myEnv)
19 {
20  XrdOucEnv cfgEnv;
21  XrdOucStream Config(&m_log, getenv("XRDINSTANCE"), &cfgEnv, "=====> ");
22 
24 
25  // test if XrdEC is used
26  usingEC = getenv("XRDCL_EC")? true : false;
27 
28  std::string authLib;
29  std::string authLibParms;
30  int cfgFD = open(configfn, O_RDONLY, 0);
31  if (cfgFD < 0) {
32  m_log.Emsg("Config", errno, "open config file", configfn);
33  return false;
34  }
35  Config.Attach(cfgFD);
36  static const char *cvec[] = { "*** http tpc plugin config:", 0 };
37  Config.Capture(cvec);
38  const char *val;
39  while ((val = Config.GetMyFirstWord())) {
40  if (!strcmp("http.desthttps", val)) {
41  if (!(val = Config.GetWord())) {
42  Config.Close();
43  m_log.Emsg("Config", "http.desthttps value not specified");
44  return false;
45  }
46  if (!strcmp("1", val) || !strcasecmp("yes", val) || !strcasecmp("true", val)) {
47  m_desthttps = true;
48  } else if (!strcmp("0", val) || !strcasecmp("no", val) || !strcasecmp("false", val)) {
49  m_desthttps = false;
50  } else {
51  Config.Close();
52  m_log.Emsg("Config", "https.desthttps value is invalid", val);
53  return false;
54  }
55  } else if (!strcmp("tpc.trace", val)) {
56  if (!ConfigureLogger(Config)) {
57  Config.Close();
58  return false;
59  }
60  } else if (!strcmp("tpc.fixed_route", val)) {
61  if (!(val = Config.GetWord())) {
62  Config.Close();
63  m_log.Emsg("Config", "tpc.fixed_route value not specified");
64  return false;
65  }
66  if (!strcmp("1", val) || !strcasecmp("yes", val) || !strcasecmp("true", val)) {
67  m_fixed_route= true;
68  } else if (!strcmp("0", val) || !strcasecmp("no", val) || !strcasecmp("false", val)) {
69  m_fixed_route= false;
70  } else {
71  Config.Close();
72  m_log.Emsg("Config", "tpc.fixed_route value is invalid", val);
73  return false;
74  }
75  } else if (!strcmp("tpc.header2cgi",val)) {
76  // header2cgi parsing
77  if(XrdHttpProtocol::parseHeader2CGI(Config,m_log,hdr2cgimap)){
78  Config.Close();
79  return false;
80  }
81  // remove authorization header2cgi parsing as it will anyway be added to the CGI before the file open
82  // by the HTTP/TPC logic
83  auto authHdr = XrdOucTUtils::caseInsensitiveFind(hdr2cgimap,"authorization");
84  if(authHdr != hdr2cgimap.end()) {
85  hdr2cgimap.erase(authHdr);
86  }
87  } else if (!strcmp("tpc.timeout", val)) {
88  if (!(val = Config.GetWord())) {
89  Config.Close();
90  m_log.Emsg("Config","tpc.timeout value not specified."); return false;
91  }
92  if (XrdOuca2x::a2tm(m_log, "timeout value", val, &m_timeout, 0)) return false;
93  // First byte timeout can be set separately from the continuous timeout.
94  if ((val = Config.GetWord())) {
95  if (XrdOuca2x::a2tm(m_log, "first byte timeout value", val, &m_first_timeout, 0)) return false;
96  } else {
97  m_first_timeout = 2*m_timeout;
98  }
99  } else if (!strcmp("tpc.max_active_transfers_per_queue", val)) {
100  if (!(val = Config.GetWord())) {
101  Config.Close();
102  m_log.Emsg("Config", "tpc.max_active_transfers_per_queue value not specified.");
103  return false;
104  }
105  int max_workers;
106  if (XrdOuca2x::a2i(m_log, "tpc.max_active_transfers_per_queue", val, &max_workers, 1, 1000)) return false;
107  m_request_manager.SetMaxWorkers(static_cast<unsigned>(max_workers));
108  } else if (!strcmp("tpc.max_waiting_transfers_per_queue", val)) {
109  if (!(val = Config.GetWord())) {
110  Config.Close();
111  m_log.Emsg("Config", "tpc.max_waiting_transfers_per_queue value not specified.");
112  return false;
113  }
114  int max_pending_ops;
115  if (XrdOuca2x::a2i(m_log, "tpc.max_waiting_transfers_per_queue", val, &max_pending_ops, 1, 1000)) return false;
116  m_request_manager.SetMaxIdleRequests(static_cast<unsigned>(max_pending_ops));
117  }
118  }
119  Config.Close();
120 
121  // Internal override: allow xrdtpc to use a different ca dir from the one prepared by the xrootd
122  // framework. meant for exceptional situations where the site might need a specially-prepared set
123  // of cas only for tpc (such as trying out various workarounds for libnss). Explicitly disables
124  // the NSS hack below.
125  auto env_cadir = getenv("XRDTPC_CADIR");
126  if (env_cadir) m_cadir = env_cadir;
127 
128  const char *cadir = nullptr, *cafile = nullptr;
129  if ((cadir = env_cadir ? env_cadir : myEnv->Get("http.cadir"))) {
130  m_cadir = cadir;
131  if (!env_cadir) {
132  m_ca_file.reset(new XrdTlsTempCA(&m_log, m_cadir));
133  if (!m_ca_file->IsValid()) {
134  m_log.Emsg("Config", "CAs / CRL generation for libcurl failed.");
135  return false;
136  }
137  }
138  }
139  if ((cafile = myEnv->Get("http.cafile"))) {
140  m_cafile = cafile;
141  }
142 
143  if (!cadir && !cafile) {
144  // We do not necessary need TLS to perform HTTP TPC transfers, just log that these values were not specified
145  m_log.Emsg("Config", "neither xrd.tls cadir nor certfile value specified; is TLS enabled?");
146  }
147 
148  void *sfs_raw_ptr;
149  if ((sfs_raw_ptr = myEnv->GetPtr("XrdSfsFileSystem*"))) {
150  m_sfs = static_cast<XrdSfsFileSystem*>(sfs_raw_ptr);
151  m_log.Emsg("Config", "Using filesystem object from the framework.");
152  return true;
153  } else {
154  m_log.Emsg("Config", "No filesystem object available to HTTP-TPC subsystem. Internal error.");
155  return false;
156  }
157  return true;
158 }
159 
160 bool TPCHandler::ConfigureLogger(XrdOucStream &config_obj)
161 {
162  char *val = config_obj.GetWord();
163  if (!val || !val[0])
164  {
165  m_log.Emsg("Config", "tpc.trace requires at least one directive [all | error | warning | info | debug | none]");
166  return false;
167  }
168  // If the config option is given, reset the log mask.
169  m_log.setMsgMask(0);
170 
171  do {
172  if (!strcasecmp(val, "all"))
173  {
174  m_log.setMsgMask(m_log.getMsgMask() | LogMask::All);
175  }
176  else if (!strcasecmp(val, "error"))
177  {
178  m_log.setMsgMask(m_log.getMsgMask() | LogMask::Error);
179  }
180  else if (!strcasecmp(val, "warning"))
181  {
182  m_log.setMsgMask(m_log.getMsgMask() | LogMask::Warning);
183  }
184  else if (!strcasecmp(val, "info"))
185  {
186  m_log.setMsgMask(m_log.getMsgMask() | LogMask::Info);
187  }
188  else if (!strcasecmp(val, "debug"))
189  {
190  m_log.setMsgMask(m_log.getMsgMask() | LogMask::Debug);
191  }
192  else if (!strcasecmp(val, "none"))
193  {
194  m_log.setMsgMask(0);
195  }
196  else
197  {
198  m_log.Emsg("Config", "tpc.trace encountered an unknown directive (valid values: [all | error | warning | info | debug | none]):", val);
199  return false;
200  }
201  val = config_obj.GetWord();
202  } while (val);
203 
204  return true;
205 }
A pragmatic implementation of the HTTP/DAV protocol for the Xrd framework.
#define open
Definition: XrdPosix.hh:76
bool Debug
@ Error
void SetMaxWorkers(unsigned max_workers)
void SetMaxIdleRequests(unsigned max_pending_ops)
static int parseHeader2CGI(XrdOucStream &Config, XrdSysError &err, std::map< std::string, std::string > &header2cgi)
Use this function to parse header2cgi configurations.
void * GetPtr(const char *varname)
Definition: XrdOucEnv.cc:281
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
char * GetWord(int lowcase=0)
static std::map< std::string, T >::const_iterator caseInsensitiveFind(const std::map< std::string, T > &m, const std::string &lowerCaseSearchKey)
Definition: XrdOucTUtils.hh:79
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:45
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:288
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
void setMsgMask(int mask)
Definition: XrdSysError.hh:154
int getMsgMask()
Definition: XrdSysError.hh:156
@ Warning
XrdCmsConfig Config