module Hans.Socket.Types where
import Hans.Addr (isWildcardAddr)
import Hans.Device.Types (Device)
import Hans.Network (Network(..),RouteInfo(..))
import Hans.Types (HasNetworkStack,NetworkStack)
import Control.Exception (Exception,throwIO)
import qualified Data.ByteString.Lazy as L
import Data.Typeable (Typeable)
import Data.Word (Word16)
type SockPort = Word16
data SocketConfig = SocketConfig { scRecvBufferSize :: !Int
} deriving (Show)
defaultSocketConfig :: SocketConfig
defaultSocketConfig = SocketConfig { scRecvBufferSize = 4096 }
class Socket sock where
sClose :: Network addr => sock addr -> IO ()
class (DataSocket (Client sock), Socket sock) => ListenSocket sock where
type Client sock :: * -> *
sListen :: (HasNetworkStack ns, Network addr)
=> ns -> SocketConfig -> addr -> SockPort -> Int -> IO (sock addr)
sAccept :: Network addr => sock addr -> IO (Client sock addr)
class Socket sock => DataSocket sock where
sConnect :: (HasNetworkStack ns, Network addr)
=> ns
-> SocketConfig
-> Maybe Device
-> addr
-> Maybe SockPort
-> addr
-> SockPort
-> IO (sock addr)
sCanWrite :: Network addr => sock addr -> IO Bool
sWrite :: Network addr => sock addr -> L.ByteString -> IO Int
sCanRead :: Network addr => sock addr -> IO Bool
sRead :: Network addr => sock addr -> Int -> IO L.ByteString
sTryRead :: Network addr => sock addr -> Int -> IO (Maybe L.ByteString)
data ConnectionException = AlreadyConnected
| NoConnection
| NoPortAvailable
| ConnectionRefused
| ConnectionClosing
| DoesNotExist
deriving (Show,Typeable)
data ListenException = AlreadyListening
deriving (Show,Typeable)
data RoutingException = NoRouteToHost
deriving (Show,Typeable)
instance Exception ConnectionException
instance Exception ListenException
instance Exception RoutingException
route :: Network addr
=> NetworkStack -> Maybe Device -> addr -> addr -> IO (RouteInfo addr)
route ns mbDev src dst =
do mbRoute <- route' ns mbDev src dst
case mbRoute of
Just ri -> return ri
Nothing -> throwIO NoRouteToHost
route' :: Network addr
=> NetworkStack -> Maybe Device -> addr -> addr
-> IO (Maybe (RouteInfo addr))
route' ns mbDev src dst =
do mbRoute <- lookupRoute ns dst
case mbRoute of
Just ri | maybe True (riDev ri ==) mbDev
&& (src == riSource ri || isWildcardAddr src) ->
return (Just ri)
_ -> return Nothing