@@ -6,6 +6,11 @@ module Winsock (
6
6
socket ,
7
7
connect ,
8
8
close ,
9
+ recvBuf ,
10
+ sendBuf ,
11
+
12
+ recv ,
13
+ send ,
9
14
) where
10
15
11
16
#include <windows.h>
@@ -26,6 +31,9 @@ import qualified IOCP.Manager as Manager
26
31
27
32
import Control.Applicative ((<$>) )
28
33
import Control.Monad (void )
34
+ import Data.ByteString (ByteString )
35
+ import Data.ByteString.Internal (createAndTrim )
36
+ import Data.ByteString.Unsafe (unsafeUseAsCStringLen )
29
37
import Data.IORef
30
38
import Data.Word
31
39
import Foreign.C
@@ -40,6 +48,8 @@ import qualified System.Win32.Types as Win32
40
48
newtype Socket = Socket IOCPHandle
41
49
deriving Eq
42
50
51
+ -- Note: Functions that take a 'Socket' expect WinSock to already be initialized.
52
+
43
53
socket :: NS. Family -> NS. SocketType -> NS. ProtocolNumber -> IO Socket
44
54
socket family stype protocol = do
45
55
initWinsock
@@ -69,6 +79,40 @@ close (Socket ih) =
69
79
Manager. closeWith ih $
70
80
Win32. failIf_ (/= 0 ) " close" . c_closesocket . castHANDLEToSOCKET
71
81
82
+ recvBuf :: Socket -> Ptr a -> Int -> IO Int
83
+ recvBuf (Socket ih) buf len =
84
+ withIOCP ih 0 startCB completionCB
85
+ where
86
+ startCB h ol =
87
+ Win32. failIfFalse_ " recv" $
88
+ c_winsock_recv (castHANDLEToSOCKET h) (castPtr buf) (fromIntegral len) ol
89
+
90
+ completionCB err numBytes
91
+ | err == 0 = return (fromIntegral numBytes)
92
+ | otherwise = FFI. throwWinErr " recv" err
93
+
94
+ sendBuf :: Socket -> Ptr a -> Int -> IO Int
95
+ sendBuf (Socket ih) buf len =
96
+ withIOCP ih 0 startCB completionCB
97
+ where
98
+ startCB h ol =
99
+ Win32. failIfFalse_ " send" $
100
+ c_winsock_send (castHANDLEToSOCKET h) (castPtr buf) (fromIntegral len) ol
101
+
102
+ completionCB err numBytes
103
+ | err == 0 = return (fromIntegral numBytes)
104
+ | otherwise = FFI. throwWinErr " send" err
105
+
106
+ recv :: Socket -> Int -> IO ByteString
107
+ recv sock len =
108
+ createAndTrim len $ \ buf ->
109
+ recvBuf sock buf len
110
+
111
+ send :: Socket -> ByteString -> IO Int
112
+ send sock bs =
113
+ unsafeUseAsCStringLen bs $ \ (buf, len) ->
114
+ sendBuf sock buf len
115
+
72
116
newtype Winsock = Winsock (Ptr () )
73
117
74
118
getWinsock :: IO Winsock
@@ -97,3 +141,9 @@ foreign import ccall unsafe
97
141
98
142
foreign import WINDOWS_CCONV safe " winsock2.h closesocket"
99
143
c_closesocket :: SOCKET -> IO CInt
144
+
145
+ foreign import ccall unsafe
146
+ c_winsock_recv :: SOCKET -> Ptr CChar -> # {type u_long } -> LPOVERLAPPED -> IO BOOL
147
+
148
+ foreign import ccall unsafe
149
+ c_winsock_send :: SOCKET -> Ptr CChar -> # {type u_long } -> LPOVERLAPPED -> IO BOOL
0 commit comments