|
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 // TcpComm.cpp: implementation of the CTcpComm class. |
|
18 // |
|
19 ////////////////////////////////////////////////////////////////////// |
|
20 |
|
21 #include "stdafx.h" |
|
22 #include "TcpComm.h" |
|
23 //#include "pn_const.h" |
|
24 //#include "OSTConstants.h" |
|
25 #include "Connection.h" |
|
26 |
|
27 #ifdef _DEBUG |
|
28 static char sTcpLogMsg[3000]; |
|
29 #endif |
|
30 ////////////////////////////////////////////////////////////////////// |
|
31 // Construction/Destruction |
|
32 ////////////////////////////////////////////////////////////////////// |
|
33 CTcpComm::CTcpComm() |
|
34 { |
|
35 #ifdef _DEBUG |
|
36 if (gDoLogging) |
|
37 { |
|
38 FILE* f = fopen("c:\\tcf\\tcpcommlog.txt", "at"); |
|
39 fprintf(f, "CTcpComm::CTcpComm() (default constructor)\n"); |
|
40 fclose(f); |
|
41 } |
|
42 #endif |
|
43 m_socket = INVALID_SOCKET; |
|
44 m_timeOut.tv_sec = TIMEOUT_SEC(DEFAULT_SOCKET_TIMEOUT); |
|
45 m_timeOut.tv_usec = TIMEOUT_USEC(DEFAULT_SOCKET_TIMEOUT); |
|
46 |
|
47 m_hSocketEvent = WSA_INVALID_EVENT; |
|
48 } |
|
49 |
|
50 CTcpComm::CTcpComm(ConnectData* connectSettings, DWORD connectionId, CBaseProtocol* protocol) |
|
51 { |
|
52 #ifdef _DEBUG |
|
53 if (gDoLogging) |
|
54 { |
|
55 FILE* f = fopen("c:\\tcf\\tcpcommlog.txt", "at"); |
|
56 fprintf(f, "connectSettings=%x connectionId=%d, protocol=%x\n", connectSettings, connectionId, protocol); |
|
57 fclose(f); |
|
58 } |
|
59 #endif |
|
60 m_connId = connectionId; |
|
61 m_Protocol = protocol; |
|
62 |
|
63 m_ConnectSettings = new ConnectData(); |
|
64 memcpy(m_ConnectSettings, connectSettings, sizeof(ConnectData)); |
|
65 |
|
66 #if (defined(LOG_COMM) || defined(LOG_PROCCOMM)) && defined(_DEBUG) |
|
67 if (gDoLogging) |
|
68 { |
|
69 m_CommDebugLog = new TCDebugLog("TCF_Comm", connectionId, 2000L); |
|
70 m_ProcDebugLog = new TCDebugLog("TCF_CommP", connectionId, 2000L); |
|
71 } |
|
72 #endif |
|
73 m_socket = INVALID_SOCKET; |
|
74 m_timeOut.tv_sec = TIMEOUT_SEC(DEFAULT_SOCKET_TIMEOUT); |
|
75 m_timeOut.tv_usec = TIMEOUT_USEC(DEFAULT_SOCKET_TIMEOUT); |
|
76 |
|
77 m_hSocketEvent = WSA_INVALID_EVENT; |
|
78 } |
|
79 CTcpComm::~CTcpComm() |
|
80 { |
|
81 #ifdef _DEBUG |
|
82 if (gDoLogging) |
|
83 { |
|
84 FILE* f = fopen("c:\\tcf\\tcpcommlog.txt", "at"); |
|
85 fprintf(f, "CTcpComm::~CTcpComm()\n"); |
|
86 fclose(f); |
|
87 } |
|
88 #endif |
|
89 if (IsConnected()) |
|
90 { |
|
91 shutdown(m_socket, SD_BOTH); |
|
92 closesocket(m_socket); |
|
93 WSACleanup(); |
|
94 } |
|
95 if (m_pBuffer) |
|
96 delete[] m_pBuffer; |
|
97 |
|
98 if (m_hSocketEvent != WSA_INVALID_EVENT) |
|
99 WSACloseEvent(m_hSocketEvent); |
|
100 |
|
101 } |
|
102 |
|
103 //#define USE_EVENTS |
|
104 ; |
|
105 long CTcpComm::OpenPort() |
|
106 { |
|
107 COMMLOGOPEN(); |
|
108 COMMLOGS("CTcpComm::OpenPort\n"); |
|
109 |
|
110 long err = TCAPI_ERR_NONE; |
|
111 char* ipAddress = m_ConnectSettings->tcpSettings.ipAddress; |
|
112 char* ipPort = m_ConnectSettings->tcpSettings.ipPort; |
|
113 // set this to set socket to non-blocking |
|
114 // DWORD nonblock = 1; // non-blocking |
|
115 DWORD nonblock = 0; // blocking |
|
116 |
|
117 COMMLOGA2("CTcpComm::OpenPort ipAddress=%s ipPort=%s\n", ipAddress, ipPort); |
|
118 |
|
119 WSADATA wsaData; |
|
120 int wsaErr = WSAStartup(MAKEWORD(2,2), &wsaData); |
|
121 if (wsaErr != 0) |
|
122 { |
|
123 err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA; |
|
124 // err = -1; |
|
125 } |
|
126 else |
|
127 { |
|
128 m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
|
129 if (m_socket == INVALID_SOCKET) |
|
130 { |
|
131 m_lastCommError = WSAGetLastError(); |
|
132 WSACleanup(); |
|
133 err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA; |
|
134 } |
|
135 else |
|
136 { |
|
137 if (ioctlsocket(m_socket, FIONBIO, &nonblock) == SOCKET_ERROR) |
|
138 { |
|
139 m_lastCommError = WSAGetLastError(); |
|
140 closesocket(m_socket); |
|
141 m_socket = INVALID_SOCKET; |
|
142 WSACleanup(); |
|
143 err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA; |
|
144 } |
|
145 else |
|
146 { |
|
147 int i = SO_MAX_MSG_SIZE; |
|
148 // set socket options |
|
149 BOOL keepAlive = TRUE; |
|
150 setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, (const char*)&keepAlive, sizeof(BOOL)); |
|
151 int sockRecvSize = MAX_TCP_MESSAGE_BUFFER_LENGTH;//(256*1024L); |
|
152 setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (const char*)&sockRecvSize, sizeof(int)); |
|
153 int sockSendSize = (64*1024L); |
|
154 setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (const char*)&sockSendSize, sizeof(int)); |
|
155 WSAGetLastError(); // ignore error for now |
|
156 int gotsockRecvSize, optLen=sizeof(int); |
|
157 getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&gotsockRecvSize, &optLen); |
|
158 WSAGetLastError(); // ignore error for now |
|
159 // connect |
|
160 WORD wPort = atoi(ipPort); |
|
161 m_clientService.sin_family = AF_INET; |
|
162 m_clientService.sin_addr.S_un.S_addr = inet_addr(ipAddress); |
|
163 m_clientService.sin_port = htons(wPort); |
|
164 if (connect(m_socket, (SOCKADDR*)&m_clientService, sizeof(m_clientService)) == SOCKET_ERROR) |
|
165 { |
|
166 int wsaErr = WSAGetLastError(); |
|
167 // socket is non-blocking |
|
168 if (wsaErr != WSAEWOULDBLOCK) |
|
169 { |
|
170 m_lastCommError = wsaErr; |
|
171 |
|
172 closesocket(m_socket); |
|
173 m_socket = INVALID_SOCKET; |
|
174 WSACleanup(); |
|
175 err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA; |
|
176 } |
|
177 else // WSAEWOULDBLOCK error returned |
|
178 { |
|
179 // WSAEWOULDBLOCK use select now |
|
180 fd_set readfds, writefds, exceptfds; |
|
181 FD_ZERO(&readfds); |
|
182 FD_ZERO(&writefds); |
|
183 FD_ZERO(&exceptfds); |
|
184 FD_SET(m_socket, &readfds); |
|
185 FD_SET(m_socket, &writefds); |
|
186 FD_SET(m_socket, &exceptfds); |
|
187 |
|
188 int selRes = 0; |
|
189 while(1) |
|
190 { |
|
191 selRes = select(0, &readfds, &writefds, &exceptfds, &m_timeOut); |
|
192 if (selRes == SOCKET_ERROR) |
|
193 { |
|
194 wsaErr = WSAGetLastError(); |
|
195 if (wsaErr != WSAEWOULDBLOCK) |
|
196 { |
|
197 // real error |
|
198 m_lastCommError = wsaErr; |
|
199 shutdown(m_socket, SD_BOTH); |
|
200 closesocket(m_socket); |
|
201 m_socket = INVALID_SOCKET; |
|
202 WSACleanup(); |
|
203 err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA; |
|
204 } |
|
205 // else do another select |
|
206 } |
|
207 else if (selRes > 0)// select OK |
|
208 { |
|
209 m_lastCommError = 0; |
|
210 m_isConnected = true; |
|
211 break; // done |
|
212 } |
|
213 else |
|
214 { |
|
215 // timed out |
|
216 m_lastCommError = WSAGetLastError(); |
|
217 shutdown(m_socket, SD_BOTH); |
|
218 closesocket(m_socket); |
|
219 m_socket = INVALID_SOCKET; |
|
220 WSACleanup(); |
|
221 err = TCAPI_ERR_WHILE_CONFIGURING_MEDIA; |
|
222 } |
|
223 } |
|
224 } |
|
225 } |
|
226 else // connect return OK |
|
227 { |
|
228 m_lastCommError = 0; |
|
229 m_isConnected = true; |
|
230 } |
|
231 } |
|
232 } |
|
233 } |
|
234 if (err == TCAPI_ERR_NONE) |
|
235 { |
|
236 // we are connected |
|
237 m_numberBytes = 0; |
|
238 m_pBuffer = new BYTE[MAX_TCP_MESSAGE_BUFFER_LENGTH]; |
|
239 |
|
240 #ifdef USE_EVENTS |
|
241 // create an event for the socket closing |
|
242 m_hSocketEvent = WSACreateEvent(); |
|
243 ::WSAEventSelect(m_socket, m_hSocketEvent, FD_CLOSE); |
|
244 // above call sets socket to non-blocking |
|
245 // cannot reset to blocking after using WSAEventSelect |
|
246 // thus this ioctlsocket call will fail |
|
247 ioctlsocket(m_socket, FIONBIO, &nonblock); |
|
248 #endif |
|
249 } |
|
250 |
|
251 COMMLOGCLOSE(); |
|
252 return err; |
|
253 } |
|
254 |
|
255 long CTcpComm::ClosePort() |
|
256 { |
|
257 COMMLOGOPEN(); |
|
258 COMMLOGS("CTcpComm::ClosePort\n"); |
|
259 |
|
260 long err = TCAPI_ERR_NONE; |
|
261 |
|
262 if (!IsConnected()) |
|
263 { |
|
264 err = TCAPI_ERR_MEDIA_NOT_OPEN; |
|
265 } |
|
266 else |
|
267 { |
|
268 shutdown(m_socket, SD_BOTH); |
|
269 closesocket(m_socket); |
|
270 m_socket = INVALID_SOCKET; |
|
271 WSACleanup(); |
|
272 |
|
273 delete[] m_pBuffer; |
|
274 m_pBuffer = NULL; |
|
275 |
|
276 if (m_hSocketEvent != WSA_INVALID_EVENT) |
|
277 { |
|
278 WSACloseEvent(m_hSocketEvent); |
|
279 m_hSocketEvent = WSA_INVALID_EVENT; |
|
280 } |
|
281 } |
|
282 |
|
283 COMMLOGCLOSE(); |
|
284 return err; |
|
285 } |
|
286 |
|
287 long CTcpComm::PollPort(DWORD &outSize) |
|
288 { |
|
289 long err = TCAPI_ERR_NONE; |
|
290 DWORD numBytes = 0; |
|
291 outSize = 0; |
|
292 |
|
293 if (!IsConnected()) |
|
294 return TCAPI_ERR_MEDIA_NOT_OPEN; |
|
295 |
|
296 #ifdef USE_EVENTS |
|
297 int ret = ::WSAWaitForMultipleEvents(1, &m_hSocketEvent, FALSE, 0, FALSE); |
|
298 if (ret == WSA_WAIT_EVENT_0) |
|
299 { |
|
300 ::WSAResetEvent(m_hSocketEvent); |
|
301 err = TCAPI_ERR_COMM_ERROR; |
|
302 m_lastCommError = WSAESHUTDOWN; |
|
303 return err; |
|
304 } |
|
305 #endif |
|
306 int sockErr = 0; int optLen = sizeof(int); |
|
307 int getErr = getsockopt(m_socket, SOL_SOCKET, SO_ERROR, (char*)&sockErr, &optLen); |
|
308 if (getErr == 0) |
|
309 { |
|
310 if (sockErr) |
|
311 { |
|
312 err = TCAPI_ERR_COMM_ERROR; |
|
313 m_lastCommError = sockErr; |
|
314 return err; |
|
315 } |
|
316 } |
|
317 |
|
318 fd_set readfds, writefds, exceptfds; |
|
319 FD_ZERO(&readfds); |
|
320 FD_ZERO(&writefds); |
|
321 FD_ZERO(&exceptfds); |
|
322 FD_SET(m_socket, &readfds); |
|
323 FD_SET(m_socket, &writefds); |
|
324 FD_SET(m_socket, &exceptfds); |
|
325 |
|
326 bool portReady = false; |
|
327 { |
|
328 TIMEVAL pollTimeout = {0,0}; // just poll the status |
|
329 int selErr = select(0, &readfds, 0, 0, &pollTimeout); |
|
330 if (selErr > 0) |
|
331 { |
|
332 if (FD_ISSET(m_socket, &readfds)) |
|
333 { |
|
334 m_lastCommError = 0; |
|
335 portReady = true; |
|
336 } |
|
337 } |
|
338 else if (selErr == SOCKET_ERROR) |
|
339 { |
|
340 m_lastCommError = WSAGetLastError(); |
|
341 err = TCAPI_ERR_COMM_ERROR; |
|
342 } |
|
343 } |
|
344 |
|
345 if (portReady) |
|
346 { |
|
347 // read was signaled as ready |
|
348 int recvRet = recv(m_socket, (char*)&m_pPeekBuffer, sizeof(m_pPeekBuffer), MSG_PEEK); |
|
349 if (recvRet > 0) |
|
350 { |
|
351 if (ioctlsocket(m_socket, FIONREAD, &numBytes) == 0) |
|
352 { |
|
353 m_lastCommError = 0; |
|
354 outSize = numBytes; |
|
355 } |
|
356 else // SOCKET_ERROR |
|
357 { |
|
358 m_lastCommError = WSAGetLastError(); |
|
359 err = TCAPI_ERR_COMM_ERROR; |
|
360 } |
|
361 } |
|
362 else if (recvRet == 0) |
|
363 { |
|
364 // read was signalled as ready but recv=0 signals that remote shutdown |
|
365 m_lastCommError = WSAESHUTDOWN; |
|
366 err = TCAPI_ERR_COMM_ERROR; |
|
367 } |
|
368 else |
|
369 { |
|
370 // SOCKET_ERROR: error on recv other than a shutdown |
|
371 m_lastCommError = WSAGetLastError(); |
|
372 err = TCAPI_ERR_COMM_ERROR; |
|
373 } |
|
374 } |
|
375 return err; |
|
376 } |
|
377 |
|
378 long CTcpComm::ReadPort(DWORD inSize, void *outData, DWORD &outSize) |
|
379 { |
|
380 long err = TCAPI_ERR_NONE; |
|
381 DWORD numBytes = 0; |
|
382 outSize = 0; |
|
383 |
|
384 if (!IsConnected()) |
|
385 return TCAPI_ERR_MEDIA_NOT_OPEN; |
|
386 |
|
387 if (ioctlsocket(m_socket, FIONREAD, &numBytes) == 0) |
|
388 { |
|
389 if (numBytes > inSize) |
|
390 numBytes = inSize; |
|
391 int res = recv(m_socket, (char*)outData, numBytes, 0); |
|
392 if (res == SOCKET_ERROR) |
|
393 { |
|
394 long commErr = WSAGetLastError(); |
|
395 if ((DWORD)commErr != m_lastCommError) |
|
396 { |
|
397 m_lastCommError = commErr; |
|
398 } |
|
399 err = TCAPI_ERR_COMM_ERROR; |
|
400 } |
|
401 else if (res == 0) |
|
402 { |
|
403 // recv=0 --> connection closed |
|
404 m_lastCommError = WSAESHUTDOWN; |
|
405 err = TCAPI_ERR_COMM_ERROR; |
|
406 } |
|
407 else |
|
408 { |
|
409 m_lastCommError = 0; |
|
410 outSize = numBytes; |
|
411 } |
|
412 } |
|
413 else |
|
414 { |
|
415 // SOCKET_ERROR on ioctlsocket |
|
416 m_lastCommError = WSAGetLastError(); |
|
417 err = TCAPI_ERR_COMM_ERROR; |
|
418 } |
|
419 return err; |
|
420 } |
|
421 long CTcpComm::ProcessBuffer(CConnection* pConn, CRegistry* pRegistry, long& numberProcessed) |
|
422 { |
|
423 |
|
424 long err = TCAPI_ERR_NONE; |
|
425 long routingErr = TCAPI_ERR_NONE; |
|
426 |
|
427 if (!IsConnected()) |
|
428 return TCAPI_ERR_MEDIA_NOT_OPEN; |
|
429 |
|
430 if (!m_Protocol) |
|
431 return TCAPI_ERR_UNKNOWN_MEDIA_TYPE; |
|
432 |
|
433 DWORD protocolHeaderLength = m_Protocol->GetHeaderLength(); |
|
434 |
|
435 // fill buffer |
|
436 if (m_numberBytes < MAX_TCP_MESSAGE_BUFFER_LENGTH) |
|
437 { |
|
438 DWORD outLen = MAX_TCP_MESSAGE_BUFFER_LENGTH - m_numberBytes; |
|
439 BYTE* ptr = &m_pBuffer[m_numberBytes]; |
|
440 err = ReadPort(outLen, ptr, outLen); |
|
441 if (err == TCAPI_ERR_NONE && outLen > 0) |
|
442 { |
|
443 m_numberBytes += outLen; |
|
444 } |
|
445 } |
|
446 |
|
447 // now process buffer but only for complete messages |
|
448 if (err == TCAPI_ERR_NONE) |
|
449 { |
|
450 if (m_numberBytes >= protocolHeaderLength) |
|
451 { |
|
452 BYTE* ptr = m_pBuffer; |
|
453 long bytesRemaining = m_numberBytes; |
|
454 long usedLen = 0; |
|
455 bool done = false; |
|
456 |
|
457 while (!done) |
|
458 { |
|
459 DWORD fullMessageLength = bytesRemaining; |
|
460 DWORD rawLength = 0; |
|
461 BYTE* fullMessage = ptr; |
|
462 BYTE* rawMessage = ptr; |
|
463 BYTE msgId = 0; |
|
464 if (m_Protocol->DecodeMessage(fullMessage, fullMessageLength, msgId, rawMessage, rawLength)) |
|
465 { |
|
466 err = PreProcessMessage(msgId, fullMessageLength, fullMessage); |
|
467 if (err != TCAPI_ERR_NONE) |
|
468 { |
|
469 PROCLOGOPEN(); |
|
470 PROCLOGA1("CTcpComm::ProcessBuffer Notify err = %x\n", err); |
|
471 PROCLOGCLOSE(); |
|
472 // notify all clients right now |
|
473 pConn->NotifyClientsCommError(err, false, 0); |
|
474 err = TCAPI_ERR_NONE; |
|
475 } |
|
476 #ifdef _DEBUG |
|
477 int reallen = fullMessageLength; |
|
478 if (reallen > 50) reallen = 50; |
|
479 char msg[6]; |
|
480 msg[0] = '\0'; |
|
481 |
|
482 sTcpLogMsg[0] = '\0'; |
|
483 if (reallen > 0) |
|
484 { |
|
485 sTcpLogMsg[0] = '\0'; |
|
486 for (int i = 0; i < reallen; i++) |
|
487 { |
|
488 sprintf(msg, "%02.2x ", ptr[i]); |
|
489 strcat(sTcpLogMsg, msg); |
|
490 } |
|
491 } |
|
492 #endif |
|
493 PROCLOGOPEN(); |
|
494 PROCLOGA5("CTcpComm::ProcessBuffer - RouteMesssage pRegistry = %x id=%x len=%d len=%d\n msg=%s\n", pRegistry, msgId, fullMessageLength, rawLength, sTcpLogMsg); |
|
495 PROCLOGCLOSE(); |
|
496 |
|
497 err = pRegistry->RouteMessage(msgId, fullMessage, fullMessageLength, rawMessage, rawLength); |
|
498 if (err != TCAPI_ERR_NONE) routingErr = err; // saved for future |
|
499 |
|
500 numberProcessed++; |
|
501 usedLen += fullMessageLength; |
|
502 bytesRemaining -= fullMessageLength; |
|
503 ptr += fullMessageLength; |
|
504 if (bytesRemaining < protocolHeaderLength) |
|
505 done = true; |
|
506 } |
|
507 else |
|
508 { |
|
509 done = true; |
|
510 } |
|
511 } |
|
512 DeleteMsg(usedLen); |
|
513 } |
|
514 } |
|
515 |
|
516 if (routingErr == TCAPI_ERR_NONE) |
|
517 return err; |
|
518 else |
|
519 return routingErr; |
|
520 } |
|
521 |
|
522 |
|
523 long CTcpComm::SendDataToPort(DWORD inSize, const void* inData) |
|
524 { |
|
525 COMMLOGOPEN(); |
|
526 COMMLOGS("CTcpComm::SendDataToPort\n"); |
|
527 |
|
528 long err = TCAPI_ERR_NONE; |
|
529 |
|
530 if (!IsConnected()) |
|
531 { |
|
532 COMMLOGCLOSE(); |
|
533 return TCAPI_ERR_MEDIA_NOT_OPEN; |
|
534 } |
|
535 |
|
536 #ifdef USE_EVENTS |
|
537 int ret = ::WSAWaitForMultipleEvents(1, &m_hSocketEvent, FALSE, 0, FALSE); |
|
538 if (ret == WSA_WAIT_EVENT_0) |
|
539 { |
|
540 ::WSAResetEvent(m_hSocketEvent); |
|
541 err = TCAPI_ERR_COMM_ERROR; |
|
542 m_lastCommError = WSAESHUTDOWN; |
|
543 COMMLOGCLOSE(); |
|
544 return err; |
|
545 } |
|
546 #endif |
|
547 int sockErr = 0; int optLen = sizeof(int); |
|
548 int getErr = getsockopt(m_socket, SOL_SOCKET, SO_ERROR, (char*)&sockErr, &optLen); |
|
549 if (getErr == 0) |
|
550 { |
|
551 if (sockErr) |
|
552 { |
|
553 err = TCAPI_ERR_COMM_ERROR; |
|
554 m_lastCommError = sockErr; |
|
555 COMMLOGCLOSE(); |
|
556 return err; |
|
557 } |
|
558 } |
|
559 |
|
560 fd_set readfds, writefds, exceptfds; |
|
561 FD_ZERO(&readfds); |
|
562 FD_ZERO(&writefds); |
|
563 FD_ZERO(&exceptfds); |
|
564 FD_SET(m_socket, &readfds); |
|
565 FD_SET(m_socket, &writefds); |
|
566 FD_SET(m_socket, &exceptfds); |
|
567 |
|
568 COMMLOGS("CTcpComm::SendDataToPort select\n"); |
|
569 bool portReady = false; |
|
570 { |
|
571 int selErr = select(0, &readfds, &writefds, &exceptfds, &m_timeOut); |
|
572 if (selErr > 0) |
|
573 { |
|
574 if (FD_ISSET(m_socket, &writefds)) |
|
575 { |
|
576 m_lastCommError = 0; |
|
577 portReady = true; |
|
578 } |
|
579 } |
|
580 else if (selErr == SOCKET_ERROR) |
|
581 { |
|
582 m_lastCommError = WSAGetLastError(); |
|
583 err = TCAPI_ERR_COMM_ERROR; |
|
584 } |
|
585 else if (selErr == 0) // timeout |
|
586 { |
|
587 m_lastCommError = WSAGetLastError(); |
|
588 err = TCAPI_ERR_COMM_ERROR; |
|
589 } |
|
590 } |
|
591 COMMLOGA1("CTcpComm::SendDataToPort portReady=%d\n", portReady); |
|
592 if (portReady) |
|
593 { |
|
594 COMMLOGS("CTcpComm::SendDataToPort send start\n"); |
|
595 // loop until all bytes are sent |
|
596 DWORD bytesRemaining = inSize; |
|
597 DWORD nSent = 0; |
|
598 char* unsent = (char*)inData; |
|
599 while (bytesRemaining) |
|
600 { |
|
601 nSent = send(m_socket, unsent, bytesRemaining, 0); |
|
602 if (nSent == SOCKET_ERROR) |
|
603 { |
|
604 int wsaErr = WSAGetLastError(); |
|
605 // ignore "would block" errors |
|
606 if (wsaErr != WSAEWOULDBLOCK) |
|
607 { |
|
608 // TODO: error handling |
|
609 m_lastCommError = wsaErr; |
|
610 err = TCAPI_ERR_COMM_ERROR; |
|
611 break; |
|
612 } |
|
613 } |
|
614 else |
|
615 { |
|
616 m_lastCommError = 0; |
|
617 unsent += nSent; |
|
618 bytesRemaining -= nSent; |
|
619 } |
|
620 } // end while |
|
621 COMMLOGS("CTcpComm::SendDataToPort send done\n"); |
|
622 #ifdef _DEBUG |
|
623 BYTE* ptr = (BYTE*)inData; |
|
624 long numBytes = (inSize > 20) ? 20 : inSize; |
|
625 char msg[200]; |
|
626 sprintf(msg, "CTcpComm::SendDataToPort data = "); |
|
627 for (int i = 0; i < numBytes; i++) |
|
628 { |
|
629 sprintf(msg, "%s %02.2x", msg, ptr[i]); |
|
630 } |
|
631 sprintf(msg, "%s\n", msg); |
|
632 COMMLOGS(msg); |
|
633 #endif |
|
634 } |
|
635 |
|
636 COMMLOGCLOSE(); |
|
637 return err; |
|
638 } |
|
639 |
|
640 void CTcpComm::DeleteMsg(DWORD inMsgLength) |
|
641 { |
|
642 // inMsgLength includes header |
|
643 // delete from beginning of buffer |
|
644 if (inMsgLength == 0) |
|
645 return; |
|
646 if (m_numberBytes > 0 && m_numberBytes >= inMsgLength) |
|
647 { |
|
648 size_t moveLen = m_numberBytes - inMsgLength; |
|
649 if (moveLen > 0) |
|
650 memcpy(&m_pBuffer[0], &m_pBuffer[inMsgLength], moveLen); |
|
651 m_numberBytes -= inMsgLength; |
|
652 } |
|
653 } |
|
654 bool CTcpComm::IsConnectionEqual(ConnectData* pConn) |
|
655 { |
|
656 if ((strcmp(pConn->tcpSettings.ipAddress, m_ConnectSettings->tcpSettings.ipAddress) == 0) && |
|
657 (strcmp(pConn->tcpSettings.ipPort, m_ConnectSettings->tcpSettings.ipPort) == 0)) |
|
658 { |
|
659 return true; |
|
660 } |
|
661 else |
|
662 { |
|
663 return false; |
|
664 } |
|
665 } |
|
666 |