module M.IO.Internal.Socket (Connection (..), withcxfromsocket) where
import Data.ByteString qualified as B
import M.Crypto
import M.IO.Internal.Datagram
import M.IO.Obs
import Network.SocketA
import System.IO.Streams
import UnliftIO
data Connection = Connection
{
Connection -> TVar (Maybe ByteString)
cxkey :: TVar (Maybe ByteString),
Connection -> TVar Int
cxcompth :: TVar Int,
Connection -> InputStream Uninterpreted
cxinput :: InputStream Uninterpreted,
Connection -> OutputStream Uninterpreted
cxoutput :: OutputStream Uninterpreted
}
withcxfromsocket :: (MonadUnliftIO m) => Socket -> (Connection -> m a) -> m a
withcxfromsocket :: forall (m :: * -> *) a.
MonadUnliftIO m =>
Socket -> (Connection -> m a) -> m a
withcxfromsocket Socket
sk Connection -> m a
cont = do
th <- Int -> m (TVar Int)
forall (m :: * -> *) a. MonadIO m => a -> m (TVar a)
newTVarIO (-Int
1)
(i0, o0) <- liftIO (socketToStreams sk)
(ef, df) <- liftA2 (,) (newTVarIO pure) (newTVarIO pure)
(i1, o1) <-
liftA2
(,)
(liftIO $ makedecrypting df i0)
(liftIO $ makeencrypting ef o0)
(i2, o2) <-
liftA2
(,)
(liftIO $ makepacketstreami th i1)
(liftIO $ makepacketstreamo th o1)
k <- newTVarIO Nothing
let watchk = IO Any -> m Any
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Any -> m Any) -> IO Any -> m Any
forall a b. (a -> b) -> a -> b
$ TVar (Maybe ByteString)
-> (Maybe ByteString -> Maybe ByteString -> STM (Maybe ByteString))
-> (Maybe ByteString -> Maybe ByteString -> IO ())
-> IO Any
forall (m :: * -> *) a b.
(MonadIO m, Eq a) =>
TVar a -> (a -> a -> STM a) -> (a -> a -> m ()) -> m b
obs
do k
do (Maybe ByteString -> STM (Maybe ByteString))
-> Maybe ByteString -> Maybe ByteString -> STM (Maybe ByteString)
forall a b. a -> b -> a
const Maybe ByteString -> STM (Maybe ByteString)
forall a. a -> STM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
do
(Maybe ByteString -> IO ())
-> Maybe ByteString -> Maybe ByteString -> IO ()
forall a b. a -> b -> a
const \case
Maybe ByteString
Nothing -> STM () -> IO ()
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically do
TVar (ByteString -> IO ByteString)
-> (ByteString -> IO ByteString) -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (ByteString -> IO ByteString)
ef ByteString -> IO ByteString
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
TVar (ByteString -> IO ByteString)
-> (ByteString -> IO ByteString) -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (ByteString -> IO ByteString)
df ByteString -> IO ByteString
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
Just ByteString
key -> do
aese <- forall (mode :: Mode). AESClass mode => ByteString -> IO (AES mode)
aesnew @'Encrypt ByteString
key
aesd <- aesnew @'Decrypt key
atomically do
writeTVar ef (aesupdate aese)
writeTVar df (aesupdate aesd)
withAsync watchk \Async Any
s -> do
Async Any -> m ()
forall (m :: * -> *) a. MonadIO m => Async a -> m ()
link Async Any
s
(SomeException -> m a) -> m a -> m a
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
(e -> m a) -> m a -> m a
handle
do \(SomeException
e :: SomeException) -> SomeException -> m a
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO SomeException
e
do
Connection -> m a
cont
Connection
{ cxkey :: TVar (Maybe ByteString)
cxkey = TVar (Maybe ByteString)
k,
cxcompth :: TVar Int
cxcompth = TVar Int
th,
cxinput :: InputStream Uninterpreted
cxinput = InputStream Uninterpreted
i2,
cxoutput :: OutputStream Uninterpreted
cxoutput = OutputStream Uninterpreted
o2
}
socketToStreams ::
Socket ->
IO (InputStream ByteString, OutputStream ByteString)
socketToStreams :: Socket -> IO (InputStream ByteString, OutputStream ByteString)
socketToStreams Socket
sk = do
i <- IO (Maybe ByteString) -> IO (InputStream ByteString)
forall a. IO (Maybe a) -> IO (InputStream a)
makeInputStream do
c <- Socket -> Int -> IO ByteString
recv Socket
sk Int
2048
pure
if B.null c
then Nothing
else Just c
o <- makeOutputStream \case
Maybe ByteString
Nothing -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just ByteString
x -> Socket -> ByteString -> IO ()
sendall Socket
sk ByteString
x
pure (i, o)