27 #ifndef HAVE_FEATURES_H
33 #include <sys/socket.h>
34 #include <sys/types.h>
35 #include <netinet/tcp.h>
42 #include <arpa/inet.h>
47 #ifdef HAVE_FEATURES_H
48 #define __compat_select ::select
50 int __compat_select(
int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
54 return ::select(nfds, readfds, writefds, exceptfds, NULL);
59 struct timeval to_copy;
60 ::memcpy(&to_copy, timeout,
sizeof to_copy);
63 int ret = ::select(nfds, readfds, writefds, exceptfds, &to_copy);
68 while ((us > 1000000) && (timeout->tv_sec > 0))
74 if (us >= static_cast<size_t>(timeout->tv_usec))
80 timeout->tv_usec -= us;
87 vsocket::pipesocket::pipesocket()
91 vsocket::pipesocket::~pipesocket()
95 int vsocket::pipesocket::getOutput()
const throw (socket_exception)
97 if (_state == SOCKET_DOWN)
throw socket_exception(
"output fd not available");
101 void vsocket::pipesocket::up() throw (socket_exception)
103 if (_state != SOCKET_DOWN)
104 throw socket_exception(
"socket is already up");
109 if (::pipe(pipe_fds) < 0)
112 throw socket_exception(
"failed to create pipe");
116 _output_fd = pipe_fds[1];
118 this->set_blocking_mode(
false);
119 this->set_blocking_mode(
false, _output_fd);
124 void vsocket::pipesocket::down() throw (socket_exception)
126 if (_state != SOCKET_UP)
127 throw socket_exception(
"socket is not up");
131 _state = SOCKET_DOWN;
134 void vsocket::pipesocket::read(
char *buf,
size_t len)
throw (socket_exception)
136 ssize_t ret = ::read(this->fd(), buf, len);
138 throw socket_exception(
"read error");
140 throw socket_exception(
"end of file");
143 void vsocket::pipesocket::write(
const char *buf,
size_t len)
throw (socket_exception)
145 ssize_t ret = ::write(_output_fd, buf, len);
147 throw socket_exception(
"write error");
150 vsocket::SocketState::SocketState(STATE initial)
155 vsocket::SocketState::~SocketState()
159 vsocket::SocketState::STATE vsocket::SocketState::get()
const
164 void vsocket::SocketState::set(STATE s)
throw (state_exception)
170 throw state_exception(
"illegal state requested");
173 if ((_state != DOWN) && (_state != PENDING_UP))
174 throw state_exception(
"state is not DOWN");
180 if ((_state != PENDING_DOWN) && (_state != SAFE_DOWN) && (_state != PENDING_UP))
181 throw state_exception(
"state is not PENDING_DOWN, PENDING_UP or SAFE_DOWN");
188 throw state_exception(
"state is not DOWN");
194 if ((_state != IDLE) && (_state != DOWN_REQUEST))
195 throw state_exception(
"state is not IDLE or DOWN_REQUEST");
201 if ((_state != PENDING_UP) && (_state != SAFE) && (_state != SELECT))
202 throw state_exception(
"state is not PENDING_UP, SAFE or SELECT");
208 if ((_state != IDLE) && (_state != SELECT))
209 throw state_exception(
"state is not IDLE or SELECT");
216 if (_state != SELECT)
217 throw state_exception(
"state is not SELECT or DOWN_REQUEST");
223 if ((_state != SAFE_REQUEST) && (_state != IDLE))
224 throw state_exception(
"state is not SAFE_REQUEST or IDLE");
228 }
catch (
const Conditional::ConditionalAbortException &e) {
229 throw state_exception(e.what());
233 void vsocket::SocketState::setwait(STATE s, STATE abortstate)
throw (state_exception)
239 throw state_exception(
"illegal state requested");
242 while ((_state != DOWN) && (_state != PENDING_UP)) {
243 if (_state == abortstate)
244 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
252 while ((_state != PENDING_DOWN) && (_state != SAFE_DOWN)) {
253 if (_state == abortstate)
254 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
262 while (_state != DOWN) {
263 if (_state == abortstate)
264 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
272 while ((_state != IDLE) && (_state != DOWN_REQUEST)) {
273 if (_state == abortstate)
274 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
282 while ((_state != PENDING_UP) && (_state != SAFE) && (_state != SELECT)) {
283 if (_state == abortstate)
284 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
292 while ((_state != IDLE) && (_state != SELECT)) {
293 if (_state == abortstate)
294 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
303 while (_state != SELECT) {
304 if (_state == abortstate)
305 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
313 while ((_state != SAFE_REQUEST) && (_state != IDLE)) {
314 if (_state == abortstate)
315 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
321 }
catch (
const Conditional::ConditionalAbortException &e) {
322 throw state_exception(e.what());
326 void vsocket::SocketState::wait(STATE s, STATE abortstate)
throw (state_exception)
329 while (_state != s) {
330 if (_state == abortstate)
331 throw state_exception(
"abort state " + __getname(abortstate) +
" reached");
334 }
catch (
const Conditional::ConditionalAbortException &e) {
335 throw state_exception(e.what());
339 void vsocket::SocketState::__change(STATE s)
346 std::string vsocket::SocketState::__getname(STATE s)
const
358 return "PENDING_DOWN";
364 return "SAFE_REQUEST";
366 return "DOWN_REQUEST";
374 vsocket::SafeLock::SafeLock(SocketState &state, vsocket &sock)
380 while ( (_state.get() != SocketState::DOWN) && (_state.get() != SocketState::IDLE) && (_state.get() != SocketState::SELECT) ) {
384 if (_state.get() == SocketState::SELECT) {
385 _state.set(SocketState::SAFE_REQUEST);
388 _state.wait(SocketState::SAFE);
389 }
else if (_state.get() == SocketState::DOWN) {
390 _state.set(SocketState::SAFE_DOWN);
392 _state.set(SocketState::SAFE);
396 vsocket::SafeLock::~SafeLock()
400 if (_state.get() == SocketState::SAFE)
402 _state.set(SocketState::IDLE);
404 else if (_state.get() == SocketState::SAFE_DOWN)
406 _state.set(SocketState::DOWN);
410 throw SocketState::state_exception(
"socket not in safe state");
414 vsocket::SelectGuard::SelectGuard(SocketState &state,
int &counter)
415 : _state(state), _counter(counter)
420 _state.setwait(SocketState::SELECT, SocketState::DOWN);
423 }
catch (
const SocketState::state_exception&) {
424 throw vsocket_interrupt(
"select interrupted while waiting for IDLE socket");
428 vsocket::SelectGuard::~SelectGuard()
437 if (_state.get() == SocketState::SAFE_REQUEST) {
438 _state.set(SocketState::SAFE);
439 }
else if (_state.get() == SocketState::DOWN_REQUEST) {
440 _state.set(SocketState::PENDING_DOWN);
442 _state.set(SocketState::IDLE);
446 throw vsocket_interrupt(
"select interrupted while checking SAFE_REQUEST state");
451 : _state(SocketState::DOWN), _select_count(0)
463 SafeLock l(_state, *
this);
464 _sockets.insert(socket);
469 SafeLock l(_state, *
this);
470 _sockets.insert(socket);
471 _socket_map[iface].insert(socket);
476 SafeLock l(_state, *
this);
477 _sockets.erase(socket);
480 for (std::map<vinterface, socketset>::iterator iter = _socket_map.begin(); iter != _socket_map.end(); ++iter)
489 return _sockets.size();
494 SafeLock l(_state, *
this);
503 for (socketset::iterator iter = _sockets.begin(); iter != _sockets.end(); ++iter)
519 std::map<vinterface, socketset>::const_iterator iter = _socket_map.find(iface);
521 if (iter == _socket_map.end()) {
526 return (*iter).second;
534 _state.setwait(SocketState::PENDING_UP, SocketState::IDLE);
537 for (socketset::iterator iter = _sockets.begin(); iter != _sockets.end(); ++iter) {
539 if (!(*iter)->ready()) (*iter)->up();
540 }
catch (
const socket_exception&) {
542 for (socketset::iterator riter = _sockets.begin(); riter != iter; ++riter) {
547 _state.set(SocketState::DOWN);
554 _state.set(SocketState::IDLE);
561 if (_state.get() == SocketState::SELECT) {
562 _state.setwait(SocketState::DOWN_REQUEST, SocketState::DOWN);
565 _state.wait(SocketState::PENDING_DOWN);
568 _state.setwait(SocketState::PENDING_DOWN, SocketState::DOWN);
576 for (socketset::iterator iter = _sockets.begin(); iter != _sockets.end(); ++iter) {
578 if ((*iter)->ready()) (*iter)->down();
579 }
catch (
const socket_exception&) { }
583 _state.set(SocketState::DOWN);
586 void vsocket::interrupt()
601 SelectGuard guard(_state, _select_count);
608 FD_SET(_pipe.fd(), &fds_read);
609 high_fd = _pipe.fd();
613 for (socketset::iterator iter = _sockets.begin();
614 iter != _sockets.end(); ++iter)
617 if (!sock.
ready())
continue;
619 if (readset != NULL) {
620 FD_SET(sock.
fd(), &fds_read);
621 if (high_fd < sock.
fd()) high_fd = sock.
fd();
624 if (writeset != NULL) {
625 FD_SET(sock.
fd(), &fds_write);
626 if (high_fd < sock.
fd()) high_fd = sock.
fd();
629 if (errorset != NULL) {
630 FD_SET(sock.
fd(), &fds_error);
631 if (high_fd < sock.
fd()) high_fd = sock.
fd();
637 int res =
__compat_select(high_fd + 1, &fds_read, &fds_write, &fds_error, tv);
640 if (errno == EINTR) {
644 else if (errno == 0) {
654 if (FD_ISSET(_pipe.fd(), &fds_read))
668 for (socketset::iterator iter = _sockets.begin();
669 iter != _sockets.end(); ++iter)
673 if (readset != NULL) {
674 if (FD_ISSET(sock->
fd(), &fds_read))
676 readset->insert(sock);
680 if (writeset != NULL) {
681 if (FD_ISSET(sock->
fd(), &fds_write))
683 writeset->insert(sock);
687 if (errorset != NULL) {
688 if (FD_ISSET(sock->
fd(), &fds_error))
690 errorset->insert(sock);