From 16594884da1c20c60fa1211c76939696547c02b5 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 20 Dec 2013 19:04:23 -0800 Subject: Sockets are now working properly under MSVC. I guess I broke mingw32 though, but we'll fix this later. --- src/Handle.cc | 4 ++-- src/Selectable.cc | 43 ++++++++++++++++++++++++++++++++++++------- src/Socket.cc | 49 ++++++++++++++++++++++++++++++++++++------------- 3 files changed, 74 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/Handle.cc b/src/Handle.cc index e6c0777..c1542ac 100644 --- a/src/Handle.cc +++ b/src/Handle.cc @@ -47,7 +47,7 @@ ssize_t Balau::Handle::write(const void * buf, size_t count) throw (GeneralExcep } ssize_t Balau::Handle::forceRead(void * _buf, size_t count, Events::BaseEvent * evt) throw (GeneralException) { - ssize_t total; + ssize_t total = 0; uint8_t * buf = (uint8_t *) _buf; if (!canRead()) throw GeneralException("Handle can't read"); @@ -74,7 +74,7 @@ ssize_t Balau::Handle::forceRead(void * _buf, size_t count, Events::BaseEvent * } ssize_t Balau::Handle::forceWrite(const void * _buf, size_t count, Events::BaseEvent * evt) throw (GeneralException) { - ssize_t total; + ssize_t total = 0; const uint8_t * buf = (const uint8_t *) _buf; if (!canWrite()) throw GeneralException("Handle can't write"); diff --git a/src/Selectable.cc b/src/Selectable.cc index 40e85bc..798a448 100644 --- a/src/Selectable.cc +++ b/src/Selectable.cc @@ -3,6 +3,9 @@ #ifndef _MSC_VER #include #endif +#ifdef _WIN32 +#include +#endif #include #include #include @@ -15,7 +18,11 @@ #include "Task.h" #include "TaskMan.h" -#ifndef _WIN32 +#ifdef _WIN32 +inline static SOCKET getSocket(int fd) { return _get_osfhandle(fd); } +#else +inline static int getSocket(int fd) { return fd; } + namespace { class SigpipeBlocker : public Balau::AtStart { @@ -60,7 +67,8 @@ void Balau::Selectable::setFD(int fd) throw (GeneralException) { m_evtW = new SelectableEvent(m_fd, ev::WRITE); #ifdef _WIN32 u_long iMode = 1; - ioctlsocket(m_fd, FIONBIO, &iMode); + int r = ioctlsocket(_get_osfhandle(m_fd), FIONBIO, &iMode); + EAssert(r == NO_ERROR, "ioctlsocket FIONBIO failed with error %i", r); #else fcntl(m_fd, F_SETFL, O_NONBLOCK); #endif @@ -85,7 +93,7 @@ ssize_t Balau::Selectable::read(void * buf, size_t count) throw (GeneralExceptio int spins = 0; do { - ssize_t r = recv(m_fd, (char *) buf, count, 0); + ssize_t r = recv(getSocket(m_fd), (char *) buf, count, 0); if (r >= 0) { if (r == 0) @@ -93,7 +101,19 @@ ssize_t Balau::Selectable::read(void * buf, size_t count) throw (GeneralExceptio return r; } - if ((errno == EAGAIN) || (errno == EINTR) || (errno == EWOULDBLOCK)) { +#ifndef _WIN32 + int err = errno; +#else + int err = WSAGetLastError(); +#ifdef _MSC_VER + if (err == WSAEWOULDBLOCK) +#else + if (err == WSAWOULDBLOCK) +#endif + err = EAGAIN; +#endif + + if ((err == EAGAIN) || (err == EINTR) || (err == EWOULDBLOCK)) { Task::operationYield(m_evtR, Task::INTERRUPTIBLE); } else { m_evtR->stop(); @@ -113,7 +133,7 @@ ssize_t Balau::Selectable::write(const void * buf, size_t count) throw (GeneralE int spins = 0; do { - ssize_t r = send(m_fd, (const char *) buf, count, 0); + ssize_t r = send(getSocket(m_fd), (const char *) buf, count, 0); EAssert(r != 0, "send() returned 0 (broken pipe ?)"); @@ -121,13 +141,22 @@ ssize_t Balau::Selectable::write(const void * buf, size_t count) throw (GeneralE return r; #ifndef _WIN32 - if (errno == EPIPE) { + int err = errno; + if (err == EPIPE) { close(); return 0; } +#else + int err = WSAGetLastError(); +#ifdef _MSC_VER + if (err == WSAEWOULDBLOCK) +#else + if (err == WSAWOULDBLOCK) +#endif + err = EAGAIN; #endif - if ((errno == EAGAIN) || (errno == EINTR) || (errno == EWOULDBLOCK)) { + if ((err == EAGAIN) || (err == EINTR) || (err == EWOULDBLOCK)) { Task::operationYield(m_evtW, Task::INTERRUPTIBLE); } else { m_evtW->stop(); diff --git a/src/Socket.cc b/src/Socket.cc index 62fa8bc..7673c45 100644 --- a/src/Socket.cc +++ b/src/Socket.cc @@ -1,6 +1,8 @@ #ifndef _WIN32 #include #include +#else +#include #endif #include #ifdef _MSC_VER @@ -19,6 +21,12 @@ #include "Task.h" #include "TaskMan.h" +#ifdef _WIN32 +inline static SOCKET getSocket(int fd) { return _get_osfhandle(fd); } +#else +inline static int getSocket(int fd) { return fd; } +#endif + static Balau::String getErrorMessage() { Balau::String msg; #ifdef _WIN32 @@ -198,7 +206,11 @@ static Balau::DNSRequest * resolveName(const char * name, const char * service = } Balau::Socket::Socket() throw (GeneralException) { +#ifdef _WIN32 + int fd = _open_osfhandle(WSASocket(AF_INET6, SOCK_STREAM, 0, 0, 0, 0), 0); +#else int fd = socket(AF_INET6, SOCK_STREAM, 0); +#endif m_name = "Socket(nonconnected)"; RAssert(fd >= 0, "socket() returned %i", fd); @@ -206,7 +218,7 @@ Balau::Socket::Socket() throw (GeneralException) { setFD(fd); int on = 0; - int r = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on, sizeof(on)); + int r = setsockopt(getSocket(fd), IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); EAssert(r == 0, "setsockopt returned %i", r); memset(&m_localAddr, 0, sizeof(m_localAddr)); @@ -244,7 +256,7 @@ void Balau::Socket::close() throw (GeneralException) { if (isClosed()) return; #ifdef _WIN32 - closesocket(getFD()); + _close(getFD()); #else ::close(getFD()); #endif @@ -309,7 +321,7 @@ bool Balau::Socket::setLocal(const char * hostname, int port) { int enable = 1; setsockopt(getFD(), SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); #endif - return bind(getFD(), (struct sockaddr *) &m_localAddr, sizeof(m_localAddr)) == 0; + return bind(getSocket(getFD()), (struct sockaddr *) &m_localAddr, sizeof(m_localAddr)) == 0; } #if defined(_WIN32) && !defined(EISCONN) @@ -375,7 +387,7 @@ bool Balau::Socket::connect(const char * hostname, int port) { int r; int err; if (spins == 0) { - r = ::connect(getFD(), (sockaddr *) &m_remoteAddr, sizeof(m_remoteAddr)); + r = ::connect(getSocket(getFD()), (sockaddr *)&m_remoteAddr, sizeof(m_remoteAddr)); #ifdef _WIN32 err = WSAGetLastError(); #else @@ -383,7 +395,7 @@ bool Balau::Socket::connect(const char * hostname, int port) { #endif } else { socklen_t sLen = sizeof(err); - int g = getsockopt(getFD(), SOL_SOCKET, SO_ERROR, (char *) &err, &sLen); + int g = getsockopt(getSocket(getFD()), SOL_SOCKET, SO_ERROR, (char *) &err, &sLen); EAssert(g == 0, "getsockopt failed; g = %i", g); r = err != 0 ? -1 : 0; } @@ -394,10 +406,10 @@ bool Balau::Socket::connect(const char * hostname, int port) { socklen_t len; len = sizeof(m_localAddr); - getsockname(getFD(), (sockaddr *) &m_localAddr, &len); + getsockname(getSocket(getFD()), (sockaddr *)&m_localAddr, &len); len = sizeof(m_remoteAddr); - getpeername(getFD(), (sockaddr *) &m_remoteAddr, &len); + getpeername(getSocket(getFD()), (sockaddr *)&m_remoteAddr, &len); char prtLocal[INET6_ADDRSTRLEN], prtRemote[INET6_ADDRSTRLEN]; const char * rLocal, * rRemote; @@ -446,13 +458,13 @@ bool Balau::Socket::listen() { AAssert(!m_connected, "You can't call Socket::listen() on a connected socket"); AAssert(!isClosed(), "You can't call Socket::listen() on a closed socket"); - if (::listen(getFD(), 16) == 0) { + if (::listen(getSocket(getFD()), 16) == 0) { m_listening = true; socklen_t len; len = sizeof(m_localAddr); - getsockname(getFD(), (sockaddr *) &m_localAddr, &len); + getsockname(getSocket(getFD()), (sockaddr *)&m_localAddr, &len); char prtLocal[INET6_ADDRSTRLEN]; const char * rLocal; @@ -486,13 +498,24 @@ Balau::IO Balau::Socket::accept() throw (GeneralException) { sockaddr_in6 remoteAddr; socklen_t len = sizeof(sockaddr_in6); Printer::elog(E_SOCKET, "Socket %i (%s) is going to accept()", getFD(), m_name.to_charp()); - int s = ::accept(getFD(), (sockaddr *) &remoteAddr, &len); +#ifdef _WIN32 + SOCKET s; +#else + int s; +#endif + s = ::accept(getSocket(getFD()), (sockaddr *)&remoteAddr, &len); +#ifndef _WIN32 if (s < 0) { int err = errno; -#ifdef _WIN32 - err = WSAGetLastError(); +#else + if (s == INVALID_SOCKET) { + int err = WSAGetLastError(); +#ifdef _MSC_VER if (err == WSAEWOULDBLOCK) +#else + if (err == WSAWOULDBLOCK) +#endif err = EAGAIN; #endif if ((err == EAGAIN) || (err == EINTR) || (err == EWOULDBLOCK)) { @@ -504,7 +527,7 @@ Balau::IO Balau::Socket::accept() throw (GeneralException) { } else { Printer::elog(E_SOCKET, "Listener at %p got a new connection", this); m_evtR->reset(); - return IO(new Socket(s)); + return IO(new Socket(_open_osfhandle(s, 0))); } } } -- cgit v1.2.3