void csocket::connect(const sockaddrunion& su) { if(is_sock_err(::connect(sd, &su.s, get_addrlen(su)))) { // EINPROGRESS just means socket is non-blocking and requires TCP handshake, not really an error if(sock_err::get_last() != sock_err::einprogress) throw e_check_sock_err("connect()", true); } }
size_t send_rv(ssize_t bytes, const char* fn) { if(is_sock_err(bytes)) { if(sock_err_is_wouldblock(sock_err::get_last())) return 0; else throw e_check_sock_err(fn, true); } return bytes; }
void network_init() { #ifdef WINSOCK dout() << "network_init: doing WSAStartup()"; WSADATA not_interested; int rv = WSAStartup(MAKEWORD(2,2), ¬_interested); if(rv != 0) { eout() << "WSAStartup failed: " << get_windows_errorstr(rv); throw e_check_sock_err("WSAStartup failed", true); } #endif }
size_t recv_rv(ssize_t bytes, size_t len, const char* fn) { if(is_sock_err(bytes)) { if(sock_err_is_wouldblock(sock_err::get_last())) return 0; else throw e_check_sock_err(fn, true); } if(bytes == 0 && len != 0) sock_err::set_last(sock_err::enotconn); return bytes; }
bool tuntap::send_packet(dbuf &buf, size_t len) { #ifdef WINDOWS if(sent_sync || HasOverlappedIoCompleted(&send_overlapped)) { std::swap(buf, send_buf); if(buf.size() < send_buf.size()) buf.resize(send_buf.size()); do_write(len); return true; } // else previous async send has not completed return false; #else ssize_t nwritten = write(fd, buf, len); if(nwritten > 0) return true; if(errno == EWOULDBLOCK || errno == EAGAIN) return false; throw e_check_sock_err("write to tuntap failed", true); #endif }
size_t tuntap::recv_packet(dbuf &buf) { #ifdef WINDOWS // interesting possible trouble: if async read fails then obviously want to retry, but then how to avoid busy looping? // -> maybe do the retry but also then throw exception to indicate the failure // this means that before throw the buffers have to be swapped back so that non-error previous read is not lost if(received_sync > 0) { DWORD bytes_read = received_sync; std::swap(buf, recv_buf); if(buf.size() < recv_buf.size()) buf.resize(recv_buf.size()); do_read(); return bytes_read; } else if(HasOverlappedIoCompleted(&recv_overlapped)) { DWORD bytes_read; if(GetOverlappedResult(fd, &recv_overlapped, &bytes_read, FALSE) == FALSE) { #warning fixme GetLastError, throw exception // GetLastError should not be ERROR_IO_INCOMPLETE because otherwise HasOverlappedIoCompleted should have been false } std::swap(buf, recv_buf); if(buf.size() < recv_buf.size()) buf.resize(recv_buf.size()); do_read(); return bytes_read; } // else async read is still in progress, no data to return yet return 0; #else ssize_t nread = read(fd, buf, buf.size()); if(nread >= 0) return nread; if(errno == EWOULDBLOCK || errno == EAGAIN) return 0; throw e_check_sock_err("read from tuntap failed", true); #endif }