#include <io.h>
#include <Windows.h>
#include <process.h>
#include <Winsock2.h>
namespace panda { namespace unievent {
static inline HANDLE fd2handle (fd_t fd) {
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) throw Error(last_sys_error());
return h;
}
static inline fd_t handle2fd (HANDLE h) {
int mode = 0; // TODO: ????
fd_t fd = _open_osfhandle((intptr_t)h, mode);
if (fd < 0) throw Error(last_sys_error());
return fd;
}
fd_t file_dup (fd_t src) {
HANDLE h = fd2handle(src);
HANDLE proc = GetCurrentProcess();
HANDLE dup_h;
auto ok = DuplicateHandle(proc, h, proc, &dup_h, 0, false, DUPLICATE_SAME_ACCESS);
if (!ok) throw Error(last_sys_error());
int dup_fd;
try {
dup_fd = handle2fd(dup_h);
} catch (...) {
CloseHandle(dup_h);
throw;
}
return dup_fd;
}
sock_t sock_dup (sock_t sock) {
WSAPROTOCOL_INFOW info;
if (WSADuplicateSocketW(sock, GetCurrentProcessId(), &info)) throw Error(last_sys_sock_error());
auto new_sock = WSASocketW(
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
&info,
0,
WSA_FLAG_OVERLAPPED
);
if (new_sock == INVALID_SOCKET) throw Error(last_sys_sock_error());
return new_sock;
}
sock_t fd2sock (fd_t fd) {
return (sock_t)fd2handle(fd);
}
fd_t sock2fd (sock_t sock) {
return handle2fd((HANDLE)sock);
}
std::error_code sys_error (int syserr) {
//printf("win sys_error %d -> %d -> %d\n", syserr, uv_translate_sys_error(syserr), uvx_error(uv_translate_sys_error(syserr)).value());
return uvx_error(uv_translate_sys_error(syserr));
}
std::error_code last_sys_error () {
return sys_error(GetLastError());
}
std::error_code last_sys_sock_error () {
return sys_error(WSAGetLastError());
}
excepted<sock_t, std::error_code> socket (int domain, int type, int protocol) {
auto sock = ::socket(domain, type, protocol);
if (sock == INVALID_SOCKET) return make_unexpected(last_sys_sock_error());
return sock;
}
excepted<sock_t, std::error_code> accept (sock_t srv, net::SockAddr* sa) {
net::SockAddr stub;
if (!sa) sa = &stub;
int sz = sizeof(stub);
auto sock = ::accept(srv, sa->get(), &sz);
if (sock == INVALID_SOCKET) return make_unexpected(last_sys_sock_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, (const char*)optval, optlen);
if (status != 0) return make_unexpected(last_sys_sock_error());
return {};
}
excepted<void, std::error_code> setblocking (sock_t sock, bool val) {
unsigned long mode = val ? 0 : 1;
auto status = ioctlsocket(sock, FIONBIO, &mode);
if (status != 0) return make_unexpected(last_sys_sock_error());
return {};
}
excepted<void, std::error_code> close (sock_t sock) {
auto status = ::closesocket(sock);
if (status != 0) return make_unexpected(last_sys_sock_error());
return {};
}
excepted<net::SockAddr, std::error_code> getsockname (sock_t sock) {
net::SockAddr ret;
int sz = sizeof(ret);
auto status = ::getsockname(sock, ret.get(), &sz);
if (status != 0) return make_unexpected(last_sys_sock_error());
return ret;
}
excepted<net::SockAddr, std::error_code> getpeername (sock_t sock) {
net::SockAddr ret;
int sz = sizeof(ret);
auto status = ::getpeername(sock, ret.get(), &sz);
if (status != 0) return make_unexpected(last_sys_sock_error());
return ret;
}
}}