AGI 1.1.1 → 1.2
raw patch · 3 files changed
+61/−15 lines, 3 filesdep +networkPVP ok
version bump matches the API change (PVP)
Dependencies added: network
API changes (from Hackage documentation)
- Network.AGI: instance MonadReader [(String, String)] AGI
+ Network.AGI: fastAGI :: Maybe PortID -> (HostName -> PortNumber -> AGI a) -> IO ()
+ Network.AGI: instance MonadReader AGIEnv AGI
+ Network.AGI: runInternal :: AGI a -> Handle -> Handle -> IO a
Files
- AGI.cabal +3/−3
- Network/AGI.hs +52/−12
- debian/changelog +6/−0
AGI.cabal view
@@ -7,7 +7,7 @@ can be used to write external programs that interact with Asterisk. It is typically used for creating Interactive Voice Response (IVR) systems. -Version: 1.1.1+Version: 1.2 License: BSD3 License-File: LICENSE Author: Jeremy Shaw@@ -33,9 +33,9 @@ build-depends: parsec, mtl if flag(small_base)- build-depends: base >= 3, random, unix+ build-depends: base >= 3, random, unix, network else- build-depends: base < 3+ build-depends: base < 3, network Exposed-modules: Network.AGI
Network/AGI.hs view
@@ -3,6 +3,8 @@ ( Digit(..) , AGI , run+ , fastAGI+ , runInternal , ppDigit , ppEscapeDigits , SoundType(..)@@ -18,6 +20,8 @@ , record ) where +import Control.Concurrent+import Control.Exception (finally) import Control.Monad import Control.Monad.Trans import Control.Monad.Reader@@ -25,14 +29,20 @@ import Data.Char import Data.Maybe import Data.Word+import Network import Text.ParserCombinators.Parsec import System.IO import System.Posix.Signals import System.Random -newtype AGI a = AGI { runAGI :: ReaderT [(String, String)] IO a }- deriving (Monad, MonadIO, Functor, MonadError IOError, MonadReader [(String, String)])+data AGIEnv = AGIEnv { agiVars :: [(String, String)]+ , agiInH :: Handle+ , agiOutH :: Handle+ } +newtype AGI a = AGI { runAGI :: ReaderT AGIEnv IO a }+ deriving (Monad, MonadIO, Functor, MonadError IOError, MonadReader AGIEnv)+ data Digit = Pound | Star@@ -76,26 +86,54 @@ show GSM = "gsm" -- TODO: let user install a custom sipHUP handler (sigHUP is sent when the caller hangs ups)+-- |Top-level wrapper for single-shot AGI scripts.+-- Example:+-- @ main = run yourAGI Ignore @ run :: AGI a -> Handler -> IO a run agi hupHandler = do installHandler sigHUP hupHandler Nothing- hSetBuffering stdin LineBuffering- hSetBuffering stdout LineBuffering- agiVars <- readAgiVars- runReaderT (runAGI agi) agiVars+ runInternal agi stdin stdout -readAgiVars :: IO [(String, String)]-readAgiVars = +-- |Top-level for long running AGI scripts.+-- Example:+-- @ main = fastAGI Nothing yourAGI @+-- You should be sure to compile with -threaded. Note that 'yourAGI'+-- may be running simultaneously in multiple threads, so you will need+-- some concurrency control for shared data.+-- TODO: support a hang-up handler+fastAGI :: Maybe PortID -> (HostName -> PortNumber -> AGI a) -> IO ()+fastAGI portId agi =+ do installHandler sigPIPE Ignore Nothing + s <- listenOn $ fromMaybe (PortNumber 4573) portId+ (forever $ (do (h, hostname, portNum) <- accept s+ forkIO $ runInternal (agi hostname portNum) h h >> hClose h+ )) `finally` (sClose s)+++-- |runInternal - run an AGI script using the supplied Handles for input and output+-- You probably want 'run' or 'fastAGI'. This function is exposed so+-- that 3rd party libraries such as HAppS can easily add support for+-- FastAGI support.+-- TODO: support general method of handling extra arguments (query_string vs command-line arguments)+runInternal :: AGI a -> Handle -> Handle -> IO a+runInternal agi inh outh =+ do vars <- readAgiVars inh+ hSetBuffering inh LineBuffering+ hSetBuffering outh LineBuffering+ runReaderT (runAGI agi) (AGIEnv vars inh outh)++readAgiVars :: Handle -> IO [(String, String)]+readAgiVars inh = do mAgiVar <- readAgiVar case mAgiVar of Nothing -> return [] Just agiVar ->- do rest <- readAgiVars+ do rest <- readAgiVars inh return (agiVar:rest) where readAgiVar :: IO (Maybe (String, String)) readAgiVar =- do l <- getLine+ do l <- hGetLine inh case l of "" -> return Nothing _ -> let (a,v) = break ((==) ':') l in@@ -103,8 +141,10 @@ sendRecv :: Command -> AGI String sendRecv cmd =- liftIO $ do putStrLn cmd- getLine+ do inh <- liftM agiInH $ ask+ outh <- liftM agiOutH $ ask+ liftIO $ do hPutStrLn inh cmd+ hGetLine outh {- Usage: ANSWER
debian/changelog view
@@ -1,3 +1,9 @@+haskell-agi (1.2) unstable; urgency=low++ * Added initial support for FastAGI (very lightly tested)++ -- Jeremy Shaw <jeremy@n-heptane.com> Wed, 02 Jul 2008 23:56:03 -0700+ haskell-agi (1.1.1) unstable; urgency=low * Debianization generated by cabal-debian