Mixe for Privacy and Anonymity in the Internet
CAAccountingBIInterface.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2000, The JAP-Team
3 All rights reserved.
4 Redistribution and use in source and binary forms, with or without modification,
5 are permitted provided that the following conditions are met:
6 
7  - Redistributions of source code must retain the above copyright notice,
8  this list of conditions and the following disclaimer.
9 
10  - Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation and/or
12  other materials provided with the distribution.
13 
14  - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors
15  may be used to endorse or promote products derived from this software without specific
16  prior written permission.
17 
18 
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
20 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
22 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
27 */
28 #include "StdAfx.h"
29 #ifdef PAYMENT
31 #include "CACmdLnOptions.hpp"
32 #include "CAMsg.hpp"
33 #include "CASocketAddrINet.hpp"
34 #include "CASocket.hpp"
35 #include "CAHttpClient.hpp"
36 
37 //CAMutex* CAAccountingBIInterface::m_pPiInterfaceMutex = new CAMutex();
38 //CAAccountingBIInterface *CAAccountingBIInterface::m_pPiInterfaceSingleton = NULL;
39 
45  {
46  //m_pSocket =NULL;
47  //m_pPiInterfaceMutex = new CAMutex();
51  }
52 
57  {
59  if(m_pSocket!=NULL)
60  {
61  delete m_pSocket;
62  m_pSocket = NULL;
63  }
64  if(m_pPiServerAddress!=NULL)
65  {
66  delete m_pPiServerAddress;
67  m_pPiServerAddress = NULL;
68  }
69  if(m_phttpClient!=NULL)
70  {
71  delete m_phttpClient;
72  m_phttpClient = NULL;
73  }
74  /*if(m_pPiInterfaceMutex!=NULL)
75  {
76  delete m_pPiInterfaceMutex;
77  m_pPiInterfaceMutex = NULL;
78  }*/
79  }
80 
81 
83 {
84  UINT8 *pPiName = NULL;
85  UINT16 piPort = 0;
86  CACertificate *pPiCert = NULL;
87 
88  //m_pPiInterfaceMutex->lock();
89 
90  if(pPiServerConfig==NULL)
91  {
92  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface: could not configure PI interface: no proper configuration given.\n");
93  //m_pPiInterfaceMutex->unlock();
94  return E_UNKNOWN;
95  }
96 
97  pPiName = pPiServerConfig->getHostName();
98  pPiCert = pPiServerConfig->getCertificate();
99  piPort = (UINT16)pPiServerConfig->getPortNumber();
100 
101  if(pPiName==NULL)
102  {
103  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface: could not configure PI interface: no PI name specified.\n");
104  //m_pPiInterfaceMutex->unlock();
105  return E_UNKNOWN;
106  }
107  if(pPiCert==NULL)
108  {
109  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface: could not configure PI interface: no PI certificate specified.\n");
110  //m_pPiInterfaceMutex->unlock();
111  return E_UNKNOWN;
112  }
113 
114  if(m_pPiServerAddress == NULL)
115  {
116  //Should never happen
117  #ifdef DEBUG
118  CAMsg::printMsg(LOG_ERR,"CAAccountingBIInterface: no server address initialized while trying to configure PI interface.\n");
119  #endif
121  }
122  m_pPiServerAddress->setAddr(pPiName, piPort);
123  m_pPiServerCertificate = pPiCert;
124  //m_pPiInterfaceMutex->unlock();
125  return E_SUCCESS;
126 }
127 
132 {
133  SINT32 rc;
134  UINT8 buf[64];
135 
136  memset(buf,0,64);
137 
138  //m_pPiInterfaceMutex->lock();
139  if(m_pPiServerAddress == NULL)
140  {
141  //Should never happen
142  #ifdef DEBUG
143  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface: no address initialized while trying to connect. Connect aborted.\n");
144  #endif
145  //m_pPiInterfaceMutex->unlock();
146  return E_UNKNOWN;
147  }
148 
149  if(m_pSocket == NULL)
150  {
151  //Should never happen
152  #ifdef DEBUG
153  CAMsg::printMsg(LOG_ERR,"CAAccountingBIInterface: no socket initialized while trying to connect. Creating new one.\n");
154  #endif
156  }
157 
158  if(m_pPiServerCertificate == NULL)
159  {
160  CAMsg::printMsg(LOG_ERR,"CAAccountingBIInterface: no PI server certificate specified. Connect aborted.\n");
161  //m_pPiInterfaceMutex->unlock();
162  return E_UNKNOWN;
163  }
164  // connect
167  if(rc!=E_SUCCESS)
168  {
171  LOG_ERR,
172  "CAAccountingBIInterface: Could not connect to BI at %s:%i. Reason: %i\n",
173  buf, m_pPiServerAddress->getPort(), rc
174  //pBI->getHostName(), pBI->getPortNumber(), rc
175  );
176  m_pSocket->close();
177  //m_pPiInterfaceMutex->unlock();
178  return E_UNKNOWN;
179  }
181  CAMsg::printMsg(LOG_DEBUG,"CAAccountingBIInterface: BI connection to %s:%i established!\n", buf,m_pPiServerAddress->getPort());
183  //m_pPiInterfaceMutex->unlock();
184  return E_SUCCESS;
185 }
186 
187 
188 
193 {
194  //m_pPiInterfaceMutex->lock();
195  if(m_pSocket == NULL)
196  {
197  //Should never happen
198  #ifdef DEBUG
199  CAMsg::printMsg(LOG_ERR,"CAAccountingBIInterface: no socket initialized while trying to close connection.\n");
200  #endif
201  //m_pPiInterfaceMutex->unlock();
202  return E_UNKNOWN;
203  }
204  m_pSocket->close();
205  //m_pPiInterfaceMutex->unlock();
206  return E_SUCCESS;
207 }
208 
209 //TODO: not finished yet
210 CAXMLErrorMessage **CAAccountingBIInterface::settleAll(CAXMLCostConfirmation **ccs, UINT32 nrOfCCs,
211  CAXMLErrorMessage **settleException)
212 {
213  XERCES_CPP_NAMESPACE::DOMDocument *allCCsEnvelopeDoc = createDOMDocument();
214  DOMElement *allCCsEnvelope = createDOMElement(allCCsEnvelopeDoc, XML_ELEMENT_CCS);
215  CAXMLErrorMessage **resultMessages = NULL;
216  DOMNodeList *errorMsgList = NULL;
217  UINT8 *allCCsAsString = NULL, *response = NULL;
218  UINT32 contentLength = 0, nrOfErrorMessages = 0, i = 0;
219  UINT32 status = 0;
220  SINT32 transmitStatus = 0, domStatus;
221  bool settleSuccessful = false;
222 
223 
224  if(nrOfCCs <= 0)
225  {
226  return NULL;
227  }
228 
229  allCCsEnvelopeDoc->appendChild(allCCsEnvelope);
230 
231  for (i = 0; i < nrOfCCs; i++)
232  {
233  allCCsEnvelope->appendChild(allCCsEnvelopeDoc->importNode(
234  ccs[i]->getXMLDocument()->getDocumentElement(), true));
235  }
236 
237  allCCsAsString = DOM_Output::dumpToMem(allCCsEnvelopeDoc, &contentLength);
238  transmitStatus = (allCCsAsString != NULL) ?
240  allCCsAsString, contentLength) : E_UNKNOWN;
241 
242  allCCsEnvelopeDoc->release();
243  allCCsEnvelopeDoc = NULL;
244  allCCsEnvelope = NULL;
245 
246  delete [] allCCsAsString;
247  allCCsAsString = NULL;
248 
249  if( transmitStatus != E_SUCCESS )
250  {
251  return NULL;
252  }
253 
254  m_pSocket->setNonBlocking(true);
255  transmitStatus = m_phttpClient->parseHTTPHeader(&contentLength, &status, 20000);
256  if( (transmitStatus != E_SUCCESS) || (status != 200) || (contentLength == 0))
257  {
258  if(transmitStatus == E_TIMEDOUT)
259  {
260  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: timeout while receiving response!\n");
261  }
262  else
263  {
264  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: received bad response from PI: %u!\n", status);
265  }
266  return NULL;
267  }
268 #ifdef DEBUG
269  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: got response header [Status,content-Length]=[%i,%i]!\n",
270  status, contentLength);
271 #endif
272  response = new UINT8[contentLength+1];
273 
274  transmitStatus = m_pSocket->receiveFullyT(response, contentLength, 3000);
275  if(transmitStatus !=E_SUCCESS)
276  {
277  if(transmitStatus == E_TIMEDOUT)
278  {
279  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: timeout while receiving settle message!\n");
280  }
281  else
282  {
283  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: error\n");
284  }
285  delete [] response;
286  response = NULL;
287  return NULL;
288  }
289 
290 
291 
292  response[contentLength]='\0';
293 #ifdef DEBUG
294  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: response body received: %s\n", response);
295 #endif
296 
297  allCCsEnvelopeDoc = parseDOMDocument(response, contentLength);
298  if(allCCsEnvelopeDoc != NULL)
299  {
300  errorMsgList = getElementsByTagName(allCCsEnvelopeDoc->getDocumentElement(),
302  domStatus =
303  getDOMElementAttribute(allCCsEnvelopeDoc->getDocumentElement(), XML_ATTR_SETTLE_SUCCESSFUL, settleSuccessful);
304  if(domStatus != E_SUCCESS)
305  {
306  settleSuccessful = false;
307  }
308 
309  nrOfErrorMessages = errorMsgList->getLength();
310  if(settleSuccessful)
311  {
312  if(nrOfErrorMessages == nrOfCCs)
313  {
314  resultMessages = new CAXMLErrorMessage *[nrOfCCs];
315  for (i = 0; i < nrOfErrorMessages; i++)
316  {
317  resultMessages[i] = new CAXMLErrorMessage((DOMElement *) errorMsgList->item(i));
318  }
319  }
320  else
321  {
322  CAMsg::printMsg(LOG_WARNING, "CAAccountingBIInterface::settle: BUG: number of messages != number of cost confirmations!\n");
323  //This would be a bug.
324  *settleException =
326 
327 
328  }
329  }
330  else
331  {
332  CAMsg::printMsg(LOG_WARNING, "CAAccountingBIInterface::settle: PI exception raised.\n");
333  *settleException = (nrOfErrorMessages > 0) ?
334  new CAXMLErrorMessage((DOMElement *) errorMsgList->item(0)) :
336  }
337  }
338 
339  delete [] response;
340  response = NULL;
341 
342  if(allCCsEnvelopeDoc != NULL)
343  {
344  allCCsEnvelopeDoc->release();
345  allCCsEnvelopeDoc = NULL;
346  }
347 
348  return (settleException != NULL) ? resultMessages : NULL;
349 }
355 {
356  UINT8 * pStrCC=NULL;
357  UINT8* response=NULL;
358  UINT32 contentLen=0, status=0;
359  SINT32 ret = 0;
360  CAXMLErrorMessage *pErrMsg;
361 
362  //m_pPiInterfaceMutex->lock();
363  pStrCC = cc.dumpToMem(&contentLen);
364  if( pStrCC==NULL || m_phttpClient->sendPostRequest((UINT8*)"/settle", pStrCC,contentLen)!= E_SUCCESS)
365  {
366  delete[] pStrCC;
367  pStrCC = NULL;
368  //m_pPiInterfaceMutex->unlock();
369  return NULL;
370  }
371  delete[] pStrCC;
372  pStrCC = NULL;
373  contentLen=0;
374  status=0;
375 
376  m_pSocket->setNonBlocking(true);
377  ret = m_phttpClient->parseHTTPHeader(&contentLen, &status, 20000);
378  if( ret !=E_SUCCESS || (status!=200) || (contentLen==0))
379  {
380  if(ret == E_TIMEDOUT)
381  {
382  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: timeout while receiving response!\n");
383  }
384  else
385  {
386  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: received bad response from PI!\n");
387  }
388  //m_pPiInterfaceMutex->unlock();
389  return NULL;
390  }
391 #ifdef DEBUG
392  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: got response header [Status,content-Lenght]=[%i,%i]!\n",status,contentLen);
393 #endif
394  response = new UINT8[contentLen+1];
395 
396  ret = m_pSocket->receiveFullyT(response, contentLen, 3000);
397  if(ret !=E_SUCCESS)
398  {
399  if(ret == E_TIMEDOUT)
400  {
401  CAMsg::printMsg(LOG_ERR, "CAAccountingBIInterface::settle: timeout while receiving settle message!\n");
402  }
403  else
404  {
405  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: error\n");
406  }
407  delete[] response;
408  response = NULL;
409  //m_pPiInterfaceMutex->unlock();
410  return NULL;
411  }
412 #ifdef DEBUG
413  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::settle: response body received!\n");
414 #endif
415  response[contentLen]='\0';
416  pErrMsg = new CAXMLErrorMessage(response);
417  delete[] response;
418  response = NULL;
419  //m_pPiInterfaceMutex->unlock();
420  return pErrMsg;
421 }
422 
423 /*CAAccountingBIInterface *CAAccountingBIInterface::getInstance(CAXMLBI* pPiServerConfig)
424 {
425  SINT32 ret;
426  m_pPiInterfaceMutex->lock();
427  if(m_pPiInterfaceSingleton == NULL)
428  {
429  if(pPiServerConfig == NULL)
430  {
431  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::could not create PI interface: no proper configuration specified!\n");
432  m_pPiInterfaceMutex->unlock();
433  return NULL;
434  }
435  m_pPiInterfaceSingleton = new CAAccountingBIInterface();
436  ret = m_pPiInterfaceSingleton->setPIServerConfiguration(pPiServerConfig);
437  if(ret != E_SUCCESS)
438  {
439  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface::could not create PI interface: no proper configuration specified!\n");
440  m_pPiInterfaceMutex->unlock();
441  return NULL;
442  }
443  }
444  else
445  {
446  CAMsg::printMsg(LOG_DEBUG, "CAAccountingBIInterface:: PI Interface already running!\n");
447  }
448  m_pPiInterfaceMutex->unlock();
449  return m_pPiInterfaceSingleton;
450 
451 }*/
452 
453 /*
454 
455 **
456  * Request a new Balance certificate from the JPI
457  * TODO: Error handling
458  *
459  * @param balanceCert an old balance certificate that the AI wishes to update
460  * @param response a buffer to receive the new balanceCert
461  * @param responseLen the maximum size of the buffer
462  *
463 SINT32 CAAccountingBIInterface::update(UINT8 *balanceCert, UINT8 * response, UINT32 *responseLen)
464 {
465  UINT8 requestF[] = "<?xml version=\"1.0\">\n<Balances>\n%s</Balances>\n";
466  UINT32 sendbuflen = strlen((char *)balanceCert) + strlen((char *)requestF) + 10;
467  UINT8* sendbuf=new UINT8[sendbuflen];
468  UINT32 status;
469  sprintf((char *)sendbuf, (char *)requestF, (char *)balanceCert);
470  m_httpClient.sendPostRequest((UINT8 *)"/update", sendbuf, strlen((char *)sendbuf));
471  delete sendbuf;
472  receiveResponse(&status, response, responseLen);
473  return E_SUCCESS;
474 }
475 */
476 
477 #endif
#define XML_ELEMENT_CCS
#define XML_ATTR_SETTLE_SUCCESSFUL
#define POST_CMD_SETTLEALL
#define PI_CONNECT_TIMEOUT
XERCES_CPP_NAMESPACE::DOMDocument * parseDOMDocument(const UINT8 *const buff, UINT32 len)
Parses a buffer containing an XML document and returns this document.
Definition: CAUtil.cpp:663
DOMNodeList * getElementsByTagName(DOMElement *pElem, const char *const name)
Definition: CAUtil.cpp:1711
XERCES_CPP_NAMESPACE::DOMDocument * createDOMDocument()
Parses a timestamp in JDBC timestamp escape format (as it comes from the BI) and outputs the value in...
Definition: CAUtil.cpp:1568
DOMElement * createDOMElement(XERCES_CPP_NAMESPACE::DOMDocument *pOwnerDoc, const char *const name)
Creates a new DOMElement with the given name which belongs to the DOMDocument owernDoc.
Definition: CAUtil.cpp:814
SINT32 getDOMElementAttribute(const DOMNode *const elem, const char *attrName, UINT8 *value, UINT32 *len)
Definition: CAUtil.cpp:780
#define XML_ELEMENT_ERROR_MSG
unsigned short UINT16
Definition: basetypedefs.h:133
signed int SINT32
Definition: basetypedefs.h:132
unsigned char UINT8
Definition: basetypedefs.h:135
unsigned int UINT32
Definition: basetypedefs.h:131
CAAccountingBIInterface()
private constructor just initializes fields, server configuration is done separately
SINT32 terminateBIConnection()
Terminate HTTP(s) connection to the BI (JPI)
CASocketAddrINet * m_pPiServerAddress
SINT32 initBIConnection()
Establishes HTTP(s) connection to the BI (JPI)
CAXMLErrorMessage ** settleAll(CAXMLCostConfirmation **CCs, UINT32 nrOfCCs, CAXMLErrorMessage **settleException)
SINT32 setPIServerConfiguration(CAXMLBI *pPiServerConfig)
~CAAccountingBIInterface()
private destructor
CAXMLErrorMessage * settle(CAXMLCostConfirmation &cc)
Send a cost confirmation to the JPI.
Very simple http client.
SINT32 sendPostRequest(const UINT8 *url, const UINT8 *data, const UINT32 dataLen)
Sends a HTTP POST request to the server.
SINT32 parseHTTPHeader(UINT32 *contentLength, UINT32 *statusCode=NULL, UINT32 msTimeOut=3000)
receives the HTTP header and parses the content length
SINT32 setSocket(CASocket *pSocket)
static SINT32 printMsg(UINT32 typ, const char *format,...)
Writes a given message to the log.
Definition: CAMsg.cpp:251
This class represents a socket address for Internet (IP) connections.
SINT32 setAddr(const UINT8 *szIP, UINT16 port)
Sets the address to szIP and port.
SINT32 getHostName(UINT8 *buff, UINT32 len) const
Returns the hostname for this address.
UINT16 getPort() const
Returns the port value of the address.
virtual SINT32 receiveFullyT(UINT8 *buff, UINT32 len, UINT32 msTimeOut)
Trys to receive all bytes.
Definition: CASocket.cpp:677
virtual SINT32 setNonBlocking(bool b)
Definition: CASocket.cpp:947
SINT32 close()
Shuts down the socket.
SINT32 connect(const CASocketAddr &psa, UINT32 msTimeout)
Establishes the actual TCP/IP connection and performs the TLS handshake.
SINT32 setServerCertificate(CACertificate *pCert)
Sets the Certifcate we accept as server identification.
This class encapsulates an error or success message.
static const UINT32 ERR_INTERNAL_SERVER_ERROR
static SINT32 dumpToMem(const DOMNode *node, UINT8 *buff, UINT32 *size)
Dumps the node and all childs into buff.
Definition: DOM_Output.hpp:161
const SINT32 E_SUCCESS
Definition: errorcodes.hpp:2
#define E_UNKNOWN
Definition: errorcodes.hpp:3
#define E_TIMEDOUT
Definition: errorcodes.hpp:10