00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "StdAfx.h"
00034 #ifdef PAYMENT
00035
00036
00037 #include "CAAccountingInstance.hpp"
00038 #include "CAAccountingControlChannel.hpp"
00039 #include "CABase64.hpp"
00040 #include "CAMsg.hpp"
00041 #include "CAUtil.hpp"
00042 #include "CASignature.hpp"
00043 #include "CAXMLErrorMessage.hpp"
00044
00045
00046
00047
00048
00049
00050 CAAccountingInstance * CAAccountingInstance::ms_pInstance = NULL;
00051
00052
00053
00054
00055
00056
00057 CAAccountingInstance::CAAccountingInstance()
00058 {
00059
00060 CAMsg::printMsg( LOG_DEBUG, "AccountingInstance initialising\n" );
00061 m_pQueue = new CAQueue();
00062 m_pIPBlockList = new CATempIPBlockList(60000);
00063
00064
00065 m_dbInterface = new CAAccountingDBInterface();
00066 if(m_dbInterface->initDBConnection() != E_SUCCESS)
00067 {
00068 CAMsg::printMsg( LOG_ERR, "**************** AccountingInstance: Could not connect to DB!");
00069 exit(1);
00070 }
00071
00072
00073 m_AiName = new UINT8[256];
00074 options.getAiID(m_AiName, 256);
00075 m_pJpiVerifyingInstance = options.getBI()->getVerifier();
00076 options.getPaymentHardLimit(&m_iHardLimitBytes);
00077 options.getPaymentSoftLimit(&m_iSoftLimitBytes);
00078
00079
00080 m_pThread = new CAThread();
00081 m_pThread->setMainLoop( aiThreadMainLoop );
00082 m_bThreadRunning = true;
00083 m_pThread->start( this );
00084
00085
00086 m_pSettleThread = new CAAccountingSettleThread();
00087 }
00088
00089
00090
00091
00092
00093
00094 CAAccountingInstance::~CAAccountingInstance()
00095 {
00096 CAMsg::printMsg( LOG_DEBUG, "AccountingInstance dying\n" );
00097 m_bThreadRunning = false;
00098 m_pThread->join();
00099 delete m_pThread;
00100
00101 delete m_dbInterface;
00102 delete m_pIPBlockList;
00103 delete m_pQueue;
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 SINT32 CAAccountingInstance::handleJapPacket( MIXPACKET *pPacket, fmHashTableEntry *pHashEntry)
00121 {
00122 aiAccountingInfo * pAccInfo;
00123 timespec now;
00124 getcurrentTime(now);
00125 pAccInfo = pHashEntry->pAccountingInfo;
00126
00127
00128 m_Mutex.lock();
00129 pAccInfo->transferredBytes += sizeof(MIXPACKET);
00130
00131 if(pAccInfo->authFlags & (AUTH_FATAL_ERROR))
00132 {
00133
00134 return 3;
00135 }
00136
00137 if(pAccInfo->authFlags & (AUTH_GOT_ACCOUNTCERT) )
00138 {
00139
00140
00141
00142 if( pAccInfo->authFlags & AUTH_FAKE )
00143 {
00144 m_Mutex.unlock();
00145 CAMsg::printMsg( LOG_DEBUG, "AccountingInstance: AUTH_FAKE flag is set ... byebye\n");
00146 return 3;
00147 }
00148 if( !(pAccInfo->authFlags & AUTH_ACCOUNT_OK) )
00149 {
00150
00151 if(now.tv_sec >= pAccInfo->lastRequestSeconds + REQUEST_TIMEOUT)
00152 {
00153 m_Mutex.unlock();
00154 CAMsg::printMsg( LOG_DEBUG, "AccountingInstance: Jap refused to send response to challenge (Request Timeout)...\n");
00155 return 3;
00156 }
00157 }
00158
00159 if( pAccInfo->authFlags & AUTH_ACCOUNT_EMPTY )
00160 {
00161 CAMsg::printMsg( LOG_DEBUG, "AccountingInstance: Account is empty. Closing connection.\n");
00162 CAXMLErrorMessage msg(CAXMLErrorMessage::ERR_ACCOUNT_EMPTY);
00163 DOM_Document doc;
00164 msg.toXmlDocument(doc);
00165 pAccInfo->pControlChannel->sendMessage(doc);
00166 pAccInfo->authFlags |= AUTH_FATAL_ERROR;
00167 m_Mutex.unlock();
00168 return 3;
00169 }
00170
00171
00172
00173 else if ((pAccInfo->transferredBytes-pAccInfo->confirmedBytes) >= m_iHardLimitBytes)
00174 {
00175 #ifdef DEBUG
00176 CAMsg::printMsg( LOG_DEBUG, "Accounting instance: User refused "
00177 "to send cost confirmation (HARDLIMIT EXCEEDED).\n");
00178 #endif
00179 m_pIPBlockList->insertIP( pHashEntry->peerIP );
00180 CAXMLErrorMessage msg(CAXMLErrorMessage::ERR_NO_CONFIRMATION);
00181 DOM_Document doc;
00182 msg.toXmlDocument(doc);
00183 pAccInfo->pControlChannel->sendMessage(doc);
00184 pAccInfo->authFlags |= AUTH_FATAL_ERROR;
00185 m_Mutex.unlock();
00186 return 3;
00187 }
00188
00189
00190
00191 else if( (pAccInfo->transferredBytes-pAccInfo->confirmedBytes) >= m_iSoftLimitBytes)
00192 {
00193 if( (pAccInfo->authFlags & AUTH_SENT_CC_REQUEST) )
00194 {
00195 if( (pAccInfo->authFlags & AUTH_SENT_SECOND_CC_REQUEST))
00196 {
00197 if(now.tv_sec >= pAccInfo->lastRequestSeconds + REQUEST_TIMEOUT)
00198 {
00199 #ifdef DEBUG
00200 CAMsg::printMsg( LOG_DEBUG, "Accounting instance: User refused "
00201 "to send cost confirmation (REQUEST TIMEOUT).\n");
00202 #endif
00203 m_pIPBlockList->insertIP( pHashEntry->peerIP );
00204 CAXMLErrorMessage msg(CAXMLErrorMessage::ERR_NO_CONFIRMATION);
00205 DOM_Document doc;
00206 msg.toXmlDocument(doc);
00207 pAccInfo->pControlChannel->sendMessage(doc);
00208 pAccInfo->authFlags |= AUTH_FATAL_ERROR;
00209 m_Mutex.unlock();
00210 return 3;
00211 }
00212 else
00213 {
00214 m_Mutex.unlock();
00215 return 1;
00216 }
00217 }
00218 else if(now.tv_sec >= pAccInfo->lastRequestSeconds + REQUEST_TIMEOUT)
00219 {
00220
00221 DOM_Document doc;
00222 #ifdef DEBUG
00223 CAMsg::printMsg(LOG_DEBUG, "AccountingInstance sending REMINDER CC request.\n");
00224 #endif
00225 makeCCRequest(pAccInfo->accountNumber, pAccInfo->transferredBytes, doc);
00226 pAccInfo->pControlChannel->sendMessage(doc);
00227 pAccInfo->authFlags |= AUTH_SENT_SECOND_CC_REQUEST;
00228 pAccInfo->lastRequestSeconds = now.tv_sec;
00229 m_Mutex.unlock();
00230 return 1;
00231 }
00232 else
00233 {
00234 m_Mutex.unlock();
00235 return 1;
00236 }
00237 }
00238 else
00239 {
00240
00241 DOM_Document doc;
00242 #ifdef DEBUG
00243 CAMsg::printMsg(LOG_DEBUG, "AccountingInstance sending CC request.\n");
00244 #endif
00245 makeCCRequest(pAccInfo->accountNumber, pAccInfo->transferredBytes, doc);
00246 pAccInfo->pControlChannel->sendMessage(doc);
00247 pAccInfo->authFlags |= AUTH_SENT_CC_REQUEST;
00248 pAccInfo->lastRequestSeconds = now.tv_sec;
00249 m_Mutex.unlock();
00250 return 1;
00251 }
00252 }
00253 else
00254 {
00255
00256
00257
00258 if( (( (pAccInfo->transferredBytes - pAccInfo->lastbalTransferredBytes) >=
00259 ((pAccInfo->lastbalDeposit - pAccInfo->lastbalSpent) / 33))&&
00260 ((pAccInfo->transferredBytes - pAccInfo->lastbalTransferredBytes) >= 256*1024))
00261 || (pAccInfo->lastbalDeposit == 0))
00262 {
00263 if( (pAccInfo->authFlags & AUTH_SENT_BALANCE_REQUEST) )
00264 {
00265 if( (pAccInfo->authFlags & AUTH_SENT_SECOND_BALANCE_REQUEST))
00266 {
00267 if(now.tv_sec >= pAccInfo->lastRequestSeconds + REQUEST_TIMEOUT)
00268 {
00269 #ifdef DEBUG
00270 CAMsg::printMsg( LOG_DEBUG, "Accounting instance: User refused "
00271 "to send balance cert (request Timeout).\n",
00272 pAccInfo->accountNumber, pHashEntry->peerIP[ 0 ], pHashEntry->peerIP[ 1 ],
00273 pHashEntry->peerIP[ 2 ], pHashEntry->peerIP[ 3 ] );
00274 #endif
00275 m_pIPBlockList->insertIP( pHashEntry->peerIP );
00276 CAXMLErrorMessage msg(CAXMLErrorMessage::ERR_NO_BALANCE);
00277 DOM_Document doc;
00278 msg.toXmlDocument(doc);
00279 pAccInfo->pControlChannel->sendMessage(doc);
00280 pAccInfo->authFlags |= AUTH_FATAL_ERROR;
00281 m_Mutex.unlock();
00282 return 3;
00283 }
00284 else
00285 {
00286 m_Mutex.unlock();
00287 return 1;
00288 }
00289 }
00290 else if(now.tv_sec >= pAccInfo->lastRequestSeconds + REQUEST_TIMEOUT)
00291 {
00292
00293
00294 DOM_Document doc;
00295 #ifdef DEBUG
00296 CAMsg::printMsg(LOG_DEBUG, "AccountingInstance sending REMINDER balance request.\n");
00297 #endif
00298 makeBalanceRequest((SINT32)now.tv_sec-600, doc);
00299 pAccInfo->reqbalMinSeconds = now.tv_sec - 600;
00300 pAccInfo->pControlChannel->sendMessage(doc);
00301 pAccInfo->authFlags |= AUTH_SENT_SECOND_BALANCE_REQUEST;
00302 pAccInfo->lastRequestSeconds = now.tv_sec;
00303 m_Mutex.unlock();
00304 return 1;
00305 }
00306 else
00307 {
00308 m_Mutex.unlock();
00309 return 1;
00310 }
00311 }
00312 else
00313 {
00314
00315 DOM_Document doc;
00316 makeBalanceRequest(now.tv_sec-600, doc);
00317 #ifdef DEBUG
00318 CAMsg::printMsg(LOG_DEBUG, "AccountingInstance sending balance request.\n");
00319 #endif
00320 pAccInfo->reqbalMinSeconds = now.tv_sec - 600;
00321 pAccInfo->pControlChannel->sendMessage(doc);
00322 pAccInfo->authFlags |= AUTH_SENT_BALANCE_REQUEST;
00323 pAccInfo->lastRequestSeconds = now.tv_sec;
00324 m_Mutex.unlock();
00325 return 1;
00326 }
00327 }
00328 else
00329 {
00330
00331 m_Mutex.unlock();
00332 return 1;
00333 }
00334 }
00335 }
00336 else
00337 {
00338
00339
00340
00341 if(pAccInfo->authFlags & AUTH_SENT_ACCOUNT_REQUEST)
00342 {
00343 if(pAccInfo->authFlags & AUTH_SENT_SECOND_ACCOUNT_REQUEST)
00344 {
00345
00346 if(now.tv_sec >= pAccInfo->lastRequestSeconds + REQUEST_TIMEOUT)
00347 {
00348
00349 #ifdef DEBUG
00350 CAMsg::printMsg( LOG_DEBUG, "Accounting instance: User refused "
00351 "to send account certificate.(request timeout)\n");
00352 #endif
00353 CAXMLErrorMessage msg(CAXMLErrorMessage::ERR_NO_ACCOUNTCERT);
00354 DOM_Document doc;
00355 msg.toXmlDocument(doc);
00356 pAccInfo->pControlChannel->sendMessage(doc);
00357 pAccInfo->authFlags |= AUTH_FATAL_ERROR;
00358 m_Mutex.unlock();
00359 return 2;
00360 }
00361 m_Mutex.unlock();
00362 return 1;
00363 }
00364 if(now.tv_sec >= pAccInfo->lastRequestSeconds + REQUEST_TIMEOUT)
00365 {
00366
00367 #ifdef DEBUG
00368 CAMsg::printMsg(LOG_DEBUG, "AccountingInstance sending REMINDER account request.\n");
00369 #endif
00370 DOM_Document doc;
00371 makeAccountRequest(doc);
00372 pAccInfo->pControlChannel->sendMessage(doc);
00373 pAccInfo->authFlags |= AUTH_SENT_SECOND_ACCOUNT_REQUEST;
00374 pAccInfo->lastRequestSeconds = now.tv_sec;
00375 }
00376 m_Mutex.unlock();
00377 return 1;
00378 }
00379 else
00380 {
00381
00382 #ifdef DEBUG
00383 CAMsg::printMsg(LOG_DEBUG, "AccountingInstance sending account request.\n");
00384 #endif
00385 DOM_Document doc;
00386 makeAccountRequest(doc);
00387 pAccInfo->pControlChannel->sendMessage(doc);
00388 pAccInfo->authFlags |= AUTH_SENT_ACCOUNT_REQUEST;
00389 pAccInfo->lastRequestSeconds = now.tv_sec;
00390 m_Mutex.unlock();
00391 return 1;
00392 }
00393 }
00394 CAMsg::printMsg(LOG_ERR,
00395 "Unknown error in CAAccountingInstance::handleJapPacket()."
00396 "..... this should never happen!\n"
00397 );
00398 return 4;
00399 }
00400
00401
00402
00403 SINT32 CAAccountingInstance::makeCCRequest(const UINT64 accountNumber, const UINT64 transferredBytes, DOM_Document& doc)
00404 {
00405
00406 doc = DOM_Document::createDocument();
00407 DOM_Element elemRoot = doc.createElement("PayRequest");
00408 elemRoot.setAttribute("version", "1.0");
00409 doc.appendChild(elemRoot);
00410
00411 DOM_Element elemCC = doc.createElement("CC");
00412 elemCC.setAttribute("version", "1.0");
00413 elemRoot.appendChild(elemCC);
00414
00415 DOM_Element elemAiName = doc.createElement("AiID");
00416 setDOMElementValue(elemAiName, m_AiName);
00417 elemCC.appendChild(elemAiName);
00418
00419 DOM_Element elemAccount = doc.createElement("AccountNumber");
00420 setDOMElementValue(elemAccount, (UINT64)accountNumber);
00421 elemCC.appendChild(elemAccount);
00422
00423 DOM_Element elemBytes = doc.createElement("TransferredBytes");
00424 setDOMElementValue(elemBytes, transferredBytes);
00425 elemCC.appendChild(elemBytes);
00426
00427 return E_SUCCESS;
00428 }
00429
00430
00431 SINT32 CAAccountingInstance::makeBalanceRequest(const SINT32 seconds, DOM_Document &doc)
00432 {
00433 UINT8 timeBuf[128];
00434 UINT32 timeBufLen = 128;
00435
00436 doc = DOM_Document::createDocument();
00437 DOM_Element elemRoot = doc.createElement("PayRequest");
00438 elemRoot.setAttribute("version", "1.0");
00439 doc.appendChild(elemRoot);
00440 DOM_Element elemAcc = doc.createElement("BalanceRequest");
00441 elemRoot.appendChild(elemAcc);
00442 DOM_Element elemDate = doc.createElement("NewerThan");
00443 elemAcc.appendChild(elemDate);
00444 formatJdbcTimestamp(seconds, timeBuf, timeBufLen);
00445 setDOMElementValue(elemDate, timeBuf);
00446 return E_SUCCESS;
00447 }
00448
00449
00450 SINT32 CAAccountingInstance::makeAccountRequest(DOM_Document &doc)
00451 {
00452 doc = DOM_Document::createDocument();
00453 DOM_Element elemRoot = doc.createElement("PayRequest");
00454 elemRoot.setAttribute("version", "1.0");
00455 doc.appendChild(elemRoot);
00456 DOM_Element elemAcc = doc.createElement("AccountRequest");
00457 elemRoot.appendChild(elemAcc);
00458 return E_SUCCESS;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467 THREAD_RETURN CAAccountingInstance::aiThreadMainLoop( void *param )
00468 {
00469 CAAccountingInstance * instance;
00470 aiQueueItem item;
00471 UINT32 itemSize;
00472 instance = ( CAAccountingInstance * ) param;
00473 CAMsg::printMsg( LOG_DEBUG, "AI Thread starting\n" );
00474
00475 while ( instance->m_bThreadRunning )
00476 {
00477 itemSize = sizeof( aiQueueItem );
00478 instance->m_pQueue->getOrWait( (UINT8*)&item, &itemSize );
00479 instance->processJapMessage( item.pHashEntry, item.pDomDoc );
00480
00481 }
00482
00483 return (THREAD_RETURN)0;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 void CAAccountingInstance::processJapMessage(fmHashTableEntry * pHashEntry,DOM_Document * pDomDoc)
00496 {
00497 DOM_Element root = pDomDoc->getDocumentElement();
00498 char * docElementName = root.getTagName().transcode();
00499
00500
00501 if ( strcmp( docElementName, "AccountCertificate" ) == 0 )
00502 {
00503 #ifdef DEBUG
00504 CAMsg::printMsg( LOG_DEBUG, "Received an AccountCertificate. Calling handleAccountCertificate()\n" );
00505 #endif
00506 handleAccountCertificate( pHashEntry, root );
00507 }
00508 else if ( strcmp( docElementName, "Response" ) == 0)
00509 {
00510 #ifdef DEBUG
00511 CAMsg::printMsg( LOG_DEBUG, "Received a Response (challenge-response)\n");
00512 #endif
00513 handleChallengeResponse( pHashEntry, root );
00514 }
00515 else if ( strcmp( docElementName, "CC" ) == 0 )
00516 {
00517 #ifdef DEBUG
00518 CAMsg::printMsg( LOG_DEBUG, "Received a CC. Calling handleCostConfirmation()\n" );
00519 #endif
00520 handleCostConfirmation( pHashEntry, root );
00521 }
00522 else if ( strcmp( docElementName, "Balance" ) == 0 )
00523 {
00524 #ifdef DEBUG
00525 CAMsg::printMsg( LOG_DEBUG, "Received a BalanceCertificate. Calling handleBalanceCertificate()\n" );
00526 #endif
00527 handleBalanceCertificate( pHashEntry, root );
00528 }
00529 else
00530 {
00531 CAMsg::printMsg(
00532 LOG_ERR,
00533 "AI Received XML message with unknown root element \"%s\". Ignoring...\n",
00534 docElementName
00535 );
00536 }
00537 delete pDomDoc;
00538 delete [] docElementName;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 void CAAccountingInstance::handleAccountCertificate(fmHashTableEntry *pHashEntry, DOM_Element &root)
00551 {
00552 aiAccountingInfo * pAccInfo = pHashEntry->pAccountingInfo;
00553 DOM_Element elGeneral;
00554 timespec now;
00555 getcurrentTime(now);
00556
00557
00558 m_Mutex.lock();
00559 if(pAccInfo->authFlags&AUTH_GOT_ACCOUNTCERT)
00560 {
00561 #ifdef DEBUG
00562 CAMsg::printMsg(LOG_DEBUG, "Already got an account cert. Ignoring!");
00563 #endif
00564 CAXMLErrorMessage err(
00565 CAXMLErrorMessage::ERR_BAD_REQUEST,
00566 (UINT8*)"You have already sent an Account Certificate"
00567 );
00568 DOM_Document errDoc;
00569 err.toXmlDocument(errDoc);
00570 pAccInfo->pControlChannel->sendMessage(errDoc);
00571 m_Mutex.unlock();
00572 return ;
00573 }
00574
00575
00576 if ( getDOMChildByName( root, (UINT8 *)"AccountNumber", elGeneral, false ) != E_SUCCESS ||
00577 getDOMElementValue( elGeneral, pAccInfo->accountNumber ) != E_SUCCESS ||
00578 pAccInfo->accountNumber == 0 )
00579 {
00580 CAMsg::printMsg( LOG_ERR, "AccountCertificate has wrong or no accountnumber. Ignoring\n");
00581 CAXMLErrorMessage err(CAXMLErrorMessage::ERR_WRONG_FORMAT);
00582 DOM_Document errDoc;
00583 err.toXmlDocument(errDoc);
00584 pAccInfo->pControlChannel->sendMessage(errDoc);
00585 m_Mutex.unlock();
00586 return ;
00587 }
00588
00589
00590 if ( getDOMChildByName( root, (UINT8 *)"JapPublicKey", elGeneral, false ) != E_SUCCESS )
00591 {
00592 CAMsg::printMsg( LOG_ERR, "AccountCertificate contains no public key. Ignoring\n");
00593 CAXMLErrorMessage err(CAXMLErrorMessage::ERR_KEY_NOT_FOUND);
00594 DOM_Document errDoc;
00595 err.toXmlDocument(errDoc);
00596 pAccInfo->pControlChannel->sendMessage(errDoc);
00597 m_Mutex.unlock();
00598 return ;
00599 }
00600 #ifdef DEBUG
00601 UINT8* aij;
00602 UINT32 aijsize;
00603 aij = DOM_Output::dumpToMem(elGeneral, &aijsize);
00604 aij[aijsize-1]=0;
00605 CAMsg::printMsg( LOG_DEBUG, "Setting user public key %s>\n", aij );
00606 delete[] aij;
00607 #endif
00608 pAccInfo->pPublicKey = new CASignature();
00609 if ( pAccInfo->pPublicKey->setVerifyKey( elGeneral ) != E_SUCCESS )
00610 {
00611 CAXMLErrorMessage err(CAXMLErrorMessage::ERR_INTERNAL_SERVER_ERROR);
00612 DOM_Document errDoc;
00613 err.toXmlDocument(errDoc);
00614 pAccInfo->pControlChannel->sendMessage(errDoc);
00615 m_Mutex.unlock();
00616 return ;
00617 }
00618
00619 if ( (!m_pJpiVerifyingInstance)||
00620 (m_pJpiVerifyingInstance->verifyXML( (DOM_Node &)root, (CACertStore *)NULL ) != E_SUCCESS ))
00621 {
00622
00623 CAMsg::printMsg( LOG_INFO, "CAAccountingInstance::handleAccountCertificate(): Bad Jpi signature\n" );
00624 CAXMLErrorMessage err(CAXMLErrorMessage::ERR_BAD_SIGNATURE, (UINT8*)"Your account certificate is invalid");
00625 DOM_Document errDoc;
00626 err.toXmlDocument(errDoc);
00627 pAccInfo->pControlChannel->sendMessage(errDoc);
00628 pAccInfo->authFlags |= AUTH_FAKE | AUTH_GOT_ACCOUNTCERT;
00629 pAccInfo->authFlags &= ~AUTH_ACCOUNT_OK;
00630 m_Mutex.unlock();
00631 return ;
00632 }
00633
00634 UINT8 * arbChallenge;
00635 UINT8 b64Challenge[ 512 ];
00636 UINT32 b64Len = 512;
00637
00638
00639 arbChallenge = ( UINT8* ) malloc( 222 );
00640 getRandom( arbChallenge, 222 );
00641 CABase64::encode( arbChallenge, 222, b64Challenge, &b64Len );
00642 if ( pAccInfo->pChallenge != NULL )
00643 delete[] pAccInfo->pChallenge;
00644 pAccInfo->pChallenge = arbChallenge;
00645
00646
00647 DOM_Document doc = DOM_Document::createDocument();
00648 DOM_Element elemRoot = doc.createElement( "Challenge" );
00649 DOM_Element elemPanic = doc.createElement( "DontPanic" );
00650 elemPanic.setAttribute( "version", "1.0" );
00651 doc.appendChild( elemRoot );
00652 elemRoot.appendChild( elemPanic );
00653 setDOMElementValue( elemPanic, b64Challenge );
00654
00655
00656 pAccInfo->pControlChannel->sendMessage(doc);
00657 pAccInfo->authFlags = AUTH_CHALLENGE_SENT | AUTH_GOT_ACCOUNTCERT;
00658 pAccInfo->lastRequestSeconds = now.tv_sec;
00659 m_Mutex.unlock();
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 void CAAccountingInstance::handleChallengeResponse(fmHashTableEntry *pHashEntry, const DOM_Element &root)
00671 {
00672 UINT8 decodeBuffer[ 512 ];
00673 UINT32 decodeBufferLen = 512;
00674 UINT32 usedLen;
00675 DOM_Element elemPanic;
00676
00677 aiAccountingInfo * pAccInfo = pHashEntry->pAccountingInfo;
00678
00679
00680 m_Mutex.lock();
00681 if( (!(pAccInfo->authFlags & AUTH_GOT_ACCOUNTCERT)) ||
00682 (!(pAccInfo->authFlags & AUTH_CHALLENGE_SENT))
00683 )
00684 {
00685 m_Mutex.unlock();
00686 return ;
00687 }
00688 pAccInfo->authFlags &= ~AUTH_CHALLENGE_SENT;
00689
00690
00691
00692 if ( getDOMElementValue( root, decodeBuffer, &decodeBufferLen ) != E_SUCCESS )
00693 {
00694 CAMsg::printMsg( LOG_DEBUG, "ChallengeResponse has wrong XML format. Ignoring\n" );
00695 return ;
00696 }
00697 usedLen = decodeBufferLen;
00698 decodeBufferLen = 512;
00699 CABase64::decode( decodeBuffer, usedLen, decodeBuffer, &decodeBufferLen );
00700
00701
00702
00703
00704 CASignature * sigTester = pHashEntry->pAccountingInfo->pPublicKey;
00705 #pragma message Signature verifying must be implemented here !!!!!!!!!!
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 pAccInfo->authFlags |= AUTH_ACCOUNT_OK;
00723
00724
00725 CAXMLCostConfirmation * pCC = NULL;
00726 m_dbInterface->getCostConfirmation(pAccInfo->accountNumber, &pCC);
00727 if(pCC!=NULL)
00728 {
00729 pAccInfo->transferredBytes += pCC->getTransferredBytes();
00730 #ifdef DEBUG
00731 CAMsg::printMsg(LOG_DEBUG, "TransferredBytes is now %lld\n", pAccInfo->transferredBytes);
00732 #endif
00733 pAccInfo->confirmedBytes = pCC->getTransferredBytes();
00734 delete pCC;
00735 }
00736
00737 if ( pHashEntry->pAccountingInfo->pChallenge != NULL )
00738 {
00739 delete[] pHashEntry->pAccountingInfo->pChallenge;
00740 pHashEntry->pAccountingInfo->pChallenge = NULL;
00741 }
00742 m_Mutex.unlock();
00743 }
00744
00745
00746
00747
00748
00749
00750 void CAAccountingInstance::handleCostConfirmation(fmHashTableEntry *pHashEntry,DOM_Element &root)
00751 {
00752 aiAccountingInfo *pAccInfo;
00753
00754 pAccInfo = pHashEntry->pAccountingInfo;
00755 m_Mutex.lock();
00756
00757
00758 if( (!pAccInfo->authFlags & AUTH_GOT_ACCOUNTCERT) ||
00759 (!pAccInfo->authFlags & AUTH_ACCOUNT_OK))
00760 {
00761 m_Mutex.unlock();
00762 return ;
00763 }
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 CAXMLCostConfirmation cc(root);
00783
00784
00785 if( cc.verifySignature( *(pAccInfo->pPublicKey)) != E_SUCCESS)
00786 {
00787
00788 CAMsg::printMsg( LOG_INFO, "CostConfirmation has INVALID SIGNATURE! (IGNORING)\n" );
00789
00790
00791
00792
00793
00794
00795 }
00796 #ifdef DEBUG
00797 else
00798 {
00799 CAMsg::printMsg( LOG_DEBUG, "CostConfirmation Signature is OK.\n");
00800 }
00801 #endif
00802 m_Mutex.unlock();
00803
00804
00805
00806 UINT8 * pAiID = cc.getAiID();
00807 if( strcmp( (char *)pAiID, (char *)m_AiName ) != 0)
00808 {
00809 CAMsg::printMsg( LOG_INFO, "CostConfirmation has wrong AIName %s. Ignoring...\n", pAiID );
00810 CAXMLErrorMessage err(CAXMLErrorMessage::ERR_WRONG_DATA, (UINT8*)"Your CostConfirmation has a wrong AI name");
00811 DOM_Document errDoc;
00812 err.toXmlDocument(errDoc);
00813 pAccInfo->pControlChannel->sendMessage(errDoc);
00814 delete[] pAiID;
00815 return ;
00816 }
00817 delete[] pAiID;
00818
00819
00820 m_Mutex.lock();
00821 if(cc.getTransferredBytes() < pAccInfo->confirmedBytes )
00822 {
00823 CAMsg::printMsg( LOG_INFO, "CostConfirmation has Wrong Number of Bytes (%lld). Ignoring...\n", cc.getTransferredBytes() );
00824 CAXMLErrorMessage err(CAXMLErrorMessage::ERR_WRONG_DATA,
00825 (UINT8*)"Your CostConfirmation has a wrong number of transferred bytes");
00826 DOM_Document errDoc;
00827 err.toXmlDocument(errDoc);
00828 pAccInfo->pControlChannel->sendMessage(errDoc);
00829 m_Mutex.unlock();
00830 return ;
00831 }
00832 pAccInfo->confirmedBytes = cc.getTransferredBytes();
00833 if(pAccInfo->confirmedBytes >= pAccInfo->reqConfirmBytes)
00834 {
00835 pAccInfo->authFlags &= ~AUTH_SENT_CC_REQUEST;
00836 pAccInfo->authFlags &= ~AUTH_SENT_SECOND_CC_REQUEST;
00837 }
00838 m_Mutex.unlock();
00839
00840 m_dbInterface->storeCostConfirmation( cc );
00841 return ;
00842 }
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 void CAAccountingInstance::handleBalanceCertificate(fmHashTableEntry *pHashEntry, const DOM_Element &root)
00853 {
00854 CASignature * pSigTester;
00855 UINT8 strGeneral[ 256 ];
00856 UINT32 strGeneralLen = 256;
00857 UINT64 newDeposit, newSpent;
00858 SINT32 seconds;
00859 DOM_Element elGeneral;
00860 aiAccountingInfo * pAccInfo = pHashEntry->pAccountingInfo;
00861
00862
00863
00864 m_Mutex.lock();
00865
00866 if( !m_pJpiVerifyingInstance ||
00867 (m_pJpiVerifyingInstance->verifyXML( (DOM_Node &)root, (CACertStore *)NULL ) != E_SUCCESS)
00868 )
00869 {
00870 CAMsg::printMsg( LOG_INFO, "BalanceCertificate has BAD SIGNATURE! Ignoring\n" );
00871 m_Mutex.unlock();
00872 return ;
00873 }
00874 m_Mutex.unlock();
00875
00876
00877 if ( (getDOMChildByName( root, (UINT8*)"Timestamp", elGeneral, false ) != E_SUCCESS)
00878 || (getDOMElementValue( elGeneral, strGeneral, &strGeneralLen ) != E_SUCCESS) )
00879 {
00880 return ;
00881 }
00882 parseJdbcTimestamp(strGeneral, seconds);
00883
00884 m_Mutex.lock();
00885 if(seconds < pAccInfo->reqbalMinSeconds)
00886 {
00887
00888
00889
00890 m_Mutex.unlock();
00891 return ;
00892 }
00893
00894
00895
00896 if( (getDOMChildByName( root, (UINT8*)"Deposit", elGeneral, false ) != E_SUCCESS) ||
00897 (getDOMElementValue( elGeneral, newDeposit ) != E_SUCCESS) ||
00898 (newDeposit < pAccInfo->lastbalDeposit) )
00899 {
00900 m_Mutex.unlock();
00901 #ifdef DEBUG
00902 CAMsg::printMsg(LOG_DEBUG, "invalid deposit value...");
00903 #endif
00904 return;
00905 }
00906 #ifdef DEBUG
00907 else {
00908 CAMsg::printMsg(LOG_DEBUG, "Balance: deposit=%lld\n", newDeposit);
00909 }
00910 #endif
00911
00912
00913 if( (getDOMChildByName( root, (UINT8*)"Spent", elGeneral, false ) != E_SUCCESS) ||
00914 (getDOMElementValue( elGeneral, newSpent ) != E_SUCCESS) ||
00915 (newSpent < pAccInfo->lastbalSpent) )
00916 {
00917 m_Mutex.unlock();
00918 #ifdef DEBUG
00919 CAMsg::printMsg(LOG_DEBUG, "invalid spent value...");
00920 #endif
00921 return;
00922 }
00923 #ifdef DEBUG
00924 else {
00925 CAMsg::printMsg(LOG_DEBUG, "Balance: Spent=%lld\n", newSpent);
00926 }
00927 #endif
00928
00929
00930 if( (newDeposit-newSpent <= MIN_BALANCE ) ||
00931 ((newDeposit-newSpent-pAccInfo->transferredBytes) <= MIN_BALANCE )
00932 )
00933 {
00934
00935 pAccInfo->authFlags |= AUTH_ACCOUNT_EMPTY;
00936 }
00937
00938 pAccInfo->lastbalDeposit = newDeposit;
00939 pAccInfo->lastbalSpent = newSpent;
00940 pAccInfo->lastbalTransferredBytes = pAccInfo->transferredBytes;
00941
00942
00943 pAccInfo->authFlags &= ~(AUTH_SENT_BALANCE_REQUEST|AUTH_SENT_SECOND_BALANCE_REQUEST);
00944 m_Mutex.unlock();
00945 }
00946
00947
00948
00949
00950
00951
00952 SINT32 CAAccountingInstance::initTableEntry( fmHashTableEntry * pHashEntry )
00953 {
00954 pHashEntry->pAccountingInfo = new aiAccountingInfo;
00955 memset( pHashEntry->pAccountingInfo, 0, sizeof( aiAccountingInfo ) );
00956 return E_SUCCESS;
00957 }
00958
00959
00960
00961
00962
00963
00964
00965
00966 SINT32 CAAccountingInstance::cleanupTableEntry( fmHashTableEntry *pHashEntry )
00967 {
00968 aiAccountingInfo * pAccInfo;
00969 if ( pHashEntry->pAccountingInfo != 0 )
00970 {
00971 pAccInfo = pHashEntry->pAccountingInfo;
00972 if ( pAccInfo->pPublicKey )
00973 {
00974 delete pAccInfo->pPublicKey;
00975 }
00976 if ( pAccInfo->pChallenge )
00977 {
00978 delete [] pAccInfo->pChallenge;
00979 }
00980 delete pHashEntry->pAccountingInfo;
00981 }
00982 return E_SUCCESS;
00983 }
00984
00985
00986
00987 #endif