|
Mixe for Privacy and Anonymity in the Internet
|
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
1.7.6.1