connectivity/com.nokia.tcf/native/TCFNative/TCFServer/ConnectionImpl.cpp
changeset 60 9d2210c8eed2
child 366 b054461d2f85
equal deleted inserted replaced
59:c892c53c664e 60:9d2210c8eed2
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 // ConnectionImpl.cpp: implementation of the CConnectionImpl class.
       
    18 //
       
    19 //////////////////////////////////////////////////////////////////////
       
    20 
       
    21 #include "stdafx.h"
       
    22 #include "ConnectionImpl.h"
       
    23 #include "RegistryImpl.h"
       
    24 #include "ServerManager.h"
       
    25 
       
    26 #ifdef _DEBUG
       
    27 extern BOOL gDoLogging;
       
    28 #endif
       
    29 
       
    30 #define LOG_CONNECTION
       
    31 #if defined(LOG_CONNECTION) && defined(_DEBUG)
       
    32 #define TCDEBUGOPEN() if (gDoLogging) { this->m_DebugLog->WaitForAccess(); }
       
    33 #define TCDEBUGLOGS(s) if (gDoLogging) { sprintf(this->m_DebugLogMsg,"%s", s); this->m_DebugLog->log(this->m_DebugLogMsg); }
       
    34 #define TCDEBUGLOGA1(s, a1) if (gDoLogging) { sprintf(this->m_DebugLogMsg, s, a1); this->m_DebugLog->log(this->m_DebugLogMsg); }
       
    35 #define TCDEBUGLOGA2(s, a1, a2) if (gDoLogging) { sprintf(this->m_DebugLogMsg, s, a1, a2); this->m_DebugLog->log(this->m_DebugLogMsg); }
       
    36 #define TCDEBUGLOGA3(s, a1, a2, a3) if (gDoLogging) { sprintf(this->m_DebugLogMsg, s, a1, a2, a3); this->m_DebugLog->log(this->m_DebugLogMsg); }
       
    37 #define TCDEBUGLOGA4(s, a1, a2, a3, a4) if (gDoLogging) { sprintf(this->m_DebugLogMsg, s, a1, a2, a3, a4); this->m_DebugLog->log(this->m_DebugLogMsg); }
       
    38 #define TCDEBUGCLOSE() if (gDoLogging) { this->m_DebugLog->ReleaseAccess(); }
       
    39 #else
       
    40 #define TCDEBUGOPEN()
       
    41 #define TCDEBUGLOGS(s)
       
    42 #define TCDEBUGLOGA1(s, a1)
       
    43 #define TCDEBUGLOGA2(s, a1, a2)
       
    44 #define TCDEBUGLOGA3(s, a1, a2, a3)
       
    45 #define TCDEBUGLOGA4(s, a1, a2, a3, a4)
       
    46 #define TCDEBUGCLOSE()
       
    47 #endif
       
    48 
       
    49 //////////////////////////////////////////////////////////////////////
       
    50 // Construction/Destruction
       
    51 //////////////////////////////////////////////////////////////////////
       
    52 
       
    53 CConnectionImpl::CConnectionImpl()
       
    54 {
       
    55 	m_ConnectSettings = NULL;
       
    56 	m_ClientList = NULL;
       
    57 	m_Status = eDisconnected;
       
    58 	m_Registry = NULL;
       
    59 	m_ConnectionID = 0;
       
    60 	m_OsError = 0;
       
    61 	m_BaseComm = NULL;
       
    62 	m_BaseProtocol = NULL;
       
    63 	m_BaseCommHandle = NULL;
       
    64 	m_BaseProtocolHandle = NULL;
       
    65 
       
    66 	// message processing thread flags and handles
       
    67 	m_MessageProcessorState = MP_NONE;
       
    68 	m_ExitMessageProcessor = false;
       
    69 	m_PauseMessageProcessing = false;
       
    70 	m_StartMessageProcessing = false;
       
    71 	m_hMessageProcessorExittedEvent = NULL;
       
    72 	m_hMessageProcessorStoppedEvent = NULL;
       
    73 	m_hMessageProcessorStartedEvent = NULL;
       
    74 	m_hMessageProcessorThread = NULL;
       
    75 	m_dwMessageProcessorThreadId = 0;
       
    76 
       
    77 	m_NextRetryTime = m_RetryTimeoutTime = 0;
       
    78 
       
    79 	m_NextFlushFileTime = 0;
       
    80 }
       
    81 
       
    82 CConnectionImpl::CConnectionImpl(ConnectData conData, DWORD connectionId)
       
    83 {
       
    84 #ifdef _DEBUG
       
    85 	if (gDoLogging)
       
    86 	{
       
    87 		m_DebugLog = new TCDebugLog("TCF_ConnectionLog", connectionId);
       
    88 		m_DebugLog2 = new TCDebugLog("TCF_ProcessorLog", connectionId);
       
    89 	}
       
    90 	else
       
    91 	{
       
    92 		m_DebugLog = NULL;
       
    93 		m_DebugLog2 = NULL;
       
    94 	}
       
    95 #else
       
    96 	m_DebugLog = NULL;
       
    97 	m_DebugLog2 = NULL;
       
    98 #endif
       
    99 
       
   100 	TCDEBUGOPEN();
       
   101 	TCDEBUGLOGA1("CConnectionImpl::CConnectionImpl id = %d\n", connectionId);
       
   102 
       
   103 	m_ConnectSettings = new ConnectData();
       
   104 
       
   105 	memcpy(m_ConnectSettings, &conData, sizeof(ConnectData));
       
   106 
       
   107 	m_ClientList = new ClientList();
       
   108 	m_ClientList->clear();
       
   109 	m_Status = eDisconnected;
       
   110 	m_Registry = new CRegistryImpl(connectionId);
       
   111 	m_ConnectionID = connectionId;
       
   112 	m_BaseComm = NULL;
       
   113 	m_BaseProtocol = NULL;
       
   114 	m_BaseCommHandle = NULL;
       
   115 	m_BaseProtocolHandle = NULL;
       
   116 
       
   117 	// message processing thread flags and handles
       
   118 	m_MessageProcessorState = MP_NONE;
       
   119 	m_ExitMessageProcessor = false;
       
   120 	m_PauseMessageProcessing = false;
       
   121 	m_StartMessageProcessing = false;
       
   122 
       
   123 	// create named events
       
   124 	char eventName[100];
       
   125 
       
   126 	sprintf(eventName, "%s%d", MESSAGEPROCESSOR_EXITEVENT_BASENAME, connectionId);
       
   127 	m_hMessageProcessorExittedEvent = ::CreateEvent(NULL, FALSE, FALSE, eventName);
       
   128 
       
   129 	sprintf(eventName, "%s%d", MESSAGEPROCESSOR_STOPEVENT_BASENAME, connectionId);
       
   130 	m_hMessageProcessorStoppedEvent = ::CreateEvent(NULL, FALSE, FALSE, eventName);
       
   131 
       
   132 	sprintf(eventName, "%s%d", MESSAGEPROCESSOR_STARTEVENT_BASENAME, connectionId);
       
   133 	m_hMessageProcessorStartedEvent = ::CreateEvent(NULL, FALSE, FALSE, eventName);
       
   134 
       
   135 	m_hMessageProcessorThread = NULL;
       
   136 	m_dwMessageProcessorThreadId = 0;
       
   137 
       
   138 	m_NextRetryTime = m_RetryTimeoutTime = 0;
       
   139 
       
   140 	m_NextFlushFileTime = 0;
       
   141 	m_OsError = 0;
       
   142 
       
   143 	TCDEBUGCLOSE();
       
   144 }
       
   145 CConnectionImpl::~CConnectionImpl()
       
   146 {
       
   147 	TCDEBUGOPEN();
       
   148 	TCDEBUGLOGS("CConnectionImpl::~CConnectionImpl\n");
       
   149 
       
   150 	// terminate the message processor thread if running
       
   151 
       
   152 	if (m_hMessageProcessorThread != NULL)
       
   153 	{
       
   154 		BOOL t = ::TerminateThread(m_hMessageProcessorThread, 0);
       
   155 		::CloseHandle(m_hMessageProcessorThread);
       
   156 	}
       
   157 
       
   158 	if (m_hMessageProcessorExittedEvent != NULL)
       
   159 	{
       
   160 		::CloseHandle(m_hMessageProcessorExittedEvent);
       
   161 	}
       
   162 
       
   163 	if (m_hMessageProcessorStoppedEvent != NULL)
       
   164 	{
       
   165 		::CloseHandle(m_hMessageProcessorStoppedEvent);
       
   166 	}
       
   167 
       
   168 	if (m_ConnectSettings)
       
   169 		delete m_ConnectSettings;
       
   170 
       
   171 
       
   172 	if (m_ClientList)
       
   173 	{
       
   174 		m_ClientList->clear();
       
   175 		delete m_ClientList;
       
   176 	}
       
   177 
       
   178 	if (m_Registry)
       
   179 	{
       
   180 		delete m_Registry;
       
   181 	}
       
   182 
       
   183 	if (m_BaseComm)
       
   184 	{
       
   185 		delete m_BaseComm;
       
   186 	}
       
   187 
       
   188 	if (m_BaseCommHandle)
       
   189 	{
       
   190 		::FreeLibrary(m_BaseCommHandle);
       
   191 	}
       
   192 	if (m_BaseProtocol)
       
   193 	{
       
   194 		delete m_BaseProtocol;
       
   195 	}
       
   196 
       
   197 	if (m_BaseProtocolHandle)
       
   198 	{
       
   199 		::FreeLibrary(m_BaseProtocolHandle);
       
   200 	}
       
   201 
       
   202 	TCDEBUGCLOSE();
       
   203 	if (m_DebugLog)
       
   204 		delete m_DebugLog;
       
   205 	if (m_DebugLog2)
       
   206 		delete m_DebugLog2;
       
   207 
       
   208 }
       
   209 
       
   210 BOOL CConnectionImpl::IsEqual(CConnection* connection)
       
   211 {
       
   212 	TCDEBUGOPEN();
       
   213 	TCDEBUGLOGS("CConnectionImpl::IsEqual\n");
       
   214 
       
   215 	BOOL equal = FALSE;
       
   216 
       
   217 	if (strcmp(m_ConnectSettings->connectType, connection->m_ConnectSettings->connectType) == 0)
       
   218 	{
       
   219 		if (m_BaseComm)
       
   220 		{
       
   221 			if (m_BaseComm->IsConnectionEqual(connection->m_ConnectSettings))
       
   222 			{
       
   223 				equal = TRUE;
       
   224 			}
       
   225 		}
       
   226 		else
       
   227 		{
       
   228 			equal = TRUE;
       
   229 		}
       
   230 	}
       
   231 
       
   232 	TCDEBUGCLOSE();
       
   233 	return equal;
       
   234 }
       
   235 
       
   236 BOOL CConnectionImpl::IsEqual(pConnectData pConData)
       
   237 {
       
   238 	TCDEBUGOPEN();
       
   239 	TCDEBUGLOGS("CConnectionImpl::IsEqual\n");
       
   240 
       
   241 	BOOL equal = FALSE;
       
   242 
       
   243 	if (strcmp(m_ConnectSettings->connectType, pConData->connectType) == 0)
       
   244 	{
       
   245 		if (m_BaseComm)
       
   246 		{
       
   247 			if (m_BaseComm->IsConnectionEqual(pConData))
       
   248 			{
       
   249 				equal = TRUE;
       
   250 			}
       
   251 		}
       
   252 		else
       
   253 		{
       
   254 			equal = TRUE;
       
   255 		}
       
   256 	}
       
   257 	TCDEBUGCLOSE();
       
   258 	return equal;
       
   259 }
       
   260 
       
   261 long CConnectionImpl::DoConnect()
       
   262 {
       
   263 	TCDEBUGOPEN();
       
   264 	TCDEBUGLOGS("CConnectionImpl::DoConnect\n");
       
   265 
       
   266 	long ret = TCAPI_ERR_NONE;
       
   267 
       
   268 	if (m_BaseComm && m_BaseProtocol)
       
   269 	{
       
   270 		ret = m_BaseComm->OpenPort();
       
   271 		if (ret != TCAPI_ERR_NONE)
       
   272 		{
       
   273 			m_OsError = m_BaseComm->m_lastCommError;
       
   274 			TCDEBUGLOGA1(" m_BaseComm->OpenPort = %d\n", ret);
       
   275 		}
       
   276 	}
       
   277 	else
       
   278 	{
       
   279 		ret = TCAPI_ERR_UNKNOWN_MEDIA_TYPE;
       
   280 	}
       
   281 
       
   282 	if (ret == TCAPI_ERR_NONE)
       
   283 	{
       
   284 		m_Status = eConnected;
       
   285 
       
   286 		TCDEBUGCLOSE();
       
   287 
       
   288 		StartProcessing();
       
   289 	}
       
   290 	else
       
   291 	{
       
   292 //		if (m_BaseComm != NULL)
       
   293 //		{
       
   294 //			delete m_BaseComm;
       
   295 //			m_BaseComm = NULL;
       
   296 //		}
       
   297 		TCDEBUGCLOSE();
       
   298 	}
       
   299 	return ret;
       
   300 }
       
   301 
       
   302 long CConnectionImpl::DoDisconnect()
       
   303 {
       
   304 	TCDEBUGOPEN();
       
   305 	TCDEBUGLOGS("CConnectionImpl::DoDisconnect\n");
       
   306 
       
   307 	long ret = TCAPI_ERR_NONE;
       
   308 	if (IsConnected())
       
   309 	{
       
   310 		ret = m_BaseComm->ClosePort();
       
   311 //		delete m_BaseComm;
       
   312 //		m_BaseComm = NULL;
       
   313 	}
       
   314 	m_Status = eDisconnected;
       
   315 
       
   316 	TCDEBUGCLOSE();
       
   317 	return ret;
       
   318 }
       
   319 
       
   320 BOOL CConnectionImpl::AddClient(CClient* client)
       
   321 {
       
   322 	TCDEBUGOPEN();
       
   323 	TCDEBUGLOGS("CConnectionImpl::AddClient\n");
       
   324 
       
   325 	BOOL ok = TRUE;
       
   326 
       
   327 	m_ClientList->push_back(client);
       
   328 
       
   329 	TCDEBUGCLOSE();
       
   330 	return ok;
       
   331 }
       
   332 
       
   333 long CConnectionImpl::DoSendMessage(long encodeOption, BYTE protocolVersion, BOOL useMsgId, BYTE msgId, DWORD msgLength, BYTE* pMsg)
       
   334 {
       
   335 	TCDEBUGOPEN();
       
   336 	TCDEBUGLOGS("CConnectionImpl::DoSendMessage\n");
       
   337 
       
   338 	long err = TCAPI_ERR_NONE;
       
   339 	if (IsRetryInProgress())
       
   340 	{
       
   341 		err = TCAPI_ERR_COMM_RETRY_IN_PROGRESS;
       
   342 	}
       
   343 	else if (IsRetryTimedOut())
       
   344 	{
       
   345 		err = TCAPI_ERR_COMM_TIMEOUT;
       
   346 	}
       
   347 	else if (m_Status == eConnected)
       
   348 	{
       
   349 		BYTE* encodedMessage = new BYTE[msgLength + 40]; // add enough for header (msgLength may be 0)
       
   350 		// if msgLength == 0, then encodeOption SHOULD be ENCODE_FORMAT since com expects to send something!
       
   351 		if (encodeOption == ENCODE_FORMAT)
       
   352 		{
       
   353 #ifdef _DEBUG
       
   354 			char msg[200]; msg[0] = '\0';
       
   355 			int len = (msgLength > 30) ? 30 : msgLength;
       
   356 			for (int i = 0; i < len; i ++)
       
   357 			{
       
   358 				sprintf(msg, "%s%02.2x ", msg, pMsg[i]);
       
   359 			}
       
   360 			sprintf(msg, "%s\n", msg);
       
   361 			TCDEBUGLOGS(msg);
       
   362 #endif
       
   363 			// msgLength maybe 0 and pMsg maybe NULL (we're not sending a raw message, just a protocol header)
       
   364 			msgLength = m_BaseProtocol->EncodeMessage(pMsg, msgLength, protocolVersion, msgId, encodedMessage, msgLength+40);
       
   365 #ifdef _DEBUG
       
   366 			msg[0] = '\0';
       
   367 			len = (msgLength > 30) ? 30 : msgLength;
       
   368 			for (i = 0; i < len; i ++)
       
   369 			{
       
   370 				sprintf(msg, "%s%02.2x ", msg, encodedMessage[i]);
       
   371 			}
       
   372 			sprintf(msg, "%s\n", msg);
       
   373 			TCDEBUGLOGS(msg);
       
   374 #endif
       
   375 			err = m_BaseComm->SendDataToPort(msgLength, encodedMessage);
       
   376 		}
       
   377 		else
       
   378 		{
       
   379 #ifdef _DEBUG
       
   380 			char msg[200]; msg[0] = '\0';
       
   381 			int len = (msgLength > 30) ? 30 : msgLength;
       
   382 			for (int i = 0; i < len; i ++)
       
   383 			{
       
   384 				sprintf(msg, "%s%02.2x ", msg, pMsg[i]);
       
   385 			}
       
   386 			sprintf(msg, "%s\n", msg);
       
   387 			TCDEBUGLOGS(msg);
       
   388 #endif
       
   389 			// msgLength != 0 and pMsg != NULL
       
   390 			err = m_BaseComm->SendDataToPort(msgLength, pMsg);
       
   391 		}
       
   392 		delete[] encodedMessage;
       
   393 
       
   394 		TCDEBUGLOGS("CConnectionImpl::DoSendMessage done\n");
       
   395 		if (err == TCAPI_ERR_COMM_ERROR)
       
   396 		{
       
   397 			EnterRetryPeriod(err, true, m_BaseComm->m_lastCommError);
       
   398 			m_OsError = m_BaseComm->m_lastCommError;
       
   399 		}
       
   400 	}
       
   401 	else
       
   402 	{
       
   403 		err = TCAPI_ERR_MEDIA_NOT_OPEN;
       
   404 	}
       
   405 
       
   406 	TCDEBUGLOGA1("CConnectionImpl::DoSendMessage err = %d\n", err);
       
   407 	TCDEBUGCLOSE();
       
   408 	return err;
       
   409 }
       
   410 
       
   411 long CConnectionImpl::DoRetryProcessing()
       
   412 {
       
   413 	long err = TCAPI_ERR_NONE;
       
   414 
       
   415 	// if not connected
       
   416 	//   return no error
       
   417 	if (m_BaseComm == NULL /*|| m_BaseComm->IsConnected() == false*/)
       
   418 		return TCAPI_ERR_MEDIA_NOT_OPEN;
       
   419 
       
   420 	// if retry not in progress && retry not timed out
       
   421 	//   return no error
       
   422 	if (!IsRetryInProgress() && !IsRetryTimedOut())
       
   423 		return TCAPI_ERR_NONE;
       
   424 
       
   425 //	TCDEBUGOPEN();
       
   426 //	TCDEBUGLOGS("CConnectionImpl::DoRetryProcessing\n");
       
   427 //	TCDEBUGCLOSE();
       
   428 	// if retry timeout flag already set
       
   429 	//   return timeout error
       
   430 	if (IsRetryTimedOut())
       
   431 		return TCAPI_ERR_COMM_TIMEOUT;
       
   432 
       
   433 	// get current time
       
   434 	time_t ctime;
       
   435 	time(&ctime);
       
   436 	// if retry timeout period has expired
       
   437 	if (ctime >= m_RetryTimeoutTime)
       
   438 	{
       
   439 		TCDEBUGOPEN();
       
   440 		TCDEBUGLOGS("CConnectionImpl::DoRetryProcessing retry timeout\n");
       
   441 		TCDEBUGCLOSE();
       
   442 		// send timeout error to all clients
       
   443 		NotifyClientsCommError(TCAPI_ERR_COMM_TIMEOUT);
       
   444 		// close comm port
       
   445 		m_BaseComm->ClosePort();
       
   446 		// set retry timeout flag
       
   447 		SetRetryTimedOut();
       
   448 		// return retry timeout error
       
   449 		err = TCAPI_ERR_COMM_TIMEOUT;
       
   450 	}
       
   451 	// else if retry time has passed
       
   452 	else if (ctime >= m_NextRetryTime)
       
   453 	{
       
   454 		TCDEBUGOPEN();
       
   455 		TCDEBUGLOGS("CConnectionImpl::DoRetryProcessing retry time\n");
       
   456 		TCDEBUGCLOSE();
       
   457 		// close comm port
       
   458 		// reopen comm port
       
   459 		m_BaseComm->ClosePort();
       
   460 		int openErr = m_BaseComm->OpenPort();
       
   461 		// if comm error
       
   462 		if (openErr != TCAPI_ERR_NONE)
       
   463 		{
       
   464 			// set next retry time
       
   465 			// return comm error
       
   466 			m_NextRetryTime = ctime + m_ConnectSettings->retryInterval;
       
   467 			err = TCAPI_ERR_COMM_RETRY_IN_PROGRESS;
       
   468 			m_OsError = m_BaseComm->m_lastCommError;
       
   469 		}
       
   470 		else
       
   471 		{
       
   472 		TCDEBUGOPEN();
       
   473 		TCDEBUGLOGS("CConnectionImpl::DoRetryProcessing reconnected\n");
       
   474 		TCDEBUGCLOSE();
       
   475 			// send reconnect warning to all clients
       
   476 			NotifyClientsCommError(TCAPI_INFO_COMM_RECONNECTED);
       
   477 			// set connected
       
   478 			SetConnected();
       
   479 			err = TCAPI_ERR_NONE;
       
   480 		}
       
   481 	} 
       
   482 	else // still in retry
       
   483 	{
       
   484 		err = TCAPI_ERR_COMM_RETRY_IN_PROGRESS;
       
   485 	}
       
   486 
       
   487 
       
   488 //	TCDEBUGOPEN();
       
   489 //	TCDEBUGLOGA1("CConnectionImpl::DoRetryProcessing err = %d\n", err);
       
   490 //	TCDEBUGCLOSE();
       
   491 	return err;
       
   492 }
       
   493 long CConnectionImpl::EnterRetryPeriod(long commErr, bool passOsErr, DWORD osErr)
       
   494 {
       
   495 	TCDEBUGOPEN();
       
   496 	TCDEBUGLOGS("CConnectionImpl::EnterRetryPeriod\n");
       
   497 	TCDEBUGCLOSE();
       
   498 
       
   499 	long err = TCAPI_ERR_NONE;
       
   500 
       
   501 	// set next retry time
       
   502 	time_t ctime;
       
   503 	time(&ctime);
       
   504 	m_NextRetryTime = ctime + m_ConnectSettings->retryInterval;
       
   505 	// set retry timeout time
       
   506 	m_RetryTimeoutTime = ctime + m_ConnectSettings->retryTimeout;
       
   507 	// send comm error to all clients
       
   508 	NotifyClientsCommError(commErr, passOsErr, osErr);
       
   509 	// set retry in progress flag
       
   510 	SetRetryInProgress();
       
   511 
       
   512 	return err;
       
   513 }
       
   514 
       
   515 BOOL CConnectionImpl::RemoveClient(CClient* client)
       
   516 {
       
   517 	TCDEBUGOPEN();
       
   518 	TCDEBUGLOGS("CConnectionImpl::RemoveClient\n");
       
   519 
       
   520 	BOOL found = FALSE;
       
   521 
       
   522 	if (m_ClientList->size() != 0)
       
   523 	{
       
   524 		ClientList::iterator iter;
       
   525 		for (iter = m_ClientList->begin(); iter != m_ClientList->end(); iter++)
       
   526 		{
       
   527 			if ((*iter)->GetClientId() == client->GetClientId())
       
   528 			{
       
   529 				m_ClientList->erase(iter);
       
   530 				found = TRUE;
       
   531 				break;
       
   532 			}
       
   533 		}
       
   534 	}
       
   535 
       
   536 	TCDEBUGCLOSE();
       
   537 	return found;
       
   538 }
       
   539 
       
   540 BOOL CConnectionImpl::ExitProcessing()
       
   541 {
       
   542 	TCDEBUGOPEN();
       
   543 	TCDEBUGLOGS("CConnectionImpl::ExitProcessing\n");
       
   544 
       
   545 	// exit the messageprocessing thread
       
   546 	if (m_hMessageProcessorThread != NULL)
       
   547 	{
       
   548 		m_MessageProcessorState = MP_EXIT;
       
   549 
       
   550 		m_StartMessageProcessing = false;
       
   551 		m_PauseMessageProcessing = true;
       
   552 		m_ExitMessageProcessor = true;
       
   553 		DWORD waitStatus = ::WaitForSingleObject(m_hMessageProcessorExittedEvent, MESSAGEPROCESSOR_EVENTWAIT_TIMEOUT);
       
   554 		TCDEBUGLOGA1("CConnectionImpl::ExitProcessing waitStatus=%x\n", waitStatus);
       
   555 		::CloseHandle(m_hMessageProcessorThread);
       
   556 		m_hMessageProcessorThread = NULL;
       
   557 	}
       
   558 	
       
   559 	TCDEBUGCLOSE();
       
   560 	return TRUE;
       
   561 }
       
   562 
       
   563 BOOL CConnectionImpl::StartProcessing()
       
   564 {
       
   565 	TCDEBUGOPEN();
       
   566 	TCDEBUGLOGS("CConnectionImpl::StartProcessing\n");
       
   567 
       
   568 	// starts processing thread
       
   569 	if (m_hMessageProcessorThread == NULL)
       
   570 	{
       
   571 		m_MessageProcessorState = MP_PAUSE;
       
   572 
       
   573 		m_ExitMessageProcessor = false;
       
   574 		m_StartMessageProcessing = false;
       
   575 		m_PauseMessageProcessing = false;
       
   576 		// TODO: create thread
       
   577 		m_hMessageProcessorThread = ::CreateThread(
       
   578 			NULL,
       
   579 			0,
       
   580 			(LPTHREAD_START_ROUTINE) MessageProcessor,
       
   581 			this,
       
   582 			0,
       
   583 			&m_dwMessageProcessorThreadId);
       
   584 	}
       
   585 
       
   586 	TCDEBUGCLOSE();
       
   587 	return PauseProcessing();//RestartProcessing();
       
   588 }
       
   589 
       
   590 BOOL CConnectionImpl::PauseProcessing()
       
   591 {
       
   592 	TCDEBUGOPEN();
       
   593 	TCDEBUGLOGS("CConnectionImpl::PauseProcessing\n");
       
   594 
       
   595 	// tells the processing thread to pause
       
   596 	if (m_hMessageProcessorThread != NULL)
       
   597 	{
       
   598 		m_MessageProcessorState = MP_PAUSE;
       
   599 
       
   600 		m_ExitMessageProcessor = false;
       
   601 		m_StartMessageProcessing = false;
       
   602 		m_PauseMessageProcessing = true;
       
   603 		DWORD waitStatus = ::WaitForSingleObject(m_hMessageProcessorStoppedEvent, MESSAGEPROCESSOR_EVENTWAIT_TIMEOUT);
       
   604 		TCDEBUGLOGA1("CConnectionImpl::PauseProcessing waitStatus=%x\n", waitStatus);
       
   605 	}
       
   606 	
       
   607 	TCDEBUGCLOSE();
       
   608 	return TRUE;
       
   609 }
       
   610 
       
   611 BOOL CConnectionImpl::RestartProcessing()
       
   612 {
       
   613 	TCDEBUGOPEN();
       
   614 	TCDEBUGLOGS("CConnectionImpl::RestartProcessing\n");
       
   615 
       
   616 	// tell the processing thread to restart
       
   617 	if (m_hMessageProcessorThread != NULL)
       
   618 	{
       
   619 		m_MessageProcessorState = MP_START;
       
   620 
       
   621 		m_ExitMessageProcessor = false;
       
   622 		m_StartMessageProcessing = true;
       
   623 		m_PauseMessageProcessing = false;
       
   624 		DWORD waitStatus = ::WaitForSingleObject(m_hMessageProcessorStartedEvent, MESSAGEPROCESSOR_EVENTWAIT_TIMEOUT);
       
   625 		TCDEBUGLOGA1("CConnectionImpl::RestartProcessing waitStatus=%x\n", waitStatus);
       
   626 	}
       
   627 	
       
   628 	TCDEBUGCLOSE();
       
   629 	return TRUE;
       
   630 }
       
   631 
       
   632 BOOL CConnectionImpl::RemoveClientFromRegistry(CClient* client)
       
   633 {
       
   634 	TCDEBUGOPEN();
       
   635 	TCDEBUGLOGS("CConnectionImpl::RemoveClientFromRegistry\n");
       
   636 	TCDEBUGCLOSE();
       
   637 
       
   638 	return m_Registry->RemoveClient(client);
       
   639 }
       
   640 
       
   641 BOOL CConnectionImpl::AddClientToRegistry(CClient* client, long numberIds, BYTE* ids)
       
   642 {
       
   643 	TCDEBUGOPEN();
       
   644 	TCDEBUGLOGS("CConnectionImpl::AddClientToRegistry\n");
       
   645 	TCDEBUGCLOSE();
       
   646 
       
   647 	return m_Registry->AddClient(client, numberIds, ids);
       
   648 }
       
   649 
       
   650 void CConnectionImpl::NotifyClientsCommError(long tcfError, bool passOsError, DWORD osError)
       
   651 {
       
   652 //	TCDEBUGOPEN();
       
   653 //	TCDEBUGLOGS("CConnectionImpl::NotifyClientsCommError\n");
       
   654 //	TCDEBUGCLOSE();
       
   655 
       
   656 	if (m_ClientList->size() != 0)
       
   657 	{
       
   658 		ClientList::iterator iter;
       
   659 		for (iter = m_ClientList->begin(); iter != m_ClientList->end(); iter++)
       
   660 		{
       
   661 			CErrorMonitor* errorMonitor = (*iter)->m_ErrorMonitor;
       
   662 			errorMonitor->PutError(tcfError, passOsError, osError);
       
   663 		}
       
   664 	}
       
   665 }
       
   666 BOOL CConnectionImpl::HasVersion()
       
   667 {
       
   668 	BOOL found = FALSE;
       
   669 
       
   670 	if (m_BaseComm && m_BaseComm->HasVersion())
       
   671 		found = TRUE;
       
   672 
       
   673 	return found;
       
   674 }
       
   675 void CConnectionImpl::GetVersion(char* version)
       
   676 {
       
   677 	if (HasVersion()) {
       
   678 		m_BaseComm->GetVersion(version);
       
   679 	}
       
   680 }
       
   681 
       
   682 void CConnectionImpl::UnLockAllDestinations()
       
   683 {
       
   684 	if (m_ClientList->size() != 0)
       
   685 	{
       
   686 		ClientList::iterator iter;
       
   687 		for (iter = m_ClientList->begin(); iter != m_ClientList->end(); iter++)
       
   688 		{
       
   689 			CInputStream* inputStream = (*iter)->m_InputStream;
       
   690 			CMessageFile* file = (*iter)->m_MessageFile;
       
   691 			if (inputStream != NULL) 
       
   692 			{
       
   693 				inputStream->UnLockStream();
       
   694 			}
       
   695 			else if (file != NULL)
       
   696 			{
       
   697 				file->UnLockMessageFile();
       
   698 			}
       
   699 		}
       
   700 	}
       
   701 }
       
   702 
       
   703 #define LOG_MPROCESSOR
       
   704 #if defined(LOG_MPROCESSOR) && defined(_DEBUG)
       
   705 #define MPLOGOPEN() if (gDoLogging) { pThis->m_DebugLog2->WaitForAccess(); }
       
   706 #define MPLOGS(s) if (gDoLogging) { sprintf(pThis->m_DebugLogMsg2,"%s", s); pThis->m_DebugLog2->log(pThis->m_DebugLogMsg2); }
       
   707 #define MPLOGA1(s, a1) if (gDoLogging) { sprintf(pThis->m_DebugLogMsg2, s, a1); pThis->m_DebugLog2->log(pThis->m_DebugLogMsg2); }
       
   708 #define MPLOGA2(s, a1, a2) if (gDoLogging) { sprintf(pThis->m_DebugLogMsg2, s, a1, a2); pThis->m_DebugLog2->log(pThis->m_DebugLogMsg2); }
       
   709 #define MPLOGA3(s, a1, a2, a3) if (gDoLogging) { sprintf(pThis->m_DebugLogMsg2, s, a1, a2, a3); pThis->m_DebugLog2->log(pThis->m_DebugLogMsg2); }
       
   710 #define MPLOGCLOSE() if (gDoLogging) { pThis->m_DebugLog2->ReleaseAccess(); }
       
   711 #else
       
   712 #define MPLOGOPEN()
       
   713 #define MPLOGS(s)
       
   714 #define MPLOGA1(s, a1)
       
   715 #define MPLOGA2(s, a1, a2)
       
   716 #define MPLOGA3(s, a1, a2, a3)
       
   717 #define MPLOGCLOSE()
       
   718 #endif
       
   719 
       
   720 DWORD WINAPI CConnectionImpl::MessageProcessor(LPVOID lpParam)
       
   721 {
       
   722 	CConnectionImpl* pThis = (CConnectionImpl*)lpParam;
       
   723 
       
   724 	MPLOGOPEN();
       
   725 	MPLOGS("MessageProcessor start thread\n");
       
   726 
       
   727 	bool processing = false;
       
   728 	long err = TCAPI_ERR_NONE;
       
   729 	DWORD pollSize = 0;
       
   730 
       
   731 	while (pThis->m_MessageProcessorState != MP_EXIT)
       
   732 	{
       
   733 		if (pThis->m_MessageProcessorState == MP_PAUSE)
       
   734 		{
       
   735 			MPLOGS("MessageProcessor pause\n");
       
   736 
       
   737 			processing = false; 
       
   738 			pThis->m_PauseMessageProcessing = false;
       
   739 			pThis->m_MessageProcessorState = MP_NONE;
       
   740 			BOOL ok = ::SetEvent(pThis->m_hMessageProcessorStoppedEvent);
       
   741 		}
       
   742 
       
   743 		if (pThis->IsRetryInProgress())
       
   744 			err = pThis->DoRetryProcessing();
       
   745 		else if (pThis->IsRetryTimedOut())
       
   746 			err = TCAPI_ERR_COMM_TIMEOUT;
       
   747 
       
   748 		if (processing && err == TCAPI_ERR_NONE)
       
   749 		{
       
   750 			if (pThis->m_BaseComm && pThis->m_BaseComm->IsConnected())
       
   751 			{
       
   752 				err = pThis->m_BaseComm->PollPort(pollSize);
       
   753 				MPLOGA2("MessageProcessor PollPort = %d pollsize = %d\n", err, pollSize);
       
   754 				if (err != TCAPI_ERR_NONE)
       
   755 				{
       
   756 					MPLOGA2("MessageProcessor  err = %d osError = %d\n", err, pThis->m_BaseComm->m_lastCommError);
       
   757 					pThis->EnterRetryPeriod(err, true, pThis->m_BaseComm->m_lastCommError);
       
   758 				}
       
   759 				else
       
   760 				{
       
   761 					if (pollSize == 0)
       
   762 					{
       
   763 						Sleep(1);
       
   764 					}
       
   765 					else
       
   766 					{
       
   767 						long numberProcessed = 0;
       
   768 //						MPLOGA1("MessageProcessor ProcessBuffer pRegistry = %x\n", pThis->m_Registry);
       
   769 						err = pThis->m_BaseComm->ProcessBuffer(pThis, pThis->m_Registry, numberProcessed);
       
   770 
       
   771 						MPLOGA2("MessageProcessor ProcessBuffer err = %d number = %d\n", err, numberProcessed);
       
   772 
       
   773 						if (err == TCAPI_ERR_COMM_ERROR)
       
   774 						{
       
   775 							// for this error we have os error, but we probably caught this in PollPort already
       
   776 							pThis->EnterRetryPeriod(err, true, pThis->m_BaseComm->m_lastCommError);
       
   777 						}
       
   778 						else if (err != TCAPI_ERR_NONE)
       
   779 						{
       
   780 							// all clients already notified in ProcessBuffer
       
   781 							err = TCAPI_ERR_NONE;
       
   782 						}
       
   783 						pThis->UnLockAllDestinations(); // unlock all input streams, if they became locked during AddMessage()
       
   784 //						Sleep(1);
       
   785 					}
       
   786 				}
       
   787 //				MPLOGS("MessageProcessor FlushAllClientMessageFiles\n");
       
   788 				pThis->FlushAllClientMessageFiles();
       
   789 			}
       
   790 			else
       
   791 			{
       
   792 				// basecom not connected
       
   793 				Sleep(1);
       
   794 			}
       
   795 		}
       
   796 		else
       
   797 		{
       
   798 			// processing is not being done
       
   799 			Sleep(1);
       
   800 		}
       
   801 		if (pThis->m_MessageProcessorState == MP_START)
       
   802 		{
       
   803 			MPLOGS("MessageProcessor start\n");
       
   804 
       
   805 			processing = true;
       
   806 			pThis->m_StartMessageProcessing = false;
       
   807 			pThis->m_MessageProcessorState = MP_PROCESSING;
       
   808 			BOOL ok = ::SetEvent(pThis->m_hMessageProcessorStartedEvent);
       
   809 		}
       
   810 	}
       
   811 	// signal we're stopping
       
   812 	pThis->m_ExitMessageProcessor = false;
       
   813 	pThis->m_MessageProcessorState = MP_NONE;
       
   814 	::SetEvent(pThis->m_hMessageProcessorExittedEvent);
       
   815 
       
   816 	MPLOGS("MessageProcessor exit thread\n");
       
   817 	MPLOGCLOSE();
       
   818 
       
   819 	return 0;
       
   820 }
       
   821 
       
   822 void CConnectionImpl::FlushAllClientMessageFiles()
       
   823 {
       
   824 	DWORD cTick = GetTickCount();
       
   825 
       
   826 //	MPLOGA2("CConnectionImpl::FlushAllClientMessageFiles cTick=%d m_NextFlushFileTime=%d\n", cTick, m_NextFlushFileTime);
       
   827 
       
   828 	if (cTick > m_NextFlushFileTime)
       
   829 	{
       
   830 //	MPLOGS("CConnectionImpl::FlushAllClientMessageFiles flush timeout\n");
       
   831 		if (m_ClientList->size() != 0)
       
   832 		{
       
   833 			ClientList::iterator iter;
       
   834 			for (iter = m_ClientList->begin(); iter != m_ClientList->end(); iter++)
       
   835 			{
       
   836 				CMessageFile* file = (*iter)->m_MessageFile;
       
   837 				if (file != NULL)
       
   838 				{
       
   839 //	MPLOGS("CConnectionImpl::FlushAllClientMessageFiles flush client\n");
       
   840 					file->FlushFile();
       
   841 				}
       
   842 			}
       
   843 		}
       
   844 		m_NextFlushFileTime = GetTickCount() + FLUSH_TIME;		
       
   845 	}
       
   846 }
       
   847 
       
   848 BOOL CConnectionImpl::CreateCommProtocols(const char* commPath, const char* protPath)
       
   849 {
       
   850 	BOOL loaded = FALSE;
       
   851 
       
   852 	TCDEBUGOPEN();
       
   853 	TCDEBUGLOGS("CConnectionImpl::CreateCommProtocols\n");
       
   854 
       
   855 	TCDEBUGLOGA2(" commPath=%s protPath=%s\n", commPath, protPath);
       
   856 
       
   857 	m_BaseCommHandle = ::LoadLibrary(commPath);
       
   858 	m_BaseProtocolHandle = ::LoadLibrary(protPath);
       
   859 	if (m_BaseCommHandle == NULL || m_BaseProtocolHandle == NULL)
       
   860 	{
       
   861 		TCDEBUGLOGA2(" error loading library, m_BaseCommHandle=%x m_BaseProtocolHandle=%x\n", m_BaseCommHandle, m_BaseProtocolHandle);
       
   862 		if (m_BaseCommHandle) ::FreeLibrary(m_BaseCommHandle); m_BaseCommHandle = NULL;
       
   863 		if (m_BaseProtocolHandle) ::FreeLibrary(m_BaseProtocolHandle); m_BaseProtocolHandle = NULL;
       
   864 
       
   865 	}
       
   866 	else
       
   867 	{
       
   868 		COMMCREATE lpCommFn = (COMMCREATE)::GetProcAddress(m_BaseCommHandle, COMMCREATE_FNNAME);
       
   869 		PROTOCOLCREATE lpProtFn = (PROTOCOLCREATE)::GetProcAddress(m_BaseProtocolHandle, PROTOCOLCREATE_FNNAME);
       
   870 		if (lpCommFn == NULL || lpProtFn == NULL)
       
   871 		{
       
   872 			TCDEBUGLOGA2(" error finding function, lpCommFn=%x lpProtFn=%x\n", lpCommFn, lpProtFn);
       
   873 			if (m_BaseCommHandle) ::FreeLibrary(m_BaseCommHandle); m_BaseCommHandle = NULL;
       
   874 			if (m_BaseProtocolHandle) ::FreeLibrary(m_BaseProtocolHandle); m_BaseProtocolHandle = NULL;
       
   875 		}
       
   876 		else
       
   877 		{
       
   878 			m_BaseProtocol = lpProtFn();
       
   879 			if (m_BaseProtocol == NULL)
       
   880 			{
       
   881 				TCDEBUGLOGA1(" error creating protocol, m_BaseProtocol=%x\n", m_BaseProtocol);
       
   882 				if (m_BaseCommHandle) ::FreeLibrary(m_BaseCommHandle); m_BaseCommHandle = NULL;
       
   883 				if (m_BaseProtocolHandle) ::FreeLibrary(m_BaseProtocolHandle); m_BaseProtocolHandle = NULL;
       
   884 			}
       
   885 			else
       
   886 			{
       
   887 				m_BaseComm = lpCommFn(m_ConnectSettings, m_ConnectionID, m_BaseProtocol);
       
   888 				if (m_BaseComm == NULL)
       
   889 				{
       
   890 					TCDEBUGLOGA1(" error creating comm, m_BaseComm=%x\n", m_BaseComm);
       
   891 					if (m_BaseProtocol) delete m_BaseProtocol; m_BaseProtocol = NULL;
       
   892 
       
   893 					if (m_BaseCommHandle) ::FreeLibrary(m_BaseCommHandle); m_BaseCommHandle = NULL;
       
   894 					if (m_BaseProtocolHandle) ::FreeLibrary(m_BaseProtocolHandle); m_BaseProtocolHandle = NULL;
       
   895 				}
       
   896 				else
       
   897 				{
       
   898 					loaded = TRUE;
       
   899 					TCDEBUGLOGA4(" created class, m_BaseComm=%x m_BaseProtocol=%x m_BaseCommHandle=%x m_BaseProtocolHandle=%x\n", m_BaseComm, m_BaseProtocol, m_BaseCommHandle, m_BaseProtocolHandle);
       
   900 				}
       
   901 			}
       
   902 		}
       
   903 	}
       
   904 
       
   905 	TCDEBUGCLOSE();
       
   906 	return loaded;
       
   907 }