-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Setups secure (unsorted) UDP packet transfer. -- -- This simple module allows to send packages ensuring delivering over an -- UDP connection using ACKs and timeouts under the hood, also setups the -- threads needed for listening and sending, making them transparent to -- the user. -- -- As the packages can be delivered just when they arrive, is not -- guarenteed that they arrive in order. -- -- Once a sent package has passed many timeouts without been ACKed from -- the recipient it can be recognized as a lost package, meaning that the -- recipient cannot longer be reached. @package secureUDP @version 0.1.1.1 -- | The main module contains all the operations needed to create a channel -- and send or receive packages. -- --
-- import SecureUDP
--
-- import qualified Network.Socket as So
-- import qualified System.IO as SI
--
-- main = do
-- -- This is needed so lazyness doens't mess with inner thread communication.
-- SI.hSetBuffering SI.stdout SI.NoBuffering
-- -- Create the socket:
-- sock <- So.socket So.AF_INET So.Datagram So.defaultProtocol
-- -- Bind the socket to the address 0.0.0.0 so it can receive packages from everywhere.
-- let port = 7272
-- let address = So.tupleToHostAddress (0,0,0,0)
-- So.bind sock (So.SockAddrInet port address)
-- -- Create the configuration for a new channel,
-- -- this values should be OK for most purposes:
-- let chcfg = ChannelConfig {
-- socket = sock,
-- resendTimeout = 280000000000, -- 0.28 seconds.
-- maxResends = 8,
-- allowed = (_ -> return (True)), -- Allow any incomming address.
-- maxPacketSize = 500,
-- recvRetention = 10
-- }
-- -- Start the channel with the given configuration:
-- channel <- startChannel chcfg
--
-- -- ...
--
--
-- Then you can use the channel to send and receive messages from and to
-- any address, using sendMessages and getReceived.
--
-- You can also use getLoss to check which messages that you
-- sent weren't ACKed.
--
-- Make sure that you call getReceived and getLoss once
-- in a while, even if you don't use them, so the messages won't
-- accumulate in memory.
module SecureUDP
-- | Holds the configuration of a channel.
data ChannelConfig
ChannelConfig :: Socket -> Integer -> Int -> (SockAddr -> IO (Bool)) -> Int -> Integer -> ChannelConfig
-- | The UDP Socket from Network.Socket that the channel will use to send
-- and receive messages.
[socket] :: ChannelConfig -> Socket
-- | Picoseconds after a package is re-send if no ACK for it is received.
[resendTimeout] :: ChannelConfig -> Integer
-- | Times that the same package can be re-sended without ACK after
-- considerating it lost.
[maxResends] :: ChannelConfig -> Int
-- | Function used to determinate if accept or not incomming packages from
-- the given address.
[allowed] :: ChannelConfig -> SockAddr -> IO (Bool)
-- | Max bytes that can be sent on this channel packages, larger packages
-- will throw and exception.
[maxPacketSize] :: ChannelConfig -> Int
-- | Time that a received and delivired package will remain on memory in
-- order to avoid duplicated receptions. The packages will be stored
-- recvRetention *resendTimeout * maxResends picoseconds after
-- reception and after that, will be freed on the next getReceived call.
[recvRetention] :: ChannelConfig -> Integer
-- | Starts a sending and a receiving threads for the protocol, returns a
-- channel that can be used to insert and extract messages.
startChannel :: ChannelConfig -> IO (ChannelSt)
-- | Terminates a channel, ending its threads and making it unable to send
-- or receive messages.
closeChannel :: ChannelSt -> IO ()
-- | Check if the given channel has been closed.
checkClosed :: ChannelSt -> IO (Bool)
-- | The configuration that was used to start the given channel.
channelConf :: ChannelSt -> ChannelConfig
-- | Get the received messages and their sender addresses, then erases
-- them.
--
-- It's important that your program calls this once in a while or the
-- packages will remain in memory.
getReceived :: ChannelSt -> IO ([(SockAddr, ByteString)])
-- | Get the messages that weren't ACKed from the target recipent host and
-- erases them. Useful to detect missing connections.
--
-- It's also important that your program calls this once in a while or
-- the packages will remain in memory.
getLoss :: ChannelSt -> IO ([(SockAddr, ByteString)])
-- | Trought the given channel, send packages to the given addresses and
-- message bytestrings.
--
-- Returns False if the channel has being closed, True
-- otherwise.
sendMessages :: ChannelSt -> [(SockAddr, ByteString)] -> IO (Bool)
-- | Represents the status of a channel, also holds, internally,
-- information about the threads that it uses. After a channel is
-- created, it is used as an argument for the main functions.
type ChannelSt = (ChannelConfig, MVar ChannelStatus)