7 #include <sys/socket.h>
10 #include <netinet/ip.h>
11 #include <netinet/tcp.h>
15 ostream logstream(clog.rdbuf());
17 void setLogStream(ostream *os) {
if (os) logstream.rdbuf(os->rdbuf()); }
18 void error(
string msg) { logstream <<
"Error: " << msg << endl; }
19 void error(
string label,
string msg) { logstream <<
"Error: " << label <<
": " << msg << endl; }
20 void warning(
string msg) { logstream <<
"Warning: " << msg << endl; }
21 void warning(
string label,
string msg) { logstream <<
"Warning: " << label <<
": " << msg << endl; }
22 void log(
string msg) { logstream << msg << endl; }
23 void log(
string label,
string msg) { logstream << label <<
": " << msg << endl;}
27 handle_ = epoll_create1(0);
29 error(
"epoll_create1",strerror(errno));
41 bool EPoll::add(
Socket& socket,
int events)
43 struct epoll_event ev;
46 ev.data.fd = socket.socket_;
47 if (epoll_ctl(handle_,EPOLL_CTL_ADD,socket.socket_,&ev) != -1) {
48 sockets[socket.socket_] = &socket;
54 bool EPoll::update(Socket& socket,
int events)
57 struct epoll_event ev;
59 ev.data.fd = socket.socket_;
60 result = (epoll_ctl(handle_,EPOLL_CTL_MOD,socket.socket_,&ev) != -1);
64 bool EPoll::remove(Socket& socket)
67 if (epoll_ctl(handle_,EPOLL_CTL_DEL,socket.socket_,NULL) != -1) {
68 sockets.erase(socket.socket_);
76 int nfds = epoll_wait(handle_,events,MAX_EVENTS,timeout);
79 error(
"epoll_wait",strerror(errno));
81 for (
int n = 0; n < nfds; ++n) {
82 handleEvents(events[n].events,events[n].data.fd);
87 void EPoll::handleEvents(uint32_t events,
int fd)
89 Socket* socket = sockets[fd];
90 if (socket !=
nullptr) {
97 Socket::Socket(
EPoll &epoll,
const int domain,
const int socket,
const bool blocking,
const int events) : epoll_(epoll), events_(events), domain_(domain), socket_(socket)
100 error(
"Socket",
"Only IPv4 and IPv6 are supported.");
104 error(
"Socket",
"Socket parameter is < 0");
111 error(
"socket", strerror(errno));
114 int flags = fcntl(socket_,F_GETFL,0);
116 error(
"fcntl (get)",strerror(errno));
121 flags = flags & ~O_NONBLOCK;
123 if (fcntl(socket_,F_SETFL,flags) == -1) {
124 error(
"fcntl (set)",strerror(errno));
128 if (!epoll_.add(*
this,events)) {
129 error(
"Unable to add socket to epoll");
139 epoll_.remove(*
this);
140 if (::close(socket_) == -1) {
141 error(
"close",strerror(errno));
152 if (events != events_) {
153 if (epoll_.update(*
this,events)) {
166 if (
state_ == SocketState::CONNECTED) {
167 ::shutdown(socket_,SHUT_RDWR);
176 if (
state_ != SocketState::DISCONNECTED) {
179 state_ = SocketState::DISCONNECTED;
182 warning(
"Already disconnected");
192 if (
ssl_ && (
state_ == SocketState::CONNECTED)) {
219 size = read_(&buffer[0],256);
220 for (
int i=0;i<size;i++) {
221 inputBuffer.push_back(buffer[i]);
229 size_t size = outputBuffer.size();
230 if (size == 0)
return;
231 uint8_t *buffer = (uint8_t*)malloc(size);
232 for (
size_t i=0;i<size;i++) {
233 buffer[i] = outputBuffer.at(0);
234 outputBuffer.pop_front();
236 size_t res = write_(buffer,size);
239 for (
size_t i=res;i<size;i++) {
240 outputBuffer.push_front(buffer[i]);
249 int events = EPOLLIN | EPOLLRDHUP;
257 if (
state_ == SocketState::CONNECTED) {
258 if (events & EPOLLRDHUP) {
261 if (events & EPOLLIN) {
265 if (outputBuffer.size() > 0U) {
267 canSend(outputBuffer.size() > 0U);
273 if (events & EPOLLOUT) {
276 canSend(outputBuffer.size() > 0U);
283 size_t DataSocket::read_(
void *buffer,
size_t size)
285 if (
state_ == SocketState::CONNECTED) {
290 result = ::recv(
socket(),buffer,size,0);
298 size_t DataSocket::write_(
const void *buffer,
size_t size)
300 if (
state_ == SocketState::CONNECTED) {
305 result = ::send(
socket(),buffer,size,MSG_NOSIGNAL);
318 result = max<size_t>(size,inputBuffer.size());
320 for (
size_t i=0;i<result;++i) {
321 ((uint8_t*)buffer)[i] = inputBuffer.at(0);
322 inputBuffer.pop_front();
336 for (
size_t i=0;i<size;++i) {
337 outputBuffer.push_back(((uint8_t*)buffer)[i]);
341 }
catch (
const std::bad_alloc&) {
351 return new SSL(*
this,*context);
359 struct addrinfo hints;
360 struct addrinfo *result;
364 memset(&hints,0,
sizeof(
struct addrinfo));
365 hints.ai_family = AF_UNSPEC;
366 hints.ai_flags = AI_NUMERICHOST;
367 errorcode = getaddrinfo(host,
nullptr,&hints,&result);
368 if (errorcode == 0) {
369 domain = result->ai_family;
373 if (domain == AF_UNSPEC) {
374 hints.ai_flags = AI_CANONNAME;
375 errorcode = getaddrinfo(host,port,&hints,&result);
376 if (errorcode == 0) {
377 domain = result->ai_family;
380 if (domain == AF_UNSPEC) {