-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathSimpleSocket.cpp
More file actions
117 lines (98 loc) · 2.52 KB
/
Copy pathSimpleSocket.cpp
File metadata and controls
117 lines (98 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "SimpleSocket.h"
#include "TempFailure.h"
#include <poll.h>
#include <unistd.h>
#include <cstring>
#include <cerrno>
using namespace NET;
SocketException::SocketException( std::string_view message, bool inclSysMsg /* = true */)
: m_message(message)
, m_errorcode(0)
{
if(inclSysMsg)
{
m_errorcode = errno;
m_message += ": ";
m_message += strerror(m_errorcode);
}
}
SimpleSocket::SimpleSocket( int domain, int type, int protocol)
: m_peerDisconnected(false)
{
if( (m_socket = ::socket( domain, type, protocol)) < 0)
throw SocketException("Socket creation failed (socket)");
}
SimpleSocket::SimpleSocket( int sockfd)
: m_socket(sockfd)
, m_peerDisconnected(false)
{
if(sockfd < 0)
throw SocketException("Tried to initialize Socket with invalid Handle", false);
}
SimpleSocket::~SimpleSocket()
{
TEMP_FAILURE_RETRY (::close(m_socket));
// on Windows do cleanup here
}
int SimpleSocket::send( const void* buffer, size_t len)
{
int sent = TEMP_FAILURE_RETRY (::send( m_socket, (const raw_type*) buffer, len, 0));
if( sent < 0)
{
switch(errno)
{
case ECONNRESET:
case ECONNREFUSED:
m_peerDisconnected = true;
break;
default:
throw SocketException("Send failed (send)");
}
}
return sent;
}
int SimpleSocket::receive( void* buffer, size_t len)
{
int ret = TEMP_FAILURE_RETRY (::recv( m_socket, (raw_type*) buffer, len, 0));
if( ret < 0) throw SocketException("Received failed (receive)");
return ret;
}
int SimpleSocket::timedReceive( void* buffer, size_t len, int timeout)
{
struct pollfd poll;
poll.fd = m_socket;
poll.events = POLLIN | POLLPRI | POLLRDHUP;
int ret = TEMP_FAILURE_RETRY (::poll( &poll, 1, timeout));
if( ret == 0) return 0;
if( ret < 0) throw SocketException("timedReceive failed (poll)");
if( poll.revents & POLLRDHUP)
m_peerDisconnected = true;
if( poll.revents & POLLIN || poll.revents & POLLPRI)
{
ret = TEMP_FAILURE_RETRY (::recv( m_socket, (raw_type*) buffer, len, 0));
if( ret < 0)
throw SocketException("timedReceive failed (recv)");
}
return ret;
}
void SimpleSocket::disconnect()
{
sockaddr addr;
std::memset( &addr, 0, sizeof(addr));
addr.sa_family = AF_UNSPEC;
if( ::connect( m_socket, &addr, sizeof(addr)) < 0)
{
if( errno != ECONNRESET)
throw SocketException("Disconnect failed (connect)");
m_peerDisconnected = false;
}
}
void SimpleSocket::shutdown( ShutdownDirection type)
{
if( ::shutdown( m_socket, type) < 0)
throw SocketException("Shutdown failed (shutdown)");
}
bool SimpleSocket::peerDisconnected() const
{
return m_peerDisconnected;
}