diff -r 3406c99bc375 -r 07b41fa8d1dd hti/PC_Tools/HTIGateway/HtiGateway/src/HtiDispatcher.cpp --- a/hti/PC_Tools/HTIGateway/HtiGateway/src/HtiDispatcher.cpp Thu Jul 15 20:25:38 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,554 +0,0 @@ -/* -* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: -* This file contains implementation of HtiDispatcher class. -*/ - -#include "stdsoap2.h" //should be first because of WinSock2.h errors - -#include "common.h" -#include "HtiDispatcher.h" -#include "soapHandler.h" - -#include "HtiMessage.h" -#include "util.h" -#include - -#include - -const static char* HTI_PLUGIN_FOLDER = "ServicePlugins/"; -//used to redispatch hti framework error messages (like not authorized) - -/** -* namespace table is needed to correclty send fault messages -* each service plugin should explicitly set its one namespace table before processing -* request -*/ -SOAP_NMAC struct Namespace namespaces[] = -{ - {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope", NULL}, - {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding", NULL}, - {NULL, NULL, NULL, NULL} -}; - -//********************************************************************************** -// Class HtiDispatcher -// -// This class -// -forwards Soap requests and Hti messages to correct SOAPHandlers -// -Is used to initiate SOAPHandlers by reading them from dll's and start them -//********************************************************************************** -HtiDispatcher::HtiDispatcher(SafeQueue* qIn, - SafeQueue* qOut) - : m_Running(true), - m_QueueIn(qIn), - m_QueueOut(qOut), - m_IncomingHtiMessage(NULL) -{ -} - -HtiDispatcher::~HtiDispatcher() -{ - for( htiSoapActionHashMap::const_iterator i = m_SoapHandlers.begin(); - i != m_SoapHandlers.end(); - ++i) - { - delete i->second; - } -} - -/** - * This method is used to read all the available SoapHandler dll's and initialize an instance of them and store a reference to m_SoapHandlers(by soap action) - * and m_HanlersUidMap(by service uid) maps. - */ -void HtiDispatcher::InitHandlers() -{ - Util::Info( "HtiDispatcher::InitHandlers" ); - //1. read exe/plugin directory - WIN32_FIND_DATA FileData; - HANDLE hSearch; - bool fFinished = false; - - // Start searching for .dll files - string searchMask = HTI_PLUGIN_FOLDER; - searchMask.append( "*.dll" ); - hSearch = FindFirstFile( searchMask.c_str(), &FileData ); - if (hSearch == INVALID_HANDLE_VALUE) - { - Util::Info("No DLLs found."); - return; - } - - while (!fFinished) - { - - //2. get list of all DLLs - //SoapHandler* t = new SoapHandler("ws_hti.dll"); - string pluginPath = HTI_PLUGIN_FOLDER; - pluginPath.append( FileData.cFileName ); - Util::Info("Try to load:"); - Util::Info(pluginPath); - SoapHandler* t = new SoapHandler( pluginPath ); - if( t->LoadPlugin() ) - { - //3. add them to m_SoapHandlers - char* soapAction = t->soapAction(); - m_SoapHandlers[ soapAction ] = t; - //add to uid map as well - int uid = t->serviceUID(); - m_HanlersUidMap[ uid ] = t; - - stringstream s; - s<<"Loaded plugin: "; - s<second)->SetDispatcher(this); - (i->second)->Start(); - } -} - -/* - * This loop is used to forward incoming Hti messages(arriving from CommChannelPlugin to m_QueueOut side) to correct SoapHandlers - */ -void HtiDispatcher::Run() -{ - Util::Debug("HtiDispatcher::Run"); - //m_testHandler.SetDispatcher(this); - //m_testHandler.Start(); - InitHandlers(); - StartHandlers(); - - BYTE* shortData = NULL; //keep data if it's too short to have HtiHeader - //or if one Data msg have more than one HtiMessage - DWORD msgBufferSize = 8096; - BYTE* msgBuffer = (BYTE*)malloc( msgBufferSize ); - DWORD shortDataLen = 0; - - // By setting this threads priority below others will give soaphandler threads - // more runtime to process the received messages.. This is to avoid the situation - // where two messages arrive so close to each other that m_hReceiveHtiEvent is - // signalled twice before the first message has even been processed by the soap plugin. - if(!SetThreadPriority( ThreadHandle(), THREAD_PRIORITY_BELOW_NORMAL )) - Util::Info("Warning: Could not set HtiDispatcher priority!"); - - while (m_Running) - { - try - { - Data* d = m_QueueOut->front(50); - BYTE* p = (BYTE *)d->GetData(); - DWORD l = d->GetLength(); - //printf("\td = %d\n", m_QueueOut->size()); - - if (Util::GetVerboseLevel() == Util::VerboseLevel::debug) - { - char tmp[64]; - sprintf(tmp, "[HtiDispatcher] HTI MsgSize = %d", l); - string s(tmp); - Util::Debug(s); - //Util::Hex(p, d->GetLength()); - } - - //Util::Debug("leftovers"); - //copy leftovers to the beginning of the buffer - if ( shortDataLen > 0 ) - { - memcpy( msgBuffer, shortData, shortDataLen ); - } - shortData = msgBuffer; //set shortData to the beginning - - //copy data to buffer - if ( shortDataLen + l > msgBufferSize ) - { - msgBufferSize = shortDataLen + l; - msgBuffer = (BYTE*)realloc(msgBuffer, msgBufferSize); - shortData = msgBuffer; - } - //copy data gotten from queue to the end of shortData - memcpy(shortData + shortDataLen, p, l ); - shortDataLen = l + shortDataLen; - - while ( shortDataLen != 0 && - (shortDataLen >= HtiMessage::MinHeaderSize() || - m_IncomingHtiMessage != NULL ) ) - { - //new message - if ( m_IncomingHtiMessage == NULL ) - { - if ( shortDataLen >= HtiMessage::MinHeaderSize() ) - { - if ( HtiMessage::CheckValidHtiHeader(shortData) ) - { - m_IncomingHtiMessage = new HtiMessage( shortData, shortDataLen ); - - if (Util::GetVerboseLevel() == Util::VerboseLevel::debug) - { - char tmp[64]; - sprintf(tmp,"New hti message %d", m_IncomingHtiMessage->HtiDataSize()); - string s(tmp); - Util::Debug(s); - //Util::Hex(p, d->GetLength()); - } - - //_RPT2(_CRT_WARN, "income msg %x <%d>\n", m_IncomingHtiMessage, sizeof(HtiMessage)); - //check message - if ( m_IncomingHtiMessage->IsMessageComplete() ) - { - Util::Debug("HTI message complete"); - DWORD msgSize = m_IncomingHtiMessage->HtiDataSize(); - if ( msgSize < shortDataLen ) - { - //remove used part - //BYTE* temp = new BYTE[shortDataLen-msgSize]; - //_RPT2(_CRT_WARN, "temp %x <%d>\n", shortData , shortDataLen-msgSize); - //memcpy(temp, shortData + msgSize, shortDataLen-msgSize); - //_RPT1(_CRT_WARN, "del shortData %x\n", shortData); - //delete[] shortData; - //shortData = temp; - shortData += msgSize; //just move pointer - shortDataLen -= msgSize; - - } - else - { - //_RPT1(_CRT_WARN, "del shortData %x\n", shortData); - //delete[] shortData; - //shortData = NULL; - shortDataLen = 0; - } - //Dispatch incoming message - DispatchToSoapHandlers(); - } - else - { - //_RPT1(_CRT_WARN, "del shortData %x\n", shortData); - //delete[] shortData; - //shortData = NULL; - shortDataLen = 0; - } - } - else - { - //invalid header - Util::Error("Invalid HTI header, dismiss Data message"); - Util::Hex(shortData, HtiMessage::MinHeaderSize() ); - //_RPT1(_CRT_WARN, "del shortData %x\n", shortData); - //delete[] shortData; - //shortData = NULL; - shortDataLen = 0; - } - } - } - else //body parts - { - Util::Debug("add"); - DWORD added = m_IncomingHtiMessage->AddToBody( shortData, - shortDataLen ); - //printf("reminder %d\n", m_IncomingHtiMessage->Reminder()); - if ( added < shortDataLen ) - { - //only part of message was added - //remove added part - //BYTE* temp = new BYTE[shortDataLen-added]; - //_RPT2(_CRT_WARN, "temp %x <%d>\n", shortData , shortDataLen-added); - //memcpy(temp, shortData + added, shortDataLen-added); - //_RPT1(_CRT_WARN, "del shortData %x\n", shortData ); - //delete[] shortData; - //shortData = temp; - shortData += added; - shortDataLen -= added; - } - else //all data were added - { - //_RPT1(_CRT_WARN, "del shortData %x\n", shortData ); - //delete[] shortData; - //shortData = NULL; - shortDataLen = 0; - } - - if ( m_IncomingHtiMessage->IsMessageComplete() ) - { - Util::Debug("HTI message complete"); - //Dispatch incoming message - DispatchToSoapHandlers(); - } - } - } - - m_QueueOut->pop(); - //_RPT1(_CRT_WARN, "del data %x\n", d); - delete d; - d = NULL; - } catch (TimeoutException te) - { - //Util::Debug("[DataGatewaySocketWriterThread]timeout exception"); - } - } - free( msgBuffer ); -} - -/** - * This method is used to forward the incoming HTI message to correct SoapHandler - * The correct SoapHandler is found by service uid - */ -void HtiDispatcher::DispatchToSoapHandlers() -{ - htiUIDHashMap::const_iterator i; - int targetServiceUid; - if ( m_IncomingHtiMessage->IsErrorMessage() ) - { - targetServiceUid = m_IncomingHtiMessage->ErrorServiceUid(); - - stringstream s; - s<<"Received HTI error message\nhtiErrorCode: "; - s<HtiErrorCode(); - s<<"\nserviceUid: "; - s<ErrorServiceUid(); - s<<"\nserviceErrorCode: "; - s<ServiceErrorCode(); - s<<"\nErrorDescription: "; - s<ErrorDescription(); - s<<"\ntargetServiceUid: "; - s<GetServiceUID(); - } - - if ( targetServiceUid == HTI_SYSTEM_SERVICE_UID && - m_IncomingHtiMessage->IsErrorMessage() ) - { - Util::Debug("dispatch error"); - //if system plugin doesn't wait for a message then find plugin that - //is waiting for a message and delivery the incoming msg to it - i = m_HanlersUidMap.find( targetServiceUid ); - if ( i != m_HanlersUidMap.end() ) - { - if ( (i->second)->IsWaitsForHtiMessage() ) - { - Util::Debug("dispatch error to system cause it waits"); - if ( !(i->second)->ReceiveHtiMessage(m_IncomingHtiMessage) ) - { - Util::Error("Failed to dispatch hti message"); - Util::Hex(m_IncomingHtiMessage->HtiData(), HtiMessage::MinHeaderSize()); - //dismiss message - delete m_IncomingHtiMessage; - } - } - else - { - Util::Debug("find handler that waits"); - //find the handler that waits for hti message - for( htiUIDHashMap::const_iterator i = m_HanlersUidMap.begin(); - i != m_HanlersUidMap.end(); - ++i) - { - Util::Debug((i->second)->soapAction()); - if ( (i->second)->IsWaitsForHtiMessage() ) - { - Util::Debug("found"); - if ( !(i->second)->ReceiveHtiMessage(m_IncomingHtiMessage) ) - { - Util::Error("Failed to dispatch hti message"); - Util::Hex(m_IncomingHtiMessage->HtiData(), HtiMessage::MinHeaderSize()); - //dismiss message - delete m_IncomingHtiMessage; - } - break; - } - } - } - } - } - else - { - i = m_HanlersUidMap.find( targetServiceUid ); - if ( i != m_HanlersUidMap.end() ) - { - if ( !(i->second)->ReceiveHtiMessage(m_IncomingHtiMessage) ) - { - Util::Error("Failed to dispatch hti message"); - Util::Hex(m_IncomingHtiMessage->HtiData(), HtiMessage::MinHeaderSize()); - //dismiss message - delete m_IncomingHtiMessage; - } - } - else - { - Util::Error("Failed to dispatch hti message, no plug-in with appropriate uid",m_IncomingHtiMessage->GetServiceUID() ); - Util::Hex(m_IncomingHtiMessage->HtiData(), HtiMessage::MinHeaderSize()); - //dismiss message - delete m_IncomingHtiMessage; - } - } - m_IncomingHtiMessage = NULL; - - // This will give other threads (soaphandlers) some runtime to process the - // received message. - Sleep(0); -} - -/* - * This method is used to forward soap request to correct SOAPHandler - * Correct SOAPHandler is found by soap action - */ -bool HtiDispatcher::DispatchSoapServe(struct soap* soapEnv) -{ - Util::Debug("HtiDispatcher::DispatchSoapServe()"); -/* - _CrtMemState localMem; - _CrtMemCheckpoint( &localMem ); -*/ - soap_begin( soapEnv ); - if (soap_begin_recv(soapEnv)) - { - soap_set_namespaces( soapEnv, namespaces); - soap_send_fault(soapEnv); - return false; - } - - if ( !(soapEnv->action) ) - { - //Util::Error("soapAction is missing"); - soap_set_namespaces( soapEnv, namespaces); - soapEnv->error = soap_sender_fault(soapEnv, "soapAction is missing", NULL); - soap_send_fault(soapEnv); - return false; - } -/* - //_RPT0(_CRT_WARN, "!!!!!!!!!!!!!!!! Local Objects !!!!!!!!!!!!!!!!\n"); - - _CrtMemDumpAllObjectsSince( &localMem ); - //_RPT1(_CRT_WARN, "action address %x\n", soapEnv->action); -*/ - htiSoapActionHashMap::const_iterator it; - it = m_SoapHandlers.find( soapEnv->action ); - if ( it != m_SoapHandlers.end() ) - { - return (it->second)->ServeSoap( soapEnv ); - } - else - { - //Util::Error("soapAction is unknown:"); - //Util::Error(soapEnv->action); - //soapEnv->error = SOAP_NO_METHOD; - soap_set_namespaces( soapEnv, namespaces); - soapEnv->error = soap_sender_fault(soapEnv, "No plugin found", "no plugin found for requested service in actionSOAP header field"); - soap_send_fault(soapEnv); - return false; - } - - Util::Debug("HtiDispatcher::DispatchSoapServe() OK"); -} - -/* - * SoapHandler calls this method - * The method creates a Data object from the HtiMessage given as parameter - * and puts the Data object into incoming queue(going eventually to CommChannelPlugin) - */ -void HtiDispatcher::SendHtiMessage(HtiMessage* msg) -{ - Util::Debug("HtiDispatcher::SendHtiMessage()"); - if (msg) - { - Data* d = new Data(msg->HtiData(), msg->HtiDataSize(), Data::EData); - //_RPT2(_CRT_WARN, "d %x <%d>\n", d , sizeof(Data)); - - if (Util::GetVerboseLevel() == Util::VerboseLevel::debug) - { - char tmp[64]; - sprintf(tmp, "[HtiDispatcher] HTI MsgSize = %d", msg->HtiDataSize()); - string s(tmp); - Util::Debug(s); - Util::Hex( (char*)(msg->HtiData()), 16); - } - m_QueueIn->push(d); - //delete msg; - } - Util::Debug("HtiDispatcher::SendHtiMessage() OK"); -} - -void HtiDispatcher::Stop() -{ - m_Running = false; - HANDLE* handles = new HANDLE[ m_SoapHandlers.size() ]; - int h = 0; - for( htiSoapActionHashMap::const_iterator i = m_SoapHandlers.begin(); - i != m_SoapHandlers.end(); - ++i) - { - (i->second)->Stop(); - handles[ h++ ] = (i->second)->ThreadHandle(); - } - - WaitForMultipleObjects(m_SoapHandlers.size(), - handles, - TRUE, - 5000/*g_MaximumShutdownWaitTime*/); - - delete[] handles; -} - -bool HtiDispatcher::IsRunning() -{ - return m_Running; -}