simple-socket library 1.1.5

SimpleSocket.cpp

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