-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathsclasses.cc
More file actions
135 lines (121 loc) · 3.46 KB
/
Copy pathsclasses.cc
File metadata and controls
135 lines (121 loc) · 3.46 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "sclasses.hh"
#include <assert.h>
#include <sys/poll.h>
#include <fmt/format.h>
#include <fmt/printf.h>
int waitForRWData(int fd, bool waitForRead, double* timeout, bool* error, bool* disconnected)
{
int ret;
struct pollfd pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.fd = fd;
if(waitForRead)
pfd.events=POLLIN;
else
pfd.events=POLLOUT;
ret = poll(&pfd, 1, timeout ? (*timeout * 1000) : -1);
if ( ret == -1 ) {
throw std::runtime_error("Waiting for data: "+std::string(strerror(errno)));
}
if(ret > 0) {
if (error && (pfd.revents & POLLERR)) {
*error = true;
}
if (disconnected && (pfd.revents & POLLHUP)) {
*disconnected = true;
}
}
return ret;
}
int waitForData(int fd, double* timeout)
{
return waitForRWData(fd, true, timeout);
}
int SConnectWithTimeout(int sockfd, const ComboAddress& remote, double timeout=-1)
{
int ret = connect(sockfd, (struct sockaddr*)&remote, remote.getSocklen());
if(ret < 0) {
int savederrno = errno;
if (savederrno == EINPROGRESS) {
/* we wait until the connection has been established */
bool error = false;
bool disconnected = false;
int res = waitForRWData(sockfd, false, &timeout, &error, &disconnected);
if (res == 1) {
if (error) {
savederrno = 0;
socklen_t errlen = sizeof(savederrno);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&savederrno, &errlen) == 0) {
throw std::runtime_error(fmt::sprintf("connecting to %s failed: %s", remote.toStringWithPort(), strerror(savederrno)));
}
else {
throw std::runtime_error(fmt::sprintf("connecting to %s failed", remote.toStringWithPort()));
}
}
if (disconnected) {
throw std::runtime_error(fmt::sprintf("%s closed the connection", remote.toStringWithPort()));;
}
return 0;
}
else if (res == 0) {
throw std::runtime_error(fmt::sprintf("timeout while connecting to %s", remote.toStringWithPort()));
} else if (res < 0) {
savederrno = errno;
throw std::runtime_error(fmt::sprintf("waiting to connect to %s: %s", remote.toStringWithPort(), strerror(savederrno)));
}
}
else {
throw std::runtime_error(fmt::sprintf("connecting to %s: %s", remote.toStringWithPort(), strerror(savederrno)));
}
}
return ret;
}
bool ReadBuffer::getMoreData()
{
assert(d_pos == d_endpos);
double timeout = d_timeout;
for(;;) {
int res = read(d_fd, &d_buffer[0], d_buffer.size());
if(res < 0 && errno == EAGAIN) {
waitForData(d_fd, &timeout);
continue;
}
if(res < 0)
throw std::runtime_error("Getting more data: " + std::string(strerror(errno)));
if(!res)
return false;
d_endpos = res;
d_pos=0;
break;
}
return true;
}
bool SocketCommunicator::getLine(std::string& line)
{
line.clear();
char c;
while(d_rb.getChar(&c)) {
line.append(1, c);
if(c=='\n')
return true;
}
return !line.empty();
}
void SocketCommunicator::writen(const std::string& content)
{
unsigned int pos=0;
int res;
while(pos < content.size()) {
res=write(d_fd, &content[pos], content.size()-pos);
if(res < 0) {
if(errno == EAGAIN) {
waitForRWData(d_fd, false);
continue;
}
throw std::runtime_error("Writing to socket: "+std::string(strerror(errno)));
}
if(res==0)
throw std::runtime_error("EOF on write");
pos += res;
}
}