Mixe for Privacy and Anonymity in the Internet
CAInfoService.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000, The JAP-Team
00003 All rights reserved.
00004 Redistribution and use in source and binary forms, with or without modification,
00005 are permitted provided that the following conditions are met:
00006 
00007   - Redistributions of source code must retain the above copyright notice,
00008     this list of conditions and the following disclaimer.
00009 
00010   - Redistributions in binary form must reproduce the above copyright notice,
00011     this list of conditions and the following disclaimer in the documentation and/or
00012     other materials provided with the distribution.
00013 
00014   - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors
00015     may be used to endorse or promote products derived from this software without specific
00016     prior written permission.
00017 
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
00020 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00021 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
00022 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00025 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00027 */
00028 #include "StdAfx.h"
00029 #ifndef ONLY_LOCAL_PROXY
00030 #include "CAInfoService.hpp"
00031 #include "CASocket.hpp"
00032 #include "CACmdLnOptions.hpp"
00033 #include "CAMsg.hpp"
00034 #include "CASocketAddrINet.hpp"
00035 #include "CAUtil.hpp"
00036 #include "xml/DOM_Output.hpp"
00037 #include "CASingleSocketGroup.hpp"
00038 #include "CALastMix.hpp"
00039 #include "CAHttpClient.hpp"
00040 #include "CACertificate.hpp"
00041 #include "CAXMLBI.hpp"
00042 #include "CALibProxytest.hpp"
00043 #include "CADynamicCascadeConfigurator.hpp"
00044 
00045 const char * STRINGS_REQUEST_TYPES[NR_REQUEST_TYPES]={"POST","GET"};
00046 const char * STRINGS_REQUEST_COMMANDS[NR_REQUEST_COMMANDS]={"configure","helo","mixinfo/", "dynacascade", "cascade", "feedback", "tc"};
00047 
00048 const UINT64 CAInfoService::MINUTE = 60;
00049 const UINT64 CAInfoService::SEND_LOOP_SLEEP = 60;
00050 const UINT64 CAInfoService::SEND_CASCADE_INFO_WAIT = MINUTE * 10;
00051 const UINT64 CAInfoService::SEND_MIX_INFO_WAIT = MINUTE * 10;
00052 const UINT64 CAInfoService::SEND_STATUS_INFO_WAIT = MINUTE;
00053 const UINT32 CAInfoService::SEND_INFO_TIMEOUT_MS = 3000; // timeout for single send operations
00054 const UINT32 CAInfoService::REPEAT_ON_STATUS_SENT_ERROR = 3;
00055 
00056 THREAD_RETURN CAInfoService::InfoLoop(void *p)
00057   {
00058     INIT_STACK;
00059     BEGIN_STACK("CAInfoService::InfoLoop");
00060 
00061     CAMsg::printMsg(LOG_DEBUG, "CAInfoService - InfoLoop() started\n");
00062     CAMsg::printMsg(LOG_DEBUG, "CAInfoService - InfoLoop() PID: %i\n",getpid());
00063     CAInfoService* pInfoService=(CAInfoService*)p;
00064     bool bIsFirst=true; //send our own certifcate only the first time
00065     bool bOneUpdateDone = false;
00066 
00067     UINT32 currentTime;
00068     UINT32 lastCascadeUpdate;
00069     UINT32 lastStatusUpdate;
00070     UINT32 lastMixInfoUpdate;
00071     UINT32 nextUpdate;
00072 #ifdef DYNAMIC_MIX
00073     UINT32 loops = 4;
00074     UINT32 interval = 0;
00075 #endif
00076     lastCascadeUpdate=lastMixInfoUpdate=lastStatusUpdate=(UINT32)time(NULL);
00077     // tell the algorithm it is time to update
00078     lastCascadeUpdate -= CAInfoService::SEND_CASCADE_INFO_WAIT;
00079     lastMixInfoUpdate -= CAInfoService::SEND_MIX_INFO_WAIT;
00080     lastStatusUpdate -= CAInfoService::SEND_STATUS_INFO_WAIT;
00081     UINT32 statusSentErrorBurst = 0;
00082 
00083     pInfoService->m_pLoopCV->lock();
00084     pInfoService->m_pLoopCV->wait(CAInfoService::SEND_LOOP_SLEEP * 1000);
00085     pInfoService->m_pLoopCV->unlock();
00086 
00087     while(pInfoService->isRunning())
00088     {
00089 #ifdef DYNAMIC_MIX
00090 
00091       if(loops < 4)
00092       {
00093         sSleep(interval);
00094         loops++;
00095         continue;
00096       }
00097 #endif
00098   // 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...
00099 
00100       currentTime=time(NULL);
00101       if (currentTime >= (lastStatusUpdate + CAInfoService::SEND_STATUS_INFO_WAIT))
00102       {
00103         if(pInfoService->m_pMix->isConnected() && pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2)) && 
00104           pInfoService->sendStatus(bIsFirst)==E_SUCCESS)
00105         {
00106           lastStatusUpdate=time(NULL);
00107           bIsFirst=false;
00108           bOneUpdateDone = true;
00109           statusSentErrorBurst = 0;
00110           //CAMsg::printMsg(LOG_DEBUG,"InfoService: Successfully sent Status information.\n");
00111         }
00112         else if (pInfoService->m_pMix->isConnected() && pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2)))
00113         {
00114           statusSentErrorBurst++;
00115           CAMsg::printMsg(LOG_WARNING,"InfoService: Could not send Status information.\n");
00116         }
00117         /* send terms and conditions */
00118         //pInfoService->sendOperatorTnCData();
00119       }
00120 
00121       // check every minute if configuring, every 10 minutes otherwise
00122       currentTime=time(NULL);
00123       if (currentTime >= (lastCascadeUpdate + CAInfoService::SEND_CASCADE_INFO_WAIT) || pInfoService->isConfiguring())
00124       {
00125         if (CALibProxytest::getOptions()->isFirstMix() || (CALibProxytest::getOptions()->isLastMix() && pInfoService->isConfiguring()))
00126         {
00127           if(pInfoService->m_pMix->isConnected() && pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2)) 
00128             && pInfoService->sendCascadeHelo() == E_SUCCESS)
00129           {
00130             lastCascadeUpdate=time(NULL);
00131             bOneUpdateDone = true;
00132             CAMsg::printMsg(LOG_INFO,"InfoService: Successfully sent Cascade information.\n");
00133           }
00134           else if (pInfoService->m_pMix->isConnected() && pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2)))
00135           {
00136             CAMsg::printMsg(LOG_WARNING,"InfoService: Could not send Cascade information.\n");
00137           }
00138         }
00139         currentTime=time(NULL);
00140         if ((currentTime >= (lastMixInfoUpdate + CAInfoService::SEND_MIX_INFO_WAIT) &&
00141           pInfoService->m_pMix->getLastConnectionTime() < (currentTime - (SEND_LOOP_SLEEP / 2))) || pInfoService->isConfiguring())
00142         {
00143           if (pInfoService->sendMixHelo() != E_SUCCESS)
00144           {
00145             CAMsg::printMsg(LOG_WARNING,"InfoService: Could not send MixInfo information.\n");
00146           }
00147           else
00148           {
00149             lastMixInfoUpdate=time(NULL);
00150             bOneUpdateDone = true;
00151             CAMsg::printMsg(LOG_INFO,"InfoService: Successfully sent MixInfo information.\n");
00152           }
00153         }
00154       }
00155 #ifdef DYNAMIC_MIX
00156       // LERNGRUPPE
00157       // Check regulary for new cascade information
00163       if( CALibProxytest::getOptions()->isDynamic() )
00164       {
00165         pInfoService->dynamicCascadeConfiguration();
00166       }
00167 #endif
00168       currentTime=time(NULL);
00169       //@TODO BUGGy -- because it assumes knowledge about update times, which are configurable in StdAfx.hpp
00170       // wait CAInfoService::SEND_LOOP_SLEEP seconds at most
00171       /*temp = (currentTime - lastStatusUpdate);
00172       if (bOneUpdateDone && temp > 0)
00173       {
00174           if (temp <= CAInfoService::SEND_LOOP_SLEEP)
00175           {
00176             bPreventLoop = false;
00177             nextUpdate = CAInfoService::SEND_LOOP_SLEEP - temp;
00178           }
00179           else if (bPreventLoop)
00180           {
00181             // prevent infinite loops
00182             bPreventLoop = false;
00183             nextUpdate = CAInfoService::SEND_LOOP_SLEEP;
00184           }
00185           else
00186           {
00187             bPreventLoop = true;
00188             nextUpdate = 0;
00189           }
00190       }
00191       else
00192       {
00193         bPreventLoop = false;
00194         nextUpdate = CAInfoService::SEND_LOOP_SLEEP;
00195       }*/
00196 
00197       /* Not the optimal solution; would be best, if infoservice send
00198        * routines can be called by other threads if certain events occur, i.e.
00199        * cascade reconnection, etc.
00200        */
00201       if ( bOneUpdateDone && (statusSentErrorBurst > 0) )
00202       {
00203         //TODO: handle case when status sent error burst exceeds an upper limit */
00204         nextUpdate = CAInfoService::REPEAT_ON_STATUS_SENT_ERROR;
00205       }
00206       else
00207       {
00208         nextUpdate = CAInfoService::SEND_LOOP_SLEEP;
00209       }
00210 #ifdef DYNAMIC_MIX
00211       interval = nextUpdate / 4;
00212       CAMsg::printMsg(LOG_DEBUG,"InfoService: Next update in %i seconds...interval %i\n", nextUpdate, interval);
00213       loops = 0;
00214 #else
00215       if(nextUpdate > 20)
00216       {
00217         CAMsg::printMsg(LOG_DEBUG,"InfoService: Next update in %i seconds...\n", nextUpdate);
00218       }
00219       /* We can interrupt this thread if the mix is shutting down */
00220       pInfoService->m_pLoopCV->lock();
00221       pInfoService->m_pLoopCV->wait(nextUpdate * 1000);
00222       pInfoService->m_pLoopCV->unlock();
00223 
00224       //sSleep(nextUpdate);
00225 #endif
00226     }
00227     CAMsg::printMsg(LOG_DEBUG, "CAInfoService - InfoLoop() exited\n");
00228     FINISH_STACK("CAInfoService::InfoLoop");
00229     THREAD_RETURN_SUCCESS;
00230   }
00231 
00232 
00233 struct CAInfoService::InfoServiceHeloMsg
00234 {
00235   UINT8* strXML;
00236   UINT32 len;
00237   CASocketAddrINet* addr;
00238   CAInfoService* is;
00239   SINT32 requestCommand;
00240   const UINT8* param;
00241   SINT32 retVal;
00242 };
00243 
00244 THREAD_RETURN CAInfoService::TCascadeHelo(void *p)
00245 {
00246   INIT_STACK;
00247   BEGIN_STACK("CAInfoService::TCascadeHelo");
00248 
00249   InfoServiceHeloMsg* message = (InfoServiceHeloMsg*)p;
00250   message->retVal = message->is->sendCascadeHelo(message->strXML, message->len, message->addr);
00251   FINISH_STACK("CAInfoService::TCascadeHelo");
00252   THREAD_RETURN_SUCCESS;
00253 }
00254 
00255 THREAD_RETURN CAInfoService::TCascadeStatus(void *p)
00256 {
00257   INIT_STACK;
00258   BEGIN_STACK("CAInfoService::TCascadeStatus");
00259 
00260   InfoServiceHeloMsg* message = (InfoServiceHeloMsg*)p;
00261   message->retVal = message->is->sendStatus(message->strXML, message->len, message->addr);
00262 
00263   FINISH_STACK("CAInfoService::TCascadeStatus");
00264   THREAD_RETURN_SUCCESS;
00265 }
00266 
00267 THREAD_RETURN CAInfoService::TMixHelo(void *p)
00268 {
00269   INIT_STACK;
00270   BEGIN_STACK("CAInfoService::TMixHelo");
00271 
00272   InfoServiceHeloMsg* message = (InfoServiceHeloMsg*)p;
00273   message->retVal = message->is->sendMixHelo(message->strXML, message->len, message->requestCommand, message->param, message->addr);
00274 
00275   FINISH_STACK("CAInfoService::TMixHelo");
00276   THREAD_RETURN_SUCCESS;
00277 }
00278 
00279 
00280 
00281 #ifdef DYNAMIC_MIX
00282 
00283 bool CAInfoService::newCascadeAvailable()
00284 {
00285   CASocket socket;
00286   CASocketAddrINet *address = NULL;
00287   CAHttpClient httpClient;
00288   bool ret = false;
00289 
00290   UINT32 status, contentLength;
00291   UINT8 buff[255];
00292   UINT8 bufMixId[60];
00293   UINT32 mixIdLen = 60;
00294   CALibProxytest::getOptions()->getMixId( bufMixId, mixIdLen );
00295   sprintf((char*)buff, "/newcascadeinformationavailable/%s",bufMixId );
00296   if( CALibProxytest::getOptions()->getRandomInfoService(address) != E_SUCCESS)
00297   {
00298     CAMsg::printMsg( LOG_ERR, "Unable to get a random InfoService - This will cause problems! Check your configuration!\n");
00299     return false;
00300   }
00301   if(socket.connect(*address)!=E_SUCCESS)
00302   {
00303     goto EXIT;
00304   }
00305   //Send request
00306   httpClient.setSocket(&socket);
00307   httpClient.sendGetRequest(buff);
00308   httpClient.parseHTTPHeader(&contentLength, &status);
00309   if(status!=200)
00310   {
00311     socket.close();
00312     ret = false;
00313     goto EXIT;
00314   }
00315   ret = true;
00316 EXIT:
00317   delete address;
00318   address = NULL;
00319   return ret;
00320 }
00321 
00329 SINT32 CAInfoService::dynamicCascadeConfiguration()
00330 {
00331   SINT32 ret = E_UNKNOWN;
00332   CADynamicCascadeConfigurator *configurator = NULL;
00333 
00334   if(!newCascadeAvailable())
00335     return E_SUCCESS;
00336 
00338   if(m_bReconfig) return E_SUCCESS;
00339   CAMsg::printMsg( LOG_DEBUG, "Starting dynamic reconfiguration...\n");
00340   m_bReconfig = true;
00341 
00342   configurator = new CADynamicCascadeConfigurator( m_pSignature, m_pMix );
00343   ret = configurator->configure();
00345   if(ret != E_SUCCESS)
00346   {
00347     CALibProxytest::getOptions()->resetNextMix();
00348     CALibProxytest::getOptions()->resetPrevMix();
00349     CALibProxytest::getOptions()->setCascadeProposal(NULL, 0);
00350     m_pMix->dynaReconfigure(false);
00351   }
00352   m_bReconfig = false;
00353   delete configurator;
00354   configurator = NULL;
00355 
00356   return ret;
00357 }
00358 #endif
00359 
00360 CAInfoService::CAInfoService()
00361 {
00362     m_pMix=NULL;
00363     m_bRun=false;
00364     //m_pSignature=NULL;
00365     m_pMultiSignature=NULL;
00366     m_minuts=0;
00367     m_lastMixedPackets=0;
00368     m_expectedMixRelPos = 0;
00369       m_pLoopCV = new CAConditionVariable();
00370     m_pthreadRunLoop=new CAThread((UINT8*)"InfoServiceThread");
00371 #ifdef DYNAMIC_MIX
00372     m_bReconfig = false;
00373 #endif
00374 }
00375 
00376 CAInfoService::CAInfoService(CAMix* pMix)
00377   {
00378     m_pMix=NULL;
00379     m_bRun=false;
00380     //m_pSignature=NULL;
00381     m_pMultiSignature=NULL;
00382     m_minuts=0;
00383     m_lastMixedPackets=0;
00384     m_expectedMixRelPos = 0;
00385     m_pLoopCV = new CAConditionVariable();
00386     m_pthreadRunLoop=new CAThread((UINT8*)"InfoServiceThread");
00387     m_pMix=pMix;
00388 #ifdef DYNAMIC_MIX
00389     m_bReconfig = false;
00390 #endif
00391   }
00392 
00393 CAInfoService::~CAInfoService()
00394   {
00395     stop();
00396     delete m_pLoopCV;
00397     m_pLoopCV = NULL;
00398     delete m_pthreadRunLoop;
00399     m_pthreadRunLoop = NULL;
00400   }
00401 
00402 
00403 SINT32 CAInfoService::setMultiSignature(CAMultiSignature* pMultiSig)
00404 {
00405   m_pMultiSignature = pMultiSig;
00406   return E_SUCCESS;
00407 }
00408 
00409 SINT32 CAInfoService::getLevel(SINT32* puser,SINT32* prisk,SINT32* ptraffic)
00410 {
00411     if(m_pMix!=NULL && CALibProxytest::getOptions()->isFirstMix())
00412         return ((CAFirstMix*)m_pMix)->getLevel(puser,prisk,ptraffic);
00413     return E_UNKNOWN;
00414 }
00415 
00416 SINT32 CAInfoService::getMixedPackets(UINT64& ppackets)
00417   {
00418     if(m_pMix!=NULL && CALibProxytest::getOptions()->isFirstMix())
00419       return ((CAFirstMix*)m_pMix)->getMixedPackets(ppackets);
00420     return E_UNKNOWN;
00421   }
00422 
00423 SINT32 CAInfoService::start()
00424   {
00425     if(m_pMultiSignature==NULL)
00426     {
00427       return E_UNKNOWN;
00428     }
00429     m_bRun=true;
00430     set64(m_lastMixedPackets,(UINT32)0);
00431     m_minuts=1;
00432     m_pthreadRunLoop->setMainLoop(InfoLoop);
00433     #ifdef DEBUG
00434       CAMsg::printMsg(LOG_DEBUG, "CAInfoService::start() - starting InfoService thread\n");
00435     #endif
00436 
00437     return m_pthreadRunLoop->start(this);
00438   }
00439 
00440 
00441 SINT32 CAInfoService::signal()
00442 {
00443   m_pLoopCV->lock();
00444   m_pLoopCV->signal();
00445   m_pLoopCV->unlock();
00446   return E_SUCCESS;
00447 }
00448 
00449 SINT32 CAInfoService::stop()
00450   {
00451     if(m_bRun)
00452       {
00453         m_bRun=false;
00454         /* Interrupt this thread */
00455         m_pLoopCV->lock();
00456         m_pLoopCV->signal();
00457         m_pLoopCV->unlock();
00458 
00459         m_pthreadRunLoop->join();
00460       }
00461     return E_SUCCESS;
00462   }
00463 
00464 SINT32 CAInfoService::sendStatus(bool bIncludeCerts)
00465 {
00466   if(!CALibProxytest::getOptions()->isFirstMix())
00467   {
00468     return E_SUCCESS;
00469   }
00470 
00471 
00472   if( !(m_pMix->isConnected())) // && !bIncludeCerts )
00473   {
00474 #ifdef DEBUG
00475     CAMsg::printMsg(LOG_INFO, "Mix not connected. Skipping status.\n");
00476 #endif
00477     return E_UNKNOWN;
00478   }
00479 
00480   UINT32 len=0;
00481   SINT32 ret=E_UNKNOWN;
00482   UINT8* strStatusXML=getStatusXMLAsString(bIncludeCerts,len);
00483 
00484   if(strStatusXML==NULL)
00485   {
00486     return E_UNKNOWN;
00487   }
00488 
00489   if( !(m_pMix->isConnected()))
00490   {
00491     CAMsg::printMsg(LOG_INFO, "Mix not connected. Skip sending already created status message.\n");
00492   }
00493   else
00494   {
00495     ret = sendHelo(strStatusXML, len, TCascadeStatus, (UINT8*)"Status Thread", REQUEST_COMMAND_STATUS);
00496   }
00497 
00498   delete[] strStatusXML;
00499   strStatusXML = NULL;
00500   return ret;
00501 }
00502 
00503 
00504 
00505 UINT8* CAInfoService::getStatusXMLAsString(bool bIncludeCerts,UINT32& len)
00506   {
00507     SINT32 tmpUser,tmpRisk,tmpTraffic;
00508     UINT64 tmpPackets;
00509 
00510     //httpClient.setSocket(&oSocket);
00511     UINT8 strMixId[255];
00512     CALibProxytest::getOptions()->getMixId(strMixId,255);
00513 
00514     tmpUser=tmpTraffic=tmpRisk=-1;
00515     set64(tmpPackets,(UINT32)-1);
00516     getLevel(&tmpUser,&tmpRisk,&tmpTraffic);
00517     SINT32 ret=getMixedPackets(tmpPackets);
00518     if(ret==E_SUCCESS)
00519       {
00520         UINT32 avgTraffic=div64(tmpPackets,m_minuts);
00521         UINT32 diffTraffic=diff64(tmpPackets,m_lastMixedPackets);
00522         if(avgTraffic==0)
00523           {
00524             if(diffTraffic==0)
00525               tmpTraffic=0;
00526             else
00527               tmpTraffic=100;
00528           }
00529         else
00530           {
00531             double dTmp=(double)diffTraffic/(double)avgTraffic;
00532             tmpTraffic=min(SINT32(50.*dTmp),100);
00533           }
00534         set64(m_lastMixedPackets,tmpPackets);
00535       }
00536     m_minuts++;
00537 //let the attributes in alphabetical order..
00538 #define XML_MIX_CASCADE_STATUS "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
00539 <MixCascadeStatus LastUpdate=\"%s\" currentRisk=\"%i\" id=\"%s\" mixedPackets=\"%s\" nrOfActiveUsers=\"%i\" trafficSituation=\"%i\"\
00540 ></MixCascadeStatus>"
00541 
00542     UINT32 buffLen=8192;
00543     UINT8* buff=new UINT8[buffLen];
00544     memset(buff, 0, buffLen);
00545     UINT8 tmpBuff[1024];
00546     UINT8 buffMixedPackets[50];
00547     print64(buffMixedPackets,tmpPackets);
00548     UINT64 currentMillis;
00549     UINT8 tmpStrCurrentMillis[50];
00550     if(getcurrentTimeMillis(currentMillis)==E_SUCCESS)
00551       print64(tmpStrCurrentMillis,currentMillis);
00552     else
00553       tmpStrCurrentMillis[0]=0;
00554     sprintf((char*)tmpBuff,XML_MIX_CASCADE_STATUS,tmpStrCurrentMillis,tmpRisk,strMixId,buffMixedPackets,tmpUser,tmpTraffic);
00555 
00556 
00557     if(m_pMultiSignature->signXML(tmpBuff, strlen((char*)tmpBuff), buff, &buffLen, bIncludeCerts) != E_SUCCESS)
00558     {
00559       delete[] buff;
00560       buff = NULL;
00561     }
00562     else
00563     {
00564       len=buffLen;
00565     }
00566     return buff;
00567   }
00568 
00569 
00575 
00576 SINT32 CAInfoService::sendStatus(const UINT8* a_strStatusXML,UINT32 a_len, const CASocketAddrINet* a_pSocketAddress) const
00577   {
00578     UINT8 buffHeader[512];
00579     SINT32 ret = E_UNKNOWN;
00580     UINT8 hostname[255];
00581     UINT32 currentTimeout = MIX_TO_INFOSERVICE_TIMEOUT;
00582     UINT64 startupTime, currentMillis;
00583 
00584 
00585     #ifdef DEBUG
00586       CAMsg::printMsg(LOG_DEBUG, "CAInfoService::sendStatus()\n");
00587     #endif
00588     if(!CALibProxytest::getOptions()->isFirstMix())
00589     {
00590       return E_SUCCESS;
00591     }
00592     CASocket oSocket(true);
00593     if (a_pSocketAddress == NULL)
00594     {
00595       oSocket.close();
00596       return E_UNKNOWN;
00597     }
00598 
00599     
00600     if(oSocket.connect(*a_pSocketAddress, MIX_TO_INFOSERVICE_TIMEOUT)!=E_SUCCESS)
00601     {
00602       if(a_pSocketAddress->getIPAsStr(hostname, 255) == E_SUCCESS)
00603       {
00604         CAMsg::printMsg(LOG_DEBUG, "InfoService: Could not connect to InfoService %s:%d. Reason: %s (%i)\n", 
00605           hostname, a_pSocketAddress->getPort(), GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
00606       }
00607       else
00608       {
00609         CAMsg::printMsg(LOG_DEBUG, "InfoService: Could not connect to InfoService (host unknown) at port %d. Reason: %s (%i)\n", 
00610           a_pSocketAddress->getPort(), GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
00611       }
00612       oSocket.close();
00613       return E_UNKNOWN;
00614     }
00615 
00616     if(a_pSocketAddress->getIPAsStr(hostname, 255) == E_SUCCESS)
00617     {
00618       CAMsg::printMsg(LOG_DEBUG, "InfoService: Sending current status to InfoService %s:%d.\n", hostname, a_pSocketAddress->getPort());
00619       sprintf((char*)buffHeader,"POST /feedback HTTP/1.0\r\nContent-Length: %u\r\n\r\n",a_len);
00620 
00621       getcurrentTimeMillis(startupTime);
00622       oSocket.sendFullyTimeOut(buffHeader,strlen((char*)buffHeader), currentTimeout, SEND_INFO_TIMEOUT_MS);
00623 
00624       getcurrentTimeMillis(currentMillis);
00625       currentTimeout -= (currentMillis - startupTime);
00626       ret=oSocket.sendFullyTimeOut(a_strStatusXML, a_len, currentTimeout, SEND_INFO_TIMEOUT_MS);
00627     }
00628 
00629     oSocket.close();
00630     if(ret==E_SUCCESS)
00631     {
00632       return E_SUCCESS;
00633     }
00634     CAMsg::printMsg(LOG_DEBUG, "InfoService: Sending status failed, ret: %d \n", ret);
00635     return E_UNKNOWN;
00636   }
00637 
00638 
00639 SINT32 CAInfoService::sendOperatorTnCData()
00640 {
00641   /*SINT32 ret = E_SUCCESS;
00642   UINT32 *lengths_ptr = NULL;
00643   XMLSize_t nrOfTnCs = 0;
00644   UINT32 i = 0;
00645   UINT8 **tncData = getOperatorTnCsAsStrings(&lengths_ptr, &nrOfTnCs);
00646 
00647   if(tncData != NULL)
00648   {
00649     for (;i < nrOfTnCs; i++)
00650     {
00651 #ifdef DEBUG
00652       CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixTnCData(), object: %s, len: %u\n",
00653           tncData[i], lengths_ptr[i]);
00654 #endif
00655       if( tncData[i] != NULL )
00656       {
00657         ret |= sendHelo(tncData[i], lengths_ptr[i],
00658             TMixHelo, (UINT8*)"Mix TnC Thread",
00659             REQUEST_COMMAND_TNC_DATA, NULL);
00660         delete [] tncData[i];
00661         tncData[i] = NULL;
00662       }
00663       else
00664       {
00665         CAMsg::printMsg(LOG_ERR,"InfoService:sendMixTnCData() -- Element %u is invalid!\n", (i+1) );
00666         ret |= E_UNKNOWN;
00667       }
00668 
00669     }
00670     delete [] lengths_ptr;
00671     lengths_ptr = NULL;
00672 
00673     delete [] tncData;
00674   }
00675   else
00676   {
00677     CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixTnCData() -- No TnC data specified!\n");
00678     return E_SUCCESS;
00679   }
00680   return ret;*/
00681   return E_SUCCESS;
00682 }
00683 
00686 /*SINT32 CAInfoService::sendMixInfo(const UINT8* pMixID)
00687 {
00688   return sendMixHelo(REQUEST_COMMAND_MIXINFO,pMixID, NULL);
00689 }
00690 */
00691 SINT32 CAInfoService::sendMixHelo(SINT32 requestCommand,const UINT8* param)
00692 {
00693   UINT32 len;
00694   SINT32 ret;
00695   UINT8* strMixHeloXML=getMixHeloXMLAsString(len);
00696 
00697   if(strMixHeloXML==NULL)
00698   {
00699     CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixHelo() -- Error: getMixHeloXMLAsString() returned NULL!\n");
00700     return E_UNKNOWN;
00701   }
00702 
00703   // CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixHelo(): Initialising helo thread...\n");
00704   ret = sendHelo(strMixHeloXML, len, TMixHelo, (UINT8*)"Mix Helo Thread", requestCommand, param);
00705   // CAMsg::printMsg(LOG_DEBUG,"InfoService:sendMixHelo(): Finished helo thread!\n");
00706 
00707   delete[] strMixHeloXML;
00708   strMixHeloXML = NULL;
00709   return ret;
00710 }
00711 
00722 UINT8 **CAInfoService::getOperatorTnCsAsStrings(UINT32 **lengths, XMLSize_t *nrOfTnCs)
00723 {
00724 
00725   XERCES_CPP_NAMESPACE::DOMElement *tnCs = CALibProxytest::getOptions()->getTermsAndConditions();
00726   if(tnCs == NULL)
00727   {
00728     return NULL;
00729   }
00730 
00731   XERCES_CPP_NAMESPACE::DOMNodeList *docTnCsList =
00732     getElementsByTagName(tnCs, OPTIONS_NODE_TNCS_TRANSLATION);
00733 
00734   if(docTnCsList == NULL)
00735   {
00736     return NULL;
00737   }
00738 
00739   UINT8 **elementList = NULL;
00740   DOMNode *iterator = NULL;
00741   XMLSize_t i = 0;
00742 
00743   UINT8 tmpOpSKIBuff[TMP_BUFF_SIZE];
00744   UINT32 tmpOpSKILen = TMP_BUFF_SIZE;
00745 
00746   CALibProxytest::getOptions()->getOperatorSubjectKeyIdentifier(tmpOpSKIBuff, &tmpOpSKILen);
00747   if( tmpOpSKILen == 0 )
00748   {
00749     return NULL;
00750   }
00751 
00752   UINT8 tmpDate[TMP_BUFF_SIZE];
00753   UINT32 tmpDateLen = TMP_BUFF_SIZE;
00754 
00755   getDOMElementAttribute(tnCs, OPTIONS_ATTRIBUTE_TNC_DATE, tmpDate, &tmpDateLen);
00756   if(tmpDateLen == 0)
00757   {
00758     return NULL;
00759   }
00760 
00761   UINT8 tmpVersion[TMP_BUFF_SIZE];
00762   UINT32 tmpVersionLen = TMP_BUFF_SIZE;
00763 
00764   UINT8* serial = NULL;
00765 
00766   getDOMElementAttribute(tnCs, OPTIONS_ATTRIBUTE_TNC_VERSION, tmpVersion, &tmpVersionLen);
00767   if(tmpVersionLen > 0)
00768   {
00769     serial = new UINT8[tmpDateLen+tmpVersionLen+1];
00770     memcpy(serial, tmpDate, tmpDateLen);
00771     memcpy(serial + tmpDateLen, tmpVersion, tmpVersionLen);
00772     serial[tmpDateLen + tmpVersionLen] = 0;
00773   }
00774   else
00775   {
00776     serial = new UINT8[tmpDateLen+1];
00777     memcpy(serial, tmpDate, tmpDateLen);
00778     serial[tmpDateLen] = 0;
00779   }
00780 
00781   UINT32 locale_len = 3;
00782   UINT8* id=new UINT8[tmpOpSKILen+locale_len+1];
00783   UINT8* locale=new UINT8[locale_len];
00784 
00785   locale[locale_len-1]=0;
00786 
00787   memcpy(id, tmpOpSKIBuff, tmpOpSKILen);
00788   id[tmpOpSKILen]=0;
00789   id[tmpOpSKILen+(locale_len-1)+1] = 0;
00790 
00791   (*nrOfTnCs) = docTnCsList->getLength();
00792   elementList = new UINT8 *[(*nrOfTnCs)];
00793   (*lengths) = new UINT32[(*nrOfTnCs)];
00794   for (; i < (*nrOfTnCs); i++)
00795   {
00796     //after every loop turn locale is explicitly reset to 3 because ...
00797     locale_len = 3;
00798     iterator = docTnCsList->item(i);
00799     //... it is modified by getDOMElementAttribute
00800     getDOMElementAttribute(iterator, OPTIONS_ATTRIBUTE_TNC_LOCALE, locale, &locale_len);
00801     if(locale_len == 0)
00802     {
00803       elementList[i] = NULL;
00804       continue;
00805     }
00806     //only append the locale code to the id when it is
00807     //not the default locale
00808     if( strncasecmp((char *)locale, LOCALE_DEFAULT, 2) == 0 )
00809     {
00810       id[tmpOpSKILen] = 0;
00811     }
00812     else
00813     {
00814       id[tmpOpSKILen] = '_';
00815       memcpy((id+tmpOpSKILen+1), locale, locale_len);
00816     }
00817 
00818     if(setDOMElementAttribute(iterator, OPTIONS_ATTRIBUTE_TNC_ID, id) != E_SUCCESS)
00819     {
00820       elementList[i] = NULL;
00821       continue;
00822     }
00823     if(setDOMElementAttribute(iterator, OPTIONS_ATTRIBUTE_TNC_DATE, tmpDate) != E_SUCCESS)
00824     {
00825       elementList[i] = NULL;
00826       continue;
00827     }
00828     if(setDOMElementAttribute(iterator, OPTIONS_ATTRIBUTE_TNC_SERIAL, serial) != E_SUCCESS)
00829     {
00830       elementList[i] = NULL;
00831       continue;
00832     }
00833     setCurrentTimeMilliesAsDOMAttribute(iterator);
00834     elementList[i] = xmlDocToStringWithSignature(iterator, (*lengths)[i], true);
00835   }
00836 
00837   delete[] serial;
00838   delete[] id;
00839   delete[] locale;
00840   return elementList;
00841 
00842 }
00843 
00844 UINT8* CAInfoService::getMixHeloXMLAsString(UINT32& a_len)
00845 {
00846   XERCES_CPP_NAMESPACE::DOMDocument* docMixInfo = NULL;
00847   XERCES_CPP_NAMESPACE::DOMElement* mixInfoRoot = NULL;
00848 
00849   if( (CALibProxytest::getOptions()->getMixXml(docMixInfo) != E_SUCCESS) ||
00850     (docMixInfo == NULL) )
00851   {
00852     return NULL;
00853   }
00854 
00855   if(m_serial != 0)
00856   {
00857     mixInfoRoot = docMixInfo->getDocumentElement();
00858     if( mixInfoRoot != NULL )
00859     {
00860       setDOMElementAttribute(mixInfoRoot, ATTRIBUTE_SERIAL, m_serial);
00861     }
00862   }
00863   return xmlDocToStringWithSignature(docMixInfo, a_len, true);
00864 }
00865 
00866 UINT8* CAInfoService::xmlDocToStringWithSignature(DOMNode *a_node, UINT32& a_len, bool bIncludeCerts)
00867 {
00868   a_len = 0;
00869 
00870   UINT32 sendBuffLen = 0;
00871   UINT8* sendBuff = NULL;
00872 
00873   if( a_node == NULL)
00874   {
00875     return NULL;
00876   }
00877   if(m_pMultiSignature->signXML(a_node, bIncludeCerts) != E_SUCCESS)
00878   {
00879     return NULL;
00880   }
00881 
00882   sendBuff = DOM_Output::dumpToMem(a_node, &sendBuffLen);
00883   if(sendBuff == NULL)
00884   {
00885     return NULL;
00886   }
00887   a_len = sendBuffLen;
00888   return sendBuff;
00889 }
00890 
00893 SINT32 CAInfoService::sendMixHelo(const UINT8* a_strMixHeloXML,UINT32 a_len,SINT32 requestCommand,const UINT8* param,
00894                   const CASocketAddrINet* a_pSocketAddress)
00895   {
00896     UINT8* recvBuff = NULL;
00897     SINT32 ret = E_SUCCESS;
00898     UINT32 len = 0;
00899 
00900   CASocket oSocket(true);
00901   UINT8 hostname[255];
00902   UINT8 buffHeader[255];
00903   CAHttpClient httpClient;
00904 
00905   UINT64 currentTimeout = MIX_TO_INFOSERVICE_TIMEOUT;
00906   UINT64 startupTime, currentMillis;
00907 
00908     UINT32 requestType = REQUEST_TYPE_POST;
00909     bool receiveAnswer = false;
00910 
00911     if (a_pSocketAddress == NULL)
00912     {
00913       goto ERR;
00914     }
00915 
00916     if(requestCommand<0)
00917   {
00918         if(m_bConfiguring)
00919     {
00920       requestCommand = REQUEST_COMMAND_CONFIGURE;
00921       receiveAnswer = true;
00922     }
00923         else
00924     {
00925       requestCommand = REQUEST_COMMAND_HELO;
00926       receiveAnswer = true;
00927     }
00928   }
00929   else if(requestCommand==REQUEST_COMMAND_MIXINFO)
00930   {
00931     requestType=REQUEST_TYPE_GET;
00932     receiveAnswer = true;
00933   }
00934 
00935   if(a_pSocketAddress->getIPAsStr(hostname, 255)!=E_SUCCESS)
00936   {
00937     goto ERR;
00938   }
00939 
00940     oSocket.setRecvBuff(255);
00941   if((ret = oSocket.connect(*a_pSocketAddress, MIX_TO_INFOSERVICE_TIMEOUT))==E_SUCCESS)
00942   {
00943     httpClient.setSocket(&oSocket);
00944     const char* strRequestCommand=STRINGS_REQUEST_COMMANDS[requestCommand];
00945     const char* strRequestType=STRINGS_REQUEST_TYPES[requestType];
00946     CAMsg::printMsg(LOG_DEBUG,"InfoService: Sending [%s] %s to InfoService %s:%d.\r\n", strRequestType,strRequestCommand, hostname, a_pSocketAddress->getPort());
00947     if(requestCommand==REQUEST_COMMAND_MIXINFO)
00948     {
00949       sprintf((char*)buffHeader,"%s /%s%s HTTP/1.0\r\nContent-Length: %u\r\n\r\n", strRequestType, strRequestCommand, param,a_len);
00950     }
00951     else
00952     {
00953       sprintf((char*)buffHeader,"%s /%s HTTP/1.0\r\nContent-Length: %u\r\n\r\n", strRequestType, strRequestCommand, a_len);
00954     }
00955 
00956     getcurrentTimeMillis(startupTime);
00957     if (oSocket.sendFullyTimeOut(buffHeader,strlen((char*)buffHeader), currentTimeout, SEND_INFO_TIMEOUT_MS)!=E_SUCCESS)
00958     {
00959       goto ERR;
00960     }
00961 
00962     // CAMsg::printMsg(LOG_DEBUG,"InfoService: Sending XML data...\n");
00963     getcurrentTimeMillis(currentMillis);
00964     currentTimeout -= (currentMillis - startupTime);
00965     if (currentTimeout <= 0 ||
00966       oSocket.sendFullyTimeOut(a_strMixHeloXML, a_len, currentTimeout, SEND_INFO_TIMEOUT_MS)!=E_SUCCESS)
00967     {
00968       goto ERR;
00969     }
00970 
00971     if(receiveAnswer)
00972     {
00973       // CAMsg::printMsg(LOG_DEBUG,"InfoService: Parsing header...\n");
00974       getcurrentTimeMillis(currentMillis);
00975       currentTimeout -= (currentMillis - startupTime);
00976       if(currentTimeout <= 0 || httpClient.parseHTTPHeader(&len) != E_SUCCESS)
00977       {
00978         goto ERR;
00979       }
00980       // CAMsg::printMsg(LOG_DEBUG,"InfoService: Header parsed!\n");
00981 
00982       if(len > 0)
00983       {
00984         getcurrentTimeMillis(currentMillis);
00985         currentTimeout -= (currentMillis - startupTime);
00986 
00987           recvBuff = new UINT8[len+1];
00988           CAMsg::printMsg(LOG_DEBUG,"InfoService: Receiving answer...\n");
00989           if (currentTimeout <= 0 ||
00990           oSocket.receiveFullyT(recvBuff, len, currentTimeout) != E_SUCCESS)
00991           {
00992           delete []recvBuff;
00993               recvBuff=NULL;
00994               goto ERR;
00995           }
00996         recvBuff[len]=0;
00997         CAMsg::printMsg(LOG_DEBUG,"Received from Infoservice:\n");
00998         CAMsg::printMsg(LOG_DEBUG,(char*)recvBuff);
00999         CAMsg::printMsg(LOG_DEBUG,"\n");
01000       }
01001         }
01002         oSocket.close();
01003 
01004         if(recvBuff != NULL)
01005         {
01006             delete[] recvBuff;
01007             recvBuff=NULL;
01008         }
01009         /* REMOVED by Rolf Wendolsky on 2009-12-11 becuase this looks  dangerous: each InfoService may reconfigure the Mix! Without verificaton!
01010         if(recvBuff != NULL)
01011         {
01012             XERCES_CPP_NAMESPACE::DOMDocument* doc=parseDOMDocument(recvBuff,len);
01013             delete[] recvBuff;
01014             recvBuff=NULL;
01015             DOMElement* root=NULL;
01016             if(doc!=NULL && (root = doc->getDocumentElement()) != NULL)
01017             {
01018                 if(equals(root->getNodeName(),"MixCascade"))
01019                 {
01020                     ret = handleConfigEvent(doc);
01021                     if(ret == E_SUCCESS)
01022                         m_bConfiguring = false;
01023                     else
01024                         return ret;
01025                 }
01026                 else if(equals(root->getNodeName(),"Mix"))
01027                 {
01028                     if(m_expectedMixRelPos < 0)
01029           {
01030             XMLCh* id=XMLString::transcode("id");
01031             char* tmpStr=XMLString::transcode(root->getAttribute(id));
01032                         CAMsg::printMsg(LOG_DEBUG,"InfoService: Setting new previous mix: %s\n",tmpStr);
01033                         XMLString::release(&tmpStr);
01034                         XMLString::release(&id);
01035                         CALibProxytest::getOptions()->setPrevMix(doc);
01036           }
01037                     else if(m_expectedMixRelPos > 0)
01038           {
01039             XMLCh* id=XMLString::transcode("id");
01040             char* tmpStr=XMLString::transcode(root->getAttribute(id));
01041                         CAMsg::printMsg(LOG_DEBUG,"InfoService: Setting new next mix: %s\n",tmpStr);
01042                         XMLString::release(&id);
01043                         XMLString::release(&tmpStr);
01044                         CALibProxytest::getOptions()->setNextMix(doc);
01045           }
01046                 }
01047                 CAMsg::printMsg(LOG_DEBUG,"InfoService::sendMixHelo(): XML infoservice doc 0x%x not needed anymore.\n",
01048                     doc);
01049             }
01050             else
01051             {
01052                 CAMsg::printMsg(LOG_CRIT,"InfoService: Error parsing answer from InfoService!\n");
01053             }
01054         }*/
01055     return E_SUCCESS;
01056   }
01057   else
01058   {
01059     if (ret != E_UNKNOWN)
01060     {
01061       CAMsg::printMsg(LOG_ERR,"InfoService: sendMixHelo() connecting to InfoService %s:%d failed for reason: %s (%i)\n",
01062           hostname, a_pSocketAddress->getPort(), GET_NET_ERROR_STR(GET_NET_ERROR), GET_NET_ERROR);
01063     }
01064     else
01065     {
01066       CAMsg::printMsg(LOG_ERR,"InfoService: sendMixHelo() connecting to InfoService %s:%d failed!\n",
01067                 hostname, a_pSocketAddress->getPort());
01068     }
01069   }
01070 ERR:
01071 
01072   //CAMsg::printMsg(LOG_DEBUG,"InfoService: Closing socket to %s:%d due to error...\n", hostname, a_pSocketAddress->getPort());
01073   oSocket.close();
01074   //CAMsg::printMsg(LOG_DEBUG,"InfoService: Socket closed to %s:%d due to error.\n", hostname, a_pSocketAddress->getPort());
01075   return E_UNKNOWN;
01076 }
01077 
01078 
01079 SINT32 CAInfoService::sendHelo(UINT8* a_strXML, UINT32 a_len, THREAD_RETURN (*a_thread)(void *), UINT8* a_strThreadName, SINT32 requestCommand, const UINT8* param)
01080 {
01081   SINT32 returnValue = E_UNKNOWN;
01082   UINT32 nrAddresses;
01083   CAListenerInterface** socketAddresses = CALibProxytest::getOptions()->getInfoServices(nrAddresses);
01084   CAThread** threads = new CAThread*[nrAddresses];
01085   InfoServiceHeloMsg** messages = new InfoServiceHeloMsg*[nrAddresses];
01086 
01087   for (UINT32 i = 0; i < nrAddresses; i++)
01088   {
01089     messages[i] = new InfoServiceHeloMsg();
01090     messages[i]->addr = (CASocketAddrINet*)socketAddresses[i]->getAddr();
01091     messages[i]->len = a_len;
01092     messages[i]->strXML = a_strXML;
01093     messages[i]->is = this;
01094     messages[i]->requestCommand = requestCommand;
01095     messages[i]->param = param;
01096 #if !defined(NO_INFOSERVICE_TRHEADS) 
01097     threads[i] = new CAThread(a_strThreadName);
01098     threads[i]->setMainLoop((THREAD_RETURN (*)(void *))a_thread);
01099     threads[i]->start((void*)(messages[i]), false, true);
01100 #else
01101     (*a_thread)(messages[i]);
01102       if (messages[i]->retVal == E_SUCCESS)
01103       {
01104         returnValue = E_SUCCESS;
01105       }
01106 #endif
01107   }
01108 
01109   for (UINT32 i = 0; i < nrAddresses; i++)
01110   {
01111 #if !defined(NO_INFOSERVICE_TRHEADS)
01112     if (threads[i]->join() == E_SUCCESS)
01113     {
01114       // CAMsg::printMsg(LOG_DEBUG,"InfoService: helo thread %u joined.\n", i);
01115       if (messages[i]->retVal == E_SUCCESS)
01116       {
01117         returnValue = E_SUCCESS;
01118       }
01119     }
01120     delete threads[i];
01121     threads[i] = NULL;
01122 #endif
01123     delete messages[i]->addr;
01124     messages[i]->addr = NULL;
01125     delete messages[i];
01126     messages[i] = NULL;
01127   }
01128   //Message looks senseless but please keep it because Rolf reported a helo thread deadlock.
01129   //Perhaps there is a problem when the threads are joined.
01130   // CAMsg::printMsg(LOG_DEBUG,"InfoService: all helo threads joined. continue.\n");
01131   delete[] messages;
01132   messages = NULL;
01133   delete[] threads;
01134   threads = NULL;
01135 
01136   return returnValue;
01137 }
01138 
01139 
01140 
01141 SINT32 CAInfoService::sendCascadeHelo()
01142 {
01143   if(CALibProxytest::getOptions()->isMiddleMix())
01144     {
01145     return E_SUCCESS;
01146     }
01147 
01148   UINT32 len;
01149   SINT32 ret;
01150   UINT8* strCascadeHeloXML=getCascadeHeloXMLAsString(len);
01151   if(strCascadeHeloXML==NULL)
01152   {
01153     return E_UNKNOWN;
01154   }
01155 
01156   if( !(m_pMix->isConnected()) )
01157   {
01158 #ifdef DEBUG
01159     CAMsg::printMsg(LOG_INFO, "not connected: skipping cascade helo.\n");
01160 #endif
01161     delete[] strCascadeHeloXML;
01162     strCascadeHeloXML = NULL;
01163     return E_UNKNOWN;
01164   }
01165 
01166   ret = sendHelo(strCascadeHeloXML, len, TCascadeHelo, (UINT8*)"Cascade Helo Thread", REQUEST_COMMAND_CASCADE);
01167   delete[] strCascadeHeloXML;
01168   strCascadeHeloXML = NULL;
01169   return ret;
01170 }
01171 
01172 UINT8* CAInfoService::getCascadeHeloXMLAsString(UINT32& a_len)
01173   {
01174     a_len=0;
01175     UINT32 sendBuffLen;
01176     UINT8* sendBuff=NULL;
01177     XERCES_CPP_NAMESPACE::DOMDocument* docMixInfo=NULL;
01178     DOMElement* elemTimeStamp=NULL;
01179     DOMElement* elemRoot=NULL;
01180 
01181     if(m_pMix->getMixCascadeInfo(docMixInfo)!=E_SUCCESS)
01182     {
01183       // CAMsg::printMsg(LOG_INFO,"InfoService: Cascade not yet configured.\n");
01184       goto ERR;
01185     }
01186     //insert (or update) the Timestamp
01187     elemRoot=docMixInfo->getDocumentElement();
01188 
01189     if(getDOMChildByName(elemRoot,"LastUpdate",elemTimeStamp,false)!=E_SUCCESS)
01190     {
01191       elemTimeStamp=createDOMElement(docMixInfo,"LastUpdate");
01192       elemRoot->appendChild(elemTimeStamp);
01193     }
01194     UINT64 currentMillis;
01195     getcurrentTimeMillis(currentMillis);
01196     UINT8 tmpStrCurrentMillis[50];
01197     print64(tmpStrCurrentMillis, currentMillis);
01198     setDOMElementValue(elemTimeStamp, tmpStrCurrentMillis);
01199 
01200     if (m_serial != 0)
01201     {
01202       print64(tmpStrCurrentMillis, m_serial);
01203       setDOMElementAttribute(elemRoot, ATTRIBUTE_SERIAL, tmpStrCurrentMillis);
01204     }
01205 
01206     if(m_pMultiSignature->signXML(docMixInfo, true)!=E_SUCCESS)
01207     {
01208       goto ERR;
01209     }
01210 
01211     sendBuff=DOM_Output::dumpToMem(docMixInfo,&sendBuffLen);
01212     if(sendBuff==NULL)
01213       goto ERR;
01214 
01215     a_len=sendBuffLen;
01216     return sendBuff;
01217 ERR:
01218     delete []sendBuff;
01219     sendBuff = NULL;
01220     return NULL;
01221   }
01222 
01231 SINT32 CAInfoService::sendCascadeHelo(const UINT8* a_strCascadeHeloXML,UINT32 a_len,const CASocketAddrINet* a_pSocketAddress) const
01232 {
01233   if(CALibProxytest::getOptions()->isMiddleMix() || (CALibProxytest::getOptions()->isLastMix() && !m_bConfiguring))
01234   {
01235     return E_SUCCESS;
01236   }
01237   CASocket oSocket(true);
01238   UINT8 hostname[255];
01239   UINT8 buffHeader[255];
01240   UINT64 currentTimeout = MIX_TO_INFOSERVICE_TIMEOUT;
01241   UINT64 startupTime, currentMillis;
01242 
01243   if (a_pSocketAddress == NULL)
01244   {
01245     goto ERR;
01246   }
01247 
01248   if(a_pSocketAddress->getIPAsStr(hostname, 255)!=E_SUCCESS)
01249   {
01250     goto ERR;
01251   }
01252   if(oSocket.connect(*a_pSocketAddress, MIX_TO_INFOSERVICE_TIMEOUT)==E_SUCCESS)
01253   {
01254      if(CALibProxytest::getOptions()->isFirstMix())
01255     {
01256             CAMsg::printMsg(LOG_DEBUG,"InfoService: Sending cascade helo to InfoService %s:%d.\r\n", hostname, a_pSocketAddress->getPort());
01257     }
01258       else
01259     {
01260             CAMsg::printMsg(LOG_DEBUG,"InfoService: Sending cascade configuration request to InfoService %s:%d.\r\n", hostname, a_pSocketAddress->getPort());
01261     }
01262         // LERNGRUPPE
01263         // Semi-dynamic cascades are temporary cascades, not yet established! InfoService can cope with them now
01264         // using the /dynacascade command
01265     if( CALibProxytest::getOptions()->isLastMix() && m_bConfiguring )
01266     {
01267       sprintf((char*)buffHeader,"POST /dynacascade HTTP/1.0\r\nContent-Length: %u\r\n\r\n",a_len);
01268     }
01269     else
01270     {
01271       sprintf((char*)buffHeader,"POST /cascade HTTP/1.0\r\nContent-Length: %u\r\n\r\n",a_len);
01272     }
01273 
01274     getcurrentTimeMillis(startupTime);
01275     if( oSocket.sendFullyTimeOut(buffHeader, strlen((char*)buffHeader), currentTimeout, SEND_INFO_TIMEOUT_MS)!=E_SUCCESS)
01276     {
01277       goto ERR;
01278     }
01279     getcurrentTimeMillis(currentMillis);
01280     currentTimeout -= (currentMillis - startupTime);
01281     if (currentTimeout <= 0 ||
01282         oSocket.sendFullyTimeOut(a_strCascadeHeloXML, a_len, currentTimeout, SEND_INFO_TIMEOUT_MS)!=E_SUCCESS)
01283     {
01284       goto ERR;
01285     }
01286     //Receive answer --> 200 Ok or failure
01287     //HTTP/1.1 200 Ok
01288     getcurrentTimeMillis(currentMillis);
01289     currentTimeout -= (currentMillis - startupTime);
01290     if(currentTimeout <= 0 ||
01291        oSocket.receiveFullyT(buffHeader, 12, currentTimeout)!=E_SUCCESS)
01292     {
01293       goto ERR;
01294     }
01295     if(memcmp(buffHeader+9,"200",3)!=0)
01296     {
01297       goto ERR;
01298     }
01299     oSocket.close();
01300     return E_SUCCESS;
01301   }
01302 ERR:
01303   oSocket.close();
01304   return E_UNKNOWN;
01305 }
01306 
01307 SINT32 CAInfoService::handleConfigEvent(XERCES_CPP_NAMESPACE::DOMDocument* doc) const
01308 {
01310 /*    CAMsg::printMsg(LOG_INFO,"InfoService: Cascade info received from InfoService\n");
01311 
01312     DOM_Element root=doc.getDocumentElement();
01313     DOM_Node mixesElement;
01314     getDOMChildByName(root,(UINT8*)"Mixes", mixesElement, false);
01315     char* mixId;
01316     char* prevMixId = NULL;
01317     char* myNextMixId = NULL;
01318     char* myPrevMixId = NULL;
01319     bool bFoundMix = false;
01320     UINT8 myMixId[64];
01321     CALibProxytest::getOptions()->getMixId(myMixId,64);
01322     DOM_Node child = mixesElement.getFirstChild();
01323     while(child!=NULL)
01324     {
01325         if(child.getNodeName().equals("Mix") && child.getNodeType() == DOM_Node::ELEMENT_NODE)
01326         {
01327             mixId = static_cast<const DOM_Element&>(child).getAttribute("id").transcode();
01328             if(strcmp(mixId,(char*)myMixId) == 0)
01329             {
01330                 bFoundMix = true;
01331                 myPrevMixId = prevMixId;
01332             }
01333             else if(bFoundMix == true)
01334             {
01335                 myNextMixId = mixId;
01336                 break;
01337             }
01338             prevMixId = mixId;
01339         }
01340         child = child.getNextSibling();
01341     }
01342 
01343     SINT32 ret = 0;
01344     //char* c;
01345 
01346     if(myPrevMixId != NULL)
01347     {
01348         CAMsg::printMsg(LOG_INFO,"InfoService: Asking InfoService about previous mix ...\n");
01349 
01350         m_expectedMixRelPos = -1;
01351         //c = new char[8+strlen(myPrevMixId)+1];
01352         //strcpy(c,"mixinfo/");
01353         //strcat(c,myPrevMixId);
01354         ret = sendMixInfo((UINT8*)myPrevMixId);
01355         //delete[] c;
01356         if(ret != E_SUCCESS)
01357         {
01358             CAMsg::printMsg(LOG_CRIT,"InfoService: Error retrieving mix info from InfoService!\n");
01359             return ret;
01360         }
01361     }
01362 
01363     if(myNextMixId != NULL)
01364     {
01365         CAMsg::printMsg(LOG_INFO,"InfoService: Asking InfoService about next mix ...\n");
01366 
01367         m_expectedMixRelPos = 1;
01368         //c = new char[8+strlen(myNextMixId)+1];
01369         //strcpy(c,"mixinfo/");
01370         //strcat(c,myNextMixId);
01371         ret = sendMixInfo((UINT8*)myNextMixId);
01372         //delete[] c;
01373         if(ret != E_SUCCESS)
01374         {
01375             CAMsg::printMsg(LOG_CRIT,"InfoService: Error retrieving mix info from InfoService!\n");
01376             return ret;
01377         }
01378 
01379     }
01380     */
01381     return E_SUCCESS;
01382 }
01383 
01384 #ifdef PAYMENT
01385 SINT32 CAInfoService::getPaymentInstance(const UINT8* a_pstrPIID,CAXMLBI** a_pXMLBI)
01386 {
01387   SINT32 returnValue = E_UNKNOWN;
01388   SINT32 currentValue;
01389   UINT32 nrAddresses;
01390   CAListenerInterface** socketAddresses = CALibProxytest::getOptions()->getInfoServices(nrAddresses);
01391   for (UINT32 i = 0; i < nrAddresses; i++)
01392   {
01393     currentValue = getPaymentInstance(a_pstrPIID, a_pXMLBI,
01394             (CASocketAddrINet*)socketAddresses[i]->getAddr());
01395     if (currentValue == E_SUCCESS)
01396     {
01397       returnValue = currentValue;
01398     }
01399   }
01400   return returnValue;
01401 }
01402 
01403 
01412 SINT32 CAInfoService::getPaymentInstance(const UINT8* a_pstrPIID,CAXMLBI** a_pXMLBI,
01413                      CASocketAddrINet* a_socketAddress)
01414   {
01415     CASocket socket;
01416     CASocketAddrINet address;
01417     UINT8 hostname[255];
01418     UINT8 request[255];
01419     CAHttpClient httpClient;
01420     UINT32 status, contentLength;
01421     *a_pXMLBI=NULL;
01422     //Connect to InfoService
01423     if(a_socketAddress->getIPAsStr(hostname, 255)!=E_SUCCESS)
01424     {
01425       socket.close();
01426       return E_UNKNOWN;
01427     }
01428 
01429     address.setAddr(hostname,a_socketAddress->getPort());
01430 
01431     if(socket.connect(address)!=E_SUCCESS)
01432     {
01433       socket.close();
01434       return E_UNKNOWN;
01435     }
01436 
01437     //#ifdef DEBUG
01438       CAMsg::printMsg(LOG_DEBUG, "CAInfoService::getPaymentInstance() - connected to InfoService %s:%d\n",hostname, a_socketAddress->getPort());
01439     //#endif
01440 
01441     //Send request
01442     httpClient.setSocket(&socket);
01443     sprintf((char*) request, "/paymentinstance/%s", (char*) a_pstrPIID);
01444     httpClient.sendGetRequest(request);
01445     httpClient.parseHTTPHeader(&contentLength, &status);
01446     #ifdef DEBUG
01447       CAMsg::printMsg(LOG_DEBUG, "CAInfoService::getPaymentInstance() - Request sent, HTTP status: %i, content length: %i\n", status, contentLength);
01448     #endif
01449     if(status!=200||contentLength>0x00FFFF)
01450       {
01451         socket.close();
01452         return E_UNKNOWN;
01453       }
01454 
01455     UINT8* content=new UINT8[contentLength+1];
01456     if(httpClient.getContent(content, &contentLength)!=E_SUCCESS)
01457       {
01458         delete []content;
01459         content = NULL;
01460         socket.close();
01461         return E_UNKNOWN;
01462       }
01463     socket.close();
01464     //Parse XML
01465     XERCES_CPP_NAMESPACE::DOMDocument* doc = parseDOMDocument(content,contentLength);
01466     delete []content;
01467     content = NULL;
01468     if(doc==NULL)
01469       return E_UNKNOWN;
01470     DOMElement* elemRoot=doc->getDocumentElement();
01471 
01472     *a_pXMLBI = CAXMLBI::getInstance(elemRoot);
01473     CAMsg::printMsg(LOG_DEBUG, "CAInfoService::getPaymentInstance(): XML doc not needed anymore\n");
01474     if (*a_pXMLBI != NULL)
01475       {
01476         return E_SUCCESS;
01477       }
01478     else
01479       {
01480         return E_UNKNOWN;
01481       }
01482   }
01483 #endif
01484 #endif //ONLY_LOCAL_PROXY