Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

phSocket.cpp

Go to the documentation of this file.
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
SourceForge.net Logo

Generated on Sat Jun 16 02:44:03 2007 for phission by  doxygen 1.4.4