2020-06-25 14:07:33 +03:00
|
|
|
module Control.Linear.Network
|
|
|
|
|
|
|
|
-- An experimental linear type based API to sockets
|
|
|
|
|
2021-04-07 22:02:23 +03:00
|
|
|
import Data.Maybe
|
|
|
|
|
2020-06-25 14:07:33 +03:00
|
|
|
import Control.Linear.LIO
|
|
|
|
|
|
|
|
import public Network.Socket.Data
|
|
|
|
import Network.Socket
|
|
|
|
|
|
|
|
public export
|
|
|
|
data SocketState = Ready | Bound | Listening | Open | Closed
|
|
|
|
|
|
|
|
export
|
|
|
|
data Socket : SocketState -> Type where
|
|
|
|
MkSocket : Socket.Data.Socket -> Socket st
|
|
|
|
|
|
|
|
export
|
|
|
|
newSocket : LinearIO io
|
|
|
|
=> (fam : SocketFamily)
|
|
|
|
-> (ty : SocketType)
|
|
|
|
-> (pnum : ProtocolNumber)
|
|
|
|
-> (success : (1 _ : Socket Ready) -> L io ())
|
|
|
|
-> (fail : SocketError -> L io ())
|
|
|
|
-> L io ()
|
|
|
|
newSocket fam ty pnum success fail
|
|
|
|
= do Right rawsock <- socket fam ty pnum
|
|
|
|
| Left err => fail err
|
|
|
|
success (MkSocket rawsock)
|
|
|
|
|
|
|
|
export
|
|
|
|
close : LinearIO io => (1 _ : Socket st) -> L io {use=1} (Socket Closed)
|
|
|
|
close (MkSocket sock)
|
|
|
|
= do Socket.close sock
|
|
|
|
pure1 (MkSocket sock)
|
|
|
|
|
|
|
|
export
|
|
|
|
done : LinearIO io => (1 _ : Socket Closed) -> L io ()
|
|
|
|
done (MkSocket sock) = pure ()
|
|
|
|
|
|
|
|
export
|
|
|
|
bind : LinearIO io =>
|
|
|
|
(1 _ : Socket Ready) ->
|
|
|
|
(addr : Maybe SocketAddress) ->
|
|
|
|
(port : Port) ->
|
2021-04-07 22:02:23 +03:00
|
|
|
L io {use=1} (Res (Maybe SocketError)
|
|
|
|
(\res => Socket (case res of
|
|
|
|
Just _ => Closed
|
|
|
|
Nothing => Bound)))
|
2020-06-25 14:07:33 +03:00
|
|
|
bind (MkSocket sock) addr port
|
|
|
|
= do ok <- Socket.bind sock addr port
|
2021-04-07 22:02:23 +03:00
|
|
|
let mbErr = toMaybe (ok /= 0) ok
|
|
|
|
pure1 $ mbErr # MkSocket sock
|
2020-06-25 14:07:33 +03:00
|
|
|
|
|
|
|
export
|
|
|
|
connect : LinearIO io =>
|
|
|
|
(sock : Socket) ->
|
|
|
|
(addr : SocketAddress) ->
|
|
|
|
(port : Port) ->
|
2021-04-07 22:02:23 +03:00
|
|
|
L io {use=1} (Res (Maybe SocketError)
|
|
|
|
(\res => Socket (case res of
|
|
|
|
Just _ => Closed
|
|
|
|
Nothing => Open)))
|
2020-06-25 14:07:33 +03:00
|
|
|
connect sock addr port
|
|
|
|
= do ok <- Socket.connect sock addr port
|
2021-04-07 22:02:23 +03:00
|
|
|
let mbErr = toMaybe (ok /= 0) ok
|
|
|
|
pure1 $ mbErr # MkSocket sock
|
2020-06-25 14:07:33 +03:00
|
|
|
|
|
|
|
export
|
|
|
|
listen : LinearIO io =>
|
|
|
|
(1 _ : Socket Bound) ->
|
2021-04-07 22:02:23 +03:00
|
|
|
L io {use=1} (Res (Maybe SocketError)
|
|
|
|
(\res => Socket (case res of
|
|
|
|
Just _ => Closed
|
|
|
|
Nothing => Listening)))
|
2020-06-25 14:07:33 +03:00
|
|
|
listen (MkSocket sock)
|
|
|
|
= do ok <- Socket.listen sock
|
2021-04-07 22:02:23 +03:00
|
|
|
let mbErr = toMaybe (ok /= 0) ok
|
|
|
|
pure1 $ mbErr # MkSocket sock
|
2020-06-25 14:07:33 +03:00
|
|
|
|
|
|
|
export
|
|
|
|
accept : LinearIO io =>
|
|
|
|
(1 _ : Socket Listening) ->
|
2021-04-07 22:02:23 +03:00
|
|
|
L io {use=1} (Res (Maybe SocketError) (\case
|
|
|
|
Just _ => Socket Listening
|
|
|
|
Nothing => LPair (Socket Listening) (Socket Open)))
|
2020-06-25 14:07:33 +03:00
|
|
|
accept (MkSocket sock)
|
|
|
|
= do Right (sock', sockaddr) <- Socket.accept sock
|
2021-04-07 22:02:23 +03:00
|
|
|
| Left err => pure1 (Just err # MkSocket sock)
|
|
|
|
pure1 (Nothing # (MkSocket sock # MkSocket sock'))
|
2020-06-25 14:07:33 +03:00
|
|
|
|
|
|
|
export
|
|
|
|
send : LinearIO io =>
|
|
|
|
(1 _ : Socket Open) ->
|
|
|
|
(msg : String) ->
|
2021-04-07 22:02:23 +03:00
|
|
|
L io {use=1} (Res (Maybe SocketError)
|
|
|
|
(\res => Socket (case res of
|
|
|
|
Just _ => Closed
|
|
|
|
Nothing => Open)))
|
2020-06-25 14:07:33 +03:00
|
|
|
send (MkSocket sock) msg
|
|
|
|
= do Right c <- Socket.send sock msg
|
2021-04-07 22:02:23 +03:00
|
|
|
| Left err => pure1 (Just err # MkSocket sock)
|
|
|
|
pure1 (Nothing # MkSocket sock)
|
2020-07-08 02:56:12 +03:00
|
|
|
|
2020-06-25 14:07:33 +03:00
|
|
|
export
|
|
|
|
recv : LinearIO io =>
|
|
|
|
(1 _ : Socket Open) ->
|
|
|
|
(len : ByteLength) ->
|
2021-04-07 22:02:23 +03:00
|
|
|
L io {use=1} (Res (Either SocketError (String, ResultCode))
|
2020-06-25 14:07:33 +03:00
|
|
|
(\res => Socket (case res of
|
2021-04-07 22:02:23 +03:00
|
|
|
Left _ => Closed
|
|
|
|
Right _ => Open)))
|
2020-06-25 14:07:33 +03:00
|
|
|
recv (MkSocket sock) len
|
|
|
|
= do Right msg <- Socket.recv sock len
|
2021-04-07 22:02:23 +03:00
|
|
|
| Left err => pure1 (Left err # MkSocket sock)
|
|
|
|
pure1 (Right msg # MkSocket sock)
|
2020-06-25 14:07:33 +03:00
|
|
|
|
|
|
|
export
|
|
|
|
recvAll : LinearIO io =>
|
|
|
|
(1 _ : Socket Open) ->
|
2021-04-07 22:02:23 +03:00
|
|
|
L io {use=1} (Res (Either SocketError String)
|
2020-06-25 14:07:33 +03:00
|
|
|
(\res => Socket (case res of
|
2021-04-07 22:02:23 +03:00
|
|
|
Left _ => Closed
|
|
|
|
Right _ => Open)))
|
2020-06-25 14:07:33 +03:00
|
|
|
recvAll (MkSocket sock)
|
|
|
|
= do Right msg <- Socket.recvAll sock
|
2021-04-07 22:02:23 +03:00
|
|
|
| Left err => pure1 (Left err # MkSocket sock)
|
|
|
|
pure1 (Right msg # MkSocket sock)
|