@@ -4,7 +4,7 @@
44||| Modified (C) The Idris Community, 2015, 2016
55module Network.Socket
66
7−import public Network.Socket.Types
7+import public Network.Socket.Data
88import Network.Socket.Raw
99
1010%include C "idris_net.h"
@@ -12,11 +12,12 @@ import Network.Socket.Raw
1212%include C "sys/socket.h"
1313%include C "netdb.h"
1414
15+%access export
16+
1517-- ----------------------------------------------------- [ Network Socket API. ]
1618
1719||| Creates a UNIX socket with the given family, socket type and protocol
1820||| number. Returns either a socket or an error.
19−export
2021socket : (fam : SocketFamily)
2122 -> (ty : SocketType)
2223 -> (pnum : ProtocolNumber)
@@ -31,34 +32,30 @@ socket sf st pn = do
3132 else pure $ Right (MkSocket socket_res sf st pn)
3233
3334||| Close a socket
34−export
3535close : Socket -> IO ()
3636close sock = foreign FFI_C "close" (Int -> IO ()) (descriptor sock)
3737
38−private
39−saString : (Maybe SocketAddress) -> String
40−saString (Just sa) = show sa
41−saString Nothing = ""
42−
4338||| Binds a socket to the given socket address and port.
4439||| Returns 0 on success, an error code otherwise.
45−export
4640bind : (sock : Socket)
4741 -> (addr : Maybe SocketAddress)
4842 -> (port : Port)
4943 -> IO Int
5044bind sock addr port = do
51− bind_res <- foreign FFI_C "idrnet_bind"
52− (Int -> Int -> Int -> String -> Int -> IO Int)
53− (descriptor sock) (toCode $ family sock)
54− (toCode $ socketType sock) (saString addr) port
55− if bind_res == (-1)
56− then getErrno
57− else pure 0
45+ bind_res <- foreign FFI_C "idrnet_bind"
46+ (Int -> Int -> Int -> String -> Int -> IO Int)
47+ (descriptor sock) (toCode $ family sock)
48+ (toCode $ socketType sock) (saString addr) port
49+ if bind_res == (-1)
50+ then getErrno
51+ else pure 0
52+ where
53+ saString : Maybe SocketAddress -> String
54+ saString (Just sa) = show sa
55+ saString Nothing = ""
5856
5957||| Connects to a given address and port.
6058||| Returns 0 on success, and an error number on error.
61−export
6259connect : (sock : Socket)
6360 -> (addr : SocketAddress)
6461 -> (port : Port)
@@ -75,7 +72,6 @@ connect sock addr port = do
7572||| Listens on a bound socket.
7673|||
7774||| @sock The socket to listen on.
78−export
7975listen : (sock : Socket) -> IO Int
8076listen sock = do
8177 listen_res <- foreign FFI_C "listen" (Int -> Int -> IO Int)
@@ -84,40 +80,6 @@ listen sock = do
8480 then getErrno
8581 else pure 0
8682
87−||| Parses a textual representation of an IPv4 address into a SocketAddress
88−parseIPv4 : String -> SocketAddress
89−parseIPv4 str =
90− case splitted of
91− (i1 :: i2 :: i3 :: i4 :: _) => IPv4Addr i1 i2 i3 i4
92− otherwise => InvalidAddress
93− where
94− toInt' : String -> Integer
95− toInt' = cast
96−
97− toInt : String -> Int
98− toInt s = fromInteger $ toInt' s
99−
100− splitted : List Int
101− splitted = map toInt (Prelude.Strings.split (\c => c == '.') str)
102−
103−||| Retrieves a socket address from a sockaddr pointer
104−getSockAddr : SockaddrPtr -> IO SocketAddress
105−getSockAddr (SAPtr ptr) = do
106− addr_family_int <- foreign FFI_C "idrnet_sockaddr_family"
107− (Ptr -> IO Int)
108− ptr
109−
110− -- ASSUMPTION: Foreign call returns a valid int
111− assert_total (case getSocketFamily addr_family_int of
112− Just AF_INET => do
113− ipv4_addr <- foreign FFI_C "idrnet_sockaddr_ipv4"
114− (Ptr -> IO String)
115− ptr
116−
117− pure $ parseIPv4 ipv4_addr
118− Just AF_INET6 => pure IPv6Addr
119− Just AF_UNSPEC => pure InvalidAddress)
120−
12183||| Accept a connection on the provided socket.
12284|||
12385||| Returns on failure a `SocketError`
@@ -126,7 +88,6 @@ getSockAddr (SAPtr ptr) = do
12688||| + `SocketAddress` :: The
12789|||
12890||| @sock The socket used to establish connection.
129−export
13091accept : (sock : Socket)
13192 -> IO (Either SocketError (Socket, SocketAddress))
13293accept sock = do
@@ -155,7 +116,6 @@ accept sock = do
155116|||
156117||| @sock The socket on which to send the message.
157118||| @msg The data to send.
158−export
159119send : (sock : Socket)
160120 -> (msg : String)
161121 -> IO (Either SocketError ResultCode)
@@ -168,20 +128,6 @@ send sock dat = do
168128 then map Left getErrno
169129 else pure $ Right send_res
170130
171−freeRecvStruct : RecvStructPtr -> IO ()
172−freeRecvStruct (RSPtr p) =
173− foreign FFI_C "idrnet_free_recv_struct"
174− (Ptr -> IO ())
175− p
176−
177−||| Utility to extract data.
178−freeRecvfromStruct : RecvfromStructPtr -> IO ()
179−freeRecvfromStruct (RFPtr p) =
180− foreign FFI_C "idrnet_free_recvfrom_struct"
181− (Ptr -> IO ())
182− p
183−
184−
185131||| Receive data on the specified socket.
186132|||
187133||| Returns on failure a `SocketError`
@@ -191,7 +137,6 @@ freeRecvfromStruct (RFPtr p) =
191137|||
192138||| @sock The socket on which to receive the message.
193139||| @len How much of the data to send.
194−export
195140recv : (sock : Socket)
196141 -> (len : ByteLength)
197142 -> IO (Either SocketError (String, ResultCode))
@@ -222,48 +167,6 @@ recv sock len = do
222167 freeRecvStruct (RSPtr recv_struct_ptr)
223168 pure $ Right (payload, recv_res)
224169
225−||| Sends the data in a given memory location
226−|||
227−||| Returns on failure a `SocketError`
228−||| Returns on success the `ResultCode`
229−|||
230−||| @sock The socket on which to send the message.
231−||| @ptr The location containing the data to send.
232−||| @len How much of the data to send.
233−sendBuf : (sock : Socket)
234− -> (ptr : BufPtr)
235− -> (len : ByteLength)
236− -> IO (Either SocketError ResultCode)
237−sendBuf sock (BPtr ptr) len = do
238− send_res <- foreign FFI_C "idrnet_send_buf"
239− (Int -> Ptr -> Int -> IO Int)
240− (descriptor sock) ptr len
241−
242− if send_res == (-1)
243− then map Left getErrno
244− else pure $ Right send_res
245−
246−||| Receive data from a given memory location.
247−|||
248−||| Returns on failure a `SocketError`
249−||| Returns on success the `ResultCode`
250−|||
251−||| @sock The socket on which to receive the message.
252−||| @ptr The location containing the data to receive.
253−||| @len How much of the data to receive.
254−recvBuf : (sock : Socket)
255− -> (ptr : BufPtr)
256− -> (len : ByteLength)
257− -> IO (Either SocketError ResultCode)
258−recvBuf sock (BPtr ptr) len = do
259− recv_res <- foreign FFI_C "idrnet_recv_buf"
260− (Int -> Ptr -> Int -> IO Int)
261− (descriptor sock) ptr len
262−
263− if (recv_res == (-1))
264− then map Left getErrno
265− else pure $ Right recv_res
266−
267170||| Send a message.
268171|||
269172||| Returns on failure a `SocketError`
@@ -273,7 +176,6 @@ recvBuf sock (BPtr ptr) len = do
273176||| @addr Address of the recipient.
274177||| @port The port on which to send the message.
275178||| @msg The message to send.
276−export
277179sendTo : (sock : Socket)
278180 -> (addr : SocketAddress)
279181 -> (port : Port)
@@ -288,58 +190,6 @@ sendTo sock addr p dat = do
288190 then map Left getErrno
289191 else pure $ Right sendto_res
290192
291−||| Send a message stored in some buffer.
292−|||
293−||| Returns on failure a `SocketError`
294−||| Returns on success the `ResultCode`
295−|||
296−||| @sock The socket on which to send the message.
297−||| @addr Address of the recipient.
298−||| @port The port on which to send the message.
299−||| @ptr A Pointer to the buffer containing the message.
300−||| @len The size of the message.
301−sendToBuf : (sock : Socket)
302− -> (addr : SocketAddress)
303− -> (port : Port)
304− -> (ptr : BufPtr)
305− -> (len : ByteLength)
306− -> IO (Either SocketError ResultCode)
307−sendToBuf sock addr p (BPtr dat) len = do
308− sendto_res <- foreign FFI_C "idrnet_sendto_buf"
309− (Int -> Ptr -> Int -> String -> Int -> Int -> IO Int)
310− (descriptor sock) dat len (show addr) p (toCode $ family sock)
311−
312− if sendto_res == (-1)
313− then map Left getErrno
314− else pure $ Right sendto_res
315−
316−||| Utility function to get the payload of the sent message as a `String`.
317−foreignGetRecvfromPayload : RecvfromStructPtr -> IO String
318−foreignGetRecvfromPayload (RFPtr p) =
319− foreign FFI_C "idrnet_get_recvfrom_payload"
320− (Ptr -> IO String)
321− p
322−
323−||| Utility function to return senders socket address.
324−foreignGetRecvfromAddr : RecvfromStructPtr -> IO SocketAddress
325−foreignGetRecvfromAddr (RFPtr p) = do
326− sockaddr_ptr <- map SAPtr $ foreign FFI_C "idrnet_get_recvfrom_sockaddr"
327− (Ptr -> IO Ptr)
328− p
329− getSockAddr sockaddr_ptr
330−
331−||| Utility function to return sender's IPV4 port.
332−foreignGetRecvfromPort : RecvfromStructPtr -> IO Port
333−foreignGetRecvfromPort (RFPtr p) = do
334− sockaddr_ptr <- foreign FFI_C "idrnet_get_recvfrom_sockaddr"
335− (Ptr -> IO Ptr)
336− p
337− port <- foreign FFI_C "idrnet_sockaddr_ipv4_port"
338− (Ptr -> IO Int)
339− sockaddr_ptr
340− pure port
341−
342−
343193||| Receive a message.
344194|||
345195||| Returns on failure a `SocketError`.
@@ -351,7 +201,6 @@ foreignGetRecvfromPort (RFPtr p) = do
351201||| @sock The channel on which to receive.
352202||| @len Size of the expected message.
353203|||
354−export
355204recvFrom : (sock : Socket)
356205 -> (len : ByteLength)
357206 -> IO (Either SocketError (UDPAddrInfo, String, ResultCode))
@@ -379,42 +228,3 @@ recvFrom sock bl = do
379228 freeRecvfromStruct recv_ptr'
380229 pure $ Right (MkUDPAddrInfo addr port, payload, result)
381230
382−||| Receive a message placed on a 'known' buffer.
383−|||
384−||| Returns on failure a `SocketError`.
385−||| Returns on success a pair of
386−||| + `UDPAddrInfo` :: The address of the sender.
387−||| + `Int` :: Result value from underlying function.
388−|||
389−||| @sock The channel on which to receive.
390−||| @ptr Pointer to the buffer to place the message.
391−||| @len Size of the expected message.
392−|||
393−recvFromBuf : (sock : Socket)
394− -> (ptr : BufPtr)
395− -> (len : ByteLength)
396− -> IO (Either SocketError (UDPAddrInfo, ResultCode))
397−recvFromBuf sock (BPtr ptr) bl = do
398− recv_ptr <- foreign FFI_C "idrnet_recvfrom_buf"
399− (Int -> Ptr -> Int -> IO Ptr)
400− (descriptor sock) ptr bl
401−
402− let recv_ptr' = RFPtr recv_ptr
403−
404− if !(nullPtr recv_ptr)
405− then map Left getErrno
406− else do
407− result <- foreign FFI_C "idrnet_get_recvfrom_res"
408− (Ptr -> IO Int)
409− recv_ptr
410− if result == -1
411− then do
412− freeRecvfromStruct recv_ptr'
413− map Left getErrno
414− else do
415− port <- foreignGetRecvfromPort recv_ptr'
416− addr <- foreignGetRecvfromAddr recv_ptr'
417− freeRecvfromStruct recv_ptr'
418− pure $ Right (MkUDPAddrInfo addr port, result + 1)
419−
420−-- --------------------------------------------------------------------- [ EOF ]