@@ -4,8 +4,8 @@
4module IdrisNet.Socket
4module IdrisNet.Socket
6%include C "idris_net.h"
6%include C "idris_net.h"
7−%include C "sys/types.h"
7+%include C "sys/types.h"
8−%include C "sys/socket.h"
8+%include C "sys/socket.h"
9%include C "netdb.h"
9%include C "netdb.h"
11%access public
11%access public
@@ -16,12 +16,17 @@ ByteLength = Int
16class ToCode a where
16class ToCode a where
17 toCode : a -> Int
17 toCode : a -> Int
19−-- Socket Families.
19+||| Socket Families
20−-- The ones that people might actually use. We're not going to need US Government
21+||| The ones that people might actually use. We're not going to need US
21−-- proprietary ones...
22+||| Government proprietary ones.
22−data SocketFamily = AF_UNSPEC -- Unspecified
23+data SocketFamily =
26+ ||| IP / UDP etc. IPv4
23− | AF_INET -- IP / UDP etc. IPv4
27+ AF_INET |
28+ ||| IP / UDP etc. IPv6
24− | AF_INET6 -- IP / UDP etc. IPv6
29+ AF_INET6
26instance Show SocketFamily where
31instance Show SocketFamily where
27 show AF_UNSPEC = "AF_UNSPEC"
32 show AF_UNSPEC = "AF_UNSPEC"
@@ -36,11 +41,16 @@ instance ToCode SocketFamily where
36getSocketFamily : Int -> Maybe SocketFamily
41getSocketFamily : Int -> Maybe SocketFamily
37getSocketFamily i = Prelude.List.lookup i [(0, AF_UNSPEC), (2, AF_INET), (10, AF_INET6)]
42getSocketFamily i = Prelude.List.lookup i [(0, AF_UNSPEC), (2, AF_INET), (10, AF_INET6)]
39−-- Socket Types.
44+||| Socket Types.
40−data SocketType = NotASocket -- Not a socket, used in certain operations
46+ ||| Not a socket, used in certain operations
41− | Stream -- TCP
48+ ||| TCP
42− | Datagram -- UDP
50+ ||| UDP
43− | RawSocket -- Raw sockets. A guy can dream.
52+ ||| Raw sockets
45instance Show SocketType where
55instance Show SocketType where
46 show NotASocket = "Not a socket"
56 show NotASocket = "Not a socket"
@@ -60,15 +70,17 @@ data RecvfromStructPtr = RFPtr Ptr
60data BufPtr = BPtr Ptr
70data BufPtr = BPtr Ptr
61data SockaddrPtr = SAPtr Ptr
71data SockaddrPtr = SAPtr Ptr
63−-- Protocol Number. Generally good enough to just set it to 0.
75+||| Generally good enough to just set it to 0.
64ProtocolNumber : Type
76ProtocolNumber : Type
65ProtocolNumber = Int
77ProtocolNumber = Int
67−-- SocketError: Error thrown by a socket operation
79+||| SocketError: Error thrown by a socket operation
68SocketError : Type
80SocketError : Type
69SocketError = Int
81SocketError = Int
71−-- SocketDescriptor: Native C Socket Descriptor
83+||| SocketDescriptor: Native C Socket Descriptor
72SocketDescriptor : Type
84SocketDescriptor : Type
73SocketDescriptor = Int
85SocketDescriptor = Int
@@ -86,7 +98,7 @@ instance Show SocketAddress where
86Port : Type
98Port : Type
89−-- Backlog used within listen() call -- number of incoming calls
101+||| Backlog used within listen() call -- number of incoming calls
90BACKLOG : Int
102BACKLOG : Int
91BACKLOG = 20
103BACKLOG = 20
@@ -109,7 +121,7 @@ record UDPAddrInfo : Type where
109 (remote_port : Port) ->
121 (remote_port : Port) ->
110 UDPAddrInfo
122 UDPAddrInfo
112−-- Frees a given pointer
124+||| Frees a given pointer
114sock_free : BufPtr -> IO ()
126sock_free : BufPtr -> IO ()
115sock_free (BPtr ptr) = mkForeign (FFun "idrnet_free" [FPtr] FUnit) ptr
127sock_free (BPtr ptr) = mkForeign (FFun "idrnet_free" [FPtr] FUnit) ptr
@@ -118,12 +130,14 @@ public
118sockaddr_free : SockaddrPtr -> IO ()
130sockaddr_free : SockaddrPtr -> IO ()
119sockaddr_free (SAPtr ptr) = mkForeign (FFun "idrnet_free" [FPtr] FUnit) ptr
131sockaddr_free (SAPtr ptr) = mkForeign (FFun "idrnet_free" [FPtr] FUnit) ptr
121−-- Allocates an amount of memory given by the ByteLength parameter.
133+||| Allocates an amount of memory given by the ByteLength parameter.
122−-- Used to allocate a mutable pointer to be given to the Recv functions.
135+||| Used to allocate a mutable pointer to be given to the Recv functions.
124sock_alloc : ByteLength -> IO BufPtr
137sock_alloc : ByteLength -> IO BufPtr
125sock_alloc bl = map BPtr $ mkForeign (FFun "idrnet_malloc" [FInt] FPtr) bl
138sock_alloc bl = map BPtr $ mkForeign (FFun "idrnet_malloc" [FInt] FPtr) bl
140+||| The metadata about a socket
127record Socket : Type where
141record Socket : Type where
128 MkSocket : (descriptor : SocketDescriptor) ->
142 MkSocket : (descriptor : SocketDescriptor) ->
129 (family : SocketFamily) ->
143 (family : SocketFamily) ->
@@ -131,20 +145,21 @@ record Socket : Type where
131 (protocolNumber : ProtocolNumber) ->
145 (protocolNumber : ProtocolNumber) ->
148+||| Get the C error number
134getErrno : IO Int
149getErrno : IO Int
135getErrno = mkForeign (FFun "idrnet_errno" [] FInt)
150getErrno = mkForeign (FFun "idrnet_errno" [] FInt)
137−-- Creates a UNIX socket with the given family, socket type and protocol number.
152+||| Creates a UNIX socket with the given family, socket type and protocol
138−-- Returns either a socket or an error.
153+||| number. Returns either a socket or an error.
139socket : SocketFamily -> SocketType -> ProtocolNumber -> IO (Either SocketError Socket)
154socket : SocketFamily -> SocketType -> ProtocolNumber -> IO (Either SocketError Socket)
140socket sf st pn = do
155socket sf st pn = do
141 socket_res <- mkForeign (FFun "socket" [FInt, FInt, FInt] FInt) (toCode sf) (toCode st) pn
156 socket_res <- mkForeign (FFun "socket" [FInt, FInt, FInt] FInt) (toCode sf) (toCode st) pn
142 if socket_res == -1 then -- error
157 if socket_res == -1 then -- error
143 map Left getErrno
158 map Left getErrno
145 return $ Right (MkSocket socket_res sf st pn)
160 return $ Right (MkSocket socket_res sf st pn)
147−
162+||| Close a socket
148close : Socket -> IO ()
163close : Socket -> IO ()
149close sock = mkForeign (FFun "close" [FInt] FUnit) (descriptor sock)
164close sock = mkForeign (FFun "close" [FInt] FUnit) (descriptor sock)
@@ -153,18 +168,18 @@ saString : (Maybe SocketAddress) -> String
153saString (Just sa) = show sa
168saString (Just sa) = show sa
154saString Nothing = ""
169saString Nothing = ""
156−-- Binds a socket to the given socket address and port.
171+||| Binds a socket to the given socket address and port.
157−-- Returns 0 on success, an error code otherwise.
172+||| Returns 0 on success, an error code otherwise.
158bind : Socket -> (Maybe SocketAddress) -> Port -> IO Int
173bind : Socket -> (Maybe SocketAddress) -> Port -> IO Int
159bind sock addr port = do
174bind sock addr port = do
160− bind_res <- (mkForeign (FFun "idrnet_bind" [FInt, FInt, FInt, FString, FInt] FInt)
175+ bind_res <- (mkForeign (FFun "idrnet_bind" [FInt, FInt, FInt, FString, FInt] FInt)
161 (descriptor sock) (toCode $ family sock) (toCode $ socketType sock) (saString addr) port)
176 (descriptor sock) (toCode $ family sock) (toCode $ socketType sock) (saString addr) port)
162 if bind_res == (-1) then -- error
177 if bind_res == (-1) then -- error
164 else return 0 -- Success
179 else return 0 -- Success
166−-- Connects to a given address and port.
181+||| Connects to a given address and port.
167−-- Returns 0 on success, and an error number on error.
182+||| Returns 0 on success, and an error number on error.
168connect : Socket -> SocketAddress -> Port -> IO Int
183connect : Socket -> SocketAddress -> Port -> IO Int
169connect sock addr port = do
184connect sock addr port = do
170 conn_res <- (mkForeign (FFun "idrnet_connect" [FInt, FInt, FInt, FString, FInt] FInt)
185 conn_res <- (mkForeign (FFun "idrnet_connect" [FInt, FInt, FInt, FString, FInt] FInt)
@@ -173,7 +188,7 @@ connect sock addr port = do
174 else return 0
189 else return 0
176−-- Listens on a bound socket.
191+||| Listens on a bound socket.
177listen : Socket -> IO Int
192listen : Socket -> IO Int
178listen sock = do
193listen sock = do
179 listen_res <- mkForeign (FFun "listen" [FInt, FInt] FInt) (descriptor sock) BACKLOG
194 listen_res <- mkForeign (FFun "listen" [FInt, FInt] FInt) (descriptor sock) BACKLOG
@@ -181,7 +196,7 @@ listen sock = do
182 else return 0
197 else return 0
184−-- Parses a textual representation of an IPv4 address into a SocketAddress
199+||| Parses a textual representation of an IPv4 address into a SocketAddress
185parseIPv4 : String -> SocketAddress
200parseIPv4 : String -> SocketAddress
186parseIPv4 str = case splitted of
201parseIPv4 str = case splitted of
187 (i1 :: i2 :: i3 :: i4 :: _) => IPv4Addr i1 i2 i3 i4
202 (i1 :: i2 :: i3 :: i4 :: _) => IPv4Addr i1 i2 i3 i4
@@ -194,7 +209,7 @@ parseIPv4 str = case splitted of
194 splitted = map toInt (Prelude.Strings.split (\c => c == '.') str)
209 splitted = map toInt (Prelude.Strings.split (\c => c == '.') str)
197−-- Retrieves a socket address from a sockaddr pointer
212+||| Retrieves a socket address from a sockaddr pointer
198getSockAddr : SockaddrPtr -> IO SocketAddress
213getSockAddr : SockaddrPtr -> IO SocketAddress
199getSockAddr (SAPtr ptr) = do
214getSockAddr (SAPtr ptr) = do
200 addr_family_int <- mkForeign (FFun "idrnet_sockaddr_family" [FPtr] FInt) ptr
215 addr_family_int <- mkForeign (FFun "idrnet_sockaddr_family" [FPtr] FInt) ptr
@@ -256,13 +271,13 @@ recv sock len = do
256 return $ Right (payload, recv_res)
271 return $ Right (payload, recv_res)
259−-- Sends the data in a given memory location
274+||| Sends the data in a given memory location
260sendBuf : Socket -> BufPtr -> ByteLength -> IO (Either SocketError ByteLength)
275sendBuf : Socket -> BufPtr -> ByteLength -> IO (Either SocketError ByteLength)
261sendBuf sock (BPtr ptr) len = do
276sendBuf sock (BPtr ptr) len = do
262 send_res <- mkForeign (FFun "idrnet_send_buf" [FInt, FPtr, FInt] FInt) (descriptor sock) ptr len
277 send_res <- mkForeign (FFun "idrnet_send_buf" [FInt, FPtr, FInt] FInt) (descriptor sock) ptr len
263 if send_res == (-1) then
278 if send_res == (-1) then
264 map Left getErrno
279 map Left getErrno
266 return $ Right send_res
281 return $ Right send_res
268recvBuf : Socket -> BufPtr -> ByteLength -> IO (Either SocketError ByteLength)
283recvBuf : Socket -> BufPtr -> ByteLength -> IO (Either SocketError ByteLength)
@@ -313,7 +328,7 @@ recvFrom sock bl = do
313 recv_ptr <- mkForeign (FFun "idrnet_recvfrom" [FInt, FInt] FPtr)
328 recv_ptr <- mkForeign (FFun "idrnet_recvfrom" [FInt, FInt] FPtr)
314 (descriptor sock) bl
329 (descriptor sock) bl
315 let recv_ptr' = RFPtr recv_ptr
330 let recv_ptr' = RFPtr recv_ptr
316− if !(nullPtr recv_ptr) then -- ! notation = monadic bind shortcut, not "not"
331+ if !(nullPtr recv_ptr) then
317 map Left getErrno
332 map Left getErrno
319 result <- mkForeign (FFun "idrnet_get_recvfrom_res" [FPtr] FInt) recv_ptr
334 result <- mkForeign (FFun "idrnet_get_recvfrom_res" [FPtr] FInt) recv_ptr
@@ -332,7 +347,7 @@ recvFromBuf : Socket -> BufPtr -> ByteLength -> IO (Either SocketError (UDPAddrI
332recvFromBuf sock (BPtr ptr) bl = do
347recvFromBuf sock (BPtr ptr) bl = do
333 recv_ptr <- mkForeign (FFun "idrnet_recvfrom_buf" [FInt, FPtr, FInt] FPtr) (descriptor sock) ptr bl
348 recv_ptr <- mkForeign (FFun "idrnet_recvfrom_buf" [FInt, FPtr, FInt] FPtr) (descriptor sock) ptr bl
334 let recv_ptr' = RFPtr recv_ptr
349 let recv_ptr' = RFPtr recv_ptr
335− if !(nullPtr recv_ptr) then -- ! notation = monadic bind shortcut, not "not"
350+ if !(nullPtr recv_ptr) then
336 map Left getErrno
351 map Left getErrno
338 result <- mkForeign (FFun "idrnet_get_recvfrom_res" [FPtr] FInt) recv_ptr
353 result <- mkForeign (FFun "idrnet_get_recvfrom_res" [FPtr] FInt) recv_ptr
@@ -345,5 +360,4 @@ recvFromBuf sock (BPtr ptr) bl = do
345 freeRecvfromStruct recv_ptr'
360 freeRecvfromStruct recv_ptr'
346 return $ Right (MkUDPAddrInfo addr port, result + 1)
361 return $ Right (MkUDPAddrInfo addr port, result + 1)