#include <unistd.h>
#include <fcntl.h>
namespace panda { namespace unievent {
sock_t fd2sock (fd_t fd) {
return fd;
}
fd_t sock2fd (sock_t sock) {
return sock;
}
std::error_code sys_error (int syserr) {
return std::error_code(syserr, std::generic_category());
}
std::error_code last_sys_error () {
return sys_error(errno);
}
std::error_code last_sys_sock_error () {
return last_sys_error();
}
fd_t file_dup (fd_t src) {
auto src_flags = fcntl(src, F_GETFD, 0);
if (src_flags == -1) throw last_sys_error();
auto ret = ::dup(src);
if (ret == -1) throw last_sys_error();
if (src_flags & FD_CLOEXEC) {
auto flags = fcntl(ret, F_GETFD, 0);
if (flags == -1) {
auto err = last_sys_error();
close(ret).nevermind();
throw err;
}
auto res = fcntl(ret, F_SETFD, flags | FD_CLOEXEC);
if (res == -1) {
auto err = last_sys_error();
close(ret).nevermind();
throw err;
}
}
return ret;
}
sock_t sock_dup (sock_t sock) {
return file_dup(sock);
}
excepted<sock_t, std::error_code> socket (int domain, int type, int protocol) {
auto sock = ::socket(domain, type, protocol);
if (sock == -1) return make_unexpected(last_sys_error());
return sock;
}
excepted<sock_t, std::error_code> accept (sock_t srv, net::SockAddr* sa) {
net::SockAddr stub;
if (!sa) sa = &stub;
socklen_t sz = sizeof(stub);
auto sock = ::accept(srv, sa->get(), &sz);
if (sock == -1) return make_unexpected(last_sys_error());
return sock;
}
excepted<void, std::error_code> setsockopt (sock_t sock, int level, int optname, const void* optval, int optlen) {
auto status = ::setsockopt(sock, level, optname, optval, (socklen_t)optlen);
if (status != 0) return make_unexpected(last_sys_error());
return {};
}
excepted<void, std::error_code> setblocking (sock_t sock, bool val) {
int flags = fcntl(sock, F_GETFL, 0);
if (flags == -1) return make_unexpected(last_sys_error());
flags = val ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
flags = fcntl(sock, F_SETFL, flags);
if (flags != 0) return make_unexpected(last_sys_error());
return {};
}
excepted<void, std::error_code> close (sock_t sock) {
auto status = ::close(sock);
if (status != 0) return make_unexpected(last_sys_error());
return {};
}
excepted<net::SockAddr, std::error_code> getsockname (sock_t sock) {
net::SockAddr ret;
socklen_t sz = sizeof(ret);
auto status = ::getsockname(sock, ret.get(), &sz);
if (status != 0) return make_unexpected(last_sys_error());
return ret;
}
excepted<net::SockAddr, std::error_code> getpeername (sock_t sock) {
net::SockAddr ret;
socklen_t sz = sizeof(ret);
auto status = ::getpeername(sock, ret.get(), &sz);
if (status != 0) return make_unexpected(last_sys_error());
return ret;
}
}}