connectivity/com.nokia.tcf/native/TCFNative/TCFCommTCP/TcpComm.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 // 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