simple-socket library 1.1.5
|
00001 #include "SimpleSocket.h" 00002 #include "TempFailure.h" 00003 00004 #include <poll.h> 00005 #include <cstring> 00006 #include <cerrno> 00007 00008 using namespace NET; 00009 00010 SocketException::SocketException( const std::string& message, bool inclSysMsg /* = true */) throw() 00011 : m_message(message) 00012 , m_errorcode(0) 00013 { 00014 if(inclSysMsg) 00015 { 00016 m_errorcode = errno; 00017 m_message += ": "; 00018 m_message += strerror(m_errorcode); 00019 } 00020 } 00021 00022 SimpleSocket::SimpleSocket( int domain, int type, int protocol) 00023 : m_peerDisconnected(false) 00024 { 00025 if( (m_socket = ::socket( domain, type, protocol)) < 0) 00026 throw SocketException("Socket creation failed (socket)"); 00027 } 00028 00029 SimpleSocket::SimpleSocket( int sockfd) 00030 : m_socket(sockfd) 00031 , m_peerDisconnected(false) 00032 { 00033 if(sockfd < 0) 00034 throw SocketException("Tried to initialize Socket with invalid Handle", false); 00035 } 00036 00037 SimpleSocket::~SimpleSocket() 00038 { 00039 TEMP_FAILURE_RETRY (::close(m_socket)); 00040 // on Windows do cleanup here 00041 } 00042 00043 int SimpleSocket::send( const void* buffer, size_t len) 00044 { 00045 int sent = TEMP_FAILURE_RETRY (::send( m_socket, (const raw_type*) buffer, len, 0)); 00046 if( sent < 0) 00047 { 00048 switch(errno) 00049 { 00050 case ECONNRESET: 00051 case ECONNREFUSED: 00052 m_peerDisconnected = true; 00053 break; 00054 default: 00055 throw SocketException("Send failed (send)"); 00056 } 00057 } 00058 return sent; 00059 } 00060 00061 int SimpleSocket::receive( void* buffer, size_t len) 00062 { 00063 int ret = TEMP_FAILURE_RETRY (::recv( m_socket, (raw_type*) buffer, len, 0)); 00064 if( ret < 0) throw SocketException("Received failed (receive)"); 00065 return ret; 00066 } 00067 00068 int SimpleSocket::timedReceive( void* buffer, size_t len, int timeout) 00069 { 00070 struct pollfd poll; 00071 poll.fd = m_socket; 00072 poll.events = POLLIN | POLLPRI | POLLRDHUP; 00073 00074 int ret = TEMP_FAILURE_RETRY (::poll( &poll, 1, timeout)); 00075 00076 if( ret == 0) return 0; 00077 if( ret < 0) throw SocketException("timedReceive failed (poll)"); 00078 00079 if( poll.revents & POLLRDHUP) 00080 m_peerDisconnected = true; 00081 00082 if( poll.revents & POLLIN || poll.revents & POLLPRI) 00083 return receive( buffer, len); 00084 00085 return 0; 00086 } 00087 00088 void SimpleSocket::disconnect() 00089 { 00090 sockaddr addr; 00091 std::memset( &addr, 0, sizeof(addr)); 00092 addr.sa_family = AF_UNSPEC; 00093 00094 if( ::connect( m_socket, &addr, sizeof(addr)) < 0) 00095 { 00096 if( errno != ECONNRESET) 00097 throw SocketException("Disconnect failed (connect)"); 00098 00099 m_peerDisconnected = false; 00100 } 00101 } 00102 00103 void SimpleSocket::shutdown( ShutdownDirection type) 00104 { 00105 if( ::shutdown( m_socket, type) < 0) 00106 throw SocketException("Shutdown failed (shutdown)"); 00107 } 00108 00109 bool SimpleSocket::peerDisconnected() const 00110 { 00111 return m_peerDisconnected; 00112 }