Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

SocketModule.cxx

00001 /*
00002  * Copyright (C) 1991-9 Eric M. Hopper <hopper@omnifarious.mn.org>
00003  * 
00004  *     This program is free software; you can redistribute it and/or modify it
00005  *     under the terms of the GNU Lesser General Public License as published
00006  *     by the Free Software Foundation; either version 2 of the License, or
00007  *     (at your option) any later version.
00008  * 
00009  *     This program is distributed in the hope that it will be useful, but
00010  *     WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *     Lesser General Public License for more details.
00013  * 
00014  *     You should have received a copy of the GNU Lesser General Public
00015  *     License along with this program; if not, write to the Free Software
00016  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 /* $Header: /home/hopper/src/cvs/C++/StrMod/SocketModule.cxx,v 1.17 2002/08/30 23:49:03 hopper Exp $ */
00020 
00021 // For a log, see ./ChangeLog
00022 // $Revision: 1.17 $
00023 
00024 #ifdef __GNUG__
00025 #  pragma implementation "SocketModule.h"
00026 #endif
00027 
00028 #include <EHnet++/SocketAddress.h>
00029 #include "StrMod/SocketModule.h"
00030 #include "StrMod/FDUtil.h"
00031 #include <cstring>
00032 #include <fcntl.h>
00033 #include <sys/types.h>
00034 #include <sys/socket.h>
00035 #include <cerrno>
00036 #include <unistd.h>
00037 #include "config.h"
00038 #include "sockdecl.h"
00039 
00040 #ifndef SHUT_WR
00041 #define SHUT_WR 1
00042 #endif
00043 
00044 namespace strmod {
00045 namespace strmod {
00046 
00047 using unievent::UNIXError;
00048 using ehnet::SocketAddress;
00049 using lcore::LCoreError;
00050 
00051 const STR_ClassIdent SocketModule::identifier(12UL);
00052 
00053 // MakeSocket sets makesock_errno_.
00054 SocketModule::SocketModule(const SocketAddress &addr,
00055                            unievent::Dispatcher &disp,
00056                            unievent::UnixEventRegistry &ureg,
00057                            bool blockconnect)
00058    throw(UNIXError)
00059      : StreamFDModule(MakeSocket(*this, addr, blockconnect), disp, ureg,
00060                       StreamFDModule::CheckBoth),
00061        peer_(*(addr.Copy()))
00062 {
00063    setMaxChunkSize(64U * 1024U);
00064 }
00065 
00066 SocketModule::~SocketModule()  // This might be changed later to add
00067 {                              // a shutdown message sent to the
00068    delete &peer_;              // socket on the other side of the
00069 }                              // connection.
00070 
00071 SocketModule::SocketModule(int fd, SocketAddress *pr,
00072                            unievent::Dispatcher &disp,
00073                            unievent::UnixEventRegistry &ureg)
00074      : StreamFDModule(fd, disp, ureg, StreamFDModule::CheckBoth),
00075        peer_(*pr)
00076 {
00077    setMaxChunkSize(64U * 1024U);
00078 }
00079 
00080 void SocketModule::writeEOF()
00081 {
00082    if (getFD() >= 0)
00083    {
00084       if (hasErrorIn(ErrRead) && getErrorIn(ErrRead).isEOF())
00085       {
00086          StreamFDModule::writeEOF();
00087       }
00088       else
00089       {
00090 //       cerr << "Wheee 1\n";
00091          if (shutdown(getFD(), SHUT_WR) != 0)
00092          {
00093 //       cerr << "Wheee 2\n";
00094             const int myerrno = UNIXError::getErrno();
00095             setErrorIn(ErrWrite,
00096                        UNIXError("shutdown", myerrno,
00097                                  LCoreError(LCORE_GET_COMPILERINFO())));
00098          }
00099          else
00100          {
00101             setErrorIn(ErrWrite,
00102                        UNIXError("shutdown",
00103                                  LCoreError(LCORE_GET_COMPILERINFO())));
00104          }
00105       }
00106    }
00107 }
00108 
00109 static inline void setNonBlock(int fd) throw(UNIXError)
00110 {
00111    int errval = 0;
00112 //     cerr << "In setNonBlock(" << fd << ", " << errval << ")\n";
00113    if (!FDUtil::setNonBlock(fd, errval))
00114    {
00115       throw UNIXError("FDUtil::setNonBlock", errval,
00116                       LCoreError(LCORE_GET_COMPILERINFO()));
00117 //        cerr << "setNonBlock::errval == " << errval << "\n";
00118    }
00119 }
00120 
00121 static inline void doConnect(int fd, SocketAddress &peer) throw(UNIXError)
00122 {
00123    if (connect(fd, peer.SockAddr(), peer.AddressSize()) < 0)
00124    {
00125       const int myerrno = UNIXError::getErrno();
00126       if (myerrno != EINPROGRESS)
00127       {
00128          throw UNIXError("connect", myerrno,
00129                          LCoreError(LCORE_GET_COMPILERINFO()));
00130       }
00131    }
00132 }
00133 
00134 int SocketModule::MakeSocket(SocketModule &obj,
00135                              const SocketAddress &addr, bool blockconnect)
00136    throw(UNIXError)
00137 {
00138    int fd = -1;
00139    try {
00140       SocketAddress &peer = *(addr.Copy());
00141 
00142       if ((fd = socket(peer.SockAddr()->sa_family, SOCK_STREAM, PF_UNSPEC)) < 0)
00143       {
00144          const int myerrno = UNIXError::getErrno();
00145          throw UNIXError("socket", myerrno,
00146                          LCoreError(LCORE_GET_COMPILERINFO()));
00147       }
00148 
00149       if (blockconnect)
00150       {
00151           doConnect(fd, peer);
00152           setNonBlock(fd);
00153       }
00154       else
00155       {
00156          setNonBlock(fd);
00157          doConnect(fd, peer);
00158       }
00159    }
00160    catch(UNIXError e)
00161    {
00162       if (fd >= 0)
00163       {
00164          close(fd);
00165          fd = -1;
00166       }
00167       throw;
00168    }
00169    return(fd);
00170 }
00171 
00172 };  // End namespace strmod
00173 };  // End namespace strmod

Generated on Wed Jan 29 00:32:44 2003 for libNet by doxygen1.3-rc1