Skip to content

Commit f1f6356

Browse files
committed
Merge PR haskell#424
2 parents f853afe + 27d9815 commit f1f6356

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

Network/Socket.hs

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ module Network.Socket
141141
, withFdSocket
142142
, unsafeFdSocket
143143
, touchSocket
144+
, socketToFd
144145
, fdSocket
145146
, mkSocket
146147
, socketToHandle

Network/Socket/Types.hsc

+28
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Network.Socket.Types (
1414
, withFdSocket
1515
, unsafeFdSocket
1616
, touchSocket
17+
, socketToFd
1718
, fdSocket
1819
, mkSocket
1920
, invalidateSocket
@@ -166,6 +167,33 @@ withFdSocket (Socket ref _) f = do
166167
touch ref
167168
return r
168169

170+
-- | Socket is closed and a duplicated file descriptor is returned.
171+
-- The duplicated descriptor is no longer subject to the possibility
172+
-- of unexpectedly being closed if the socket is finalized. It is
173+
-- now the caller's responsibility to ultimately close the
174+
-- duplicated file descriptor.
175+
socketToFd :: Socket -> IO CInt
176+
socketToFd s = do
177+
#if defined(mingw32_HOST_OS)
178+
fd <- unsafeFdSocket s
179+
fd2 <- c_wsaDuplicate fd
180+
-- FIXME: throw error no if -1
181+
close s
182+
return fd2
183+
184+
foreign import ccall unsafe "wsaDuplicate"
185+
c_wsaDuplicate :: CInt -> IO CInt
186+
#else
187+
fd <- unsafeFdSocket s
188+
-- FIXME: throw error no if -1
189+
fd2 <- c_dup fd
190+
close s
191+
return fd2
192+
193+
foreign import ccall unsafe "dup"
194+
c_dup :: CInt -> IO CInt
195+
#endif
196+
169197
-- | Creating a socket from a file descriptor.
170198
mkSocket :: CInt -> IO Socket
171199
mkSocket fd = do

cbits/initWinSock.c

+15
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,19 @@ initWinSock ()
4040
return 0;
4141
}
4242

43+
SOCKET
44+
wsaDuplicate (SOCKET s)
45+
{
46+
WSAPROTOCOL_INFOW protocolInfo;
47+
if (WSADuplicateSocketW (s, GetCurrentProcessId (), &protocolInfo) != 0)
48+
return -1;
49+
50+
SOCKET res = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
51+
FROM_PROTOCOL_INFO, &protocolInfo, 0, 0);
52+
if (res == SOCKET_ERROR)
53+
return -1;
54+
55+
return res;
56+
}
57+
4358
#endif

tests/Network/SocketSpec.hs

+10
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,13 @@ spec = do
209209
threadDelay 10000
210210
void $ recv sock 1024
211211
tcpTest client server
212+
213+
describe "socketToFd" $ do
214+
it "socketToFd can send using fd" $ do
215+
let server sock = do
216+
void $ recv sock 1024
217+
client sock = do
218+
fd <- socketToFd sock
219+
s <- mkSocket fd
220+
sendAll s "HELLO WORLD"
221+
tcpTest client server

0 commit comments

Comments
 (0)