|
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 } |