Mixe for Privacy and Anonymity in the Internet
CAInfoService.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
11 notice,
12 this list of conditions and the following disclaimer in the
13 documentation and/or
14 other materials provided with the distribution.
15 
16 - Neither the name of the University of Technology Dresden, Germany nor
17 the names of its contributors
18 may be used to endorse or promote products derived from this software
19 without specific
20 prior written permission.
21 
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
24 AND ANY EXPRESS
25 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 MERCHANTABILITY
27 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 REGENTS OR CONTRIBUTORS
29 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 CONSEQUENTIAL DAMAGES
31 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 LOSS OF USE, DATA,
33 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 LIABILITY, WHETHER
35 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 ARISING IN ANY WAY
37 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38 DAMAGE
39 */
40 #include "StdAfx.h"
41 #if !defined ONLY_LOCAL_PROXY || defined INCLUDE_MIDDLE_MIX
42 #include "CAInfoService.hpp"
43 #include "CALibProxytest.hpp"
44 #include "xml/DOM_Output.hpp"
45 #include "CAHttpClient.hpp"
46 #endif
47 #ifndef ONLY_LOCAL_PROXY
48 #include "CASocket.hpp"
49 #include "CACmdLnOptions.hpp"
50 #include "CAMsg.hpp"
51 #include "CASocketAddrINet.hpp"
52 #include "CAUtil.hpp"
53 #include "CASingleSocketGroup.hpp"
54 #include "CALastMix.hpp"
55 #include "CACertificate.hpp"
56 #include "CAXMLBI.hpp"
57 
59 #endif
60 #if !defined ONLY_LOCAL_PROXY || defined INCLUDE_MIDDLE_MIX
61 
62 const char * STRINGS_REQUEST_TYPES[NR_REQUEST_TYPES] = { "POST", "GET" };
63 const char * STRINGS_REQUEST_COMMANDS[NR_REQUEST_COMMANDS] = { "configure", "helo", "mixinfo/", "dynacascade", "cascade", "feedback", "tc" };
64 
65 const UINT64 CAInfoService::MINUTE = 60;
68 const UINT64 CAInfoService::SEND_MIX_INFO_WAIT = MINUTE * 10;
70 const UINT32 CAInfoService::SEND_INFO_TIMEOUT_MS = 3000; // timeout for single send operations
72 
74 {
80  const UINT8* param;
82 };
83 
84 
85 
87 {
88  INIT_STACK;
89  BEGIN_STACK("CAInfoService::InfoLoop");
90 
91  CAMsg::printMsg(LOG_DEBUG, "CAInfoService - InfoLoop() started\n");
92  CAMsg::printMsg(LOG_DEBUG, "CAInfoService - InfoLoop() PID: %i\n", getpid());
93  CAInfoService* pInfoService = (CAInfoService*)p;
94  bool bIsFirst = true; //send our own certifcate only the first time
95  bool bOneUpdateDone = false;
96 
97  UINT32 currentTime;
98  UINT32 lastCascadeUpdate;
99  UINT32 lastStatusUpdate;
100  UINT32 lastMixInfoUpdate;
101  UINT32 nextUpdate;
102 #ifdef DYNAMIC_MIX
103  UINT32 loops = 4;
104  UINT32 interval = 0;
105 #endif
106  lastCascadeUpdate = lastMixInfoUpdate = lastStatusUpdate = (UINT32)time(NULL);
107  // tell the algorithm it is time to update
108  lastCascadeUpdate -= CAInfoService::SEND_CASCADE_INFO_WAIT;
109  lastMixInfoUpdate -= CAInfoService::SEND_MIX_INFO_WAIT;
110  lastStatusUpdate -= CAInfoService::SEND_STATUS_INFO_WAIT;
111  UINT32 statusSentErrorBurst = 0;
112 
113  pInfoService->m_pLoopCV->lock();
114  pInfoService->m_pLoopCV->wait(CAInfoService::SEND_LOOP_SLEEP * 1000);
115  pInfoService->m_pLoopCV->unlock();
116 
117  while (pInfoService->isRunning())
118  {
119 #ifdef DYNAMIC_MIX
121  if(loops < 4)
122  {
123  sSleep(interval);
124  loops++;
125  continue;
126  }
127 #endif
128  // TODO: the "pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2))" is just a work-around until we have a proper synchronization with the xml nodes...
129 
130  currentTime = time(NULL);
131  if (currentTime >= (lastStatusUpdate + CAInfoService::SEND_STATUS_INFO_WAIT))
132  {
133  if (pInfoService->m_pMix->isConnected() && pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2)) &&
134  pInfoService->sendStatus(bIsFirst) == E_SUCCESS)
135  {
136  lastStatusUpdate = time(NULL);
137  bIsFirst = false;
138  bOneUpdateDone = true;
139  statusSentErrorBurst = 0;
140  //CAMsg::printMsg(LOG_DEBUG,"InfoService: Successfully sent Status information.\n");
141  }
142  else
143  if (pInfoService->m_pMix->isConnected() && pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2)))
144  {
145  statusSentErrorBurst++;
146  CAMsg::printMsg(LOG_WARNING, "InfoService: Could not send Status information.\n");
147  }
148  /* send terms and conditions */
149  //pInfoService->sendOperatorTnCData();
150  }
151 
152  // check every minute if configuring, every 10 minutes otherwise
153  currentTime = time(NULL);
154  if (currentTime >= (lastCascadeUpdate + CAInfoService::SEND_CASCADE_INFO_WAIT) || pInfoService->isConfiguring())
155  {
156  if (CALibProxytest::getOptions()->isFirstMix() || (CALibProxytest::getOptions()->isLastMix() && pInfoService->isConfiguring()))
157  {
158  if (pInfoService->m_pMix->isConnected() && pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2))
159  && pInfoService->sendCascadeHelo() == E_SUCCESS)
160  {
161  lastCascadeUpdate = time(NULL);
162  bOneUpdateDone = true;
163  CAMsg::printMsg(LOG_INFO, "InfoService: Successfully sent Cascade information.\n");
164  }
165  else
166  if (pInfoService->m_pMix->isConnected() && pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2)))
167  {
168  CAMsg::printMsg(LOG_WARNING, "InfoService: Could not send Cascade information.\n");
169  }
170  }
171  currentTime = time(NULL);
172  if ((currentTime >= (lastMixInfoUpdate + CAInfoService::SEND_MIX_INFO_WAIT) &&
173  pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2))) || pInfoService->isConfiguring())
174  {
175  if (pInfoService->sendMixHelo() != E_SUCCESS)
176  {
177  CAMsg::printMsg(LOG_WARNING, "InfoService: Could not send MixInfo information.\n");
178  }
179  else
180  {
181  lastMixInfoUpdate = time(NULL);
182  bOneUpdateDone = true;
183  CAMsg::printMsg(LOG_INFO, "InfoService: Successfully sent MixInfo information.\n");
184  }
185  }
186  }
187 #ifdef DYNAMIC_MIX
188  // LERNGRUPPE
189  // Check regulary for new cascade information
195  if( CALibProxytest::getOptions()->isDynamic() )
196  {
197  pInfoService->dynamicCascadeConfiguration();
198  }
199 #endif
200  currentTime = time(NULL);
201  //@TODO BUGGy -- because it assumes knowledge about update times, which are configurable in StdAfx.hpp
202  // wait CAInfoService::SEND_LOOP_SLEEP seconds at most
203  /*temp = (currentTime - lastStatusUpdate);
204  if (bOneUpdateDone && temp > 0)
205  {
206  if (temp <= CAInfoService::SEND_LOOP_SLEEP)
207  {
208  bPreventLoop = false;
209  nextUpdate = CAInfoService::SEND_LOOP_SLEEP - temp;
210  }
211  else if (bPreventLoop)
212  {
213  // prevent infinite loops
214  bPreventLoop = false;
215  nextUpdate = CAInfoService::SEND_LOOP_SLEEP;
216  }
217  else
218  {
219  bPreventLoop = true;
220  nextUpdate = 0;
221  }
222  }
223  else
224  {
225  bPreventLoop = false;
226  nextUpdate = CAInfoService::SEND_LOOP_SLEEP;
227  }*/
228 
229  /* Not the optimal solution; would be best, if infoservice send
230  * routines can be called by other threads if certain events occur, i.e.
231  * cascade reconnection, etc.
232  */
233  if (bOneUpdateDone && (statusSentErrorBurst > 0))
234  {
235  //TODO: handle case when status sent error burst exceeds an upper limit */
237  }
238  else
239  {
240  nextUpdate = CAInfoService::SEND_LOOP_SLEEP;
241  }
242 #ifdef DYNAMIC_MIX
243  interval = nextUpdate / 4;
244  CAMsg::printMsg(LOG_DEBUG,"InfoService: Next update in %i seconds...interval %i\n", nextUpdate, interval);
245  loops = 0;
246 #else
247  if (nextUpdate > 20)
248  {
249  CAMsg::printMsg(LOG_DEBUG, "InfoService: Next update in %i seconds...\n", nextUpdate);
250  }
251  /* We can interrupt this thread if the mix is shutting down */
252  pInfoService->m_pLoopCV->lock();
253  pInfoService->m_pLoopCV->wait(nextUpdate * 1000);
254  pInfoService->m_pLoopCV->unlock();
255 
256  //sSleep(nextUpdate);
257 #endif
258  }
259  CAMsg::printMsg(LOG_DEBUG, "CAInfoService - InfoLoop() exited\n");
260  FINISH_STACK("CAInfoService::InfoLoop");
262 }
263 
265 {
266  INIT_STACK;
267  BEGIN_STACK("CAInfoService::TCascadeStatus");
268 
269  InfoServiceHeloMsg* message = (InfoServiceHeloMsg*)p;
270  message->retVal = message->is->sendStatus(message->strXML, message->len, message->addr);
271 
272  FINISH_STACK("CAInfoService::TCascadeStatus");
274 }
275 
277 {
278  INIT_STACK;
279  BEGIN_STACK("CAInfoService::TMixHelo");
280 
281  InfoServiceHeloMsg* message = (InfoServiceHeloMsg*)p;
282  message->retVal = message->is->sendMixHelo(message->strXML, message->len, message->requestCommand, message->param, message->addr);
283 
284  FINISH_STACK("CAInfoService::TMixHelo");
286 }
287 
288 #endif
289 #ifndef ONLY_LOCAL_PROXY
290 
292 {
293  INIT_STACK;
294  BEGIN_STACK("CAInfoService::TCascadeHelo");
295 
296  InfoServiceHeloMsg* message = (InfoServiceHeloMsg*)p;
297  message->retVal = message->is->sendCascadeHelo(message->strXML, message->len, message->addr);
298  FINISH_STACK("CAInfoService::TCascadeHelo");
300 }
301 
302 
303 
304 
305 
306 #ifdef DYNAMIC_MIX
307 
308 bool CAInfoService::newCascadeAvailable()
309 {
310  CASocket socket;
311  CASocketAddrINet *address = NULL;
312  CAHttpClient httpClient;
313  bool ret = false;
314 
315  UINT32 status, contentLength;
316  UINT8 buff[255];
317  UINT8 bufMixId[60];
318  UINT32 mixIdLen = 60;
319  CALibProxytest::getOptions()->getMixId( bufMixId, mixIdLen );
320  sprintf((char*)buff, "/newcascadeinformationavailable/%s",bufMixId );
321  if( CALibProxytest::getOptions()->getRandomInfoService(address) != E_SUCCESS)
322  {
323  CAMsg::printMsg( LOG_ERR, "Unable to get a random InfoService - This will cause problems! Check your configuration!\n");
324  return false;
325  }
326  if(socket.connect(*address)!=E_SUCCESS)
327  {
328  goto EXIT;
329  }
330  //Send request
331  httpClient.setSocket(&socket);
332  httpClient.sendGetRequest(buff);
333  httpClient.parseHTTPHeader(&contentLength, &status);
334  if(status!=200)
335  {
336  socket.close();
337  ret = false;
338  goto EXIT;
339  }
340  ret = true;
341 EXIT:
342  delete address;
343  address = NULL;
344  return ret;
345 }
346 
354 SINT32 CAInfoService::dynamicCascadeConfiguration()
355 {
356  SINT32 ret = E_UNKNOWN;
357  CADynamicCascadeConfigurator *configurator = NULL;
358 
359  if(!newCascadeAvailable())
360  {
361  return E_SUCCESS;
362  }
363 
365  if(m_bReconfig)
366  {
367  return E_SUCCESS;
368  }
369  CAMsg::printMsg( LOG_DEBUG, "Starting dynamic reconfiguration...\n");
370  m_bReconfig = true;
371 
372  configurator = new CADynamicCascadeConfigurator( m_pSignature, m_pMix );
373  ret = configurator->configure();
375  if(ret != E_SUCCESS)
376  {
377  CALibProxytest::getOptions()->resetNextMix();
378  CALibProxytest::getOptions()->resetPrevMix();
379  CALibProxytest::getOptions()->setCascadeProposal(NULL, 0);
380  m_pMix->dynaReconfigure(false);
381  }
382  m_bReconfig = false;
383  delete configurator;
384  configurator = NULL;
385 
386  return ret;
387 }
388 #endif
389 
390 
391 
392 
393 
394 
395 #endif
396 
397 #if !defined ONLY_LOCAL_PROXY || defined INCLUDE_MIDDLE_MIX
399 {
400  m_pMix = NULL;
401  m_bRun = false;
402  //m_pSignature=NULL;
403  m_pMultiSignature = NULL;
404  m_minuts = 0;
405  m_lastMixedPackets = 0;
408  m_pthreadRunLoop = new CAThread((UINT8*)"InfoServiceThread");
409 #ifdef DYNAMIC_MIX
410  m_bReconfig = false;
411 #endif
412 }
414 {
415  m_pMix = NULL;
416  m_bRun = false;
417  //m_pSignature=NULL;
418  m_pMultiSignature = NULL;
419  m_minuts = 0;
420  m_lastMixedPackets = 0;
423  m_pthreadRunLoop = new CAThread((UINT8*)"InfoServiceThread");
424  m_pMix = pMix;
425 #ifdef DYNAMIC_MIX
426  m_bReconfig = false;
427 #endif
428 }
429 
431 {
432  stop();
433  delete m_pLoopCV;
434  m_pLoopCV = NULL;
435  delete m_pthreadRunLoop;
436  m_pthreadRunLoop = NULL;
437 }
439 {
440  m_pMultiSignature = pMultiSig;
441  return E_SUCCESS;
442 }
443 
445 {
446 #if !defined ONLY_LOCAL_PROXY
447  if (m_pMix != NULL && CALibProxytest::getOptions()->isFirstMix())
448  {
449  return ((CAFirstMix*)m_pMix)->getLevel(puser, prisk, ptraffic);
450  }
451 #endif
452  return E_UNKNOWN;
453 }
454 
456 {
457 #if ! defined ONLY_LOCAL_PROXY
458  if (m_pMix != NULL && CALibProxytest::getOptions()->isFirstMix())
459  {
460  return ((CAFirstMix*)m_pMix)->getMixedPackets(ppackets);
461  }
462 #endif
463  return E_UNKNOWN;
464 }
465 
467 {
468  if (m_pMultiSignature == NULL)
469  {
470  return E_UNKNOWN;
471  }
472  m_bRun = true;
474  m_minuts = 1;
476 #ifdef DEBUG
477  CAMsg::printMsg(LOG_DEBUG, "CAInfoService::start() - starting InfoService thread\n");
478 #endif
479 
480  return m_pthreadRunLoop->start(this);
481 }
482 
483 
485 {
486  m_pLoopCV->lock();
487  m_pLoopCV->signal();
488  m_pLoopCV->unlock();
489  return E_SUCCESS;
490 }
491 
493 {
494  if (m_bRun)
495  {
496  m_bRun = false;
497  /* Interrupt this thread */
498  m_pLoopCV->lock();
499  m_pLoopCV->signal();
500  m_pLoopCV->unlock();
501 
503  }
504  return E_SUCCESS;
505 }
506 
508 {
509  if (!CALibProxytest::getOptions()->isFirstMix())
510  {
511  return E_SUCCESS;
512  }
513 
514 
515  if (!(m_pMix->isConnected())) // && !bIncludeCerts )
516  {
517 #ifdef DEBUG
518  CAMsg::printMsg(LOG_INFO, "Mix not connected. Skipping status.\n");
519 #endif
520  return E_UNKNOWN;
521  }
522 
523  UINT32 len = 0;
524  SINT32 ret = E_UNKNOWN;
525  UINT8* strStatusXML = getStatusXMLAsString(bIncludeCerts, len);
526 
527  if (strStatusXML == NULL)
528  {
529  return E_UNKNOWN;
530  }
531 
532  if (!(m_pMix->isConnected()))
533  {
534  CAMsg::printMsg(LOG_INFO, "Mix not connected. Skip sending already created status message.\n");
535  }
536  else
537  {
538  ret = sendHelo(strStatusXML, len, TCascadeStatus, (UINT8*)"Status Thread", REQUEST_COMMAND_STATUS);
539  }
540 
541  delete[] strStatusXML;
542  strStatusXML = NULL;
543  return ret;
544 }
545 
546 
548 {
549  SINT32 tmpUser, tmpRisk, tmpTraffic;
550  UINT64 tmpPackets;
551 
552  //httpClient.setSocket(&oSocket);
553  UINT8 strMixId[255];
554  CALibProxytest::getOptions()->getMixId(strMixId, 255);
555 
556  tmpUser = tmpTraffic = tmpRisk = -1;
557  set64(tmpPackets, (UINT32)-1);
558  getLevel(&tmpUser, &tmpRisk, &tmpTraffic);
559  SINT32 ret = getMixedPackets(tmpPackets);
560  if (ret == E_SUCCESS)
561  {
562  UINT32 avgTraffic = div64(tmpPackets, m_minuts);
563  UINT32 diffTraffic = diff64(tmpPackets, m_lastMixedPackets);
564  if (avgTraffic == 0)
565  {
566  if (diffTraffic == 0)
567  {
568  tmpTraffic = 0;
569  }
570  else
571  {
572  tmpTraffic = 100;
573  }
574  }
575  else
576  {
577  double dTmp = (double)diffTraffic / (double)avgTraffic;
578  tmpTraffic = min(SINT32(50.*dTmp), 100);
579  }
580  set64(m_lastMixedPackets, tmpPackets);
581  }
582  m_minuts++;
583  //let the attributes in alphabetical order..
584 #define XML_MIX_CASCADE_STATUS "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
585  <MixCascadeStatus LastUpdate=\"%s\" currentRisk=\"%i\" id=\"%s\" mixedPackets=\"%s\" nrOfActiveUsers=\"%i\" trafficSituation=\"%i\"\
586  ></MixCascadeStatus>"
587 
588  UINT32 buffLen = 8192;
589  UINT8* buff = new UINT8[buffLen];
590  memset(buff, 0, buffLen);
591  UINT8 tmpBuff[1024];
592  UINT8 buffMixedPackets[50];
593  print64(buffMixedPackets, tmpPackets);
594  UINT64 currentMillis;
595  UINT8 tmpStrCurrentMillis[50];
596  if (getcurrentTimeMillis(currentMillis) == E_SUCCESS)
597  {
598  print64(tmpStrCurrentMillis, currentMillis);
599  }
600  else
601  {
602  tmpStrCurrentMillis[0] = 0;
603  }
604  sprintf((char*)tmpBuff, XML_MIX_CASCADE_STATUS, tmpStrCurrentMillis, tmpRisk, strMixId, buffMixedPackets, tmpUser, tmpTraffic);
605 
606 
607  if (m_pMultiSignature->signXML(tmpBuff, strlen((char*)tmpBuff), buff, &buffLen, bIncludeCerts) != E_SUCCESS)
608  {
609  delete[] buff;
610  buff = NULL;
611  }
612  else
613  {
614  len = buffLen;
615  }
616  return buff;
617 }
618 
619 SINT32 CAInfoService::sendHelo(UINT8* a_strXML, UINT32 a_len, THREAD_RETURN(*a_thread)(void *), UINT8* a_strThreadName, SINT32 requestCommand, const UINT8* param)
620 {
621  SINT32 returnValue = E_UNKNOWN;
622  UINT32 nrAddresses;
623  CAListenerInterface** socketAddresses = CALibProxytest::getOptions()->getInfoServices(nrAddresses);
624  CAThread** threads = new CAThread*[nrAddresses];
625  InfoServiceHeloMsg** messages = new InfoServiceHeloMsg*[nrAddresses];
626 
627  for (UINT32 i = 0; i < nrAddresses; i++)
628  {
629  messages[i] = new InfoServiceHeloMsg();
630  messages[i]->addr = (CASocketAddrINet*)socketAddresses[i]->getAddr();
631  messages[i]->len = a_len;
632  messages[i]->strXML = a_strXML;
633  messages[i]->is = this;
634  messages[i]->requestCommand = requestCommand;
635  messages[i]->param = param;
636 #if !defined(NO_INFOSERVICE_TRHEADS)
637  threads[i] = new CAThread(a_strThreadName);
638  threads[i]->setMainLoop((THREAD_RETURN (*)(void *))a_thread);
639  threads[i]->start((void*)(messages[i]), false, true);
640 #else
641  (*a_thread)(messages[i]);
642  if (messages[i]->retVal == E_SUCCESS)
643  {
644  returnValue = E_SUCCESS;
645  }
646 #endif
647  }
648 
649  for (UINT32 i = 0; i < nrAddresses; i++)
650  {
651 #if !defined(NO_INFOSERVICE_TRHEADS)
652  if (threads[i]->join() == E_SUCCESS)
653  {
654  // CAMsg::printMsg(LOG_DEBUG,"InfoService: helo thread %u joined.\n", i);
655  if (messages[i]->retVal == E_SUCCESS)
656  {
657  returnValue = E_SUCCESS;
658  }
659  }
660  delete threads[i];
661  threads[i] = NULL;
662 #endif
663  delete messages[i]->addr;
664  messages[i]->addr = NULL;
665  delete messages[i];
666  messages[i] = NULL;
667  }
668  //Message looks senseless but please keep it because Rolf reported a helo thread deadlock.
669  //Perhaps there is a problem when the threads are joined.
670  // CAMsg::printMsg(LOG_DEBUG,"InfoService: all helo threads joined. continue.\n");
671  delete[] messages;
672  messages = NULL;
673  delete[] threads;
674  threads = NULL;
675 
676  return returnValue;
677 }
678 
679 
680 
681 
688 SINT32 CAInfoService::sendStatus(const UINT8* a_strStatusXML, UINT32 a_len, const CASocketAddrINet* a_pSocketAddress) const
689 {
690  UINT8 buffHeader[512];
691  SINT32 ret = E_UNKNOWN;
692  UINT8 hostname[255];
693  UINT32 currentTimeout = MIX_TO_INFOSERVICE_TIMEOUT;
694  UINT64 startupTime, currentMillis;
695 
696 
697 #ifdef DEBUG
698  CAMsg::printMsg(LOG_DEBUG, "CAInfoService::sendStatus()\n");
699 #endif
700  if (!CALibProxytest::getOptions()->isFirstMix())
701  {
702  return E_SUCCESS;
703  }
704  CASocket oSocket(true);
705  if (a_pSocketAddress == NULL)
706  {
707  oSocket.close();
708  return E_UNKNOWN;
709  }
710 
711 
712  if (oSocket.connect(*a_pSocketAddress, MIX_TO_INFOSERVICE_TIMEOUT) != E_SUCCESS)
713  {
714  if (a_pSocketAddress->getIPAsStr(hostname, 255) == E_SUCCESS)
715  {
716  CAMsg::printMsg(LOG_DEBUG, "InfoService: Could not connect to InfoService %s:%d. Reason: %s (%i)\n",
717  hostname, a_pSocketAddress->getPort(), GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
718  }
719  else
720  {
721  CAMsg::printMsg(LOG_DEBUG, "InfoService: Could not connect to InfoService (host unknown) at port %d. Reason: %s (%i)\n",
722  a_pSocketAddress->getPort(), GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
723  }
724  oSocket.close();
725  return E_UNKNOWN;
726  }
727 
728  if (a_pSocketAddress->getIPAsStr(hostname, 255) == E_SUCCESS)
729  {
730  CAMsg::printMsg(LOG_DEBUG, "InfoService: Sending current status to InfoService %s:%d.\n", hostname, a_pSocketAddress->getPort());
731  sprintf((char*)buffHeader, "POST /feedback HTTP/1.0\r\nContent-Length: %u\r\n\r\n", a_len);
732 
733  getcurrentTimeMillis(startupTime);
734  oSocket.sendFullyTimeOut(buffHeader, strlen((char*)buffHeader), currentTimeout, SEND_INFO_TIMEOUT_MS);
735 
736  getcurrentTimeMillis(currentMillis);
737  currentTimeout -= (currentMillis - startupTime);
738  ret = oSocket.sendFullyTimeOut(a_strStatusXML, a_len, currentTimeout, SEND_INFO_TIMEOUT_MS);
739  }
740 
741  oSocket.close();
742  if (ret == E_SUCCESS)
743  {
744  return E_SUCCESS;
745  }
746  CAMsg::printMsg(LOG_DEBUG, "InfoService: Sending status failed, ret: %d \n", ret);
747  return E_UNKNOWN;
748 }
749 SINT32 CAInfoService::sendMixHelo(SINT32 requestCommand, const UINT8* param)
750 {
751  UINT32 len;
752  SINT32 ret;
753  UINT8* strMixHeloXML = getMixHeloXMLAsString(len);
754 
755  if (strMixHeloXML == NULL)
756  {
757  CAMsg::printMsg(LOG_DEBUG, "InfoService:sendMixHelo() -- Error: getMixHeloXMLAsString() returned NULL!\n");
758  return E_UNKNOWN;
759  }
760 
761  // CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixHelo(): Initialising helo thread...\n");
762  ret = sendHelo(strMixHeloXML, len, TMixHelo, (UINT8*)"Mix Helo Thread", requestCommand, param);
763  // CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixHelo(): Finished helo thread!\n");
764 
765  delete[] strMixHeloXML;
766  strMixHeloXML = NULL;
767  return ret;
768 }
769 
771 {
772  XERCES_CPP_NAMESPACE::DOMDocument* docMixInfo = NULL;
773  DOMElement* mixInfoRoot = NULL;
774 
775  if ((CALibProxytest::getOptions()->getMixXml(docMixInfo) != E_SUCCESS) ||
776  (docMixInfo == NULL))
777  {
778  return NULL;
779  }
780 
781  if (m_serial != 0)
782  {
783  mixInfoRoot = docMixInfo->getDocumentElement();
784  if (mixInfoRoot != NULL)
785  {
787  }
788  }
789  return xmlDocToStringWithSignature(docMixInfo, a_len, true);
790 }
791 
792 UINT8* CAInfoService::xmlDocToStringWithSignature(DOMNode *a_node, UINT32& a_len, bool bIncludeCerts)
793 {
794  a_len = 0;
795 
796  UINT32 sendBuffLen = 0;
797  UINT8* sendBuff = NULL;
798 
799  if (a_node == NULL)
800  {
801  return NULL;
802  }
803  if (m_pMultiSignature->signXML(a_node, bIncludeCerts) != E_SUCCESS)
804  {
805  return NULL;
806  }
807 
808  sendBuff = DOM_Output::dumpToMem(a_node, &sendBuffLen);
809  if (sendBuff == NULL)
810  {
811  return NULL;
812  }
813  a_len = sendBuffLen;
814  return sendBuff;
815 }
816 
819 SINT32 CAInfoService::sendMixHelo(const UINT8* a_strMixHeloXML, UINT32 a_len, SINT32 requestCommand, const UINT8* param,
820  const CASocketAddrINet* a_pSocketAddress)
821 {
822  UINT8* recvBuff = NULL;
823  SINT32 ret = E_SUCCESS;
824  UINT32 len = 0;
825 
826  CASocket oSocket(true);
827  UINT8 hostname[255];
828  UINT8 buffHeader[255];
829  CAHttpClient httpClient;
830 
831  UINT64 currentTimeout = MIX_TO_INFOSERVICE_TIMEOUT;
832  UINT64 startupTime, currentMillis;
833 
834  UINT32 requestType = REQUEST_TYPE_POST;
835  bool receiveAnswer = false;
836 
837  if (a_pSocketAddress == NULL)
838  {
839  goto ERR;
840  }
841 
842  if (requestCommand < 0)
843  {
844  if (m_bConfiguring)
845  {
846  requestCommand = REQUEST_COMMAND_CONFIGURE;
847  receiveAnswer = true;
848  }
849  else
850  {
851  requestCommand = REQUEST_COMMAND_HELO;
852  receiveAnswer = true;
853  }
854  }
855  else
856  if (requestCommand == REQUEST_COMMAND_MIXINFO)
857  {
858  requestType = REQUEST_TYPE_GET;
859  receiveAnswer = true;
860  }
861 
862  if (a_pSocketAddress->getIPAsStr(hostname, 255) != E_SUCCESS)
863  {
864  goto ERR;
865  }
866 
867  oSocket.setRecvBuff(255);
868  if ((ret = oSocket.connect(*a_pSocketAddress, MIX_TO_INFOSERVICE_TIMEOUT)) == E_SUCCESS)
869  {
870  httpClient.setSocket(&oSocket);
871  const char* strRequestCommand = STRINGS_REQUEST_COMMANDS[requestCommand];
872  const char* strRequestType = STRINGS_REQUEST_TYPES[requestType];
873  CAMsg::printMsg(LOG_DEBUG, "InfoService: Sending [%s] %s to InfoService %s:%d.\r\n", strRequestType, strRequestCommand, hostname, a_pSocketAddress->getPort());
874  if (requestCommand == REQUEST_COMMAND_MIXINFO)
875  {
876  sprintf((char*)buffHeader, "%s /%s%s HTTP/1.0\r\nContent-Length: %u\r\n\r\n", strRequestType, strRequestCommand, param, a_len);
877  }
878  else
879  {
880  sprintf((char*)buffHeader, "%s /%s HTTP/1.0\r\nContent-Length: %u\r\n\r\n", strRequestType, strRequestCommand, a_len);
881  }
882 
883  getcurrentTimeMillis(startupTime);
884  if (oSocket.sendFullyTimeOut(buffHeader, strlen((char*)buffHeader), currentTimeout, SEND_INFO_TIMEOUT_MS) != E_SUCCESS)
885  {
886  goto ERR;
887  }
888 
889  // CAMsg::printMsg(LOG_DEBUG,"InfoService: Sending XML data...\n");
890  getcurrentTimeMillis(currentMillis);
891  currentTimeout -= (currentMillis - startupTime);
892  if (currentTimeout <= 0 ||
893  oSocket.sendFullyTimeOut(a_strMixHeloXML, a_len, currentTimeout, SEND_INFO_TIMEOUT_MS) != E_SUCCESS)
894  {
895  goto ERR;
896  }
897 
898  if (receiveAnswer)
899  {
900  // CAMsg::printMsg(LOG_DEBUG,"InfoService: Parsing header...\n");
901  getcurrentTimeMillis(currentMillis);
902  currentTimeout -= (currentMillis - startupTime);
903  if (currentTimeout <= 0 || httpClient.parseHTTPHeader(&len) != E_SUCCESS)
904  {
905  goto ERR;
906  }
907  // CAMsg::printMsg(LOG_DEBUG,"InfoService: Header parsed!\n");
908 
909  if (len > 0)
910  {
911  getcurrentTimeMillis(currentMillis);
912  currentTimeout -= (currentMillis - startupTime);
913 
914  recvBuff = new UINT8[len + 1];
915  CAMsg::printMsg(LOG_DEBUG, "InfoService: Receiving answer...\n");
916  if (currentTimeout <= 0 ||
917  oSocket.receiveFullyT(recvBuff, len, currentTimeout) != E_SUCCESS)
918  {
919  delete[]recvBuff;
920  recvBuff = NULL;
921  goto ERR;
922  }
923  recvBuff[len] = 0;
924  CAMsg::printMsg(LOG_DEBUG, "Received from Infoservice:\n");
925  CAMsg::printMsg(LOG_DEBUG, (char*)recvBuff);
926  CAMsg::printMsg(LOG_DEBUG, "\n");
927  }
928  }
929  oSocket.close();
930 
931  if (recvBuff != NULL)
932  {
933  delete[] recvBuff;
934  recvBuff = NULL;
935  }
936  /* REMOVED by Rolf Wendolsky on 2009-12-11 becuase this looks dangerous: each InfoService may reconfigure the Mix! Without verificaton!
937  if(recvBuff != NULL)
938  {
939  XERCES_CPP_NAMESPACE::DOMDocument* doc=parseDOMDocument(recvBuff,len);
940  delete[] recvBuff;
941  recvBuff=NULL;
942  DOMElement* root=NULL;
943  if(doc!=NULL && (root = doc->getDocumentElement()) != NULL)
944  {
945  if(equals(root->getNodeName(),"MixCascade"))
946  {
947  ret = handleConfigEvent(doc);
948  if(ret == E_SUCCESS)
949  m_bConfiguring = false;
950  else
951  return ret;
952  }
953  else if(equals(root->getNodeName(),"Mix"))
954  {
955  if(m_expectedMixRelPos < 0)
956  {
957  XMLCh* id=XMLString::transcode("id");
958  char* tmpStr=XMLString::transcode(root->getAttribute(id));
959  CAMsg::printMsg(LOG_DEBUG,"InfoService: Setting new previous mix: %s\n",tmpStr);
960  XMLString::release(&tmpStr);
961  XMLString::release(&id);
962  CALibProxytest::getOptions()->setPrevMix(doc);
963  }
964  else if(m_expectedMixRelPos > 0)
965  {
966  XMLCh* id=XMLString::transcode("id");
967  char* tmpStr=XMLString::transcode(root->getAttribute(id));
968  CAMsg::printMsg(LOG_DEBUG,"InfoService: Setting new next mix: %s\n",tmpStr);
969  XMLString::release(&id);
970  XMLString::release(&tmpStr);
971  CALibProxytest::getOptions()->setNextMix(doc);
972  }
973  }
974  CAMsg::printMsg(LOG_DEBUG,"InfoService::sendMixHelo(): XML infoservice doc 0x%x not needed anymore.\n",
975  doc);
976  }
977  else
978  {
979  CAMsg::printMsg(LOG_CRIT,"InfoService: Error parsing answer from InfoService!\n");
980  }
981  }*/
982  return E_SUCCESS;
983  }
984  else
985  {
986  if (ret != E_UNKNOWN)
987  {
988  CAMsg::printMsg(LOG_ERR, "InfoService: sendMixHelo() connecting to InfoService %s:%d failed for reason: %s (%i)\n",
989  hostname, a_pSocketAddress->getPort(), GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
990  }
991  else
992  {
993  CAMsg::printMsg(LOG_ERR, "InfoService: sendMixHelo() connecting to InfoService %s:%d failed!\n",
994  hostname, a_pSocketAddress->getPort());
995  }
996  }
997 ERR:
998 
999  //CAMsg::printMsg(LOG_DEBUG,"InfoService: Closing socket to %s:%d due to error...\n", hostname, a_pSocketAddress->getPort());
1000  oSocket.close();
1001  //CAMsg::printMsg(LOG_DEBUG,"InfoService: Socket closed to %s:%d due to error.\n", hostname, a_pSocketAddress->getPort());
1002  return E_UNKNOWN;
1003 }
1004 
1005 
1006 #endif
1007 #ifndef ONLY_LOCAL_PROXY
1008 
1010 {
1011  /*SINT32 ret = E_SUCCESS;
1012  UINT32 *lengths_ptr = NULL;
1013  XMLSize_t nrOfTnCs = 0;
1014  UINT32 i = 0;
1015  UINT8 **tncData = getOperatorTnCsAsStrings(&lengths_ptr, &nrOfTnCs);
1016 
1017  if(tncData != NULL)
1018  {
1019  for (;i < nrOfTnCs; i++)
1020  {
1021  #ifdef DEBUG
1022  CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixTnCData(), object: %s, len: %u\n",
1023  tncData[i], lengths_ptr[i]);
1024  #endif
1025  if( tncData[i] != NULL )
1026  {
1027  ret |= sendHelo(tncData[i], lengths_ptr[i],
1028  TMixHelo, (UINT8*)"Mix TnC Thread",
1029  REQUEST_COMMAND_TNC_DATA, NULL);
1030  delete [] tncData[i];
1031  tncData[i] = NULL;
1032  }
1033  else
1034  {
1035  CAMsg::printMsg(LOG_ERR,"InfoService:sendMixTnCData() -- Element %u is invalid!\n", (i+1) );
1036  ret |= E_UNKNOWN;
1037  }
1038 
1039  }
1040  delete [] lengths_ptr;
1041  lengths_ptr = NULL;
1042 
1043  delete [] tncData;
1044  }
1045  else
1046  {
1047  CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixTnCData() -- No TnC data specified!\n");
1048  return E_SUCCESS;
1049  }
1050  return ret;*/
1051  return E_SUCCESS;
1052 }
1053 
1056 /*SINT32 CAInfoService::sendMixInfo(const UINT8* pMixID)
1057 {
1058 return sendMixHelo(REQUEST_COMMAND_MIXINFO,pMixID, NULL);
1059 }
1060 */
1072 {
1073 
1074  DOMElement *tnCs = CALibProxytest::getOptions()->getTermsAndConditions();
1075  if (tnCs == NULL)
1076  {
1077  return NULL;
1078  }
1079 
1080  DOMNodeList *docTnCsList =
1082 
1083  if (docTnCsList == NULL)
1084  {
1085  return NULL;
1086  }
1087 
1088  UINT8 **elementList = NULL;
1089  DOMNode *iterator = NULL;
1090  UINT32 i = 0;
1091 
1092  UINT8 tmpOpSKIBuff[TMP_BUFF_SIZE];
1093  UINT32 tmpOpSKILen = TMP_BUFF_SIZE;
1094 
1095  CALibProxytest::getOptions()->getOperatorSubjectKeyIdentifier(tmpOpSKIBuff, &tmpOpSKILen);
1096  if (tmpOpSKILen == 0)
1097  {
1098  return NULL;
1099  }
1100 
1101  UINT8 tmpDate[TMP_BUFF_SIZE];
1102  UINT32 tmpDateLen = TMP_BUFF_SIZE;
1103 
1104  getDOMElementAttribute(tnCs, OPTIONS_ATTRIBUTE_TNC_DATE, tmpDate, &tmpDateLen);
1105  if (tmpDateLen == 0)
1106  {
1107  return NULL;
1108  }
1109 
1110  UINT8 tmpVersion[TMP_BUFF_SIZE];
1111  UINT32 tmpVersionLen = TMP_BUFF_SIZE;
1112 
1113  UINT8* serial = NULL;
1114 
1115  getDOMElementAttribute(tnCs, OPTIONS_ATTRIBUTE_TNC_VERSION, tmpVersion, &tmpVersionLen);
1116  if (tmpVersionLen > 0)
1117  {
1118  serial = new UINT8[tmpDateLen + tmpVersionLen + 1];
1119  memcpy(serial, tmpDate, tmpDateLen);
1120  memcpy(serial + tmpDateLen, tmpVersion, tmpVersionLen);
1121  serial[tmpDateLen + tmpVersionLen] = 0;
1122  }
1123  else
1124  {
1125  serial = new UINT8[tmpDateLen + 1];
1126  memcpy(serial, tmpDate, tmpDateLen);
1127  serial[tmpDateLen] = 0;
1128  }
1129 
1130  UINT32 locale_len = 3;
1131  UINT8* id = new UINT8[tmpOpSKILen + locale_len + 1];
1132  UINT8* locale = new UINT8[locale_len];
1133 
1134  locale[locale_len - 1] = 0;
1135 
1136  memcpy(id, tmpOpSKIBuff, tmpOpSKILen);
1137  id[tmpOpSKILen] = 0;
1138  id[tmpOpSKILen + (locale_len - 1) + 1] = 0;
1139 
1140  (*nrOfTnCs) = docTnCsList->getLength();
1141  elementList = new UINT8 *[(*nrOfTnCs)];
1142  (*lengths) = new UINT32[(*nrOfTnCs)];
1143  for (; i < (*nrOfTnCs); i++)
1144  {
1145  //after every loop turn locale is explicitly reset to 3 because ...
1146  locale_len = 3;
1147  iterator = docTnCsList->item(i);
1148  //... it is modified by getDOMElementAttribute
1149  getDOMElementAttribute(iterator, OPTIONS_ATTRIBUTE_TNC_LOCALE, locale, &locale_len);
1150  if (locale_len == 0)
1151  {
1152  elementList[i] = NULL;
1153  continue;
1154  }
1155  //only append the locale code to the id when it is
1156  //not the default locale
1157  if (strncasecmp((char *)locale, LOCALE_DEFAULT, 2) == 0)
1158  {
1159  id[tmpOpSKILen] = 0;
1160  }
1161  else
1162  {
1163  id[tmpOpSKILen] = '_';
1164  memcpy((id + tmpOpSKILen + 1), locale, locale_len);
1165  }
1166 
1168  {
1169  elementList[i] = NULL;
1170  continue;
1171  }
1172  if (setDOMElementAttribute(iterator, OPTIONS_ATTRIBUTE_TNC_DATE, tmpDate) != E_SUCCESS)
1173  {
1174  elementList[i] = NULL;
1175  continue;
1176  }
1178  {
1179  elementList[i] = NULL;
1180  continue;
1181  }
1183  elementList[i] = xmlDocToStringWithSignature(iterator, (*lengths)[i], true);
1184  }
1185 
1186  delete[] serial;
1187  delete[] id;
1188  delete[] locale;
1189  return elementList;
1190 
1191 }
1192 
1193 
1194 
1195 
1196 
1197 
1199 {
1200  if (CALibProxytest::getOptions()->isMiddleMix())
1201  {
1202  return E_SUCCESS;
1203  }
1204 
1205  UINT32 len;
1206  SINT32 ret;
1207  UINT8* strCascadeHeloXML = getCascadeHeloXMLAsString(len);
1208  if (strCascadeHeloXML == NULL)
1209  {
1210  return E_UNKNOWN;
1211  }
1212 
1213  if (!(m_pMix->isConnected()))
1214  {
1215 #ifdef DEBUG
1216  CAMsg::printMsg(LOG_INFO, "not connected: skipping cascade helo.\n");
1217 #endif
1218  delete[] strCascadeHeloXML;
1219  strCascadeHeloXML = NULL;
1220  return E_UNKNOWN;
1221  }
1222 
1223  ret = sendHelo(strCascadeHeloXML, len, TCascadeHelo, (UINT8*)"Cascade Helo Thread", REQUEST_COMMAND_CASCADE);
1224  delete[] strCascadeHeloXML;
1225  strCascadeHeloXML = NULL;
1226  return ret;
1227 }
1228 
1230 {
1231  a_len = 0;
1232  UINT32 sendBuffLen;
1233  UINT8* sendBuff = NULL;
1234  XERCES_CPP_NAMESPACE::DOMDocument* docMixInfo = NULL;
1235  DOMElement* elemTimeStamp = NULL;
1236  DOMElement* elemRoot = NULL;
1237 
1238  if (m_pMix->getMixCascadeInfo(docMixInfo) != E_SUCCESS)
1239  {
1240  // CAMsg::printMsg(LOG_INFO,"InfoService: Cascade not yet configured.\n");
1241  goto ERR;
1242  }
1243  //insert (or update) the Timestamp
1244  elemRoot = docMixInfo->getDocumentElement();
1245 
1246  if (getDOMChildByName(elemRoot, "LastUpdate", elemTimeStamp, false) != E_SUCCESS)
1247  {
1248  elemTimeStamp = createDOMElement(docMixInfo, "LastUpdate");
1249  elemRoot->appendChild(elemTimeStamp);
1250  }
1251  UINT64 currentMillis;
1252  getcurrentTimeMillis(currentMillis);
1253  UINT8 tmpStrCurrentMillis[50];
1254  print64(tmpStrCurrentMillis, currentMillis);
1255  setDOMElementValue(elemTimeStamp, tmpStrCurrentMillis);
1256 
1257  if (m_serial != 0)
1258  {
1259  print64(tmpStrCurrentMillis, m_serial);
1260  setDOMElementAttribute(elemRoot, ATTRIBUTE_SERIAL, tmpStrCurrentMillis);
1261  }
1262 
1263  if (m_pMultiSignature->signXML(docMixInfo, true) != E_SUCCESS)
1264  {
1265  goto ERR;
1266  }
1267 
1268  sendBuff = DOM_Output::dumpToMem(docMixInfo, &sendBuffLen);
1269  if (sendBuff == NULL)
1270  {
1271  goto ERR;
1272  }
1273 
1274  a_len = sendBuffLen;
1275  return sendBuff;
1276 ERR:
1277  delete[]sendBuff;
1278  sendBuff = NULL;
1279  return NULL;
1280 }
1281 
1290 SINT32 CAInfoService::sendCascadeHelo(const UINT8* a_strCascadeHeloXML, UINT32 a_len, const CASocketAddrINet* a_pSocketAddress) const
1291 {
1292  if (CALibProxytest::getOptions()->isMiddleMix() || (CALibProxytest::getOptions()->isLastMix() && !m_bConfiguring))
1293  {
1294  return E_SUCCESS;
1295  }
1296  CASocket oSocket(true);
1297  UINT8 hostname[255];
1298  UINT8 buffHeader[255];
1299  UINT64 currentTimeout = MIX_TO_INFOSERVICE_TIMEOUT;
1300  UINT64 startupTime, currentMillis;
1301 
1302  if (a_pSocketAddress == NULL)
1303  {
1304  goto ERR;
1305  }
1306 
1307  if (a_pSocketAddress->getIPAsStr(hostname, 255) != E_SUCCESS)
1308  {
1309  goto ERR;
1310  }
1311  if (oSocket.connect(*a_pSocketAddress, MIX_TO_INFOSERVICE_TIMEOUT) == E_SUCCESS)
1312  {
1313  if (CALibProxytest::getOptions()->isFirstMix())
1314  {
1315  CAMsg::printMsg(LOG_DEBUG, "InfoService: Sending cascade helo to InfoService %s:%d.\r\n", hostname, a_pSocketAddress->getPort());
1316  }
1317  else
1318  {
1319  CAMsg::printMsg(LOG_DEBUG, "InfoService: Sending cascade configuration request to InfoService %s:%d.\r\n", hostname, a_pSocketAddress->getPort());
1320  }
1321  // LERNGRUPPE
1322  // Semi-dynamic cascades are temporary cascades, not yet established! InfoService can cope with them now
1323  // using the /dynacascade command
1324  if (CALibProxytest::getOptions()->isLastMix() && m_bConfiguring)
1325  {
1326  sprintf((char*)buffHeader, "POST /dynacascade HTTP/1.0\r\nContent-Length: %u\r\n\r\n", a_len);
1327  }
1328  else
1329  {
1330  sprintf((char*)buffHeader, "POST /cascade HTTP/1.0\r\nContent-Length: %u\r\n\r\n", a_len);
1331  }
1332 
1333  getcurrentTimeMillis(startupTime);
1334  if (oSocket.sendFullyTimeOut(buffHeader, strlen((char*)buffHeader), currentTimeout, SEND_INFO_TIMEOUT_MS) != E_SUCCESS)
1335  {
1336  goto ERR;
1337  }
1338  getcurrentTimeMillis(currentMillis);
1339  currentTimeout -= (currentMillis - startupTime);
1340  if (currentTimeout <= 0 ||
1341  oSocket.sendFullyTimeOut(a_strCascadeHeloXML, a_len, currentTimeout, SEND_INFO_TIMEOUT_MS) != E_SUCCESS)
1342  {
1343  goto ERR;
1344  }
1345  //Receive answer --> 200 Ok or failure
1346  //HTTP/1.1 200 Ok
1347  getcurrentTimeMillis(currentMillis);
1348  currentTimeout -= (currentMillis - startupTime);
1349  if (currentTimeout <= 0 ||
1350  oSocket.receiveFullyT(buffHeader, 12, currentTimeout) != E_SUCCESS)
1351  {
1352  goto ERR;
1353  }
1354  if (memcmp(buffHeader + 9, "200", 3) != 0)
1355  {
1356  goto ERR;
1357  }
1358  oSocket.close();
1359  return E_SUCCESS;
1360  }
1361 ERR:
1362  oSocket.close();
1363  return E_UNKNOWN;
1364 }
1365 
1366 SINT32 CAInfoService::handleConfigEvent(XERCES_CPP_NAMESPACE::DOMDocument* doc) const
1367 {
1369  /* CAMsg::printMsg(LOG_INFO,"InfoService: Cascade info received from InfoService\n");
1370 
1371  DOM_Element root=doc.getDocumentElement();
1372  DOM_Node mixesElement;
1373  getDOMChildByName(root,(UINT8*)"Mixes", mixesElement, false);
1374  char* mixId;
1375  char* prevMixId = NULL;
1376  char* myNextMixId = NULL;
1377  char* myPrevMixId = NULL;
1378  bool bFoundMix = false;
1379  UINT8 myMixId[64];
1380  CALibProxytest::getOptions()->getMixId(myMixId,64);
1381  DOM_Node child = mixesElement.getFirstChild();
1382  while(child!=NULL)
1383  {
1384  if(child.getNodeName().equals("Mix") && child.getNodeType() == DOM_Node::ELEMENT_NODE)
1385  {
1386  mixId = static_cast<const DOM_Element&>(child).getAttribute("id").transcode();
1387  if(strcmp(mixId,(char*)myMixId) == 0)
1388  {
1389  bFoundMix = true;
1390  myPrevMixId = prevMixId;
1391  }
1392  else if(bFoundMix == true)
1393  {
1394  myNextMixId = mixId;
1395  break;
1396  }
1397  prevMixId = mixId;
1398  }
1399  child = child.getNextSibling();
1400  }
1401 
1402  SINT32 ret = 0;
1403  //char* c;
1404 
1405  if(myPrevMixId != NULL)
1406  {
1407  CAMsg::printMsg(LOG_INFO,"InfoService: Asking InfoService about previous mix ...\n");
1408 
1409  m_expectedMixRelPos = -1;
1410  //c = new char[8+strlen(myPrevMixId)+1];
1411  //strcpy(c,"mixinfo/");
1412  //strcat(c,myPrevMixId);
1413  ret = sendMixInfo((UINT8*)myPrevMixId);
1414  //delete[] c;
1415  if(ret != E_SUCCESS)
1416  {
1417  CAMsg::printMsg(LOG_CRIT,"InfoService: Error retrieving mix info from InfoService!\n");
1418  return ret;
1419  }
1420  }
1421 
1422  if(myNextMixId != NULL)
1423  {
1424  CAMsg::printMsg(LOG_INFO,"InfoService: Asking InfoService about next mix ...\n");
1425 
1426  m_expectedMixRelPos = 1;
1427  //c = new char[8+strlen(myNextMixId)+1];
1428  //strcpy(c,"mixinfo/");
1429  //strcat(c,myNextMixId);
1430  ret = sendMixInfo((UINT8*)myNextMixId);
1431  //delete[] c;
1432  if(ret != E_SUCCESS)
1433  {
1434  CAMsg::printMsg(LOG_CRIT,"InfoService: Error retrieving mix info from InfoService!\n");
1435  return ret;
1436  }
1437 
1438  }
1439  */
1440  return E_SUCCESS;
1441 }
1442 
1443 #ifdef PAYMENT
1444 SINT32 CAInfoService::getPaymentInstance(const UINT8* a_pstrPIID,CAXMLBI** a_pXMLBI)
1445 {
1446  SINT32 returnValue = E_UNKNOWN;
1447  SINT32 currentValue;
1448  UINT32 nrAddresses;
1449  CAListenerInterface** socketAddresses = CALibProxytest::getOptions()->getInfoServices(nrAddresses);
1450  for (UINT32 i = 0; i < nrAddresses; i++)
1451  {
1452  currentValue = getPaymentInstance(a_pstrPIID, a_pXMLBI,
1453  (CASocketAddrINet*)socketAddresses[i]->getAddr());
1454  if (currentValue == E_SUCCESS)
1455  {
1456  returnValue = currentValue;
1457  }
1458  }
1459  return returnValue;
1460 }
1461 
1462 
1471 SINT32 CAInfoService::getPaymentInstance(const UINT8* a_pstrPIID,CAXMLBI** a_pXMLBI,
1472  CASocketAddrINet* a_socketAddress)
1473 {
1474  CASocket socket;
1475  CASocketAddrINet address;
1476  UINT8 hostname[255];
1477  UINT8 request[255];
1478  CAHttpClient httpClient;
1479  UINT32 status, contentLength;
1480  *a_pXMLBI=NULL;
1481  //Connect to InfoService
1482  if(a_socketAddress->getIPAsStr(hostname, 255)!=E_SUCCESS)
1483  {
1484  socket.close();
1485  return E_UNKNOWN;
1486  }
1487 
1488  address.setAddr(hostname,a_socketAddress->getPort());
1489 
1490  if(socket.connect(address)!=E_SUCCESS)
1491  {
1492  socket.close();
1493  return E_UNKNOWN;
1494  }
1495 
1496  //#ifdef DEBUG
1497  CAMsg::printMsg(LOG_DEBUG, "CAInfoService::getPaymentInstance() - connected to InfoService %s:%d\n",hostname, a_socketAddress->getPort());
1498  //#endif
1499 
1500  //Send request
1501  httpClient.setSocket(&socket);
1502  sprintf((char*) request, "/paymentinstance/%s", (char*) a_pstrPIID);
1503  httpClient.sendGetRequest(request);
1504  httpClient.parseHTTPHeader(&contentLength, &status);
1505 #ifdef DEBUG
1506  CAMsg::printMsg(LOG_DEBUG, "CAInfoService::getPaymentInstance() - Request sent, HTTP status: %i, content length: %i\n", status, contentLength);
1507 #endif
1508  if(status!=200||contentLength>0x00FFFF)
1509  {
1510  socket.close();
1511  return E_UNKNOWN;
1512  }
1513 
1514  UINT8* content=new UINT8[contentLength+1];
1515  if(httpClient.getContent(content, &contentLength)!=E_SUCCESS)
1516  {
1517  delete []content;
1518  content = NULL;
1519  socket.close();
1520  return E_UNKNOWN;
1521  }
1522  socket.close();
1523  //Parse XML
1524  XERCES_CPP_NAMESPACE::DOMDocument* doc = parseDOMDocument(content,contentLength);
1525  delete []content;
1526  content = NULL;
1527  if(doc==NULL)
1528  {
1529  return E_UNKNOWN;
1530  }
1531  DOMElement* elemRoot=doc->getDocumentElement();
1532 
1533  *a_pXMLBI = CAXMLBI::getInstance(elemRoot);
1534  CAMsg::printMsg(LOG_DEBUG, "CAInfoService::getPaymentInstance(): XML doc not needed anymore\n");
1535  if (*a_pXMLBI != NULL)
1536  {
1537  return E_SUCCESS;
1538  }
1539  else
1540  {
1541  return E_UNKNOWN;
1542  }
1543 }
1544 #endif
1545 #endif //ONLY_LOCAL_PROXY
#define OPTIONS_ATTRIBUTE_TNC_ID
#define OPTIONS_ATTRIBUTE_TNC_VERSION
#define OPTIONS_ATTRIBUTE_TNC_SERIAL
#define OPTIONS_ATTRIBUTE_TNC_DATE
#define OPTIONS_ATTRIBUTE_TNC_LOCALE
#define OPTIONS_NODE_TNCS_TRANSLATION
const char * STRINGS_REQUEST_TYPES[NR_REQUEST_TYPES]
const char * STRINGS_REQUEST_COMMANDS[NR_REQUEST_COMMANDS]
#define XML_MIX_CASCADE_STATUS
#define REQUEST_TYPE_POST
#define NR_REQUEST_TYPES
#define REQUEST_COMMAND_MIXINFO
#define LOCALE_DEFAULT
#define NR_REQUEST_COMMANDS
#define REQUEST_COMMAND_CONFIGURE
#define REQUEST_TYPE_GET
#define REQUEST_COMMAND_STATUS
#define REQUEST_COMMAND_HELO
#define ATTRIBUTE_SERIAL
#define REQUEST_COMMAND_CASCADE
#define INIT_STACK
Definition: CAThread.hpp:48
#define BEGIN_STACK(methodName)
Definition: CAThread.hpp:49
#define FINISH_STACK(methodName)
Definition: CAThread.hpp:50
SINT32 setDOMElementAttribute(DOMNode *pElem, const char *attrName, const char *value)
Definition: CAUtil.cpp:831
SINT32 getcurrentTimeMillis(UINT64 &u64Time)
Gets the current Systemtime in milli seconds.
Definition: CAUtil.cpp:252
SINT32 setDOMElementValue(DOMElement *pElem, SINT32 value)
Definition: CAUtil.cpp:939
SINT32 setCurrentTimeMilliesAsDOMAttribute(DOMNode *pElem)
Definition: CAUtil.cpp:848
SINT32 sSleep(UINT32 sec)
Sleeps sec Seconds.
Definition: CAUtil.cpp:425
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
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 getDOMChildByName(const DOMNode *pNode, const char *const name, DOMElement *&child, bool deep)
Definition: CAUtil.cpp:458
SINT32 getDOMElementAttribute(const DOMNode *const elem, const char *attrName, UINT8 *value, UINT32 *len)
Definition: CAUtil.cpp:780
UINT32 diff64(const UINT64 &bigop, const UINT64 &smallop)
Definition: CAUtil.hpp:398
UINT32 div64(UINT64 &op1, UINT32 op2)
Definition: CAUtil.hpp:407
void print64(UINT8 *buff, UINT64 num)
Definition: CAUtil.hpp:482
void set64(UINT64 &op1, UINT32 op2)
Definition: CAUtil.hpp:321
#define TMP_BUFF_SIZE
Definition: CAUtil.hpp:38
#define GET_NET_ERROR
Definition: StdAfx.h:469
#define GET_NET_ERROR_STR(x)
Definition: StdAfx.h:471
#define THREAD_RETURN
Definition: StdAfx.h:540
#define THREAD_RETURN_SUCCESS
Definition: StdAfx.h:542
#define MIX_TO_INFOSERVICE_TIMEOUT
Definition: StdAfx.h:201
#define min(a, b)
Definition: StdAfx.h:649
signed int SINT32
Definition: basetypedefs.h:132
unsigned char UINT8
Definition: basetypedefs.h:135
unsigned int UINT32
Definition: basetypedefs.h:131
SINT32 getMixId(UINT8 *id, UINT32 len)
DOMElement * getTermsAndConditions()
SINT32 getOperatorSubjectKeyIdentifier(UINT8 *buffer, UINT32 *length)
Returns a COPY of the public test certifcate for that mix.
CAListenerInterface ** getInfoServices(UINT32 &r_size)
SINT32 signal()
Signals this object.
SINT32 wait()
Waits for a signal or for a timeout.
Very simple http client.
SINT32 sendGetRequest(const UINT8 *url)
Sends a HTTP GET request to the server.
SINT32 getContent(UINT8 *a_pContent, UINT32 *a_pLength)
Retruns the content of the response.
SINT32 parseHTTPHeader(UINT32 *contentLength, UINT32 *statusCode=NULL, UINT32 msTimeOut=3000)
receives the HTTP header and parses the content length
SINT32 setSocket(CASocket *pSocket)
CAThread * m_pthreadRunLoop
CAConditionVariable * m_pLoopCV
SINT32 getPaymentInstance(const UINT8 *a_pstrPIID, CAXMLBI **pXMLBI, CASocketAddrINet *a_socketAddress)
Gets a payment instance from the InfoService.
SINT32 sendHelo(UINT8 *a_strXML, UINT32 a_len, THREAD_RETURN(*a_thread)(void *), UINT8 *a_strThreadName, SINT32 requestCommand, const UINT8 *param=NULL)
SINT32 setMultiSignature(CAMultiSignature *pMultiSignature)
UINT8 * getMixHeloXMLAsString(UINT32 &len)
static const UINT32 REPEAT_ON_STATUS_SENT_ERROR
static THREAD_RETURN TCascadeStatus(void *p)
bool isConfiguring()
SINT32 getMixedPackets(UINT64 &ppackets)
SINT32 sendStatus(bool bIncludeCerts)
static const UINT64 SEND_STATUS_INFO_WAIT
CAMultiSignature * m_pMultiSignature
SINT32 sendMixHelo(SINT32 requestCommand=-1, const UINT8 *param=NULL)
SINT32 m_expectedMixRelPos
volatile bool m_bRun
static const UINT64 SEND_MIX_INFO_WAIT
SINT32 sendCascadeHelo()
static const UINT64 SEND_LOOP_SLEEP
UINT8 * getStatusXMLAsString(bool bIncludeCerts, UINT32 &len)
UINT64 m_lastMixedPackets
static const UINT32 SEND_INFO_TIMEOUT_MS
UINT8 ** getOperatorTnCsAsStrings(UINT32 **lengths, UINT32 *nrOfTnCs)
POSTs the MIXINFO message for a mix to the InfoService.
static const UINT64 MINUTE
SINT32 sendOperatorTnCData()
SINT32 getLevel(SINT32 *puser, SINT32 *prisk, SINT32 *ptraffic)
static THREAD_RETURN TCascadeHelo(void *p)
UINT8 * xmlDocToStringWithSignature(DOMNode *a_node, UINT32 &a_len, bool bIncludeCerts)
UINT8 * getCascadeHeloXMLAsString(UINT32 &len)
static THREAD_RETURN TMixHelo(void *p)
static const UINT64 SEND_CASCADE_INFO_WAIT
SINT32 handleConfigEvent(XERCES_CPP_NAMESPACE::DOMDocument *doc) const
static THREAD_RETURN InfoLoop(void *p)
static CACmdLnOptions * getOptions()
Definition: CAMix.hpp:49
bool isConnected()
Definition: CAMix.hpp:130
UINT32 getLastConnectionTime()
Definition: CAMix.hpp:125
SINT32 getMixCascadeInfo(XERCES_CPP_NAMESPACE::DOMDocument *&docMixCascadeInfo)
Returns the Mix-Cascade info which should be send to the InfoService.
Definition: CAMix.hpp:96
static SINT32 printMsg(UINT32 typ, const char *format,...)
Writes a given message to the log.
Definition: CAMsg.cpp:251
SINT32 signXML(DOMNode *a_node, bool appendCerts)
SINT32 unlock()
Definition: CAMutex.hpp:52
SINT32 lock()
Definition: CAMutex.hpp:41
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 getIPAsStr(UINT8 *buff, UINT32 len) const
Returns the IP-Number as an address string (doted-format).
UINT16 getPort() const
Returns the port value of the address.
virtual SINT32 setRecvBuff(UINT32 r)
Definition: CASocket.cpp:846
virtual SINT32 receiveFullyT(UINT8 *buff, UINT32 len, UINT32 msTimeOut)
Trys to receive all bytes.
Definition: CASocket.cpp:677
virtual SINT32 sendFullyTimeOut(const UINT8 *buff, UINT32 len, UINT32 msTimeOut, UINT32 msTimeOutSingleSend)
Sends all data over the network.
Definition: CASocket.cpp:488
virtual SINT32 close()
Definition: CASocket.cpp:351
virtual SINT32 connect(const CASocketAddr &psa)
Definition: CASocket.hpp:64
SINT32 start(void *param, bool bDaemon=false, bool bSilent=false)
Starts the execution of the main function of this thread.
Definition: CAThread.cpp:115
SINT32 setMainLoop(THREAD_MAIN_TYP fnc)
Sets the main function which will be executed within this thread.
Definition: CAThread.hpp:148
SINT32 join()
Waits for the main function to finish execution.
Definition: CAThread.cpp:187
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
CAMix * pMix
Definition: proxytest.cpp:75
UINT16 len
Definition: typedefs.hpp:0