Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions Network/Socket/Buffer.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,9 @@ recvBufMsg s bufsizs clen flags = do
c_recvmsg fd msgHdrPtr _cflags
#else
## if __IO_MANAGER_WINIO__ >= 2
recvBufMsgMIO fd msgHdrPtr <!> recvBufMsgWinIO fd msgHdrPtr
recvBufMsgMIO s fd msgHdrPtr <!> recvBufMsgWinIO fd msgHdrPtr
## else
recvBufMsgMIO fd msgHdrPtr
recvBufMsgMIO s fd msgHdrPtr
## endif
#endif
sockaddr <- peekSocketAddress addrPtr `catchIOError` \_ -> getPeerName s
Expand Down Expand Up @@ -460,17 +460,21 @@ foreign import CALLCONV SAFE_ON_WIN "WSASendMsg"
-- fixme Handle for SOCKET, see #426
c_sendmsg :: CSocket -> Ptr (MsgHdr sa) -> DWORD -> LPDWORD -> Ptr () -> Ptr () -> IO CInt
foreign import CALLCONV SAFE_ON_WIN "WSARecvMsg"
c_recvmsg :: CSocket -> Ptr (MsgHdr sa) -> LPDWORD -> Ptr () -> Ptr () -> IO CInt
c_recvmsg_mio :: CSocket -> Ptr (MsgHdr sa) -> LPDWORD -> Ptr () -> Ptr () -> IO CInt
foreign import CALLCONV unsafe "WSARecv"
c_WSARecv :: CSocket -> Ptr WSABuf -> DWORD -> LPDWORD -> LPDWORD -> Ptr () -> Ptr () -> IO CInt
foreign import CALLCONV unsafe "WSARecvFrom"
c_WSARecvFrom :: CSocket -> Ptr WSABuf -> DWORD -> LPDWORD -> LPDWORD -> Ptr sa -> Ptr CInt -> Ptr () -> Ptr () -> IO CInt
## if __IO_MANAGER_WINIO__ >= 2
foreign import CALLCONV unsafe "WSARecvMsg"
c_recvmsg_winio :: CSocket -> Ptr (MsgHdr sa) -> LPDWORD -> Ptr () -> Ptr () -> IO CInt
## endif

-- Helper functions for recvBufMsg on Windows
recvBufMsgMIO :: CSocket -> Ptr (MsgHdr sa) -> IO Int
recvBufMsgMIO fd msgHdrPtr = alloca $ \len_ptr -> do
_ <- throwSocketErrorIfMinus1Retry "Network.Socket.Buffer.recvmsg" $
c_recvmsg fd msgHdrPtr len_ptr nullPtr nullPtr
recvBufMsgMIO :: Socket -> CSocket -> Ptr (MsgHdr sa) -> IO Int
recvBufMsgMIO s fd msgHdrPtr = alloca $ \len_ptr -> do
_ <- throwSocketErrorWaitReadBut (== #{const WSAEMSGSIZE}) s "Network.Socket.Buffer.recvmsg" $
c_recvmsg_mio fd msgHdrPtr len_ptr nullPtr nullPtr
fromIntegral <$> peek len_ptr

## if __IO_MANAGER_WINIO__ >= 2
Expand All @@ -483,7 +487,7 @@ recvBufMsgWinIO fd msgHdrPtr = do
where
startCB :: Mgr.LPOVERLAPPED -> IO (Mgr.CbResult Int)
startCB lpOverlapped = do
ret <- c_recvmsg fd msgHdrPtr nullPtr (castPtr lpOverlapped) nullPtr
ret <- c_recvmsg_winio fd msgHdrPtr nullPtr (castPtr lpOverlapped) nullPtr
-- Check WSAGetLastError immediately: if the operation didn't
-- complete synchronously (ret /= 0), we must distinguish
-- ERROR_IO_PENDING (async completion forthcoming) from real
Expand Down
45 changes: 45 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ AC_ARG_WITH([cc],
[CC=$withval])
AC_PROG_CC()

AC_ARG_WITH([compiler],
[Haskell compiler],
[HC=$withval])
AC_ARG_WITH([hc],
[Haskell compiler],
[HC=$withval])
AS_IF([test -z "$HC"],
[HC=ghc])

AC_C_CONST

AC_CHECK_HEADERS([limits.h stdlib.h unistd.h sys/types.h fcntl.h])
Expand All @@ -96,4 +105,40 @@ dnl This is a necessary hack
AC_MSG_NOTICE([creating ./network.buildinfo])
echo "install-includes: HsNetworkConfig.h" > network.buildinfo

WINIO_GHC_OPTIONS=
AC_MSG_CHECKING([whether to use native Windows I/O manager RTS option])
case "$host_os" in
mingw*)
cat > conftest_ghc_cpp.hs <<EOF
#if !defined(__IO_MANAGER_WINIO__) || __IO_MANAGER_WINIO__ < 2
#error __IO_MANAGER_WINIO__ < 2
#endif
module Main where
main :: IO ()
main = return ()
EOF
if "$HC" -c -cpp -fforce-recomp conftest_ghc_cpp.hs >/dev/null 2>&1; then
AC_MSG_RESULT([yes])
WINIO_GHC_OPTIONS="-with-rtsopts=--io-manager=native"
else
AC_MSG_RESULT([no, $HC does not define __IO_MANAGER_WINIO__ >= 2])
fi
rm -f conftest_ghc_cpp.hi conftest_ghc_cpp.hs conftest_ghc_cpp.o
;;
*)
AC_MSG_RESULT([no, not Windows])
;;
esac

dnl This is an overlay for the existing test-suite in network.cabal. Cabal
dnl conditionals cannot read values produced by configure, so the probe result
dnl has to be expressed as generated build info.
AS_IF([test -n "$WINIO_GHC_OPTIONS"],
[cat >> network.buildinfo <<EOF

test-suite spec
ghc-options: $WINIO_GHC_OPTIONS
EOF
])

AC_OUTPUT
9 changes: 8 additions & 1 deletion include/HsNetDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@
# define CALLCONV ccall
#endif

#define SAFE_ON_WIN unsafe
/* MIO requires safe, for WINIO we need to duplicate the
imports and provide unsafe ones. Sadly we can't do this
dynamically. */
#if defined(mingw32_HOST_OS)
# define SAFE_ON_WIN safe
#else
# define SAFE_ON_WIN unsafe
#endif

#endif /* HSNETDEF_H */
3 changes: 0 additions & 3 deletions network.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,6 @@ test-suite spec
hspec >=2.6,
QuickCheck

if os(windows) && impl(ghc >=9.0)
ghc-options: -with-rtsopts=--io-manager=native

if flag(devel)
cpp-options: -DDEVELOPMENT

Expand Down
Loading