00001 /* --------------------------------------------------------------------------- 00002 Phission : 00003 Realtime Vision Processing System 00004 00005 Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu) 00006 University of Massachusetts at Lowell, 00007 Laboratory for Artificial Intelligence and Robotics 00008 00009 This file is part of Phission. 00010 00011 Phission is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU Lesser General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 Phission is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU Lesser General Public License for more details. 00020 00021 You should have received a copy of the GNU Lesser General Public License 00022 along with Phission; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 00025 ---------------------------------------------------------------------------*/ 00026 /* -------------------------------------------------------------------------- * 00027 * phSocket.cpp: C++ Wrapper class for socket programming * 00028 * * 00029 * -------------------------------------------------------------------------- * 00030 * This code is mostly from the Phission code base. * 00031 * This code was originally coded by John R. Watson in the Fall of 2003 and * 00032 * added to Phission by myself. Since then I've added some necessary * 00033 * functionality for use in a streaming JPEG/Image server/client for Phission.* 00034 * I'm using it here to further stretch/test it's functionality * 00035 * -------------------------------------------------------------------------- */ 00036 #ifdef HAVE_CONFIG_H 00037 #include <phissionconfig.h> 00038 #endif 00039 00040 #define PH_USE_SOCKET_PRIVATE 1 00041 #include <phSocketPrivate.h> 00042 00043 #if defined(WIN32) 00044 #define __USE_W32_SOCKETS 1 00045 #if !defined(_MSC_VER) 00046 #include <windows.h> 00047 #include <winsock2.h> 00048 #else 00049 #include <winsock2.h> 00050 #include <windows.h> 00051 #endif 00052 #endif 00053 00054 #if defined(HAVE_SYS_SOCKET_H) && !defined(WIN32) 00055 #include <sys/socket.h> 00056 #endif /* defined(HAVE_SYS_SOCKET_H) && !defined(WIN32) */ 00057 00058 #if !defined(WIN32) 00059 #if defined(HAVE_UNISTD_H) 00060 #include <unistd.h> 00061 #endif 00062 #if defined(HAVE_ERRNO_H) 00063 #include <errno.h> 00064 #endif 00065 #endif 00066 00067 #if defined(HAVE_LWIP_SOCKETS_H) 00068 #define LWIP_PROVIDE_ERRNO 00069 #include <lwip/sockets.h> 00070 #include <lwip/cglobals.h> 00071 #include <lwip/inet.h> 00072 00073 #undef accept 00074 #undef bind 00075 #undef shutdown 00076 #undef close 00077 #undef connect 00078 #undef getsockname 00079 #undef getpeername 00080 #undef setsockopt 00081 #undef getsockopt 00082 #undef listen 00083 #undef recv 00084 #undef read 00085 #undef recvfrom 00086 #undef send 00087 #undef sendto 00088 #undef socket 00089 #undef write 00090 #undef select 00091 #undef ioctlsocket 00092 00093 #define ph_socket_accept(a,b,c) lwip_accept(a,b,c) 00094 #define ph_socket_bind(a,b,c) lwip_bind(a,b,c) 00095 #define ph_socket_shutdown(a,b) lwip_shutdown(a,b) 00096 #define ph_socket_close(s) lwip_close(s) 00097 #define ph_socket_connect(a,b,c) lwip_connect(a,b,c) 00098 #define ph_socket_getsockname(a,b,c) lwip_getsockname(a,b,c) 00099 #define ph_socket_getpeername(a,b,c) lwip_getpeername(a,b,c) 00100 #define ph_socket_setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e) 00101 #define ph_socket_getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e) 00102 #define ph_socket_listen(a,b) lwip_listen(a,b) 00103 #define ph_socket_recv(a,b,c,d) lwip_recv(a,b,c,d) 00104 #define ph_socket_read(a,b,c) lwip_read(a,b,c) 00105 #define ph_socket_recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f) 00106 #define ph_socket_send(a,b,c,d) lwip_send(a,b,c,d) 00107 #define ph_socket_sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f) 00108 #define ph_socket_socket(a,b,c) lwip_socket(a,b,c) 00109 #define ph_socket_write(a,b,c) lwip_write(a,b,c) 00110 #define ph_socket_select(a,b,c,d,e) lwip_select(a,b,c,d,e) 00111 #define ph_socket_ioctlsocket(a,b,c) lwip_ioctl(a,b,c) 00112 #define ph_socket_send_buftype void 00113 #define ph_socket_gethostaddr(iface,buf) gethostaddr(iface,buf) 00114 00115 const char *inet_ntop( int af, 00116 const void *src, 00117 char *dst, 00118 socklen_t size ); 00119 #else 00120 #define ph_socket_close ::close 00121 #define ph_socket_socket ::socket 00122 #define ph_socket_connect ::connect 00123 #define ph_socket_send ::send 00124 #define ph_socket_recv ::recv 00125 #define ph_socket_select select 00126 #define ph_socket_ioctlsocket ioctlsocket 00127 #define ph_socket_shutdown shutdown 00128 #define ph_socket_getpeername getpeername 00129 #define ph_socket_getsockname getsockname 00130 #define ph_socket_setsockopt setsockopt 00131 #define ph_socket_send_buftype const char 00132 #endif 00133 00134 #include <phStandard.h> 00135 00136 #include <phObject.h> 00137 #include <phMutex.h> 00138 00139 #include <phSocket.h> 00140 00141 #if !defined(WIN32) && \ 00142 defined(HAVE_FCNTL_H) && \ 00143 defined(HAVE_NETINET_IN_H) && \ 00144 defined(HAVE_ARPA_INET_H) && \ 00145 defined(HAVE_NETDB_H) 00146 00147 #include <fcntl.h> 00148 #include <netinet/in.h> 00149 #include <arpa/inet.h> 00150 #include <netdb.h> 00151 #include <errno.h> 00152 #endif /* !WIN32 */ 00153 00154 #ifndef MSG_WAITALL 00155 #define MSG_WAITALL 0 00156 #endif 00157 #ifndef MSG_NOSIGNAL 00158 #define MSG_NOSIGNAL 0 00159 #endif 00160 00161 #if HAVE_STDLIB_H 00162 #include <stdlib.h> 00163 #endif 00164 #if HAVE_STRING_H 00165 #include <string.h> 00166 #endif 00167 00168 /* ------------------------------------------------------------------------- */ 00169 #include <phError.h> 00170 #include <phMemory.h> 00171 #include <phPrint.h> 00172 00173 /* ------------------------------------------------------------------------- */ 00174 #if defined(HAVE_LWIP_SOCKETS_H) && !phHAVE(INET_NTOP) && phHAVE(PH_INET_NTOP) 00175 00176 #define INET_ADDRSTRLEN 16 00177 #define INET6_ADDRSTRLEN 46 00178 00179 const char *inet_ntop( int af, 00180 const void * src, 00181 char *dst, 00182 socklen_t size ) 00183 { 00184 uint32_t s = 0; 00185 00186 if ((src == NULL) || (dst == NULL)) return NULL; 00187 00188 if ((af == AF_INET) && (size >= INET_ADDRSTRLEN)) 00189 { 00190 s = ntohl(*((uint32_t *)src)); 00191 sprintf(dst,"%d.%d.%d.%d", 00192 (s>>24) & 0xff, 00193 (s>>16) & 0xff, 00194 (s>>8) & 0xff, 00195 (s) & 0xff); 00196 00197 return dst; 00198 } 00199 #if defined(AF_INET6) 00200 else if ((af == AF_INET6) && (size >= INET6_ADDRSTRLEN)) 00201 { 00202 s = ntohl(*((uint32_t*)src)); 00203 sprintf(dst,"%x:%x:%x:%x:%x:%x:%x:%x", 00204 (s>>112) & 0xffff, 00205 (s>>96) & 0xffff, 00206 (s>>80) & 0xffff, 00207 (s>>64) & 0xffff, 00208 (s>>48) & 0xffff, 00209 (s>>32) & 0xffff, 00210 (s>>16) & 0xffff, 00211 (s) & 0xffff 00212 ); 00213 00214 return dst; 00215 } 00216 #endif 00217 00218 return NULL; 00219 } 00220 #endif /* defined(HAVE_LWIP_SOCKETS_H) */ 00221 00222 /* ------------------------------------------------------------------------- */ 00223 struct ph_socket_info_t 00224 { 00225 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00226 /* variables for re-entrant safe version of gethostbyname */ 00227 struct hostent m_hostent_ret; 00228 int m_hostent_errno; 00229 char *m_hostent_buf; 00230 size_t m_hostent_buflen; 00231 00232 /* m_hostent_result: Stores ascii information about the host we connected to; 00233 * used for debugging or status information. This is the result of 00234 * gethostname/DNS lookup */ 00235 struct hostent *m_hostent_result; 00236 #endif 00237 /* m_src/dst_sin: the socket structure for the connection we've 00238 * established */ 00239 struct sockaddr_in m_src_sin; 00240 struct sockaddr_in m_dst_sin; 00241 /* m_sock: The socket identifier */ 00242 phSOCKET m_sock; 00243 }; 00244 00245 00246 00247 /* ------------------------------------------------------------------------- */ 00248 const char *network_errno_resolve(int n_errno) 00249 { 00250 char *message = NULL; 00251 00252 #if phHOST_NOT_FOUND 00253 if (n_errno == phHOST_NOT_FOUND) 00254 { 00255 message = "The specified host is unknown."; 00256 } 00257 #endif 00258 if (0 00259 #if defined(NO_ADDRESS) 00260 || (n_errno == NO_ADDRESS) 00261 #endif 00262 #if phNO_DATA 00263 || (n_errno == phNO_DATA) 00264 #endif 00265 ) 00266 { 00267 message = "The requested name is valid but does not have an IP address."; 00268 } 00269 #if phNO_RECOVERY 00270 if (n_errno == phNO_RECOVERY) 00271 { 00272 message = "A non-recoverable name server error occurred."; 00273 } 00274 #endif 00275 #if phTRY_AGAIN 00276 if (n_errno == phTRY_AGAIN) 00277 { 00278 message = "A temporary error occurred on an authoritative name server. Try again later."; 00279 } 00280 else 00281 { 00282 message = "Unknown network error."; 00283 } 00284 #endif 00285 00286 return (const char*)message; 00287 } 00288 00289 /* ---------------------------------------------------------------------------- 00290 * winsock2_init - used to initialize the WinSock library 00291 * ------------------------------------------------------------------------- */ 00292 #if defined(WIN32) 00293 static int winsock_inited = 0; 00294 static void winsock2_init() 00295 { 00296 char *function = "winsock2_init"; 00297 00298 if (!winsock_inited) 00299 { 00300 WORD wVersionRequested = 0; 00301 WSADATA wsaData; 00302 int err = 0; 00303 int cleanup = 0; 00304 00305 wVersionRequested = MAKEWORD( 2, 2 ); 00306 00307 err = WSAStartup( wVersionRequested, &wsaData ); 00308 if ( err != 0 ) { 00309 /* Tell the user that we could not find a usable */ 00310 /* WinSock DLL. */ 00311 phWINSOCK_ERR_PRINT( "WSAStartup() failed" ); 00312 return; 00313 } 00314 00315 /* Confirm that the WinSock DLL supports 2.2.*/ 00316 /* Note that if the DLL supports versions greater */ 00317 /* than 2.2 in addition to 2.2, it will still return */ 00318 /* 2.2 in wVersion since that is the version we */ 00319 /* requested. */ 00320 00321 if ( LOBYTE( wsaData.wVersion ) != 2 ) { 00322 phERR_PRINT("LOBYTE( wsaData.wVersion ) != 2"); 00323 cleanup = 1; 00324 } 00325 if ( HIBYTE( wsaData.wVersion ) != 2 ) { 00326 phERR_PRINT("HIBYTE( wsaData.wVersion ) != 2"); 00327 cleanup = 1; 00328 } 00329 if ( cleanup ) { 00330 /* Tell the user that we could not find a usable */ 00331 /* WinSock DLL. */ 00332 WSACleanup( ); 00333 return; 00334 } 00335 00336 winsock_inited = 1; 00337 } 00338 } 00339 #endif /* WIN32 */ 00340 00341 /* ---------------------------------------------------------------------------- 00342 * phSocket: communications object constructor 00343 * ------------------------------------------------------------------------- */ 00344 phSocket::phSocket(const char *host, 00345 const int port ) 00346 { 00347 phFUNCTION("phSocket::phSocket") 00348 int locked = 0; 00349 00350 phTHIS_LOOSE_LOCK(locked); 00351 00352 this->setName("phSocket"); 00353 00354 this->m_info = (struct ph_socket_info_t *)phCalloc(1, 00355 sizeof(struct ph_socket_info_t)); 00356 phPRINT_PTR(this->m_info,"phCalloc","phCalloc failed."); 00357 00358 #if defined(WIN32) 00359 if (!winsock_inited) winsock2_init(); 00360 #endif 00361 00362 this->m_src_port = 0; 00363 this->m_dst_port = 0; 00364 00365 this->m_dst_host = NULL; 00366 this->m_dst_host_size = 0; 00367 this->m_src_host = NULL; 00368 this->m_src_host_size = 0; 00369 this->m_temp_buf = NULL; 00370 this->m_temp_buf_size = 0; 00371 00372 this->m_blocking = phBLOCK; 00373 this->m_linger = phLINGER_OFF; 00374 this->m_linger_time = 0; 00375 this->m_call_shutdown = 0; 00376 00377 this->m_exit_trigger = 0; 00378 00379 /* initialize all the member variables */ 00380 this->m_info->m_sock = (phSOCKET)-1; 00381 this->m_warning_level = 1; 00382 this->m_family = AF_INET; 00383 this->m_protocol = IPPROTO_TCP; 00384 this->m_socket_type = SOCK_STREAM; 00385 00386 phMemset(&(this->m_info->m_src_sin), 0, sizeof(struct sockaddr_in)); 00387 phMemset(&(this->m_info->m_dst_sin), 0, sizeof(struct sockaddr_in)); 00388 this->m_info->m_src_sin.sin_family = this->m_family; 00389 this->m_info->m_dst_sin.sin_family = this->m_family; 00390 00391 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00392 this->m_info->m_hostent_result = NULL; 00393 00394 /* initialize the server address struct */ 00395 this->m_info->m_hostent_buf = (char *)phCalloc((1<<12), sizeof(char)); 00396 phPRINT_NULLPTR(this->m_info->m_hostent_buf,"phCalloc","phCalloc failed"); 00397 if (this->m_info->m_hostent_buf != NULL) 00398 { 00399 this->m_info->m_hostent_buflen = (1<<12); 00400 } 00401 #endif 00402 rc = this->setDstPort(port); 00403 rc = this->setDstHost(host); 00404 00405 phTHIS_LOOSE_UNLOCK(locked); 00406 } 00407 00408 /* ---------------------------------------------------------------------------- 00409 * ~phSocket: communications object destructor 00410 * ------------------------------------------------------------------------- */ 00411 phSocket::~phSocket() 00412 { 00413 phFUNCTION("phSocket::~phSocket") 00414 int locked = 0; 00415 00416 phTHIS_LOOSE_LOCK(locked); 00417 00418 /* close the socket */ 00419 if (this->m_info->m_sock >= 0) 00420 { 00421 if (this->m_call_shutdown && 1) 00422 { 00423 #if phHAVE(SHUTDOWN) 00424 /* Use shutdown on the socket to cleanly 00425 * shutdown the socket and get rid of it */ 00426 rc = ph_socket_shutdown(this->m_info->m_sock,phSHUT_RDWR); 00427 if (this->lastSocketError() == phENOTCONN) 00428 rc = phSUCCESS; /* ignore endpoint not connected */ 00429 phPRINT_RC(rc,"shutdown","shutdown failed"); 00430 #else 00431 #error "Don\'t have shutdown" 00432 #endif 00433 } 00434 #if defined(WIN32) && phHAVE(CLOSESOCKET) 00435 rc = closesocket(this->m_info->m_sock); 00436 #elif (!defined(WIN32)) 00437 rc = ph_socket_close(this->m_info->m_sock); 00438 #else 00439 #if defined(WIN32) 00440 #error "Don\'t have closesocket" 00441 #else 00442 #error "Don\'t have close" 00443 #endif 00444 #endif 00445 this->m_info->m_sock = (phSOCKET)-1; 00446 } 00447 00448 this->m_dst_port = 0; 00449 this->m_src_port = 0; 00450 00451 phFree(this->m_temp_buf); 00452 this->m_temp_buf_size = 0; 00453 00454 phFree(this->m_src_host); 00455 this->m_src_host_size = 0; 00456 00457 phFree(this->m_dst_host); 00458 this->m_dst_host_size = 0; 00459 00460 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00461 phFree(this->m_info->m_hostent_buf); 00462 this->m_info->m_hostent_buflen = 0; 00463 #endif 00464 phFree(this->m_info); 00465 } 00466 00467 /* -------------------------------------------------------------------------- * 00468 * setSrcPort: 00469 * -------------------------------------------------------------------------- */ 00470 int phSocket::setSrcPort(int port) 00471 { 00472 phFUNCTION("phSocket::setSrcPort") 00473 int locked = 0; 00474 00475 phTHIS_LOCK(locked); 00476 00477 /* assign the passed port number */ 00478 this->m_src_port = port; 00479 00480 #if phHAVE(HTONS) 00481 /* set the port number in the server address struct */ 00482 this->m_info->m_src_sin.sin_port = htons(this->m_src_port); 00483 #else 00484 #error "Don\'t have htons" 00485 #endif 00486 phTHIS_UNLOCK(locked); 00487 00488 return phSUCCESS; 00489 error: 00490 phTHIS_ERROR_UNLOCK(locked); 00491 00492 return phFAIL; 00493 } 00494 00495 /* -------------------------------------------------------------------------- * 00496 * getSrcPort: 00497 * -------------------------------------------------------------------------- */ 00498 int phSocket::getSrcPort() 00499 { 00500 phFUNCTION("phSocket::getSrcPort") 00501 int ret_port = 0; 00502 int locked = 0; 00503 00504 phTHIS_LOCK(locked); 00505 00506 /* Store the port number to be returned */ 00507 ret_port = this->m_src_port; 00508 00509 error: 00510 phTHIS_ERROR_UNLOCK(locked); 00511 00512 return ret_port; 00513 } 00514 00515 /* -------------------------------------------------------------------------- * 00516 * setDstPort: 00517 * -------------------------------------------------------------------------- */ 00518 int phSocket::setDstPort(int port) 00519 { 00520 phFUNCTION("phSocket::setDstPort") 00521 int locked = 0; 00522 00523 phTHIS_LOCK(locked); 00524 00525 /* assign the passed port number */ 00526 this->m_dst_port = port; 00527 #if phHAVE(HTONS) 00528 /* set the port number in the server address struct */ 00529 this->m_info->m_dst_sin.sin_port = htons(this->m_dst_port); 00530 #else 00531 #error "Don\'t have htons" 00532 #endif 00533 00534 phTHIS_UNLOCK(locked); 00535 00536 return phSUCCESS; 00537 error: 00538 phTHIS_ERROR_UNLOCK(locked); 00539 00540 return phFAIL; 00541 } 00542 00543 /* -------------------------------------------------------------------------- * 00544 * getDstPort: 00545 * -------------------------------------------------------------------------- */ 00546 int phSocket::getDstPort() 00547 { 00548 phFUNCTION("phSocket::getDstPort") 00549 int ret_port = 0; 00550 int locked = 0; 00551 00552 phTHIS_LOCK(locked); 00553 00554 /* Store the port number to be returned */ 00555 ret_port = this->m_dst_port; 00556 00557 error: 00558 phTHIS_ERROR_UNLOCK(locked); 00559 00560 return ret_port; 00561 } 00562 00563 /* -------------------------------------------------------------------------- * 00564 * getSrcSinPtr: 00565 * -------------------------------------------------------------------------- */ 00566 void *phSocket::getSrcSinPtr() 00567 { 00568 return (void *)&(this->m_info->m_src_sin); 00569 } 00570 00571 /* -------------------------------------------------------------------------- * 00572 * getDstSinPtr: 00573 * -------------------------------------------------------------------------- */ 00574 void *phSocket::getDstSinPtr() 00575 { 00576 return (void *)&(this->m_info->m_dst_sin); 00577 } 00578 00579 /* -------------------------------------------------------------------------- * 00580 * setSocket: 00581 * -------------------------------------------------------------------------- */ 00582 void phSocket::setSocket(int32_t sock) 00583 { 00584 this->m_info->m_sock = sock; 00585 } 00586 00587 /* -------------------------------------------------------------------------- * 00588 * getSocket: 00589 * -------------------------------------------------------------------------- */ 00590 int32_t phSocket::getSocket() 00591 { 00592 return (int32_t)this->m_info->m_sock; 00593 } 00594 00595 /* ------------------------------------------------------------------------- */ 00596 #if defined(WIN32) 00597 int phSocket::lastSocketError() 00598 { 00599 return WSAGetLastError(); 00600 } 00601 int phSocket::lastSystemError() 00602 { 00603 return GetLastError(); 00604 } 00605 #else 00606 int phSocket::lastSocketError() 00607 { 00608 return errno; 00609 } 00610 int phSocket::lastSystemError() 00611 { 00612 return errno; 00613 } 00614 #endif 00615 00616 /* -------------------------------------------------------------------------- * 00617 * allocBuffer: 00618 * -------------------------------------------------------------------------- */ 00619 int phSocket::allocBuffer(uint8_t **buf, uint32_t *len, uint32_t length ) 00620 { 00621 phFUNCTION("phSocket::allocBuffer") 00622 00623 if ((*buf) == NULL) 00624 { 00625 (*buf) = (uint8_t *)phCalloc(length, sizeof(uint8_t)); 00626 phCHECK_NULLPTR((*buf),"phCalloc","phCalloc failed."); 00627 00628 (*len) = length; 00629 } 00630 else if (length > (*len)) 00631 { 00632 (*len) = length; 00633 (*buf) = (uint8_t *)phRealloc((*buf),(*len)); 00634 } 00635 00636 return phSUCCESS; 00637 error: 00638 00639 return phFAIL; 00640 } 00641 00642 /* -------------------------------------------------------------------------- * 00643 * setSrcHost: 00644 * -------------------------------------------------------------------------- */ 00645 int phSocket::setSrcHost(const char *host) 00646 { 00647 phFUNCTION("phSocket::setSrcHost") 00648 int locked = 0; 00649 uint32_t length = (uint32_t)((host != NULL) ? strlen(host) : 0); 00650 #if !phHAVE(INET_PTON) && !phHAVE(INET_ATON) && phHAVE(INET_ADDR) 00651 long addr = 0; 00652 #endif 00653 if (length == 0) 00654 { 00655 return phFAIL; 00656 } 00657 00658 phTHIS_LOCK(locked); 00659 00660 rc = this->allocBuffer((uint8_t**)&this->m_src_host, 00661 &this->m_src_host_size, 00662 length+1); 00663 phCHECK_RC(rc,NULL,"allocBuffer"); 00664 00665 #if defined(HAVE_SNPRINTF) 00666 snprintf(this->m_src_host,this->m_src_host_size,"%s",host); 00667 #else 00668 sprintf(this->m_src_host,"%s",host); 00669 #endif 00670 00671 #if phHAVE(GETHOSTBYNAME_R) 00672 /* map the given hostname to an IP address, or convert from dotted 00673 * decimal notation 00674 */ 00675 rc = gethostbyname_r(this->m_src_host, 00676 &this->m_info->m_hostent_ret, 00677 this->m_info->m_hostent_buf, 00678 this->m_info->m_hostent_buflen, 00679 &this->m_info->m_hostent_result, 00680 &this->m_info->m_hostent_errno ); 00681 if (rc != 0) 00682 { 00683 phPRINT_RC(rc,NULL, 00684 "gethostbyname_r failed: %s.", 00685 network_errno_resolve(this->m_info->m_hostent_errno)); 00686 } 00687 #elif phHAVE(GETHOSTBYNAME) 00688 this->m_info->m_hostent_result = gethostbyname(this->m_src_host); 00689 #elif phHAVE(GETHOSTADDR) 00690 rc = ph_socket_gethostaddr(0,this->m_src_host); 00691 if (!rc) 00692 { 00693 phPRINT_RC(rc,"gethostaddr","gethostaddr failed (rc = %d)",rc); 00694 } 00695 #else 00696 #error "Don\'t have gethostbyname or gethostbyname_r" 00697 #endif 00698 00699 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00700 if (this->m_info->m_hostent_result != NULL) 00701 { 00702 /* Copy the address to the address structure used 00703 * in the connect call */ 00704 phMemcpy(&(this->m_info->m_src_sin.sin_addr), 00705 this->m_info->m_hostent_result->h_addr, 00706 this->m_info->m_hostent_result->h_length); 00707 } 00708 else 00709 #endif 00710 { 00711 #if phHAVE(INET_PTON) 00712 /* set up the address information to connect to */ 00713 rc = inet_pton(this->m_family, 00714 this->m_src_host, 00715 &(this->m_info->m_src_sin.sin_addr)); 00716 phPRINT_RC(rc,"inet_pton","inet_pton failed."); 00717 #elif phHAVE(INET_ATON) 00718 rc = inet_aton(this->m_src_host,&(this->m_info->m_src_sin.sin_addr)); 00719 phPRINT_RC(rc,"inet_aton","inet_aton src failed."); 00720 #elif phHAVE(INET_ADDR) 00721 addr = (long)inet_addr(this->m_src_host); 00722 if (addr == (long)INADDR_NONE) 00723 { 00724 phPRINT_RC(-1,"inet_addr","inet_addr src return INADDR_NONE"); 00725 } 00726 this->m_info->m_src_sin.sin_addr = *((struct in_addr*)&addr); 00727 #else 00728 #error "Don\'t have inet_pton, inet_aton, or inet_addr" 00729 #endif 00730 } 00731 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00732 this->m_info->m_hostent_result = NULL; 00733 #endif 00734 00735 phTHIS_UNLOCK(locked); 00736 00737 return phSUCCESS; 00738 error: 00739 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00740 this->m_info->m_hostent_result = NULL; 00741 #endif 00742 phTHIS_ERROR_UNLOCK(locked); 00743 00744 return phFAIL; 00745 } 00746 00747 /* -------------------------------------------------------------------------- * 00748 * getSrcHost: 00749 * -------------------------------------------------------------------------- */ 00750 const char *phSocket::getSrcHost() 00751 { 00752 phFUNCTION("phSocket::getSrcHost") 00753 char *ret_type = 0; 00754 int locked = 0; 00755 00756 phTHIS_LOCK(locked); 00757 00758 if (this->m_src_host == NULL) 00759 { 00760 ret_type = "unknown"; 00761 } 00762 else 00763 { 00764 ret_type = this->m_src_host; 00765 } 00766 00767 error: 00768 phTHIS_ERROR_UNLOCK(locked); 00769 00770 return ret_type; 00771 } 00772 00773 00774 /* -------------------------------------------------------------------------- * 00775 * setDstHost: 00776 * -------------------------------------------------------------------------- */ 00777 int phSocket::setDstHost(const char *host) 00778 { 00779 phFUNCTION("phSocket::setDstHost") 00780 int locked = 0; 00781 uint32_t length = (uint32_t)((host != NULL) ? strlen(host) : 0); 00782 #if !phHAVE(INET_PTON) && !phHAVE(INET_ATON) && phHAVE(INET_ADDR) 00783 long addr = 0; 00784 #endif 00785 00786 if (length == 0) 00787 { 00788 return phFAIL; 00789 } 00790 00791 phTHIS_LOCK(locked); 00792 00793 rc = this->allocBuffer((uint8_t**)&this->m_dst_host, 00794 &this->m_dst_host_size, 00795 length+1); 00796 phCHECK_RC(rc,NULL,"allocBuffer"); 00797 00798 #if defined(HAVE_SNPRINTF) 00799 snprintf(this->m_dst_host,this->m_dst_host_size,"%s",host); 00800 #else 00801 sprintf(this->m_dst_host,"%s",host); 00802 #endif 00803 00804 #if phHAVE(GETHOSTBYNAME_R) 00805 /* map the given hostname to an IP address, or convert from dotted 00806 * decimal notation 00807 */ 00808 rc = gethostbyname_r(this->m_dst_host, 00809 &this->m_info->m_hostent_ret, 00810 this->m_info->m_hostent_buf, 00811 this->m_info->m_hostent_buflen, 00812 &this->m_info->m_hostent_result, 00813 &this->m_info->m_hostent_errno ); 00814 if (rc != 0) 00815 { 00816 phPRINT_RC(rc,NULL, 00817 "gethostbyname_r failed: %s.", 00818 network_errno_resolve(this->m_info->m_hostent_errno)); 00819 } 00820 #elif phHAVE(GETHOSTBYNAME) 00821 this->m_info->m_hostent_result = gethostbyname(this->m_dst_host); 00822 //#else 00823 // #error "Don\'t have gethostbyname or gethostbyname_r" 00824 #endif 00825 00826 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00827 if (this->m_info->m_hostent_result != NULL) 00828 { 00829 /* Copy the address to the address structure used 00830 * in the connect call */ 00831 phMemcpy(&(this->m_info->m_dst_sin.sin_addr), 00832 this->m_info->m_hostent_result->h_addr, 00833 this->m_info->m_hostent_result->h_length); 00834 } 00835 else 00836 #endif 00837 { 00838 #if phHAVE(INET_PTON) 00839 /* set up the address information to connect to */ 00840 rc = inet_pton(this->m_family, 00841 this->m_dst_host, 00842 &(this->m_info->m_dst_sin.sin_addr)); 00843 phPRINT_RC(rc,"inet_pton","inet_pton failed."); 00844 #elif phHAVE(INET_ATON) 00845 rc = inet_aton(this->m_dst_host,&(this->m_info->m_dst_sin.sin_addr)); 00846 phPRINT_RC(rc,"inet_aton","inet_aton dst failed."); 00847 #elif phHAVE(INET_ADDR) 00848 addr = (long)inet_addr(this->m_dst_host); 00849 if (addr == (long)INADDR_NONE) 00850 { 00851 phPRINT_RC(-1,"inet_addr","inet_addr(%s) dst return INADDR_NONE", 00852 this->m_dst_host); 00853 } 00854 this->m_info->m_dst_sin.sin_addr = *((struct in_addr*)&addr); 00855 #else 00856 #error "Don\'t have inet_pton, inet_aton, or inet_addr" 00857 #endif 00858 } 00859 00860 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00861 this->m_info->m_hostent_result = NULL; 00862 #endif 00863 phTHIS_UNLOCK(locked); 00864 00865 return phSUCCESS; 00866 error: 00867 #if phHAVE(GETHOSTBYNAME) || phHAVE(GETHOSTBYNAME_R) 00868 this->m_info->m_hostent_result = NULL; 00869 #endif 00870 phTHIS_ERROR_UNLOCK(locked); 00871 00872 return phFAIL; 00873 } 00874 00875 /* -------------------------------------------------------------------------- * 00876 * getDstHost: 00877 * -------------------------------------------------------------------------- */ 00878 const char *phSocket::getDstHost() 00879 { 00880 phFUNCTION("phSocket::getDstHost") 00881 char *retstr = 0; 00882 int locked = 0; 00883 00884 phTHIS_LOCK(locked); 00885 00886 if (this->m_dst_host == NULL) 00887 { 00888 /* otherwise we have no idea what the hostname is */ 00889 retstr = "unknown"; 00890 } 00891 else 00892 { 00893 retstr = this->m_dst_host; 00894 } 00895 error: 00896 phTHIS_ERROR_UNLOCK(locked); 00897 00898 return retstr; 00899 } 00900 00901 /* ---------------------------------------------------------------------------- 00902 * initSocketVar: initalizes m_sock 00903 * ------------------------------------------------------------------------- */ 00904 int phSocket::initSocketVar() 00905 { 00906 phFUNCTION("phSocket::initSocketVar") 00907 int locked = 0; 00908 00909 phTHIS_LOCK(locked); 00910 00911 /* create the socket */ 00912 #if phHAVE(SOCKET) 00913 this->m_info->m_sock = ph_socket_socket(this->m_family, 00914 this->m_socket_type, 00915 this->m_protocol ); 00916 #else 00917 #error "Don\'t have socket" 00918 #endif 00919 if (this->m_info->m_sock < 0) 00920 { 00921 /* If the socket failed to be created, then return error */ 00922 if (this->m_warning_level > 0) 00923 { 00924 phSOCK_ERR_PRINT("socket() failed"); 00925 } 00926 goto error; 00927 } 00928 00929 rc = this->applyBlocking(); 00930 phPRINT_RC(rc,NULL,"applyBlocking"); 00931 00932 rc = this->applyLinger(); 00933 phPRINT_RC(rc,NULL,"applyLinger"); 00934 00935 phTHIS_UNLOCK(locked); 00936 00937 return phSUCCESS; 00938 error: 00939 phTHIS_ERROR_UNLOCK(locked); 00940 00941 return phFAIL; 00942 } 00943 00944 /* ---------------------------------------------------------------------------- 00945 * connect: connect to a host on the specified port. if polling is true, 00946 * the client will poll the server until a connection is made 00947 * ------------------------------------------------------------------------- */ 00948 int phSocket::connect( const char *host, 00949 const int port, 00950 const bool polling ) 00951 { 00952 phFUNCTION("phSocket::connect") 00953 int connectrc = 0; 00954 int error_retrc = phFAIL; 00955 int locked = 0; 00956 struct sockaddr_in connect_sin; 00957 int conn_loop_exit = 0; 00958 00959 phTHIS_LOCK(locked); 00960 00961 if (host != NULL) 00962 { 00963 rc = this->setDstHost(host); 00964 phCHECK_RC(rc,NULL,"setDstHost failed"); 00965 } 00966 00967 if ((port >= phSOCKET_PORTMIN) && (port <= phSOCKET_PORTMAX)) 00968 { 00969 rc = this->setDstPort(port); 00970 phPRINT_RC(rc,NULL,"setDstPort failed."); 00971 } 00972 00973 if (!((this->m_dst_port >= phSOCKET_PORTMIN) && (this->m_dst_port <= phSOCKET_PORTMAX))) 00974 { 00975 phCHECK_RC(-1,NULL,"Bad parameter: this->m_dst_port not in range (%d,%d)", 00976 phSOCKET_PORTMIN, 00977 phSOCKET_PORTMAX); 00978 } 00979 00980 rc = this->initSocketVar(); 00981 phCHECK_RC(rc,NULL,"initSocketVar"); 00982 00983 /* Setup the address structure used for the connect */ 00984 phMemcpy(&connect_sin,&this->m_info->m_dst_sin,sizeof(struct sockaddr_in)); 00985 00986 /* jwatson: 00987 * 00988 * if polling is true, loop until the connect() call succeeds. 00989 * although the documentation doesn't say so, connect() will molest 00990 * the socket on failure, so we must recreate it every time. 00991 * 00992 * if polling is false, we'll bomb if we can't connect. clever me 00993 * with my short-circuit ordering. 00994 * 00995 * pthoren: 00996 * 00997 * Added exit_trigger to allow an outside sorce to stop 00998 * the polling loop. 00999 * 01000 * pthoren: Unfortunately, connect polling is a problem on Linux. 01001 * If one continually 01002 * recreates the socket on failure, then eventually we'll 01003 * set up a bogus connection if we're connecting to the 01004 * same machine as the one we're connecting from. 01005 * 01006 */ 01007 01008 /* try connecting and poll if requested */ 01009 while ((conn_loop_exit == 0) && (this->m_exit_trigger == 0)) 01010 { 01011 #if phHAVE(CONNECT) 01012 rc = ph_socket_connect(this->m_info->m_sock, 01013 (struct sockaddr*)&(connect_sin), 01014 sizeof(struct sockaddr_in)); 01015 #else 01016 #error "Don\'t have connect" 01017 #endif 01018 if (this->isSelfConnected()) 01019 { 01020 int hold = this->m_linger; 01021 uint32_t holdtime = this->m_linger_time; 01022 01023 rc = this->setLinger(phNOLINGER); 01024 phPRINT_RC(rc,NULL,"setLinger"); 01025 01026 #if defined(WIN32) && phHAVE(CLOSESOCKET) 01027 rc = closesocket(this->m_info->m_sock); 01028 #elif (!defined(WIN32)) 01029 rc = ph_socket_close(this->m_info->m_sock); 01030 #else 01031 #if defined(WIN32) 01032 #error "Don\'t have closesocket" 01033 #else 01034 #error "Don\'t have close" 01035 #endif 01036 #endif 01037 this->m_info->m_sock = (phSOCKET)-1; 01038 01039 rc = this->setLinger(hold,holdtime); 01040 phPRINT_RC(rc,NULL,"setLinger"); 01041 01042 rc = this->initSocketVar(); 01043 phCHECK_RC(rc,NULL,"initSocketVar"); 01044 } 01045 else if ((rc == 0) || (polling != true)) 01046 { 01047 conn_loop_exit = 1; 01048 } 01049 else if ((rc < 0) && 01050 (this->lastSocketError() != phECONNREFUSED) && 01051 (this->lastSocketError() != phEINTR)) 01052 { 01053 phCHECK_RC(rc,"::connect","::connect failed."); 01054 } 01055 else 01056 { 01057 phYield(); 01058 } 01059 } 01060 01061 connectrc = rc; 01062 01063 if (connectrc < 0) 01064 { 01065 #if defined(WIN32) && phHAVE(CLOSESOCKET) 01066 rc = closesocket(this->m_info->m_sock); 01067 #elif (!defined(WIN32)) 01068 rc = ph_socket_close(this->m_info->m_sock); 01069 #else 01070 #if defined(WIN32) 01071 #error "Don\'t have closesocket" 01072 #else 01073 #error "Don\'t have close" 01074 #endif 01075 #endif 01076 this->m_info->m_sock = (phSOCKET)-1; 01077 } 01078 else 01079 { 01080 rc = this->updateSrcFromSock(); 01081 phPRINT_RC(rc,NULL,"updateSrcFromSock"); 01082 } 01083 01084 /* if m_exit_trigger is one here, then reset it and return with 01085 * a return value to denote we were forced to stop trying to connect */ 01086 if (this->m_exit_trigger == 1) 01087 { 01088 this->m_exit_trigger = 0; 01089 error_retrc = 1; 01090 goto error; 01091 } 01092 01093 /* if rc < 0 at this point, then connect failed. 01094 * Let's return an error code to denote this */ 01095 if (connectrc < 0) 01096 { 01097 if (this->m_warning_level > 0) 01098 { 01099 phSOCK_ERR_PRINT("connect() failed"); 01100 } 01101 error_retrc = -5; 01102 goto error; 01103 } 01104 else 01105 { 01106 /* Set the connected state to true */ 01107 this->m_connected = true; 01108 } 01109 01110 phTHIS_UNLOCK(locked); 01111 01112 return phSUCCESS; 01113 01114 error: 01115 phTHIS_ERROR_UNLOCK(locked); 01116 01117 return error_retrc; 01118 } 01119 01120 /* ---------------------------------------------------------------------------- 01121 * disconnect: 01122 * ------------------------------------------------------------------------- */ 01123 void phSocket::disconnect() 01124 { 01125 phFUNCTION("phSocket::disconnect") 01126 int locked = 0; 01127 01128 phTHIS_LOCK(locked); 01129 01130 /* this is a client sock, use close on it, instead of shutdown */ 01131 if (this->m_info->m_sock >= 0) 01132 { 01133 if (this->m_call_shutdown) 01134 { 01135 #if phHAVE(SHUTDOWN) 01136 /* Use shutdown on the socket to cleanly 01137 * shutdown the socket and get rid of it */ 01138 rc = ph_socket_shutdown(this->m_info->m_sock,phSHUT_RDWR); 01139 if (this->lastSocketError() == phENOTCONN) 01140 rc = phSUCCESS; /* ignore endpoint not connected */ 01141 phPRINT_RC(rc,"shutdown","shutdown failed"); 01142 #else 01143 #error "Don\'t have shutdown" 01144 #endif 01145 } 01146 #if defined(WIN32) && phHAVE(CLOSESOCKET) 01147 rc = closesocket(this->m_info->m_sock); 01148 #elif (!defined(WIN32)) 01149 rc = ph_socket_close(this->m_info->m_sock); 01150 #else 01151 #if defined(WIN32) 01152 #error "Don\'t have closesocket" 01153 #else 01154 #error "Don\'t have close" 01155 #endif 01156 #endif 01157 this->m_info->m_sock = (phSOCKET)-1; 01158 } 01159 /* set the connected state to false now */ 01160 this->m_connected = false; 01161 01162 error: 01163 phTHIS_ERROR_UNLOCK(locked); 01164 } 01165 01166 /* ---------------------------------------------------------------------------- 01167 * send: 01168 * ------------------------------------------------------------------------- */ 01169 int phSocket::send(const void *vdata, const int len) 01170 { 01171 phFUNCTION("phSocket::send") 01172 int nbytes = 0; 01173 int nbytes_left = len; 01174 uint8_t *dataptr = (uint8_t *)vdata; 01175 int locked = 0; 01176 int error_retrc = phFAIL; 01177 long err = 0; 01178 01179 /* Permit sending and recving at the same time, release the lock before 01180 * sending to prevent the recv from being blocked */ 01181 rc = this->m_send_lock.lock(); 01182 phPRINT_RC(rc,NULL,"this->m_send_lock.lock() failed."); 01183 01184 phTHIS_LOCK(locked); 01185 01186 /* we can't recv if we're not connected */ 01187 if (this->m_connected == false) 01188 { 01189 goto error; 01190 } 01191 01192 /* This send will send ALL of the bytes by looping 01193 * if necessary */ 01194 do 01195 { 01196 phTHIS_UNLOCK(locked); 01197 01198 #if phHAVE(SEND) 01199 /* const char * : for windows and linux 01200 * void * : for lwip */ 01201 nbytes = ph_socket_send(this->m_info->m_sock, 01202 (ph_socket_send_buftype *)dataptr, 01203 nbytes_left, 01204 MSG_NOSIGNAL); 01205 #else 01206 #error "Don\'t have send" 01207 #endif 01208 phTHIS_LOCK(locked); 01209 01210 /* Check for an error condition that isn't the INTERRUPTED 01211 * error condition */ 01212 if ((nbytes < 0) 01213 #ifdef phEINTR 01214 && (this->lastSocketError() != phEINTR) 01215 #endif 01216 && (this->lastSocketError() != phEWOULDBLOCK) 01217 ) 01218 { 01219 nbytes_left = -1; 01220 } 01221 /* if nbytes == 0, then the other end probably disconnected */ 01222 else if (nbytes == 0) 01223 { 01224 nbytes_left = -2; 01225 } 01226 else if (nbytes > 0) 01227 { 01228 /* Alter the number of bytes we've left to send */ 01229 nbytes_left -= nbytes; 01230 /* Set up a pointer to the next group to send */ 01231 dataptr += nbytes; 01232 } 01233 } while ((nbytes_left > 0) && (this->m_exit_trigger == 0)); 01234 01235 /* if m_exit_trigger is one here, then reset it and return with 01236 * a return value to denote we were forced to stop trying our 01237 * current task*/ 01238 if (this->m_exit_trigger == 1) 01239 { 01240 this->m_exit_trigger = 0; 01241 error_retrc = 1; 01242 goto error; 01243 } 01244 01245 /* if send() returns 0 then the peer disconnected */ 01246 if (nbytes_left == -2) 01247 { 01248 if (this->m_warning_level > 2) 01249 { 01250 phSOCK_ERR_PRINT("connection terminated by peer"); 01251 } 01252 this->disconnect(); 01253 } 01254 01255 err = this->lastSocketError(); 01256 /* if errno == EPIPE, then the other side did disconnect... */ 01257 if ((0) 01258 #ifdef phETIMEDOUT 01259 || (err == phETIMEDOUT) 01260 #endif 01261 ) 01262 { 01263 /* disconnect and reset the object's variables */ 01264 this->disconnect(); 01265 nbytes_left = -1; 01266 } 01267 if ((0) 01268 #ifdef phEPIPE 01269 || (err == phEPIPE) 01270 #endif 01271 #ifdef phECONNRESET 01272 || (err == phECONNRESET) 01273 #endif 01274 #ifdef phECONNABORTED 01275 || (err == phECONNABORTED) 01276 #endif 01277 #ifdef phESHUTDOWN 01278 || (err == phESHUTDOWN) 01279 #endif 01280 ) 01281 { 01282 if (this->m_warning_level > 4) 01283 { 01284 #ifdef phEPIPE 01285 if (err == phEPIPE) 01286 { 01287 phSOCK_ERR_PRINT("phEPIPE"); 01288 } 01289 #endif 01290 #ifdef phECONNRESET 01291 if (err == phECONNRESET) 01292 { 01293 phSOCK_ERR_PRINT("phECONNRESET"); 01294 } 01295 #endif 01296 #ifdef phECONNABORTED 01297 if (err == phECONNABORTED) 01298 { 01299 phSOCK_ERR_PRINT("phECONNABORTED"); 01300 } 01301 #endif 01302 #ifdef phESHUTDOWN 01303 if (err == phESHUTDOWN) 01304 { 01305 phSOCK_ERR_PRINT("phESHUTDOWN"); 01306 } 01307 #endif 01308 } 01309 /* disconnect and reset the object's variables */ 01310 this->disconnect(); 01311 nbytes_left = -1; 01312 error_retrc = -2; 01313 } 01314 /* if nbytes_left < 0 then we have some error case and 01315 * need to return an error */ 01316 if (nbytes_left < 0) 01317 { 01318 if (this->m_warning_level > 2) 01319 { 01320 phSOCK_ERR_PRINT("send() failed"); 01321 } 01322 goto error; 01323 } 01324 01325 rc = this->m_send_lock.unlock(); 01326 phPRINT_RC(rc,NULL,"this->m_send_lock.unlock() failed."); 01327 01328 phTHIS_UNLOCK(locked); 01329 01330 return phSUCCESS; 01331 01332 error: 01333 rc = this->m_send_lock.unlock(); 01334 phPRINT_RC(rc,NULL,"this->m_send_lock.unlock() failed."); 01335 01336 phTHIS_ERROR_UNLOCK(locked); 01337 return error_retrc; 01338 } 01339 01340 /* ---------------------------------------------------------------------------- 01341 * recv: 01342 * ------------------------------------------------------------------------- */ 01343 int phSocket::recv(void *data, const int len ) 01344 { 01345 int t = 0; 01346 return this->recv(data,len,t,phWAIT); 01347 } 01348 01349 /* ---------------------------------------------------------------------------- 01350 * recv: 01351 * ------------------------------------------------------------------------- */ 01352 int phSocket::recv( void *vdata, const int len, 01353 int &recv_len, int wait) 01354 { 01355 phFUNCTION("phSocket::recv") 01356 int nbytes = 0; 01357 int nbytes_left = len; 01358 uint8_t *dataptr = (uint8_t *)vdata; 01359 int locked = 0; 01360 int error_retrc = phFAIL; 01361 long err = 0; 01362 01363 rc = this->m_recv_lock.lock(); 01364 phPRINT_RC(rc,NULL,"this->m_recv_lock.lock() failed."); 01365 01366 phTHIS_LOCK(locked); 01367 01368 /* we can't recv if we're not connected */ 01369 if (this->m_connected == false) 01370 { 01371 goto error; 01372 } 01373 01374 /* initialize the receive length */ 01375 recv_len = 0; 01376 01377 /* block until we've received all of the data, 01378 * at least if thats what we want to do... */ 01379 do 01380 { 01381 phTHIS_UNLOCK(locked); 01382 01383 #if phHAVE(RECV) 01384 nbytes = ph_socket_recv(this->m_info->m_sock, 01385 (char *)dataptr, 01386 nbytes_left, 01387 /* only supply MSG_WAITALL if phWAIT == wait */ 01388 (wait ? MSG_WAITALL : 0) | MSG_NOSIGNAL); 01389 #else 01390 #error "Don\'t have recv" 01391 #endif 01392 phTHIS_LOCK(locked); 01393 01394 /* if there was an error and it wasn't the INTERRUPTED error */ 01395 if ((nbytes < 0) && (this->lastSocketError() != phEINTR)) 01396 { 01397 if (!((wait == 1) && (this->lastSocketError() == phEWOULDBLOCK)) 01398 ) 01399 { 01400 nbytes_left = -1; 01401 } 01402 } 01403 else if (nbytes == 0) 01404 { 01405 nbytes_left = -2; 01406 } 01407 else if (nbytes > 0) 01408 { 01409 /* Adjust the recv length */ 01410 recv_len += nbytes; 01411 /* Adjust the number of bytes left to send */ 01412 nbytes_left -= nbytes; 01413 /* adjust the data pointer to the next chunk of available 01414 * buffer space */ 01415 dataptr += nbytes; 01416 } 01417 } while ((nbytes_left > 0) && (wait == 1) && (this->m_exit_trigger == 0)); 01418 01419 /* if m_exit_trigger is one here, then reset it and return with 01420 * a return value to denote we were forced to stop trying our 01421 * current task*/ 01422 if (this->m_exit_trigger == 1) 01423 { 01424 this->m_exit_trigger = 0; 01425 error_retrc = 1; 01426 if (this->m_warning_level > 5) 01427 { 01428 phPROGRESS("this->m_exit_trigger == 1... leaving function.\n"); 01429 } 01430 goto error; 01431 } 01432 01433 01434 /* if recv() returns 0 then the peer disconnected */ 01435 if (nbytes_left == -2) 01436 { 01437 if (this->m_warning_level > 2) 01438 { 01439 phSOCK_ERR_PRINT("connection terminated by peer"); 01440 } 01441 /* disconnect because there was some error */ 01442 this->disconnect(); 01443 } 01444 01445 /* if the other side disconnected, then disconnect 01446 * and reset all of the object's member variables */ 01447 err = this->lastSocketError(); 01448 /* if errno == EPIPE, then the other side did disconnect... */ 01449 if ((0) 01450 #ifdef phETIMEDOUT 01451 || (err == phETIMEDOUT) 01452 #endif 01453 ) 01454 { 01455 if (this->m_warning_level > 4) 01456 { 01457 phSOCK_ERR_PRINT("ETIMEDOUT"); 01458 } 01459 this->disconnect(); 01460 nbytes_left = -1; 01461 } 01462 else if ((0) 01463 #ifdef phEPIPE 01464 || (err == phEPIPE) 01465 #endif 01466 #ifdef phECONNRESET 01467 || (err == phECONNRESET) 01468 #endif 01469 #ifdef phECONNABORTED 01470 || (err == phECONNABORTED) 01471 #endif 01472 #ifdef phESHUTDOWN 01473 || (err == phESHUTDOWN) 01474 #endif 01475 ) 01476 { 01477 if (this->m_warning_level > 4) 01478 { 01479 #ifdef phEPIPE 01480 if (err == phEPIPE) 01481 { 01482 phSOCK_ERR_PRINT("phEPIPE"); 01483 } 01484 #endif 01485 #ifdef phECONNRESET 01486 if (err == phECONNRESET) 01487 { 01488 phSOCK_ERR_PRINT("phECONNRESET"); 01489 } 01490 #endif 01491 #ifdef phECONNABORTED 01492 if (err == phECONNABORTED) 01493 { 01494 phSOCK_ERR_PRINT("phECONNABORTED"); 01495 } 01496 #endif 01497 #ifdef phESHUTDOWN 01498 if (err == phESHUTDOWN) 01499 { 01500 phSOCK_ERR_PRINT("phESHUTDOWN"); 01501 } 01502 #endif 01503 } 01504 this->disconnect(); 01505 nbytes_left = -1; 01506 error_retrc = -2; 01507 } 01508 01509 /* if there was an error condition, go to the error 01510 * return sequence */ 01511 if (nbytes_left < 0) 01512 { 01513 if (this->m_warning_level > 2) 01514 { 01515 phSOCK_ERR_PRINT("recv() failed"); 01516 } 01517 goto error; 01518 } 01519 01520 rc = this->m_recv_lock.unlock(); 01521 phPRINT_RC(rc,NULL,"this->m_recv_lock.unlock() failed."); 01522 01523 phTHIS_UNLOCK(locked); 01524 01525 return phSUCCESS; 01526 01527 error: 01528 rc = this->m_recv_lock.unlock(); 01529 phPRINT_RC(rc,NULL,"this->m_recv_lock.unlock() failed."); 01530 01531 phTHIS_ERROR_UNLOCK(locked); 01532 01533 return error_retrc; 01534 } 01535 01536 /* ---------------------------------------------------------------------------- 01537 * isSelfConnected: 01538 * ------------------------------------------------------------------------- */ 01539 int phSocket::isSelfConnected() 01540 { 01541 phFUNCTION("phSocket::isSelfConnected") 01542 int locked = 0; 01543 int retrc = 0; 01544 socklen_t len = 0; 01545 struct sockaddr_in dst_sin; 01546 struct sockaddr_in src_sin; 01547 01548 phTHIS_LOCK(locked); 01549 01550 if (this->m_info->m_sock < 0) goto success; 01551 01552 phMemset(&dst_sin,0,sizeof(struct sockaddr_in)); 01553 phMemset(&src_sin,0,sizeof(struct sockaddr_in)); 01554 01555 /* get information about our connected peer */ 01556 len = (socklen_t)sizeof(struct sockaddr); 01557 #if phHAVE(GETPEERNAME) 01558 rc = ph_socket_getpeername(this->m_info->m_sock, 01559 (struct sockaddr*)&dst_sin, 01560 &len); 01561 #else 01562 #error "Don\'t have getpeername" 01563 #endif 01564 if (rc < 0) 01565 { 01566 if (this->m_warning_level > 3) 01567 { 01568 phSOCK_ERR_PRINT("getpeername() failed"); 01569 } 01570 goto error; 01571 } 01572 01573 /* get information about ourself */ 01574 len = (socklen_t)sizeof(struct sockaddr); 01575 #if phHAVE(GETSOCKNAME) 01576 rc = ph_socket_getsockname(this->m_info->m_sock, 01577 (struct sockaddr*)&src_sin, 01578 &len); 01579 #else 01580 #error "Don\'t have getsockname" 01581 #endif 01582 if (rc < 0) 01583 { 01584 if (this->m_warning_level > 1) 01585 { 01586 phSOCK_ERR_PRINT("getsockname() failed"); 01587 } 01588 goto error; 01589 } 01590 01591 if (dst_sin.sin_port == src_sin.sin_port) 01592 { 01593 if (memcmp(&(dst_sin.sin_addr), 01594 &(src_sin.sin_addr), 01595 sizeof(struct in_addr)) == 0) 01596 { 01597 //phPROGRESS("selfConnected\n"); 01598 retrc = 1; 01599 } 01600 } 01601 01602 success: 01603 phTHIS_UNLOCK(locked); 01604 01605 return retrc; 01606 01607 error: 01608 phTHIS_ERROR_UNLOCK(locked); 01609 01610 return 0; 01611 } 01612 01613 /* ---------------------------------------------------------------------------- 01614 * updateDstFromSock: 01615 * ------------------------------------------------------------------------- */ 01616 int phSocket::updateDstFromSock() 01617 { 01618 phFUNCTION("phSocket::updateDstFromSock") 01619 int locked = 0; 01620 socklen_t len = 0; 01621 #if !(phHAVE(INET_NTOP) || phHAVE(PH_INET_NTOP)) && phHAVE(INET_NTOA) 01622 char *ptr = NULL; 01623 #endif 01624 01625 phTHIS_LOCK(locked); 01626 01627 if (this->m_info->m_sock < 0) goto success; 01628 01629 /* get information about our connected peer */ 01630 len = (socklen_t)sizeof(struct sockaddr); 01631 #if phHAVE(GETPEERNAME) 01632 rc = ph_socket_getpeername(this->m_info->m_sock, 01633 (struct sockaddr*)&(this->m_info->m_dst_sin), 01634 &len); 01635 #else 01636 #error "Don\'t have getpeername" 01637 #endif 01638 if (rc < 0) 01639 { 01640 if (this->m_warning_level > 1) 01641 { 01642 phSOCK_ERR_PRINT("getpeername() failed"); 01643 } 01644 goto error; 01645 } 01646 01647 rc = this->allocBuffer((uint8_t**)&(this->m_dst_host), 01648 &(this->m_dst_host_size), 01649 255); 01650 phCHECK_RC(rc,NULL,"allocBuffer"); 01651 01652 #if phHAVE(INET_NTOP) || phHAVE(PH_INET_NTOP) 01653 if (inet_ntop( this->m_family, 01654 &(this->m_info->m_dst_sin.sin_addr), 01655 this->m_dst_host, 01656 this->m_dst_host_size ) == NULL) 01657 { 01658 rc = phFAIL; 01659 } 01660 else 01661 { 01662 rc = phSUCCESS; 01663 } 01664 phPRINT_RC(rc,"inet_ntop","inet_ntop(dst) failed."); 01665 01666 #elif phHAVE(INET_NTOA) 01667 ptr = inet_ntoa( this->m_info->m_dst_sin.sin_addr ); 01668 if (ptr != NULL) 01669 { 01670 #if defined(HAVE_SNPRINTF) 01671 snprintf(this->m_dst_host,this->m_dst_host_size,"%s",ptr); 01672 #else 01673 sprintf(this->m_dst_host,"%s",ptr); 01674 #endif 01675 rc = phSUCCESS; 01676 } 01677 else 01678 { 01679 rc = phFAIL; 01680 } 01681 phPRINT_RC(rc,"inet_ntoa","inet_ntoa(dst) failed."); 01682 01683 #else 01684 #error "Don\'t have inet_ntop or inet_ntoa" 01685 #endif 01686 01687 #if phHAVE(NTOHS) 01688 this->m_dst_port = ntohs(this->m_info->m_dst_sin.sin_port); 01689 #else 01690 #error "Don\'t have ntohs" 01691 #endif 01692 success: 01693 phTHIS_UNLOCK(locked); 01694 01695 return phSUCCESS; 01696 01697 error: 01698 phTHIS_ERROR_UNLOCK(locked); 01699 01700 return phFAIL; 01701 } 01702 01703 /* ---------------------------------------------------------------------------- 01704 * updateSrcFromSock: 01705 * ------------------------------------------------------------------------- */ 01706 int phSocket::updateSrcFromSock() 01707 { 01708 phFUNCTION("phSocket::updateSrcFromSock") 01709 int locked = 0; 01710 #if !(phHAVE(INET_NTOP) || phHAVE(PH_INET_NTOP)) && phHAVE(INET_NTOA) 01711 char *ptr = NULL; 01712 #endif 01713 socklen_t len = 0; 01714 01715 phTHIS_LOCK(locked); 01716 01717 if (this->m_info->m_sock < 0) 01718 { 01719 /* Set outself as the source */ 01720 rc = this->allocBuffer((uint8_t **)&(this->m_temp_buf), 01721 &(this->m_temp_buf_size), 01722 255); 01723 phPRINT_RC(rc,NULL,"allocBuffer(temp_buf,temp_buf_size,255)"); 01724 01725 #if phHAVE(GETHOSTNAME) 01726 rc = gethostname(this->m_temp_buf,this->m_temp_buf_size); 01727 phPRINT_RC(rc,"gethostname","gethostname failed."); 01728 #elif phHAVE(GETHOSTADDR) 01729 rc = ph_socket_gethostaddr(0,this->m_temp_buf); 01730 if (!rc) 01731 { 01732 phPRINT_RC(-1,"gethostaddr","gethostaddr failed (rc = %d)",rc); 01733 } 01734 #else 01735 #error "Don\'t have gethostname or gethostaddr" 01736 #endif 01737 rc = this->setSrcHost(this->m_temp_buf); 01738 phPRINT_RC(rc,NULL,"setSrcHost"); 01739 01740 goto success; 01741 } 01742 /* get information about ourself */ 01743 len = (socklen_t)sizeof(struct sockaddr); 01744 #if phHAVE(GETSOCKNAME) 01745 rc = ph_socket_getsockname(this->m_info->m_sock, 01746 (struct sockaddr*)&(this->m_info->m_src_sin), 01747 &len); 01748 #else 01749 #error "Don\'t have getsockname" 01750 #endif 01751 if (rc < 0) 01752 { 01753 if (this->m_warning_level > 1) 01754 { 01755 phSOCK_ERR_PRINT("getsockname() failed"); 01756 } 01757 goto error; 01758 } 01759 01760 rc = this->allocBuffer((uint8_t**)&(this->m_src_host), 01761 &(this->m_src_host_size), 01762 255); 01763 phCHECK_RC(rc,NULL,"allocBuffer"); 01764 01765 #if phHAVE(INET_NTOP) || phHAVE(PH_INET_NTOP) 01766 if (inet_ntop( this->m_family, 01767 &(this->m_info->m_src_sin.sin_addr), 01768 this->m_src_host, 01769 this->m_src_host_size ) == NULL) 01770 { 01771 rc = phFAIL; 01772 } 01773 else 01774 { 01775 rc = phSUCCESS; 01776 } 01777 phPRINT_RC(rc,"inet_ntop","inet_ntop(src) failed."); 01778 01779 #elif phHAVE(INET_NTOA) 01780 ptr = inet_ntoa( this->m_info->m_src_sin.sin_addr ); 01781 if (ptr != NULL) 01782 { 01783 #if defined(HAVE_SNPRINTF) 01784 snprintf(this->m_src_host,this->m_src_host_size,"%s",ptr); 01785 #else 01786 sprintf(this->m_src_host,"%s",ptr); 01787 #endif 01788 rc = phSUCCESS; 01789 } 01790 else 01791 { 01792 rc = phFAIL; 01793 } 01794 phPRINT_RC(rc,"inet_ntoa","inet_ntoa(src) failed."); 01795 #else 01796 #error "Don\'t have inet_ntop or inet_ntoa" 01797 #endif 01798 01799 #if phHAVE(NTOHS) 01800 this->m_src_port = ntohs(this->m_info->m_src_sin.sin_port); 01801 #else 01802 #error "Don\'t have ntohs" 01803 #endif 01804 01805 success: 01806 phTHIS_UNLOCK(locked); 01807 01808 return phSUCCESS; 01809 01810 error: 01811 phTHIS_ERROR_UNLOCK(locked); 01812 01813 return phFAIL; 01814 } 01815 01816 /* ---------------------------------------------------------------------------- 01817 * setSock: 01818 * ------------------------------------------------------------------------- */ 01819 int phSocket::setSock(int newSock) 01820 { 01821 phFUNCTION("phSocket::setSock") 01822 int locked = 0; 01823 01824 phTHIS_LOCK(locked); 01825 01826 /* set the socket value */ 01827 this->m_info->m_sock = newSock; 01828 01829 rc = this->updateDstFromSock(); 01830 phPRINT_RC(rc,NULL,"updateDstFromSock()"); 01831 01832 rc = this->updateSrcFromSock(); 01833 phPRINT_RC(rc,NULL,"updateSrcFromSock()"); 01834 01835 rc = this->applyBlocking(); 01836 phPRINT_RC(rc,NULL,"applyBlocking"); 01837 01838 rc = this->applyLinger(); 01839 phPRINT_RC(rc,NULL,"applyLinger"); 01840 01841 /* we should be connected */ 01842 this->m_connected = true; 01843 01844 phTHIS_UNLOCK(locked); 01845 01846 return phSUCCESS; 01847 01848 error: 01849 phTHIS_ERROR_UNLOCK(locked); 01850 01851 return phFAIL; 01852 } 01853 01854 /* ---------------------------------------------------------------------------- 01855 * isReady: 01856 * ------------------------------------------------------------------------- */ 01857 bool phSocket::isReady() 01858 { 01859 phFUNCTION("phSocket::isReady") 01860 struct timeval tv; 01861 fd_set readfds; 01862 int locked = 0; 01863 bool retrc = false; 01864 01865 phTHIS_LOCK(locked); 01866 01867 /* clear the fd_set */ 01868 FD_ZERO(&readfds); 01869 01870 /* add the socket to the fd_set */ 01871 FD_SET(this->m_info->m_sock, &readfds); 01872 01873 /* set the timeout to 0 (return immediately) */ 01874 tv.tv_sec = 0; 01875 tv.tv_usec = 0; 01876 01877 #if phHAVE(SELECT) 01878 /* see if the socket is ready for reading */ 01879 01880 while (((rc = ph_socket_select((int)(this->m_info->m_sock + 1), &readfds, NULL, NULL, &tv)) < 0) 01881 && (this->lastSocketError() == phEINTR)); 01882 #else 01883 #error "Don\'t have select" 01884 #endif 01885 if (rc < 0) 01886 { 01887 if (this->m_warning_level > 1) 01888 { 01889 phSOCK_ERR_PRINT("select() failed"); 01890 } 01891 goto error; 01892 } 01893 01894 /* if it's ready, set the return to true, otherwise false */ 01895 retrc = FD_ISSET(m_info->m_sock, &readfds) ? true : false; 01896 01897 phTHIS_UNLOCK(locked); 01898 01899 return retrc; 01900 01901 error: 01902 phTHIS_ERROR_UNLOCK(locked); 01903 return false; 01904 } 01905 /* ------------------------------------------------------------------------- * 01906 * isConnected: 01907 * -------------------------------------------------------------------------- */ 01908 bool phSocket::isConnected() 01909 { 01910 return this->m_connected; 01911 } 01912 01913 /* ------------------------------------------------------------------------- * 01914 * wakeup: 01915 * -------------------------------------------------------------------------- */ 01916 void phSocket::wakeup() 01917 { 01918 phFUNCTION("phSocket::wakeup") 01919 /* set the trigger to release any loops */ 01920 this->m_exit_trigger = 1; 01921 } 01922 01923 /* ------------------------------------------------------------------------- * 01924 * applyBlocking: 01925 * -------------------------------------------------------------------------- */ 01926 int phSocket::applyBlocking( ) 01927 { 01928 phFUNCTION("phSocket::applyBlocking") 01929 #if (!defined(WIN32)) && phHAVE(FCNTL) 01930 int flags = 0; 01931 #endif 01932 int locked = 0; 01933 #if phHAVE(IOCTLSOCKET) 01934 unsigned long dwNoBlock; 01935 #endif 01936 01937 phTHIS_LOCK(locked); 01938 01939 if (this->m_info->m_sock < 0) 01940 { 01941 phCHECK_RC(-1,NULL,"Bad parameter: this->m_info->m_sock:%d <= 0", 01942 this->m_info->m_sock); 01943 } 01944 01945 #if (!defined(WIN32)) && phHAVE(FCNTL) 01946 /* get the current flags on the socket file descriptor */ 01947 flags = fcntl(this->m_info->m_sock,F_GETFL,0); 01948 phCHECK_RC(flags,"fcntl:F_GETFL","fcntl failed to get fd flags"); 01949 if (this->m_blocking != phBLOCK) 01950 { 01951 /* Set the O_NONBLOCK file descriptor flag bit */ 01952 flags |= O_NONBLOCK; 01953 } 01954 else 01955 { 01956 /* Get the complement of O_NONBLOCK: 01957 * something like 11111110111111... 01958 * then and it with the value of flags 01959 * something like 10011011000011... 01960 * to get flags with the bit turned off 01961 * something like 1001101X000011... */ 01962 flags &= (~O_NONBLOCK); 01963 } 01964 01965 /* set the flags */ 01966 rc = fcntl(this->m_info->m_sock,F_SETFL,flags); 01967 phCHECK_RC(rc,"fcntl:F_SETFL","fcntl failed to set fd flags"); 01968 #elif phHAVE(IOCTLSOCKET) 01969 dwNoBlock = (this->m_blocking != phBLOCK) ? TRUE : FALSE; 01970 rc = ph_socket_ioctlsocket(this->m_info->m_sock,FIONBIO,&dwNoBlock); 01971 phCHECK_RC(rc,"ioctlsocket","ioctlsocket failed to set blocking mode %s", 01972 (this->m_blocking != phBLOCK) ? "non-blocking" : "blocking"); 01973 #else 01974 #if defined(WIN32) 01975 #error "Don\'t have ioctlsocket(enables non-blocking support)" 01976 #else 01977 #error "Don\'t have fcntl(enables non-blocking support)" 01978 #endif 01979 #endif 01980 01981 phTHIS_UNLOCK(locked); 01982 return phSUCCESS; 01983 error: 01984 phTHIS_ERROR_UNLOCK(locked); 01985 return phFAIL; 01986 } 01987 01988 /* ------------------------------------------------------------------------- * 01989 * setBlocking: 01990 * -------------------------------------------------------------------------- */ 01991 int phSocket::setBlocking( int set_blocking ) 01992 { 01993 phFUNCTION("phSocket::setBlocking") 01994 int locked = 0; 01995 01996 phTHIS_LOCK(locked); 01997 01998 this->m_blocking = set_blocking; 01999 02000 if (this->m_info->m_sock >= 0) 02001 { 02002 rc = this->applyBlocking(); 02003 phCHECK_RC(rc,NULL,"applyBlocking"); 02004 } 02005 02006 phTHIS_UNLOCK(locked); 02007 02008 return phSUCCESS; 02009 error: 02010 phTHIS_ERROR_UNLOCK(locked); 02011 return phFAIL; 02012 } 02013 02014 /* ------------------------------------------------------------------------- * 02015 * applyLinger: 02016 * -------------------------------------------------------------------------- */ 02017 int phSocket::applyLinger( ) 02018 { 02019 phFUNCTION("phSocket::applyLinger") 02020 int locked = 0; 02021 struct linger ling; 02022 02023 phTHIS_LOCK(locked); 02024 02025 if (this->m_info->m_sock < 0) 02026 { 02027 phCHECK_RC(-1,NULL,"Bad parameter: this->m_info->m_sock:%d <= 0", 02028 this->m_info->m_sock); 02029 } 02030 02031 /* turn off linger. We don't want the socket to linger around. */ 02032 phMemset(&ling,0,sizeof(struct linger)); 02033 ling.l_onoff = ((this->m_linger == phLINGER_OFF) ? 02034 0 : /* ?TRUE */ 02035 (((this->m_linger == phLINGER) || /* ?FALSE */ 02036 (this->m_linger == phNOLINGER)) ? 02037 1 /* ?TRUE */ : 02038 0 /* ?FALSE*/ )); 02039 ling.l_linger = (this->m_linger == phLINGER) ? 02040 this->m_linger_time : 02041 0; 02042 02043 #if phHAVE(SETSOCKOPT) 02044 /* Call the setsockopt function to apply the "linger off" */ 02045 rc = ph_socket_setsockopt(this->m_info->m_sock, 02046 SOL_SOCKET, 02047 SO_LINGER, 02048 (const char *)&ling, 02049 sizeof(ling)); 02050 //phPRINT_RC(rc,"setsockopt","failed to set linger to off",rc); 02051 #else 02052 #error "Don\'t have setsockopt" 02053 #endif 02054 02055 phTHIS_UNLOCK(locked); 02056 return phSUCCESS; 02057 02058 error: 02059 phTHIS_ERROR_UNLOCK(locked); 02060 return phFAIL; 02061 } 02062 02063 /* ------------------------------------------------------------------------- * 02064 * setLinger: 02065 * -------------------------------------------------------------------------- */ 02066 int phSocket::setLinger( int set_linger, uint32_t linger_time ) 02067 { 02068 phFUNCTION("phSocket::setLinger") 02069 int locked = 0; 02070 02071 phTHIS_LOCK(locked); 02072 02073 this->m_linger = set_linger; 02074 this->m_linger_time = linger_time; 02075 02076 if (this->m_info->m_sock >= 0) 02077 { 02078 rc = this->applyLinger(); 02079 phCHECK_RC(rc,NULL,"applyLinger"); 02080 } 02081 02082 phTHIS_UNLOCK(locked); 02083 02084 return phSUCCESS; 02085 error: 02086 phTHIS_ERROR_UNLOCK(locked); 02087 return phFAIL; 02088 } 02089 02090 /* ------------------------------------------------------------------------- * 02091 * setWarningLevel: 02092 * -------------------------------------------------------------------------- */ 02093 int phSocket::setWarningLevel( int warning_level ) 02094 { 02095 phFUNCTION("phSocket::setWarningLevel") 02096 int locked = 0; 02097 02098 phTHIS_LOCK(locked); 02099 02100 /* apply the warning level */ 02101 this->m_warning_level = warning_level; 02102 02103 phTHIS_UNLOCK(locked); 02104 02105 return phSUCCESS; 02106 error: 02107 phTHIS_ERROR_UNLOCK(locked); 02108 02109 return phFAIL; 02110 } 02111 02112 /* ------------------------------------------------------------------------- * 02113 * getWarningLevel: 02114 * -------------------------------------------------------------------------- */ 02115 int phSocket::getWarningLevel() 02116 { 02117 phFUNCTION("phSocket::getWarningLevel") 02118 int retrc = phSUCCESS; 02119 int locked = 0; 02120 02121 phTHIS_LOOSE_LOCK(locked); 02122 02123 /* save the value and return it later */ 02124 retrc = this->m_warning_level; 02125 02126 phTHIS_LOOSE_UNLOCK(locked); 02127 02128 return retrc; 02129 } 02130 02131 /* ------------------------------------------------------------------------- * 02132 * setCallShutdown: 02133 * -------------------------------------------------------------------------- */ 02134 void phSocket::setCallShutdown(int sd) 02135 { 02136 this->m_call_shutdown = sd; 02137 } 02138 02139 /* -------------------------------------------------------------------------- */ 02140 uint32_t phSocket::hton32( uint32_t var ) 02141 { 02142 #if phHAVE(HTONL) 02143 return htonl( var ); 02144 #else 02145 #error "Don\'t have htonl" 02146 #endif 02147 } 02148 02149 /* -------------------------------------------------------------------------- */ 02150 uint32_t phSocket::ntoh32( uint32_t var ) 02151 { 02152 #if phHAVE(NTOHL) 02153 return ntohl( var ); 02154 #else 02155 #error "Don\'t have ntohl" 02156 #endif 02157 } 02158 02159 /* -------------------------------------------------------------------------- */ 02160 uint16_t phSocket::hton16( uint16_t var ) 02161 { 02162 #if phHAVE(HTONS) 02163 return htons( var ); 02164 #else 02165 #error "Don\'t have htons" 02166 #endif 02167 } 02168 02169 /* -------------------------------------------------------------------------- */ 02170 uint16_t phSocket::ntoh16( uint16_t var ) 02171 { 02172 #if phHAVE(NTOHS) 02173 return ntohs( var ); 02174 #else 02175 #error "Don\'t have ntohs" 02176 #endif 02177 } 02178 02179 /* -------------------------------------------------------------------------- */ 02180 int phSocket::recv_int32( int32_t *i ) 02181 { 02182 phFUNCTION("phSocket::recv_int32") 02183 int32_t d = 0; 02184 02185 rc = this->recv(&d, sizeof(int32_t)); 02186 d = (int32_t)phSocket::ntoh32(d); 02187 DEBUG_PRINT("d:%d\n",d); 02188 02189 if ((rc >= phSUCCESS) && (i != NULL)) *i = d; 02190 return rc; 02191 } 02192 02193 /* -------------------------------------------------------------------------- */ 02194 int phSocket::send_int32( int32_t d ) 02195 { 02196 phFUNCTION("phSocket::send_int32") 02197 02198 DEBUG_PRINT("d:%d\n",d); 02199 d = (int32_t)phSocket::hton32(d); 02200 rc = this->send(&d, sizeof(int32_t)); 02201 02202 return rc; 02203 } 02204 02205 /* -------------------------------------------------------------------------- */ 02206 int phSocket::recv_uint32( uint32_t *i ) 02207 { 02208 phFUNCTION("phSocket::recv_uint32") 02209 uint32_t d = 0; 02210 02211 rc = this->recv(&d, sizeof(uint32_t)); 02212 d = (uint32_t)phSocket::ntoh32(d); 02213 DEBUG_PRINT("d:%u\n",d); 02214 02215 if ((rc >= phSUCCESS) && (i != NULL)) *i = d; 02216 return rc; 02217 } 02218 02219 /* -------------------------------------------------------------------------- */ 02220 int phSocket::send_uint32( uint32_t d ) 02221 { 02222 phFUNCTION("phSocket::send_uint32") 02223 02224 DEBUG_PRINT("d:%u\n",d); 02225 d = (uint32_t)phSocket::hton32(d); 02226 rc = this->send(&d, sizeof(uint32_t)); 02227 02228 return rc; 02229 } 02230 02231 /* -------------------------------------------------------------------------- */ 02232 int phSocket::recv_int16( int16_t *i ) 02233 { 02234 phFUNCTION("phSocket::recv_int16") 02235 int16_t d = 0; 02236 02237 rc = this->recv(&d, sizeof(int16_t)); 02238 d = (int16_t)phSocket::ntoh16(d); 02239 DEBUG_PRINT("d:%hd\n",d); 02240 02241 if ((rc >= phSUCCESS) && (i != NULL)) *i = d; 02242 return rc; 02243 } 02244 02245 /* -------------------------------------------------------------------------- */ 02246 int phSocket::send_int16( int16_t d ) 02247 { 02248 phFUNCTION("phSocket::send_int16") 02249 02250 DEBUG_PRINT("d:%hd\n",d); 02251 d = (int16_t)phSocket::hton16(d); 02252 rc = this->send(&d, sizeof(int16_t)); 02253 02254 return rc; 02255 } 02256 02257 /* -------------------------------------------------------------------------- */ 02258 int phSocket::recv_uint16( uint16_t *i ) 02259 { 02260 phFUNCTION("phSocket::recv_uint16") 02261 uint16_t d = 0; 02262 02263 rc = this->recv(&d, sizeof(uint16_t)); 02264 d = (uint16_t)phSocket::ntoh16(d); 02265 DEBUG_PRINT("d:%hu\n",d); 02266 02267 if ((rc >= phSUCCESS) && (i != NULL)) *i = d; 02268 return rc; 02269 } 02270 02271 /* -------------------------------------------------------------------------- */ 02272 int phSocket::send_uint16( uint16_t d ) 02273 { 02274 phFUNCTION("phSocket::send_uint16") 02275 02276 DEBUG_PRINT("d:%hu\n",d); 02277 d = (uint16_t)phSocket::hton16(d); 02278 rc = this->send(&d, sizeof(uint16_t)); 02279 02280 return rc; 02281 } 02282 02283 02284 /* ------------------------------------------------------------------------- * 02285 * print_object: 02286 * -------------------------------------------------------------------------- */ 02287 int phSocket::print_object(FILE *fd) 02288 { 02289 phFUNCTION("phSocket::print_object") 02290 int retrc = phSUCCESS; 02291 int locked = 0; 02292 02293 if (fd == NULL) return phFAIL; 02294 02295 phTHIS_LOCK(locked); 02296 02297 fprintf(fd,"\nphSocket[ %s:%d -> %s:%d ]\n\n", 02298 this->getSrcHost(), 02299 this->getSrcPort(), 02300 this->getDstHost(), 02301 this->getDstPort() ); 02302 fflush(fd); 02303 02304 error: 02305 phTHIS_ERROR_UNLOCK(locked); 02306 02307 return retrc; 02308 }
Copyright (C) 2002 - 2007 |
Philip D.S. Thoren ( pthoren@users.sourceforge.net ) University Of Massachusetts at Lowell Robotics Lab |