|
IVT
|
00001 // **************************************************************************** 00002 // This file is part of the Integrating Vision Toolkit (IVT). 00003 // 00004 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT) 00005 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de). 00006 // 00007 // Copyright (C) 2013 Karlsruhe Institute of Technology (KIT). 00008 // All rights reserved. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are met: 00012 // 00013 // 1. Redistributions of source code must retain the above copyright 00014 // notice, this list of conditions and the following disclaimer. 00015 // 00016 // 2. Redistributions in binary form must reproduce the above copyright 00017 // notice, this list of conditions and the following disclaimer in the 00018 // documentation and/or other materials provided with the distribution. 00019 // 00020 // 3. Neither the name of the KIT nor the names of its contributors may be 00021 // used to endorse or promote products derived from this software 00022 // without specific prior written permission. 00023 // 00024 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY 00025 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00026 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY 00028 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00029 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00031 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00033 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 // **************************************************************************** 00035 // **************************************************************************** 00036 // Filename: TCPSocket.cpp 00037 // Author: Florian Hecht 00038 // Date: 08.01.2009 00039 // **************************************************************************** 00040 00041 #include <new> // for explicitly using correct new/delete operators on VC DSPs 00042 00043 #include "TCPSocket.h" 00044 00045 #include <stdio.h> 00046 #ifndef __TI_COMPILER_VERSION__ 00047 #include <memory.h> 00048 #endif 00049 00050 #include <stdlib.h> 00051 #include <errno.h> 00052 00053 00054 #if defined(WIN32) 00055 #define _WINSOCKAPI_ 00056 #include <windows.h> 00057 #include <winsock2.h> 00058 00059 static int socket_ref_count = 0; 00060 00061 void InitWinSock() 00062 { 00063 socket_ref_count++; 00064 00065 if (socket_ref_count > 1) 00066 return; 00067 00068 WORD wVersionRequested; 00069 WSADATA wsaData; 00070 int wsaerr; 00071 00072 wVersionRequested = MAKEWORD(2, 0); 00073 wsaerr = WSAStartup(wVersionRequested, &wsaData); 00074 if (wsaerr != 0) 00075 { 00076 // Tell the user that we couldn't find the WinSock DLL 00077 printf("Error: couldn't initialize WinSock!\n"); 00078 } 00079 00080 return; 00081 } 00082 00083 void ShutdownWinSock() 00084 { 00085 socket_ref_count--; 00086 if (socket_ref_count > 0) 00087 return; 00088 00089 WSACleanup(); 00090 } 00091 00092 #elif defined(__TI_COMPILER_VERSION__) 00093 #include <string.h> 00094 #include "Networking/VCNet.h" 00095 #else 00096 #include <unistd.h> 00097 #include <signal.h> 00098 #include <fcntl.h> 00099 #include <sys/socket.h> 00100 #include <sys/types.h> 00101 #include <netdb.h> 00102 #include <netinet/ip.h> 00103 #include <netinet/tcp.h> 00104 #endif 00105 00106 00107 00108 CTCPSocket::CTCPSocket() : m_socket(-1), m_bListening(false) 00109 { 00110 #ifdef WIN32 00111 InitWinSock(); 00112 #endif 00113 } 00114 00115 CTCPSocket::~CTCPSocket() 00116 { 00117 Close(); 00118 00119 #ifdef WIN32 00120 ShutdownWinSock(); 00121 #endif 00122 } 00123 00124 bool CTCPSocket::Listen(const unsigned char *ip, int port) 00125 { 00126 Close(); 00127 00128 #ifdef WIN32 00129 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); 00130 if (sock == INVALID_SOCKET) 00131 { 00132 m_socket = -1; 00133 return false; 00134 } 00135 00136 m_socket = (int)sock; 00137 00138 // set linger on - helps in closing socket immidiately 00139 linger li; 00140 li.l_onoff = true; 00141 li.l_linger = 0; 00142 00143 if(setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&li, sizeof(li)) == -1) 00144 { 00145 printf("setting linger option failed\n"); 00146 Close(); 00147 return false; 00148 } 00149 00150 // set non blocking 00151 u_long v = 1; 00152 if (ioctlsocket(sock, FIONBIO, &v) == SOCKET_ERROR) 00153 { 00154 printf("setting non-blocking option failed\n"); 00155 Close(); 00156 return false; 00157 } 00158 00159 struct sockaddr_in serv_addr; 00160 memset((char *)&serv_addr, 0, sizeof(serv_addr)); 00161 00162 serv_addr.sin_family = AF_INET; 00163 if (ip != NULL) 00164 { 00165 memcpy((char *)&serv_addr.sin_addr.s_addr, ip, 4); 00166 } 00167 else 00168 { 00169 serv_addr.sin_addr.s_addr = INADDR_ANY; 00170 } 00171 serv_addr.sin_port = htons(port); 00172 00173 if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 00174 { 00175 Close(); 00176 return false; 00177 } 00178 00179 listen(sock, 5); 00180 m_bListening = true; 00181 00182 #elif defined(__TI_COMPILER_VERSION__) 00183 uint_32 error; 00184 00185 m_socket = socket_stream(); 00186 if (m_socket == VCRT_SOCKET_ERROR) 00187 { 00188 m_socket = -1; 00189 return false; 00190 } 00191 00192 //set linger on - helps in closing socket immidiately 00193 00194 // SO_LINGER socket option is not available on VCRT. 00195 // But in Close() the shutdown flag FLAG_ABORT_CONNECTION enforces hard closing of the socket 00196 // as would SO_LINGER with zero timeout on other platforms. 00197 00198 //set non blocking 00199 00200 // there is no socket-global (non-)blocking flag on VCRT 00201 // - accept() is always blocking and therefore guarded by VCRT_selectset(). 00202 // - recv() behavior is set during Recv() depending on bWait flag 00203 // - send(): don't wait for data to be transmitted, return after buffering. this resembles behavior of Send() on other platforms 00204 uint_32 opt_value = TRUE; 00205 error = setsockopt(m_socket, SOL_TCP, OPT_SEND_NOWAIT, &opt_value, sizeof(opt_value)); 00206 if (error != VCRT_OK) 00207 { 00208 printf("Error, setsockopt(OPT_SEND_NOWAIT) failed with error code 0x%x\n", error); 00209 Close(); 00210 return false; 00211 } 00212 00213 sockaddr_in serv_addr; 00214 memset( &serv_addr, 0, sizeof(serv_addr)); 00215 serv_addr.sin_family = AF_INET; 00216 if (ip != NULL) 00217 { 00218 //never cast ip to an int pointer! this would imply 4byte alignment. 00219 memcpy((char *)&serv_addr.sin_addr.s_addr, ip, 4); 00220 // vcrt expects inverse order of ip chars 00221 // than provided by RemoteApplicationHandler.cpp 00222 serv_addr.sin_addr.s_addr = revert_byte_order(serv_addr.sin_addr.s_addr); 00223 } 00224 else 00225 { 00226 serv_addr.sin_addr.s_addr = INADDR_ANY; 00227 } 00228 serv_addr.sin_port = port; //htons(port); VCRT does not want the port in network byte order 00229 00230 error = bind(m_socket, &serv_addr, sizeof(serv_addr)); 00231 if (error!=VCRT_OK) 00232 { 00233 printf("\nsocket bind failed, error code: 0x%x\n", error); 00234 Close(); 00235 return false; 00236 } 00237 00238 error = listen(m_socket, 5); 00239 if (error!=VCRT_OK) 00240 { 00241 printf("\nsocket listen failed, error code: 0x%x\n", error); 00242 Close(); 00243 return false; 00244 } 00245 m_bListening = true; 00246 00247 #else 00248 m_socket = socket(AF_INET, SOCK_STREAM, 0); 00249 if (m_socket < 0) 00250 { 00251 m_socket = -1; 00252 return false; 00253 } 00254 00255 // set linger on - helps in closing socket immidiately 00256 linger li; 00257 li.l_onoff = true; 00258 li.l_linger = 0; 00259 00260 if(setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &li, sizeof(li)) == -1) 00261 { 00262 printf("setting linger option failed\n"); 00263 Close(); 00264 return false; 00265 } 00266 00267 // set non blocking 00268 if (fcntl(m_socket, F_SETFL, O_NONBLOCK) == -1) 00269 { 00270 printf("setting non-blocking option failed\n"); 00271 Close(); 00272 return false; 00273 } 00274 00275 struct sockaddr_in serv_addr; 00276 bzero((char *)&serv_addr, sizeof(serv_addr)); 00277 00278 serv_addr.sin_family = AF_INET; 00279 if (ip != NULL) 00280 { 00281 bcopy(ip, (char *)&serv_addr.sin_addr.s_addr, 4); 00282 } 00283 else 00284 { 00285 serv_addr.sin_addr.s_addr = INADDR_ANY; 00286 } 00287 serv_addr.sin_port = htons(port); 00288 00289 if (bind(m_socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 00290 { 00291 Close(); 00292 return false; 00293 } 00294 00295 listen(m_socket, 5); 00296 m_bListening = true; 00297 #endif 00298 00299 return true; 00300 } 00301 00302 CTCPSocket* CTCPSocket::Accept(unsigned char *ip) 00303 { 00304 if (m_socket == -1 || !m_bListening) 00305 return NULL; 00306 00307 #ifdef WIN32 00308 SOCKET sock = (SOCKET)m_socket; 00309 struct sockaddr_in cli_addr; 00310 int clilen = sizeof(cli_addr); 00311 00312 SOCKET new_socket = accept(sock, (struct sockaddr *) &cli_addr, &clilen); 00313 if (new_socket == INVALID_SOCKET) 00314 { 00315 return NULL; 00316 } 00317 00318 // set non blocking 00319 u_long v = 1; 00320 if (ioctlsocket(new_socket, FIONBIO, &v) == SOCKET_ERROR) 00321 { 00322 printf("setting non-blocking option failed\n"); 00323 Close(); 00324 return false; 00325 } 00326 00327 // set no delay for sending 00328 int v2 = 1; 00329 if (setsockopt(new_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&v2, sizeof(v2)) == -1) 00330 { 00331 printf("newly accepted socket couldn't be set to no delay mode\n"); 00332 } 00333 00334 if (ip != NULL) 00335 { 00336 memcpy(ip, (char *) &cli_addr.sin_addr.s_addr, 4); 00337 } 00338 00339 CTCPSocket *s = new CTCPSocket(); 00340 s->m_socket = (int) new_socket; 00341 00342 return s; 00343 00344 #elif defined(__TI_COMPILER_VERSION__) 00345 uint_32 error; 00346 00347 // acccept is always blocking on vcrt, so we need to test for activity first 00348 // which is not blocking 00349 error = VCRT_selectset(&m_socket, 1, (uint_32)-1); 00350 00351 if (error==0) //no new connections, nothing to do 00352 { 00353 return NULL; 00354 } 00355 if (error==VCRT_SOCKET_ERROR) //an error occured 00356 { 00357 printf("Error in accept(): VCRT_selectset failed, error code 0x%x\n", VCRT_geterror(m_socket)); 00358 return NULL; 00359 } 00360 if (error!=m_socket) //should never happen as we check only this socket. 00361 { 00362 printf("Error in accept(): VCRT_selectset returned invalid socket"); 00363 return NULL; 00364 } 00365 00366 00367 sockaddr_in cli_addr; 00368 uint_16 clilen = sizeof(cli_addr); 00369 00370 int new_socket = accept(m_socket, &cli_addr, &clilen); 00371 if (new_socket == VCRT_SOCKET_ERROR) 00372 { 00373 error = VCRT_geterror(m_socket); 00374 if (error == VCRT_OK) 00375 { 00376 printf("\nAccept: Connection reset by peer"); 00377 } 00378 else 00379 { 00380 printf("Error, accept() failed with error code 0x%x\n", error); 00381 } 00382 return NULL; 00383 } 00384 00385 00386 00387 // set non blocking 00388 00389 // there is no socket-global (non-)blocking flag on VCRT 00390 // - accept() is always blocking and therefore guarded by VCRT_selectset(). 00391 // - recv() behavior is set during Recv() depending on bWait flag 00392 // - send(): don't wait for data to be transmitted, return after buffering. this resembles behavior of Send() on other platforms 00393 uint_32 opt_value; 00394 00395 opt_value = TRUE; 00396 error = setsockopt(m_socket, SOL_TCP, OPT_SEND_NOWAIT, &opt_value, sizeof(opt_value)); 00397 if (error != VCRT_OK) 00398 { 00399 printf("Error, setsockopt(OPT_SEND_NOWAIT) failed with error code 0x%x\n", error); 00400 } 00401 00402 00403 00404 // set no delay for sending 00405 // OPT_NO_NAGLE_ALGORITHM is the VCRT equivalent to TCP_NODELAY 00406 opt_value = TRUE; 00407 error = setsockopt(m_socket, SOL_TCP, OPT_NO_NAGLE_ALGORITHM, &opt_value, sizeof(opt_value)); 00408 if (error != VCRT_OK) 00409 { 00410 printf("Error, setsockopt(OPT_NO_NAGLE_ALGORITHM) failed with error code 0x%x\n", error); 00411 } 00412 00413 00414 00415 if (ip != NULL) 00416 { 00417 // vcrt expects inverse order of ip chars 00418 // than provided by RemoteApplicationHandler.cpp 00419 cli_addr.sin_addr.s_addr = revert_byte_order(cli_addr.sin_addr.s_addr); 00420 //never cast ip to an int pointer! this would imply 4byte alignment. 00421 memcpy( ip, &cli_addr.sin_addr.s_addr, 4); 00422 } 00423 00424 CTCPSocket *sock = new CTCPSocket(); 00425 sock->m_socket = new_socket; 00426 00427 return sock; 00428 00429 #else 00430 struct sockaddr_in cli_addr; 00431 socklen_t clilen = sizeof(cli_addr); 00432 00433 int new_socket = accept(m_socket, (struct sockaddr *) &cli_addr, &clilen); 00434 if (new_socket < 0) 00435 { 00436 return NULL; 00437 } 00438 00439 // set non blocking 00440 if (fcntl(new_socket, F_SETFL, O_NONBLOCK) == -1) 00441 { 00442 printf("newly accepted socket couldn't be set to non blocking mode\n"); 00443 } 00444 00445 // set no delay for sending 00446 int v = 1; 00447 if (setsockopt(new_socket, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)) == -1) 00448 { 00449 printf("newly accepted socket couldn't be set to no delay mode\n"); 00450 } 00451 00452 if (ip != NULL) 00453 { 00454 bcopy((char *)&cli_addr.sin_addr.s_addr, ip, 4); 00455 } 00456 00457 CTCPSocket *sock = new CTCPSocket(); 00458 sock->m_socket = new_socket; 00459 00460 return sock; 00461 #endif 00462 } 00463 00464 bool CTCPSocket::Open(const unsigned char *ip, int port) 00465 { 00466 Close(); 00467 00468 #ifdef WIN32 00469 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); 00470 if (sock == INVALID_SOCKET) 00471 { 00472 m_socket = -1; 00473 return false; 00474 } 00475 00476 m_socket = (int)sock; 00477 00478 struct sockaddr_in serv_addr; 00479 memset((char *)&serv_addr, 0, sizeof(serv_addr)); 00480 00481 serv_addr.sin_family = AF_INET; 00482 memcpy((char *)&serv_addr.sin_addr.s_addr, ip, 4); 00483 serv_addr.sin_port = htons(port); 00484 00485 if (connect(sock, (const sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) 00486 { 00487 Close(); 00488 return false; 00489 } 00490 00491 // set non blocking (after connect) 00492 u_long v = 1; 00493 if (ioctlsocket(sock, FIONBIO, &v) == SOCKET_ERROR) 00494 { 00495 printf("setting non-blocking option failed\n"); 00496 Close(); 00497 return false; 00498 } 00499 00500 // set no delay for sending 00501 int v2 = 1; 00502 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&v2, sizeof(v2)) == -1) 00503 { 00504 printf("socket couldn't be set to no delay mode\n"); 00505 } 00506 00507 m_bListening = false; 00508 00509 #elif defined(__TI_COMPILER_VERSION__) 00510 uint_32 error; 00511 00512 m_socket = socket_stream(); 00513 if (m_socket == VCRT_SOCKET_ERROR) 00514 { 00515 printf("Error in Open(): socket_stream() failed\n"); 00516 m_socket = -1; 00517 return false; 00518 } 00519 00520 sockaddr_in serv_addr; 00521 memset( &serv_addr, 0, sizeof(serv_addr)); 00522 serv_addr.sin_family = AF_INET; 00523 00524 //never cast ip to an int pointer! this would imply 4byte alignment. 00525 memcpy(&(serv_addr.sin_addr.s_addr), ip, 4); 00526 // vcrt expects inverse order of ip chars 00527 // than provided by RemoteApplicationHandler.cpp 00528 serv_addr.sin_addr.s_addr = revert_byte_order(serv_addr.sin_addr.s_addr); 00529 00530 serv_addr.sin_port = port; //htons(port); VCRT does not want the port in network byte order 00531 00532 //printf("DEBUG: chars %d,%d,%d,%d, serv_addr.sin_addr.s_addr: 0x%x\n", ip[0], ip[1], ip[2], ip[3], serv_addr.sin_addr.s_addr); 00533 00534 error = connect(m_socket, &serv_addr, sizeof(serv_addr)); 00535 if (error != VCRT_OK) 00536 { 00537 printf("Error in Open(): connect failed, error code 0x%x\n", error); 00538 Close(); 00539 return false; 00540 } 00541 00542 // set non blocking (after connect) 00543 00544 // there is no socket-global (non-)blocking flag on VCRT 00545 // - accept() is always blocking and therefore guarded by VCRT_selectset(). 00546 // - recv() behavior is set during Recv() depending on bWait flag 00547 // - send(): don't wait for data to be transmitted, return after buffering. this resembles behavior of Send() on other platforms 00548 uint_32 opt_value; 00549 00550 opt_value = TRUE; 00551 error = setsockopt(m_socket, SOL_TCP, OPT_SEND_NOWAIT, &opt_value, sizeof(opt_value)); 00552 if (error != VCRT_OK) 00553 { 00554 printf("Error, setsockopt(OPT_SEND_NOWAIT) failed with error code 0x%x\n", error); 00555 Close(); 00556 return false; 00557 } 00558 00559 00560 // set no delay for sending 00561 // OPT_NO_NAGLE_ALGORITHM is the VCRT equivalent to TCP_NODELAY 00562 opt_value = TRUE; 00563 error = setsockopt(m_socket, SOL_TCP, OPT_NO_NAGLE_ALGORITHM, &opt_value, sizeof(opt_value)); 00564 if (error != VCRT_OK) 00565 { 00566 printf("Error, setsockopt(OPT_NO_NAGLE_ALGORITHM) failed with error code 0x%x\n", error); 00567 Close(); 00568 return false; 00569 } 00570 00571 m_bListening = false; 00572 00573 #else 00574 m_socket = socket(AF_INET, SOCK_STREAM, 0); 00575 if (m_socket < 0) 00576 { 00577 m_socket = -1; 00578 return false; 00579 } 00580 00581 struct sockaddr_in serv_addr; 00582 bzero((char *)&serv_addr, sizeof(serv_addr)); 00583 00584 serv_addr.sin_family = AF_INET; 00585 bcopy(ip, (char *)&serv_addr.sin_addr.s_addr, 4); 00586 serv_addr.sin_port = htons(port); 00587 00588 if (connect(m_socket, (const sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) 00589 { 00590 Close(); 00591 return false; 00592 } 00593 00594 // set non blocking (after connect) 00595 if (fcntl(m_socket, F_SETFL, O_NONBLOCK) == -1) 00596 { 00597 Close(); 00598 return false; 00599 } 00600 00601 // set no delay for sending 00602 int v = 1; 00603 if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)) == -1) 00604 { 00605 Close(); 00606 return false; 00607 } 00608 00609 m_bListening = false; 00610 #endif 00611 00612 return true; 00613 } 00614 00615 void CTCPSocket::Close() 00616 { 00617 if (m_socket == -1) 00618 return; 00619 00620 #ifdef WIN32 00621 SOCKET sock = (SOCKET)m_socket; 00622 closesocket(sock); 00623 00624 #elif defined(__TI_COMPILER_VERSION__) 00625 // FLAG_ABORT_CONNECTION enforces hard closing of the socket as specified 00626 // by the SO_LINGER socket option with zero timeout on other platforms. 00627 // SO_LINGER is not available on VCRT. 00628 uint_32 error = shutdown(m_socket, FLAG_ABORT_CONNECTION); 00629 if(error!= VCRT_OK) 00630 { 00631 printf("\nsocket shutdown failed, error code: 0x%x\n", error); 00632 } 00633 #else 00634 close(m_socket); 00635 #endif 00636 00637 m_socket = -1; 00638 } 00639 00640 bool CTCPSocket::Send(const void *pData, int nBytes) 00641 { 00642 if (m_socket == -1 || m_bListening) 00643 return false; 00644 00645 #ifdef WIN32 00646 SOCKET sock = (SOCKET)m_socket; 00647 int size = 0; 00648 unsigned char *ptr = (unsigned char*) pData; 00649 while (true) 00650 { 00651 int s = send(sock, (const char *) ptr, nBytes, 0); 00652 if (s == SOCKET_ERROR) 00653 { 00654 int errnum = WSAGetLastError(); 00655 if (errnum == WSAEWOULDBLOCK) 00656 continue; 00657 00658 return false; 00659 } 00660 00661 size += s; 00662 ptr += s; 00663 nBytes -= s; 00664 if (nBytes == 0) 00665 break; 00666 00667 } 00668 00669 #elif defined(__TI_COMPILER_VERSION__) 00670 00671 char *ptr = (char *) pData; 00672 while (nBytes>0) 00673 { 00674 // as OPT_SEND_NOWAIT is set above, this blocks until data is buffered 00675 // but does not wait for data to be send and acknowledged. 00676 // Send() therefore blocks until all data is passed on to the OS. 00677 int_32 count = send(m_socket, ptr, nBytes, 0); 00678 00679 if (count==VCRT_ERROR) 00680 { 00681 printf("Error in Send(): send failed, error code 0x%x\n", VCRT_geterror(m_socket)); 00682 return false; 00683 } 00684 00685 ptr += count; 00686 nBytes -= count; 00687 } 00688 00689 #else 00690 int size = 0; 00691 unsigned char *ptr = (unsigned char *) pData; 00692 while (true) 00693 { 00694 int s = write(m_socket, ptr, nBytes); 00695 if (s == -1) 00696 { 00697 int errnum = errno; 00698 if (errnum == EAGAIN) 00699 continue; 00700 00701 return false; 00702 } 00703 00704 size += s; 00705 ptr += s; 00706 nBytes -= s; 00707 if (nBytes == 0) 00708 break; 00709 00710 } 00711 #endif 00712 00713 return true; 00714 } 00715 00716 int CTCPSocket::Recv(void *pData, int nMaxBytes, bool bWait) 00717 { 00718 if (m_socket == -1 || m_bListening) 00719 return -1; 00720 00721 #ifdef WIN32 00722 SOCKET sock = (SOCKET) m_socket; 00723 00724 if (bWait) 00725 { 00726 int size = 0; 00727 unsigned char *ptr = (unsigned char*) pData; 00728 while (true) 00729 { 00730 int s = recv(sock, (char *) ptr, nMaxBytes, 0); 00731 if (s == SOCKET_ERROR) 00732 { 00733 int errnum = WSAGetLastError(); 00734 if (errnum == WSAEWOULDBLOCK) 00735 continue; 00736 00737 // this is really bad, the connection is probably dead 00738 return -1; 00739 } 00740 00741 ptr += s; 00742 size += s; 00743 nMaxBytes -= s; 00744 00745 if (nMaxBytes == 0) 00746 return size; 00747 00748 } 00749 } 00750 else 00751 { 00752 int size = recv(sock, (char *) pData, nMaxBytes, 0); 00753 if (size == SOCKET_ERROR) 00754 { 00755 int errnum = WSAGetLastError(); 00756 if (errnum == WSAEWOULDBLOCK) 00757 return 0; 00758 00759 // this is really bad, the connection is probably dead 00760 00761 return -1; 00762 } 00763 else if (size == 0) 00764 { 00765 return -1; 00766 } 00767 00768 return size; 00769 } 00770 00771 #elif defined(__TI_COMPILER_VERSION__) 00772 //set OPT_RECV_NOWAIT depending on bWait 00773 // if bWait==false: behaves like a non-blocking socket on other platforms 00774 // else: recv() blocks, avoiding polling with busy waiting. 00775 // recv() may non the less return early in case of a PUSH flag. 00776 uint_32 opt_value = bWait? FALSE : TRUE; 00777 uint_32 error = setsockopt(m_socket, SOL_TCP, OPT_RECEIVE_NOWAIT, &opt_value, sizeof(opt_value)); 00778 if (error != VCRT_OK) 00779 { 00780 printf("Error in Recv(), setsockopt(OPT_RECEIVE_NOWAIT) failed with error code 0x%x\n", error); 00781 return -1; 00782 } 00783 00784 if (bWait) 00785 { 00786 int size = 0; 00787 char *ptr = (char *) pData; 00788 while (nMaxBytes>0) 00789 { 00790 int_32 count = recv(m_socket, ptr, nMaxBytes, 0); //is set to blocking above 00791 00792 if (count == VCRT_ERROR) 00793 { 00794 printf("Error in Recv(): recv failed, error code 0x%x\n", VCRT_geterror(m_socket)); 00795 // this is really bad, the connection is probably dead 00796 return -1; 00797 } 00798 00799 ptr += count; 00800 size += count; 00801 nMaxBytes -= count; 00802 } 00803 return size; 00804 } 00805 else 00806 { 00807 //receive whatever data is available and return immediately 00808 int_32 count = recv(m_socket, (char*)pData, nMaxBytes, 0); //is set to non-blocking above 00809 00810 if (count == VCRT_ERROR) 00811 { 00812 printf("Error in Recv(): recv failed, error code 0x%x\n", VCRT_geterror(m_socket)); 00813 // this is really bad, the connection is probably dead 00814 return -1; 00815 } 00816 // on vcrt, count==0 means zero bytes received and not connection closed by peer. 00817 // so in this case 0 is returned and not -1. 00818 00819 return count; 00820 } 00821 00822 #else 00823 if (bWait) 00824 { 00825 int size = 0; 00826 unsigned char *ptr = (unsigned char *) pData; 00827 while (true) 00828 { 00829 int s = (int) recv(m_socket, ptr, nMaxBytes, 0); 00830 if (s == -1) 00831 { 00832 int errnum = errno; 00833 if (errnum == EAGAIN) 00834 continue; 00835 00836 // this is really bad, the connection is probably dead 00837 00838 return -1; 00839 } 00840 00841 ptr += s; 00842 size += s; 00843 nMaxBytes -= s; 00844 00845 if (nMaxBytes == 0) 00846 return size; 00847 00848 } 00849 } 00850 else 00851 { 00852 int size = (int) recv(m_socket, pData, nMaxBytes, 0); 00853 if (size == -1) 00854 { 00855 int errnum = errno; 00856 if (errnum == EAGAIN) 00857 return 0; 00858 00859 // this is really bad, the connection is probably dead 00860 00861 return -1; 00862 } 00863 else if (size == 0) 00864 { 00865 return -1; 00866 } 00867 00868 return size; 00869 } 00870 #endif 00871 00872 return -1; 00873 }