@@ -4,7 +4,7 @@
4||| Modified (C) The Idris Community, 2015, 2016
4||| Modified (C) The Idris Community, 2015, 2016
5module Network.Socket
5module Network.Socket
7−import public Network.Socket.Types
7+import public Network.Socket.Data
8import Network.Socket.Raw
8import Network.Socket.Raw
10%include C "idris_net.h"
10%include C "idris_net.h"
@@ -12,11 +12,12 @@ import Network.Socket.Raw
12%include C "sys/socket.h"
12%include C "sys/socket.h"
13%include C "netdb.h"
13%include C "netdb.h"
15-- ----------------------------------------------------- [ Network Socket API. ]
17-- ----------------------------------------------------- [ Network Socket API. ]
17||| Creates a UNIX socket with the given family, socket type and protocol
19||| Creates a UNIX socket with the given family, socket type and protocol
18||| number. Returns either a socket or an error.
20||| number. Returns either a socket or an error.
20socket : (fam : SocketFamily)
21socket : (fam : SocketFamily)
21 -> (ty : SocketType)
22 -> (ty : SocketType)
22 -> (pnum : ProtocolNumber)
23 -> (pnum : ProtocolNumber)
@@ -31,34 +32,30 @@ socket sf st pn = do
31 else pure $ Right (MkSocket socket_res sf st pn)
32 else pure $ Right (MkSocket socket_res sf st pn)
33||| Close a socket
34||| Close a socket
35close : Socket -> IO ()
35close : Socket -> IO ()
36close sock = foreign FFI_C "close" (Int -> IO ()) (descriptor sock)
36close sock = foreign FFI_C "close" (Int -> IO ()) (descriptor sock)
39−saString : (Maybe SocketAddress) -> String
40−saString (Just sa) = show sa
43||| Binds a socket to the given socket address and port.
38||| Binds a socket to the given socket address and port.
44||| Returns 0 on success, an error code otherwise.
39||| Returns 0 on success, an error code otherwise.
46bind : (sock : Socket)
40bind : (sock : Socket)
47 -> (addr : Maybe SocketAddress)
41 -> (addr : Maybe SocketAddress)
48 -> (port : Port)
42 -> (port : Port)
50bind sock addr port = do
44bind sock addr port = do
51− bind_res <- foreign FFI_C "idrnet_bind"
45+ bind_res <- foreign FFI_C "idrnet_bind"
52− (Int -> Int -> Int -> String -> Int -> IO Int)
46+ (Int -> Int -> Int -> String -> Int -> IO Int)
53− (descriptor sock) (toCode $ family sock)
47+ (descriptor sock) (toCode $ family sock)
54− (toCode $ socketType sock) (saString addr) port
48+ (toCode $ socketType sock) (saString addr) port
55− if bind_res == (-1)
49+ if bind_res == (-1)
56− then getErrno
50+ then getErrno
57− else pure 0
51+ else pure 0
53+ saString : Maybe SocketAddress -> String
54+ saString (Just sa) = show sa
55+ saString Nothing = ""
59||| Connects to a given address and port.
57||| Connects to a given address and port.
60||| Returns 0 on success, and an error number on error.
58||| Returns 0 on success, and an error number on error.
62connect : (sock : Socket)
59connect : (sock : Socket)
63 -> (addr : SocketAddress)
60 -> (addr : SocketAddress)
64 -> (port : Port)
61 -> (port : Port)
@@ -75,7 +72,6 @@ connect sock addr port = do
75||| Listens on a bound socket.
72||| Listens on a bound socket.
77||| @sock The socket to listen on.
74||| @sock The socket to listen on.
79listen : (sock : Socket) -> IO Int
75listen : (sock : Socket) -> IO Int
80listen sock = do
76listen sock = do
81 listen_res <- foreign FFI_C "listen" (Int -> Int -> IO Int)
77 listen_res <- foreign FFI_C "listen" (Int -> Int -> IO Int)
@@ -84,40 +80,6 @@ listen sock = do
84 then getErrno
80 then getErrno
85 else pure 0
81 else pure 0
87−||| Parses a textual representation of an IPv4 address into a SocketAddress
88−parseIPv4 : String -> SocketAddress
91− (i1 :: i2 :: i3 :: i4 :: _) => IPv4Addr i1 i2 i3 i4
92− otherwise => InvalidAddress
94− toInt' : String -> Integer
97− toInt : String -> Int
98− toInt s = fromInteger $ toInt' s
101− splitted = map toInt (Prelude.Strings.split (\c => c == '.') str)
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"
110− -- ASSUMPTION: Foreign call returns a valid int
111− assert_total (case getSocketFamily addr_family_int of
113− ipv4_addr <- foreign FFI_C "idrnet_sockaddr_ipv4"
117− pure $ parseIPv4 ipv4_addr
118− Just AF_INET6 => pure IPv6Addr
119− Just AF_UNSPEC => pure InvalidAddress)
121||| Accept a connection on the provided socket.
83||| Accept a connection on the provided socket.
123||| Returns on failure a `SocketError`
85||| Returns on failure a `SocketError`
@@ -126,7 +88,6 @@ getSockAddr (SAPtr ptr) = do
126||| + `SocketAddress` :: The
88||| + `SocketAddress` :: The
128||| @sock The socket used to establish connection.
90||| @sock The socket used to establish connection.
130accept : (sock : Socket)
91accept : (sock : Socket)
131 -> IO (Either SocketError (Socket, SocketAddress))
92 -> IO (Either SocketError (Socket, SocketAddress))
132accept sock = do
93accept sock = do
@@ -155,7 +116,6 @@ accept sock = do
156||| @sock The socket on which to send the message.
117||| @sock The socket on which to send the message.
157||| @msg The data to send.
118||| @msg The data to send.
159send : (sock : Socket)
119send : (sock : Socket)
160 -> (msg : String)
120 -> (msg : String)
161 -> IO (Either SocketError ResultCode)
121 -> IO (Either SocketError ResultCode)
@@ -168,20 +128,6 @@ send sock dat = do
168 then map Left getErrno
128 then map Left getErrno
169 else pure $ Right send_res
129 else pure $ Right send_res
171−freeRecvStruct : RecvStructPtr -> IO ()
172−freeRecvStruct (RSPtr p) =
173− foreign FFI_C "idrnet_free_recv_struct"
177−||| Utility to extract data.
178−freeRecvfromStruct : RecvfromStructPtr -> IO ()
179−freeRecvfromStruct (RFPtr p) =
180− foreign FFI_C "idrnet_free_recvfrom_struct"
185||| Receive data on the specified socket.
131||| Receive data on the specified socket.
187||| Returns on failure a `SocketError`
133||| Returns on failure a `SocketError`
@@ -191,7 +137,6 @@ freeRecvfromStruct (RFPtr p) =
192||| @sock The socket on which to receive the message.
138||| @sock The socket on which to receive the message.
193||| @len How much of the data to send.
139||| @len How much of the data to send.
195recv : (sock : Socket)
140recv : (sock : Socket)
196 -> (len : ByteLength)
141 -> (len : ByteLength)
197 -> IO (Either SocketError (String, ResultCode))
142 -> IO (Either SocketError (String, ResultCode))
@@ -222,48 +167,6 @@ recv sock len = do
222 freeRecvStruct (RSPtr recv_struct_ptr)
167 freeRecvStruct (RSPtr recv_struct_ptr)
223 pure $ Right (payload, recv_res)
168 pure $ Right (payload, recv_res)
225−||| Sends the data in a given memory location
227−||| Returns on failure a `SocketError`
228−||| Returns on success the `ResultCode`
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)
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
243− then map Left getErrno
244− else pure $ Right send_res
246−||| Receive data from a given memory location.
248−||| Returns on failure a `SocketError`
249−||| Returns on success the `ResultCode`
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)
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
263− if (recv_res == (-1))
264− then map Left getErrno
265− else pure $ Right recv_res
267||| Send a message.
170||| Send a message.
269||| Returns on failure a `SocketError`
172||| Returns on failure a `SocketError`
@@ -273,7 +176,6 @@ recvBuf sock (BPtr ptr) len = do
273||| @addr Address of the recipient.
176||| @addr Address of the recipient.
274||| @port The port on which to send the message.
177||| @port The port on which to send the message.
275||| @msg The message to send.
178||| @msg The message to send.
277sendTo : (sock : Socket)
179sendTo : (sock : Socket)
278 -> (addr : SocketAddress)
180 -> (addr : SocketAddress)
279 -> (port : Port)
181 -> (port : Port)
@@ -288,58 +190,6 @@ sendTo sock addr p dat = do
288 then map Left getErrno
190 then map Left getErrno
289 else pure $ Right sendto_res
191 else pure $ Right sendto_res
291−||| Send a message stored in some buffer.
293−||| Returns on failure a `SocketError`
294−||| Returns on success the `ResultCode`
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)
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)
312− if sendto_res == (-1)
313− then map Left getErrno
314− else pure $ Right sendto_res
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"
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"
329− getSockAddr sockaddr_ptr
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"
337− port <- foreign FFI_C "idrnet_sockaddr_ipv4_port"
343||| Receive a message.
193||| Receive a message.
345||| Returns on failure a `SocketError`.
195||| Returns on failure a `SocketError`.
@@ -351,7 +201,6 @@ foreignGetRecvfromPort (RFPtr p) = do
351||| @sock The channel on which to receive.
201||| @sock The channel on which to receive.
352||| @len Size of the expected message.
202||| @len Size of the expected message.
355recvFrom : (sock : Socket)
204recvFrom : (sock : Socket)
356 -> (len : ByteLength)
205 -> (len : ByteLength)
357 -> IO (Either SocketError (UDPAddrInfo, String, ResultCode))
206 -> IO (Either SocketError (UDPAddrInfo, String, ResultCode))
@@ -379,42 +228,3 @@ recvFrom sock bl = do
379 freeRecvfromStruct recv_ptr'
228 freeRecvfromStruct recv_ptr'
380 pure $ Right (MkUDPAddrInfo addr port, payload, result)
229 pure $ Right (MkUDPAddrInfo addr port, payload, result)
382−||| Receive a message placed on a 'known' buffer.
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.
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.
393−recvFromBuf : (sock : Socket)
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
402− let recv_ptr' = RFPtr recv_ptr
404− if !(nullPtr recv_ptr)
405− then map Left getErrno
407− result <- foreign FFI_C "idrnet_get_recvfrom_res"
412− freeRecvfromStruct recv_ptr'
415− port <- foreignGetRecvfromPort recv_ptr'
416− addr <- foreignGetRecvfromAddr recv_ptr'
417− freeRecvfromStruct recv_ptr'
418− pure $ Right (MkUDPAddrInfo addr port, result + 1)
420−-- --------------------------------------------------------------------- [ EOF ]