/*
* 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 the License "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:
*
*/
// RegistryImpl.cpp: implementation of the CRegistryImpl class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RegistryImpl.h"
#include "TCErrorConstants.h"
#ifdef _DEBUG
extern BOOL gDoLogging;
#endif
//#define LOG_REGISTRY
#if defined(LOG_REGISTRY) && defined(_DEBUG)
extern char TCDebugMsg[];
extern CServerManager* gManager;
#define TCDEBUGOPEN() if (gDoLogging) { gManager->m_DebugLog->WaitForAccess(); }
#define TCDEBUGLOGS(s) if (gDoLogging) { sprintf(TCDebugMsg,"%s", s); gManager->m_DebugLog->log(TCDebugMsg); }
#define TCDEBUGLOGA1(s, a1) if (gDoLogging) { sprintf(TCDebugMsg, s, a1); gManager->m_DebugLog->log(TCDebugMsg); }
#define TCDEBUGLOGA2(s, a1, a2) if (gDoLogging) { sprintf(TCDebugMsg, s, a1, a2); gManager->m_DebugLog->log(TCDebugMsg); }
#define TCDEBUGLOGA3(s, a1, a2, a3) if (gDoLogging) { sprintf(TCDebugMsg, s, a1, a2, a3); gManager->m_DebugLog->log(TCDebugMsg); }
#define TCDEBUGCLOSE() if (gDoLogging) { gManager->m_DebugLog->ReleaseAccess(); }
#else
#define TCDEBUGOPEN()
#define TCDEBUGLOGS(s)
#define TCDEBUGLOGA1(s, a1)
#define TCDEBUGLOGA2(s, a1, a2)
#define TCDEBUGLOGA3(s, a1, a2, a3)
#define TCDEBUGCLOSE()
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CRegistryImpl::CRegistryImpl()
{
TCDEBUGOPEN();
TCDEBUGLOGS("CRegistryImpl::CRegistryImpl\n");
TCDEBUGCLOSE();
}
CRegistryImpl::CRegistryImpl(DWORD connectionId)
{
TCDEBUGOPEN();
TCDEBUGLOGA1("CRegistryImpl::CRegistryImpl connectionId = %d\n", connectionId);
for (int i = 0; i < MAX_MESSAGE_IDS; i++)
{
m_Registry[i].clist = new IdClientList();
m_Registry[i].clist->clear();
}
char mutexName[200];
sprintf(mutexName, "%s%d", REGISTRY_MUTEX_BASENAME, connectionId);
m_Mutex.Open(mutexName, REGISTRY_MUTEX_TIMEOUT);
TCDEBUGCLOSE();
}
CRegistryImpl::~CRegistryImpl()
{
TCDEBUGOPEN();
TCDEBUGLOGS("CRegistryImpl::~CRegistryImpl\n");
for (int i = 0; i < MAX_MESSAGE_IDS; i++)
{
if (m_Registry[i].clist != NULL)
{
m_Registry[i].clist->clear();
delete m_Registry[i].clist;
}
}
m_Mutex.Close();
TCDEBUGCLOSE();
}
BOOL CRegistryImpl::AddClient(CClient* newClient, long numberIds, BYTE* ids)
{
TCDEBUGOPEN();
TCDEBUGLOGS("CRegistryImpl::AddClient\n");
m_Mutex.Wait();
for (int i = 0; i < numberIds; i++)
{
TCDEBUGLOGA1(" id=%x\n", ids[i]);
m_Registry[ids[i]].clist->push_back(newClient);
}
DumpRegistry();
m_Mutex.Release();
TCDEBUGCLOSE();
return TRUE;
}
BOOL CRegistryImpl::RemoveClient(CClient* client)
{
TCDEBUGOPEN();
TCDEBUGLOGS("CRegistryImpl::RemoveClient\n");
m_Mutex.Wait();
BOOL found = FALSE;
for (int i = 0; i < MAX_MESSAGE_IDS; i++)
{
long num = m_Registry[i].clist->size();
if (num != 0)
{
TCDEBUGLOGA3(" CRegistryImpl::RemoveClient client = %x i = %x num = %d\n", client, i, num);
IdClientList::iterator iter;
for (iter = m_Registry[i].clist->begin(); iter != m_Registry[i].clist->end(); iter++)
{
TCDEBUGLOGA2(" CRegistryImpl::RemoveClient iter = %x *iter = %x\n", iter, *iter);
if (client == *iter)
{
m_Registry[i].clist->erase(iter);
found = TRUE;
break;
}
}
}
}
m_Mutex.Release();
TCDEBUGCLOSE();
return found;
}
void CRegistryImpl::DumpRegistry()
{
for (int i = 0; i < MAX_MESSAGE_IDS; i++)
{
long num = m_Registry[i].clist->size();
if (num != 0)
{
TCDEBUGLOGA2(" CRegistryImpl::DumpRegistry i = %x num = %d\n", i, num);
IdClientList::iterator iter;
for (iter = m_Registry[i].clist->begin(); iter != m_Registry[i].clist->end(); iter++)
{
TCDEBUGLOGA2(" CRegistryImpl::DumpRegistry iter = %x *iter = %x\n", iter, *iter);
}
}
}
}
// fullmessage includes the protocol header
// message is unwrapped from the protocol header
// this is because some clients want the full message and some clients just want the actual message
long CRegistryImpl::RouteMessage(BYTE msgId, BYTE* fullMessage, DWORD fullLen, BYTE* realMessage, DWORD realMessageLen)
{
long err = TCAPI_ERR_NONE;
// TCDEBUGOPEN();
// TCDEBUGLOGS("CRegistryImpl::RouteMessage\n");
// TCDEBUGCLOSE();
m_Mutex.Wait();
if (msgId >= 0 && msgId < MAX_MESSAGE_IDS)
{
long numClients = m_Registry[msgId&0xff].clist->size();
TCDEBUGOPEN();
TCDEBUGLOGA2(" CRegistryImpl::RouteMessage msgId = %x numClients = %d\n", msgId, numClients);
TCDEBUGCLOSE();
if (numClients > 0)
{
IdClientList::iterator iter;
for (iter = m_Registry[msgId&0xff].clist->begin(); iter != m_Registry[msgId&0xff].clist->end(); iter++)
{
CClient* client = *iter;
if (client && client->IsStarted())
{
if (client->IsStreamOpen())
{
CInputStream* stream = client->GetInputStream();
// get unwrap format
if (client->m_Options.unWrapFormat == UNWRAP_LEAVE_HEADERS)
{
// use full message
err = stream->AddMessage(fullLen, fullMessage);
// routing errors here can be input stream overflows
// notify this client right now (no OS error)
if (err != TCAPI_ERR_NONE)
{
client->m_ErrorMonitor->PutError(err, false, 0);
err = TCAPI_ERR_NONE;
}
}
else
{
// use raw message
err = stream->AddMessage(realMessageLen, realMessage);
// routing errors here can be input stream overflows
// notify this client right now (no OS error)
if (err != TCAPI_ERR_NONE)
{
client->m_ErrorMonitor->PutError(err, false, 0);
err = TCAPI_ERR_NONE;
}
}
}
else if (client->IsMessageFileOpen())
{
CMessageFile* file = client->GetMessageFile();
// get unwrap format
if (client->m_Options.unWrapFormat == UNWRAP_LEAVE_HEADERS)
{
// use full message
err = file->AddMessage(fullLen, fullMessage);
// routing errors here can be input stream overflows
// notify this client right now (no OS error)
if (err != TCAPI_ERR_NONE)
{
client->m_ErrorMonitor->PutError(err, false, 0);
err = TCAPI_ERR_NONE;
}
}
else
{
// use raw message
err = file->AddMessage(realMessageLen, realMessage);
// routing errors here can be input stream overflows
// notify this client right now (no OS error)
if (err != TCAPI_ERR_NONE)
{
client->m_ErrorMonitor->PutError(err, false, 0);
err = TCAPI_ERR_NONE;
}
}
}
}
}
}
}
m_Mutex.Release();
return err;
}