* Added new Handler Classes for HOMER Proxy
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTHOMERProxyHandler.cxx
1 //-*- Mode: C++ -*-
2 // $Id: AliHLTHOMERProxyHandler.cxx  $
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Jochen Thaeder <thaeder@kip.uni-heidelberg.de>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 /** @file   AliHLTHOMERProxyHandler.cxx
20     @author Jochen Thaeder
21     @date
22     @brief  HOMER proxy handler for HomerManger
23 */
24
25 // see header file for class documentation
26 // or
27 // refer to README to build package
28 // or
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
30
31 #if __GNUC__>= 3
32    using namespace std;
33 #endif
34
35 #include "TDOMParser.h"
36 #include "TSocket.h"
37 #include "TSystem.h"
38 // -- -- -- -- -- -- -- 
39 #include "AliHLTHOMERProxyHandler.h"
40
41 ClassImp(AliHLTHOMERProxyHandler)
42
43 /*
44  * ---------------------------------------------------------------------------------
45  *                            Constructor / Destructor
46  * ---------------------------------------------------------------------------------
47  */
48
49 //##################################################################################
50 AliHLTHOMERProxyHandler::AliHLTHOMERProxyHandler() :
51   fRealm(kHLT),
52   fXmlRpcResponse(""),
53   fSourceList(NULL) {
54   // see header file for class documentation
55   // or
56   // refer to README to build package
57   // or
58   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
59 }
60
61 //##################################################################################
62 AliHLTHOMERProxyHandler::~AliHLTHOMERProxyHandler() {
63   // see header file for class documentation
64
65 }
66
67 //##################################################################################
68 Int_t AliHLTHOMERProxyHandler::Initialize() {
69   // see header file for class documentation
70
71   Int_t iResult = 0 ;
72
73   IdentifyRealm();
74
75   return iResult;
76 }
77
78 /*
79  * ---------------------------------------------------------------------------------
80  *                             Source List - public
81  * ---------------------------------------------------------------------------------
82  */
83
84 //##################################################################################
85 Int_t AliHLTHOMERProxyHandler::FillSourceList(TList *srcList) {
86   // see header file for class documentation
87
88   Int_t iResult = 0;
89
90   fSourceList = srcList;
91
92   iResult = RequestXmlRpcResponse();
93
94   if (!iResult)
95     iResult = ProcessXmlRpcResponse();
96
97   if (iResult)
98     HLTError("Filling SourceList failed.");
99
100   return iResult;
101 }
102
103 /*
104  * ---------------------------------------------------------------------------------
105  *                        Realms - private
106  * ---------------------------------------------------------------------------------
107  */
108
109 //##################################################################################
110 const Char_t *AliHLTHOMERProxyHandler::fgkHOMERProxyNode[] = { 
111   "portal-dcs0.internal", 
112   "alihlt-dcs0.cern.ch",
113   "alihlt-vobox0.cern.ch",
114   "alihlt-gw0.kip.uni-heidelberg.de",
115   "portal-dcs1.internal", 
116   "alihlt-dcs1.cern.ch",
117   "alihlt-vobox1.cern.ch",
118   "alihlt-gw1.kip.uni-heidelberg.de"
119 };
120
121 //##################################################################################
122 void AliHLTHOMERProxyHandler::IdentifyRealm() {
123   // see header file for class documentation
124
125   TString hostIP(gSystem->GetHostByName(gSystem->HostName()).GetHostAddress());
126
127   if ( hostIP.Contains("10.162.") )
128     fRealm = kHLT;
129   else if ( hostIP.Contains("10.160.") || hostIP.Contains("10.161.") )
130     fRealm = kACR;
131   else if ( hostIP.Contains("129.206.") )
132     fRealm = kKIP;
133   else 
134     fRealm = kGPN;
135   
136   return;
137 }
138
139 /*
140  * ---------------------------------------------------------------------------------
141  *                        Proxy Communication - private
142  * ---------------------------------------------------------------------------------
143  */
144
145 //##################################################################################
146 Int_t AliHLTHOMERProxyHandler::RequestXmlRpcResponse() {
147   // see header file for class documentation
148
149   Int_t iResult = 0;
150
151   // -- open socket
152   // ----------------
153
154   Int_t proxyPort = 19999;
155
156   TSocket *socket = new TSocket(fgkHOMERProxyNode[fRealm], proxyPort);
157   if ( ! socket->IsValid() ) {
158     HLTWarning("Failed to create socket to %s:%d,",fgkHOMERProxyNode[fRealm], proxyPort);
159     HLTWarning("trying %s:%d now.", fgkHOMERProxyNode[fRealm+kHOMERRealmsMax],proxyPort);
160
161     socket = new TSocket(fgkHOMERProxyNode[fRealm+kHOMERRealmsMax], proxyPort);
162     if ( ! socket->IsValid() ) {
163       HLTError("Failed to create socket to %s:%d and %s:%d.",
164                fgkHOMERProxyNode[fRealm], proxyPort,
165                fgkHOMERProxyNode[fRealm+kHOMERRealmsMax],proxyPort);
166       fRealm = -1;
167       return -1;
168     }
169     else
170       fRealm = fRealm+kHOMERRealmsMax;
171   }
172
173   // -- send request
174   // -----------------
175
176   Char_t reqMsg[] = "PUT / HTTP/1.1\r\n\
177 User-Agent: curl/7.18.0 (x86_64-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n\
178 Host: localhost:10000\r\n\
179 Accept: */*\r\n\
180 Content-type: text/xml\r\n\
181 Content-Length: 68\r\n\
182 \r\n<methodCall><methodName>getTcpDumpServices</methodName></methodCall>\r\n";
183
184   iResult = socket->SendRaw( reqMsg, strlen(reqMsg) );
185   if ( iResult < 1 || 
186        iResult !=  static_cast<Int_t>(strlen(reqMsg))) {
187     HLTError("Error sending! -- send length %d  -- msg length %d.", iResult, strlen(reqMsg) );
188     socket->Close();
189     return iResult;
190   }
191   
192   // -- receive answer
193   // -------------------
194
195   const Int_t bufferSize = 1024;
196   Char_t buffer[bufferSize];
197
198   Bool_t isXmlRpc = kFALSE;
199
200   fXmlRpcResponse = "";
201
202   // -- loop for getting full xmlRPC response
203   while(1) {
204
205     Int_t bufferLength = 0;
206     
207     // -- loop for reading until end of line
208     while (1) {
209
210       iResult = socket->RecvRaw(&buffer[bufferLength], 1);
211       if ( iResult < 0) {
212         HLTError("Error reading form socket.");
213         socket->Close();
214         return iResult;
215       }
216             
217       // -- Checking for  end of line
218       if ( buffer[bufferLength] == 10 ) {
219         buffer[bufferLength] = 0;
220         break;
221       }
222       
223       ++bufferLength;
224     }
225
226     TString bufferString(buffer);
227
228     // -- Checking for start of XML response
229     if ( bufferString.BeginsWith("<?xml") )
230       isXmlRpc = kTRUE;
231
232     // -- Append the xml response
233     if (isXmlRpc) {
234       fXmlRpcResponse.Append(bufferString);
235     }
236
237     // -- Checking for end of XML response
238     if( ! bufferString.CompareTo("</methodResponse>") ) 
239       break;
240   }
241   
242   // -- close socket
243   socket->Close();
244
245   return 0;
246 }
247
248 //##################################################################################
249 Int_t AliHLTHOMERProxyHandler::ProcessXmlRpcResponse() {
250   // see header file for class documentation
251
252   Int_t iResult = 0;
253
254   // -- Parse XML RPC Response
255   // ---------------------------
256
257   TDOMParser xmlParser;
258   xmlParser.SetValidate(kFALSE);
259
260   HLTInfo("XMLResponse:\n %s",fXmlRpcResponse.Data());
261
262   iResult = xmlParser.ParseBuffer(fXmlRpcResponse.Data(), fXmlRpcResponse.Length());
263   if ( iResult < 0 ) {
264     HLTError("Parsing buffer with error: %s", 
265              xmlParser.GetParseCodeMessage(xmlParser.GetParseCode()) );
266     return iResult;
267   }
268
269   TXMLNode * node = xmlParser.GetXMLDocument()->GetRootNode()->
270     GetChildren()->GetChildren()->GetChildren()->GetChildren();
271   
272   if ( strcmp( node->GetNodeName(), "string" ) ) {
273     HLTError("No node 'string' in XmlRpcResponse.");
274     return -1;
275   }
276
277   // -- Parse Content
278   // ------------------
279
280   // -- Get Content
281   TString xmlContent(node->GetText() );
282
283   HLTInfo("XMLContent:\n %s",xmlContent.Data());
284
285   iResult = xmlParser.ParseBuffer(xmlContent.Data(), xmlContent.Length());
286   if ( iResult < 0 ) {
287     HLTError("Parsing buffer with error: %s", 
288              xmlParser.GetParseCodeMessage(xmlParser.GetParseCode()) );
289     return iResult;
290   }
291   
292
293   if ( !xmlParser.GetXMLDocument()->GetRootNode()->HasChildren() ) {
294     HLTInfo("No Services active.");
295     return 0;
296   }
297
298   // -- Loop over all service nodes
299   TXMLNode* serviceNode = xmlParser.GetXMLDocument()->GetRootNode()->GetChildren();
300   TXMLNode* prevServiceNode = NULL;
301   
302   do {
303     prevServiceNode = serviceNode;
304
305     // -- Add service to list
306     iResult = AddService( serviceNode->GetChildren() );
307        
308   } while ( ( serviceNode = prevServiceNode->GetNextNode() ) && !iResult );
309
310   return iResult;
311 }
312
313 /*
314  * ---------------------------------------------------------------------------------
315  *                            Source Resolving - private
316  * ---------------------------------------------------------------------------------
317  */
318
319 //##################################################################################
320 Int_t AliHLTHOMERProxyHandler::AddService(TXMLNode *innerNode) {
321   // see header file for class documentation
322
323   Int_t iResult = 0;
324
325   HLTInfo(">> New service");    
326
327   // -- Loop over all service properties and 
328   //    read them from the service tag
329   // -----------------------------------------
330
331   TString hostname          = "";
332   Int_t   port              = 0;
333   TString dataType          = "";
334   TString dataOrigin        = "";
335   TString dataSpecification = "";
336
337   TXMLNode* prevInnerNode = NULL;
338
339   do {
340     prevInnerNode = innerNode;
341     
342     if ( ! strcmp(innerNode->GetNodeName(), "text" ) )
343       continue;
344     
345     HLTInfo(" %s ++ %s", innerNode->GetNodeName(), innerNode->GetText() );
346     
347     // -- hostname
348     if ( ! strcmp( innerNode->GetNodeName(), "address") )
349       hostname = innerNode->GetText();
350     else if ( ! strcmp( innerNode->GetNodeName(), "port") ) {
351       TString portS(innerNode->GetText());
352       if ( portS.IsDigit() )
353         port = portS.Atoi();
354       else {
355         HLTError("Port %s is not a digit.", portS.Data());
356         iResult = -1;
357       }
358     }
359     else if ( ! strcmp( innerNode->GetNodeName(), "dataorigin") )
360       dataOrigin = innerNode->GetText();
361     else if ( ! strcmp( innerNode->GetNodeName(), "datatype") )
362       dataType = innerNode->GetText();
363     else if ( ! strcmp( innerNode->GetNodeName(), "dataspecification") )
364       dataSpecification = innerNode->GetText();    
365   
366   } while ( ( innerNode = prevInnerNode->GetNextNode() ) && !iResult );
367
368   // -- Check the service properties
369   // ---------------------------------
370
371   // -- Change hostame from service with proxy, if outside HLT
372   if ( fRealm != kHLT || fRealm != kHLT+kHOMERRealmsMax )
373     hostname = fgkHOMERProxyNode[fRealm];
374
375   // -- Check for completeness of the source properties
376   if ( hostname.IsNull() || !port || dataOrigin.IsNull() ||
377        dataType.IsNull() /*|| dataSpecification.IsNull()*/ ) {
378     HLTError("Service provides not all values:\n\thostname\t\t %s\n\tport\t\t\t %d\n\tdataorigin\t\t %s\n\tdatatype\t\t %s\n\tdataspecification\t %s", hostname.Data(),
379              port, dataOrigin.Data(), dataType.Data(), dataSpecification.Data());
380     return -2;
381   }
382
383   // -- Create new source
384   // ----------------------
385
386   AliHLTHOMERSourceDesc * source = new AliHLTHOMERSourceDesc();
387   source->SetService( hostname, port, dataType, dataOrigin, dataSpecification );
388
389   fSourceList->Add( source );
390
391   HLTInfo( "New Source added : %s", source->GetSourceName().Data());
392   
393   return iResult;
394 }
395
396