@@ -8,9 +8,11 @@ module Network.Socket
88%include C "sys/socket.h"
99%include C "netdb.h"
1010
11−public export ByteLength : Type
11+public export
12+ByteLength : Type
1213ByteLength = Int
1314
15+export
1416interface ToCode a where
1517 toCode : a -> Int
1618
@@ -18,6 +20,7 @@ interface ToCode a where
1820|||
1921||| The ones that people might actually use. We're not going to need US
2022||| Government proprietary ones.
23+public export
2124data SocketFamily =
2225 ||| Unspecified
2326 AF_UNSPEC |
@@ -26,11 +29,13 @@ data SocketFamily =
2629 ||| IP / UDP etc. IPv6
2730 AF_INET6
2831
32+export
2933implementation Show SocketFamily where
3034 show AF_UNSPEC = "AF_UNSPEC"
3135 show AF_INET = "AF_INET"
3236 show AF_INET6 = "AF_INET6"
3337
38+export
3439implementation ToCode SocketFamily where
3540 toCode AF_UNSPEC = 0
3641 toCode AF_INET = 2
@@ -40,6 +45,7 @@ getSocketFamily : Int -> Maybe SocketFamily
4045getSocketFamily i = Prelude.List.lookup i [(0, AF_UNSPEC), (2, AF_INET), (10, AF_INET6)]
4146
4247||| Socket Types.
48+public export
4349data SocketType =
4450 ||| Not a socket, used in certain operations
4551 NotASocket |
@@ -50,62 +56,74 @@ data SocketType =
5056 ||| Raw sockets
5157 RawSocket
5258
59+export
5360implementation Show SocketType where
5461 show NotASocket = "Not a socket"
5562 show Stream = "Stream"
5663 show Datagram = "Datagram"
5764 show RawSocket = "Raw"
5865
66+export
5967implementation ToCode SocketType where
6068 toCode NotASocket = 0
6169 toCode Stream = 1
6270 toCode Datagram = 2
6371 toCode RawSocket = 3
6472
65−
6673data RecvStructPtr = RSPtr Ptr
6774data RecvfromStructPtr = RFPtr Ptr
6875
69−export data BufPtr = BPtr Ptr
70−export data SockaddrPtr = SAPtr Ptr
76+export
77+data BufPtr = BPtr Ptr
78+export
79+data SockaddrPtr = SAPtr Ptr
7180
7281||| Protocol Number.
7382|||
7483||| Generally good enough to just set it to 0.
84+public export
7585ProtocolNumber : Type
7686ProtocolNumber = Int
7787
7888||| SocketError: Error thrown by a socket operation
89+public export
7990SocketError : Type
8091SocketError = Int
8192
8293||| SocketDescriptor: Native C Socket Descriptor
94+public export
8395SocketDescriptor : Type
8496SocketDescriptor = Int
8597
98+public export
8699data SocketAddress = IPv4Addr Int Int Int Int
87100 | IPv6Addr -- Not implemented (yet)
88101 | Hostname String
89102 | InvalidAddress -- Used when there's a parse error
90103
104+export
91105implementation Show SocketAddress where
92106 show (IPv4Addr i1 i2 i3 i4) = concat $ Prelude.List.intersperse "." (map show [i1, i2, i3, i4])
93107 show IPv6Addr = "NOT IMPLEMENTED YET"
94108 show (Hostname host) = host
95109 show InvalidAddress = "Invalid"
96110
111+public export
97112Port : Type
98113Port = Int
99114
100115||| Backlog used within listen() call -- number of incoming calls
116+public export
101117BACKLOG : Int
102118BACKLOG = 20
103119
104120-- FIXME: This *must* be pulled in from C
105−EAGAIN : Int
121+public export
122+EAGAIN : Int
106123EAGAIN = 11
107124
108125-- TODO: Expand to non-string payloads
126+export
109127record UDPRecvData where
110128 constructor MkUDPRecvData
111129 remote_addr : SocketAddress
@@ -113,6 +131,7 @@ record UDPRecvData where
113131 recv_data : String
114132 data_len : Int
115133
134+export
116135record UDPAddrInfo where
117136 constructor MkUDPAddrInfo
118137 remote_addr : SocketAddress
@@ -135,6 +154,7 @@ sock_alloc : ByteLength -> IO BufPtr
135154sock_alloc bl = map BPtr $ foreign FFI_C "idrnet_malloc" (Int -> IO Ptr) bl
136155
137156||| The metadata about a socket
157+export
138158record Socket where
139159 constructor MkSocket
140160 descriptor : SocketDescriptor
@@ -144,6 +164,7 @@ record Socket where
144164
145165||| Creates a UNIX socket with the given family, socket type and protocol
146166||| number. Returns either a socket or an error.
167+export
147168socket : SocketFamily -> SocketType -> ProtocolNumber -> IO (Either SocketError Socket)
148169socket sf st pn = do
149170 socket_res <- foreign FFI_C "socket" (Int -> Int -> Int -> IO Int) (toCode sf) (toCode st) pn
@@ -153,6 +174,7 @@ socket sf st pn = do
153174 return $ Right (MkSocket socket_res sf st pn)
154175
155176||| Close a socket
177+export
156178close : Socket -> IO ()
157179close sock = foreign FFI_C "close" (Int -> IO ()) (descriptor sock)
158180
@@ -163,11 +185,12 @@ saString Nothing = ""
163185
164186||| Binds a socket to the given socket address and port.
165187||| Returns 0 on success, an error code otherwise.
188+export
166189bind : Socket -> (Maybe SocketAddress) -> Port -> IO Int
167190bind sock addr port = do
168− bind_res <- foreign FFI_C "idrnet_bind"
191+ bind_res <- foreign FFI_C "idrnet_bind"
169192 (Int -> Int -> Int -> String -> Int -> IO Int)
170− (descriptor sock) (toCode $ family sock)
193+ (descriptor sock) (toCode $ family sock)
171194 (toCode $ socketType sock) (saString addr) port
172195 if bind_res == (-1) then -- error
173196 getErrno
@@ -175,6 +198,7 @@ bind sock addr port = do
175198
176199||| Connects to a given address and port.
177200||| Returns 0 on success, and an error number on error.
201+export
178202connect : Socket -> SocketAddress -> Port -> IO Int
179203connect sock addr port = do
180204 conn_res <- foreign FFI_C "idrnet_connect"
@@ -185,6 +209,7 @@ connect sock addr port = do
185209 else return 0
186210
187211||| Listens on a bound socket.
212+export
188213listen : Socket -> IO Int
189214listen sock = do
190215 listen_res <- foreign FFI_C "listen" (Int -> Int -> IO Int)
@@ -205,7 +230,6 @@ parseIPv4 str = case splitted of
205230 splitted : List Int
206231 splitted = map toInt (Prelude.Strings.split (\c => c == '.') str)
207232
208−
209233||| Retrieves a socket address from a sockaddr pointer
210234getSockAddr : SockaddrPtr -> IO SocketAddress
211235getSockAddr (SAPtr ptr) = do
@@ -219,6 +243,7 @@ getSockAddr (SAPtr ptr) = do
219243 Just AF_INET6 => return IPv6Addr
220244 Just AF_UNSPEC => return InvalidAddress)
221245
246+export
222247accept : Socket -> IO (Either SocketError (Socket, SocketAddress))
223248accept sock = do
224249 -- We need a pointer to a sockaddr structure. This is then passed into
@@ -233,6 +258,7 @@ accept sock = do
233258 sockaddr_free (SAPtr sockaddr_ptr)
234259 return $ Right ((MkSocket accept_res fam ty p_num), sockaddr)
235260
261+export
236262send : Socket -> String -> IO (Either SocketError ByteLength)
237263send sock dat = do
238264 send_res <- foreign FFI_C "idrnet_send" (Int -> String -> IO Int) (descriptor sock) dat
@@ -241,7 +267,6 @@ send sock dat = do
241267 else
242268 return $ Right send_res
243269
244−
245270freeRecvStruct : RecvStructPtr -> IO ()
246271freeRecvStruct (RSPtr p) = foreign FFI_C "idrnet_free_recv_struct" (Ptr -> IO ()) p
247272
@@ -258,7 +283,7 @@ recv sock len = do
258283 errno <- getErrno
259284 freeRecvStruct (RSPtr recv_struct_ptr)
260285 return $ Left errno
261− else
286+ else
262287 if recv_res == 0 then do
263288 freeRecvStruct (RSPtr recv_struct_ptr)
264289 return $ Left 0
@@ -267,7 +292,6 @@ recv sock len = do
267292 freeRecvStruct (RSPtr recv_struct_ptr)
268293 return $ Right (payload, recv_res)
269294
270−
271295||| Sends the data in a given memory location
272296sendBuf : Socket -> BufPtr -> ByteLength -> IO (Either SocketError ByteLength)
273297sendBuf sock (BPtr ptr) len = do
@@ -287,28 +311,26 @@ recvBuf sock (BPtr ptr) len = do
287311
288312sendTo : Socket -> SocketAddress -> Port -> String -> IO (Either SocketError ByteLength)
289313sendTo sock addr p dat = do
290− sendto_res <- foreign FFI_C "idrnet_sendto"
291− (Int -> String -> String -> Int -> Int -> IO Int)
314+ sendto_res <- foreign FFI_C "idrnet_sendto"
315+ (Int -> String -> String -> Int -> Int -> IO Int)
292316 (descriptor sock) dat (show addr) p (toCode $ family sock)
293317 if sendto_res == (-1) then
294318 map Left getErrno
295319 else
296320 return $ Right sendto_res
297321
298−
299322sendToBuf : Socket -> SocketAddress -> Port -> BufPtr -> ByteLength -> IO (Either SocketError ByteLength)
300323sendToBuf sock addr p (BPtr dat) len = do
301− sendto_res <- foreign FFI_C "idrnet_sendto_buf"
302− (Int -> Ptr -> Int -> String -> Int -> Int -> IO Int)
324+ sendto_res <- foreign FFI_C "idrnet_sendto_buf"
325+ (Int -> Ptr -> Int -> String -> Int -> Int -> IO Int)
303326 (descriptor sock) dat len (show addr) p (toCode $ family sock)
304327 if sendto_res == (-1) then
305328 map Left getErrno
306329 else
307330 return $ Right sendto_res
308331
309−
310332foreignGetRecvfromPayload : RecvfromStructPtr -> IO String
311−foreignGetRecvfromPayload (RFPtr p)
333+foreignGetRecvfromPayload (RFPtr p)
312334 = foreign FFI_C "idrnet_get_recvfrom_payload" (Ptr -> IO String) p
313335
314336foreignGetRecvfromAddr : RecvfromStructPtr -> IO SocketAddress
@@ -316,7 +338,6 @@ foreignGetRecvfromAddr (RFPtr p) = do
316338 sockaddr_ptr <- map SAPtr $ foreign FFI_C "idrnet_get_recvfrom_sockaddr" (Ptr -> IO Ptr) p
317339 getSockAddr sockaddr_ptr
318340
319−
320341foreignGetRecvfromPort : RecvfromStructPtr -> IO Port
321342foreignGetRecvfromPort (RFPtr p) = do
322343 sockaddr_ptr <- foreign FFI_C "idrnet_get_recvfrom_sockaddr" (Ptr -> IO Ptr) p
@@ -325,7 +346,7 @@ foreignGetRecvfromPort (RFPtr p) = do
325346
326347recvFrom : Socket -> ByteLength -> IO (Either SocketError (UDPAddrInfo, String, ByteLength))
327348recvFrom sock bl = do
328− recv_ptr <- foreign FFI_C "idrnet_recvfrom" (Int -> Int -> IO Ptr)
349+ recv_ptr <- foreign FFI_C "idrnet_recvfrom" (Int -> Int -> IO Ptr)
329350 (descriptor sock) bl
330351 let recv_ptr' = RFPtr recv_ptr
331352 if !(nullPtr recv_ptr) then
@@ -342,7 +363,6 @@ recvFrom sock bl = do
342363 freeRecvfromStruct recv_ptr'
343364 return $ Right (MkUDPAddrInfo addr port, payload, result)
344365
345−
346366recvFromBuf : Socket -> BufPtr -> ByteLength -> IO (Either SocketError (UDPAddrInfo, ByteLength))
347367recvFromBuf sock (BPtr ptr) bl = do
348368 recv_ptr <- foreign FFI_C "idrnet_recvfrom_buf" (Int -> Ptr -> Int -> IO Ptr) (descriptor sock) ptr bl
@@ -359,5 +379,3 @@ recvFromBuf sock (BPtr ptr) bl = do
359379 addr <- foreignGetRecvfromAddr recv_ptr'
360380 freeRecvfromStruct recv_ptr'
361381 return $ Right (MkUDPAddrInfo addr port, result + 1)
362−
363−