Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

TcpSocket.cpp

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------------
00002 
00003    Copyright (c) 2000 Tyrell Corporation. All rights reserved.
00004 
00005    Tyrell DarkIce
00006 
00007    File     : TcpSocket.cpp
00008    Version  : $Revision: 1.10 $
00009    Author   : $Author: darkeye $
00010    Location : $Source: /cvsroot/darkice/darkice/src/TcpSocket.cpp,v $
00011    
00012    Copyright notice:
00013 
00014     This program is free software; you can redistribute it and/or
00015     modify it under the terms of the GNU General Public License  
00016     as published by the Free Software Foundation; either version 2
00017     of the License, or (at your option) any later version.
00018    
00019     This program is distributed in the hope that it will be useful,
00020     but WITHOUT ANY WARRANTY; without even the implied warranty of 
00021     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
00022     GNU General Public License for more details.
00023    
00024     You should have received a copy of the GNU General Public License
00025     along with this program; if not, write to the Free Software
00026     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00027 
00028 ------------------------------------------------------------------------------*/
00029 
00030 /* ============================================================ include files */
00031 
00032 #ifdef HAVE_CONFIG_H
00033 #include "config.h"
00034 #endif
00035 
00036 #ifdef HAVE_STRING_H
00037 #include <string.h>
00038 #else
00039 #error need string.h
00040 #endif
00041 
00042 #ifdef HAVE_SYS_TYPES_H
00043 #include <sys/types.h>
00044 #else
00045 #error need sys/types.h
00046 #endif
00047 
00048 #ifdef HAVE_ERRNO_H
00049 #include <errno.h>
00050 #else
00051 #error need errno.h
00052 #endif
00053 
00054 #ifdef HAVE_SYS_SOCKET_H
00055 #include <sys/socket.h>
00056 #else
00057 #error need sys/socket.h
00058 #endif
00059 
00060 #ifdef HAVE_NETINET_IN_H
00061 #include <netinet/in.h>
00062 #else
00063 #error need netinet/in.h
00064 #endif
00065 
00066 #ifdef HAVE_NETDB_H
00067 #include <netdb.h>
00068 #else
00069 #error need netdb.h
00070 #endif
00071 
00072 #ifdef HAVE_UNISTD_H
00073 #include <unistd.h>
00074 #else
00075 #error need unistd.h
00076 #endif
00077 
00078 #ifdef HAVE_SYS_TIME_H
00079 #include <sys/time.h>
00080 #else
00081 #error need sys/time.h
00082 #endif
00083 
00084 
00085 #include "Util.h"
00086 #include "Exception.h"
00087 #include "TcpSocket.h"
00088 
00089 
00090 /* ===================================================  local data structures */
00091 
00092 
00093 /* ================================================  local constants & macros */
00094 
00095 /*------------------------------------------------------------------------------
00096  *  File identity
00097  *----------------------------------------------------------------------------*/
00098 static const char fileid[] = "$Id: TcpSocket.cpp,v 1.10 2005/04/11 19:34:23 darkeye Exp $";
00099 
00100 
00101 /* ===============================================  local function prototypes */
00102 
00103 
00104 /* =============================================================  module code */
00105 
00106 /*------------------------------------------------------------------------------
00107  *  Initialize the object
00108  *----------------------------------------------------------------------------*/
00109 void
00110 TcpSocket :: init (   const char    * host,
00111                       unsigned short  port )          throw ( Exception )
00112 {
00113     this->host   = Util::strDup( host);
00114     this->port   = port;
00115     this->sockfd = 0;
00116 }
00117 
00118 
00119 /*------------------------------------------------------------------------------
00120  *  De-initialize the object
00121  *----------------------------------------------------------------------------*/
00122 void
00123 TcpSocket :: strip ( void)                           throw ( Exception )
00124 {
00125     if ( isOpen() ) {
00126         close();
00127     }
00128 
00129     delete[] host;
00130 }
00131 
00132 
00133 /*------------------------------------------------------------------------------
00134  *  Copy Constructor
00135  *----------------------------------------------------------------------------*/
00136 TcpSocket :: TcpSocket (  const TcpSocket &    ss )    throw ( Exception )
00137                 : Source( ss), Sink( ss )
00138 {
00139     int     fd;
00140     
00141     init( ss.host, ss.port);
00142 
00143     if ( (fd = ss.sockfd ? dup( ss.sockfd) : 0) == -1 ) {
00144         strip();
00145         throw Exception( __FILE__, __LINE__, "dup failure");
00146     }
00147 
00148     sockfd = fd;
00149 }
00150 
00151 
00152 /*------------------------------------------------------------------------------
00153  *  Assignment operator
00154  *----------------------------------------------------------------------------*/
00155 TcpSocket &
00156 TcpSocket :: operator= (  const TcpSocket &    ss )   throw ( Exception )
00157 {
00158     if ( this != &ss ) {
00159         int     fd;
00160 
00161         /* first strip */
00162         strip();
00163 
00164 
00165         /* then build up */
00166         Sink::operator=( ss );
00167         Source::operator=( ss );
00168 
00169         init( ss.host, ss.port);
00170         
00171         if ( (fd = ss.sockfd ? dup( ss.sockfd) : 0) == -1 ) {
00172             strip();
00173             throw Exception( __FILE__, __LINE__, "dup failure");
00174         }
00175 
00176         sockfd = fd;
00177     }
00178 
00179     return *this;
00180 }
00181 
00182 
00183 /*------------------------------------------------------------------------------
00184  *  Open the file
00185  *----------------------------------------------------------------------------*/
00186 bool
00187 TcpSocket :: open ( void )                       throw ( Exception )
00188 {
00189 #ifdef HAVE_ADDRINFO
00190     struct addrinfo         hints
00191     struct addrinfo       * ptr;
00192     struct sockaddr_storage addr;
00193     char                    portstr[6];
00194 #else
00195     struct sockaddr_in      addr;
00196     struct hostent        * pHostEntry;
00197 #endif
00198  
00199     if ( isOpen() ) {
00200         return false;
00201     }
00202 
00203 #ifdef HAVE_ADDRINFO
00204     memset(&hints, 0, sizeof(hints));
00205     hints.ai_socktype = SOCK_STREAM;
00206     hints.ai_family = AF_ANY;
00207     snprintf(portstr, sizeof(portstr), "%d", port);
00208 
00209     if (getaddrinfo(host , portstr, &hints, &ptr))
00210     throw Exception( __FILE__, __LINE__, "getaddrinfo error", errno);
00211     memcpy ( addr, ptr->ai_addr, ptr->ai_addrlen);
00212     freeaddrinfo(ptr);
00213 #else
00214     if ( !(pHostEntry = gethostbyname( host)) ) {
00215         throw Exception( __FILE__, __LINE__, "gethostbyname error", errno);
00216     }
00217     
00218     if ( (sockfd = socket( AF_INET, SOCK_STREAM,  IPPROTO_TCP)) == -1 ) {
00219         throw Exception( __FILE__, __LINE__, "socket error", errno);
00220     }
00221 
00222     memset( &addr, 0, sizeof(addr));
00223     addr.sin_family      = AF_INET;
00224     addr.sin_port        = htons(port);
00225     addr.sin_addr.s_addr = *((long*) pHostEntry->h_addr_list[0]);
00226 #endif
00227     if ( connect( sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1 ) {
00228         ::close( sockfd);
00229         sockfd = 0;
00230         throw Exception( __FILE__, __LINE__, "connect error", errno);
00231     }
00232 
00233     return true;
00234 }
00235 
00236 
00237 /*------------------------------------------------------------------------------
00238  *  Check wether read() would return anything
00239  *----------------------------------------------------------------------------*/
00240 bool
00241 TcpSocket :: canRead (      unsigned int    sec,
00242                             unsigned int    usec )      throw ( Exception )
00243 {
00244     fd_set              fdset;
00245     struct timeval      tv;
00246     int                 ret;
00247 
00248     if ( !isOpen() ) {
00249         return false;
00250     }
00251 
00252     FD_ZERO( &fdset);
00253     FD_SET( sockfd, &fdset);
00254     tv.tv_sec  = sec;
00255     tv.tv_usec = usec;
00256 
00257     ret = select( sockfd + 1, &fdset, NULL, NULL, &tv);
00258     
00259     if ( ret == -1 ) {
00260         throw Exception( __FILE__, __LINE__, "select error");
00261     }
00262 
00263     return ret > 0;
00264 }
00265 
00266 
00267 /*------------------------------------------------------------------------------
00268  *  Read from the socket
00269  *----------------------------------------------------------------------------*/
00270 unsigned int
00271 TcpSocket :: read (     void          * buf,
00272                         unsigned int    len )       throw ( Exception )
00273 {
00274     int         ret;
00275 
00276     if ( !isOpen() ) {
00277         return 0;
00278     }
00279 
00280     ret = recv( sockfd, buf, len, 0);
00281 
00282     if ( ret == -1 ) {
00283         throw Exception( __FILE__, __LINE__, "recv error", errno);
00284     }
00285 
00286     return ret;
00287 }
00288 
00289 
00290 /*------------------------------------------------------------------------------
00291  *  Check wether read() would return anything
00292  *----------------------------------------------------------------------------*/
00293 bool
00294 TcpSocket :: canWrite (    unsigned int    sec,
00295                            unsigned int    usec )      throw ( Exception )
00296 {
00297     fd_set              fdset;
00298     struct timeval      tv;
00299     int                 ret;
00300 
00301     if ( !isOpen() ) {
00302         return false;
00303     }
00304 
00305     FD_ZERO( &fdset);
00306     FD_SET( sockfd, &fdset);
00307     tv.tv_sec  = sec;
00308     tv.tv_usec = usec;
00309 
00310     ret = select( sockfd + 1, NULL, &fdset, NULL, &tv);
00311     
00312     if ( ret == -1 ) {
00313         throw Exception( __FILE__, __LINE__, "select error");
00314     }
00315 
00316     return ret > 0;
00317 }
00318 
00319 
00320 /*------------------------------------------------------------------------------
00321  *  Write to the socket
00322  *----------------------------------------------------------------------------*/
00323 unsigned int
00324 TcpSocket :: write (    const void    * buf,
00325                         unsigned int    len )       throw ( Exception )
00326 {
00327     int         ret;
00328 
00329     if ( !isOpen() ) {
00330         return 0;
00331     }
00332 
00333 #ifdef HAVE_MSG_NOSIGNAL
00334     ret = send( sockfd, buf, len, MSG_NOSIGNAL);
00335 #else
00336     ret = send( sockfd, buf, len, 0);
00337 #endif
00338 
00339     if ( ret == -1 ) {
00340         if ( errno == EAGAIN ) {
00341             ret = 0;
00342         } else {
00343             throw Exception( __FILE__, __LINE__, "send error", errno);
00344         }
00345     }
00346 
00347     return ret;
00348 }
00349 
00350 
00351 /*------------------------------------------------------------------------------
00352  *  Close the socket
00353  *----------------------------------------------------------------------------*/
00354 void
00355 TcpSocket :: close ( void )                          throw ( Exception )
00356 {
00357     if ( !isOpen() ) {
00358         return;
00359     }
00360 
00361     flush();
00362     ::close( sockfd);
00363     sockfd = 0;
00364 }
00365 
00366 
00367 
00368 /*------------------------------------------------------------------------------
00369  
00370   $Source: /cvsroot/darkice/darkice/src/TcpSocket.cpp,v $
00371 
00372   $Log: TcpSocket.cpp,v $
00373   Revision 1.10  2005/04/11 19:34:23  darkeye
00374   added IPv6 support, thanks to <jochen2@users.sourceforge.net>
00375 
00376   Revision 1.9  2002/10/19 12:22:27  darkeye
00377   cosmetic change
00378 
00379   Revision 1.8  2002/08/28 18:24:46  darkeye
00380   ported to FreeBSD (removed reference to MSG_NOSIGNAL in TcpSocket.cpp)
00381 
00382   Revision 1.7  2002/07/20 16:37:06  darkeye
00383   added fault tolerance in case a server connection is dropped
00384 
00385   Revision 1.6  2001/09/18 16:44:10  darkeye
00386   TcpSocket did not report closed state when could not connect()
00387 
00388   Revision 1.5  2001/08/30 17:25:56  darkeye
00389   renamed configure.h to config.h
00390 
00391   Revision 1.4  2000/11/17 15:50:48  darkeye
00392   added -Wall flag to compiler and eleminated new warnings
00393 
00394   Revision 1.3  2000/11/12 14:54:50  darkeye
00395   added kdoc-style documentation comments
00396 
00397   Revision 1.2  2000/11/05 14:08:28  darkeye
00398   changed builting to an automake / autoconf environment
00399 
00400   Revision 1.1.1.1  2000/11/05 10:05:55  darkeye
00401   initial version
00402 
00403   
00404 ------------------------------------------------------------------------------*/
00405 

Generated on Thu Apr 14 13:59:13 2005 for DarkIce by  doxygen 1.4.1