00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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()
00067 {
00068 delete &peer_;
00069 }
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
00091 if (shutdown(getFD(), SHUT_WR) != 0)
00092 {
00093
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
00113 if (!FDUtil::setNonBlock(fd, errval))
00114 {
00115 throw UNIXError("FDUtil::setNonBlock", errval,
00116 LCoreError(LCORE_GET_COMPILERINFO()));
00117
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 };
00173 };