Building and parsing SIP messages (strings) in Haskell
I'm attempting to learn Haskell by writing a SIP client.
The question I have is in the example below what would a function to build a string representing the SIP request look like, or in other words instead of the 9 writes I'm doing to the socket handle how would I write a function to build the string and then send it with one write?
The flip side of the a开发者_如何学运维bove question is how would I parse the string I get back from the socket to parse all the information from it. For example each SIP request has a method, URI, version etc. should I extract each item with a separate function one at a time?
The attempts I've made at the task look exactly the same as imperative code with one big "do" block which from what I can tell is not the functional way.
import Network
import System.Exit
import System.IO
import Text.Printf
server = "127.0.0.1"
port = 5060
main = do
h <- connectTo server (PortNumber (fromInteger port))
hSetBuffering h NoBuffering
write h "OPTIONS sip:1234@someserver.com SIP/2.0\r\n"
write h "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
write h "To: sip:1234@someserver.com\r\n"
write h "From: <sip:1234@someserver.com>;tag=1234\r\n"
write h "CSeq: 1 OPTIONS\r\n"
write h "Call-ID: abcdefgh\r\n"
write h "Content-Length: 0\r\n"
write h "\r\n"
listen h
write :: Handle -> String -> IO ()
write h s = do
hPrintf h "%s" s
printf "> %s" s
listen :: Handle -> IO ()
listen h = forever $ do
t <- hGetLine h
let s = init t
putStrLn s
where
forever a = do a; forever a
For your first question: How about concatting the strings and writing them in one single operation? Here's an example:
--instead of
main = do
h <- connectTo server (PortNumber (fromInteger port))
hSetBuffering h NoBuffering
write h "OPTIONS sip:1234@someserver.com SIP/2.0\r\n"
write h "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
write h "To: sip:1234@someserver.com\r\n"
write h "From: <sip:1234@someserver.com>;tag=1234\r\n"
write h "CSeq: 1 OPTIONS\r\n"
write h "Call-ID: abcdefgh\r\n"
write h "Content-Length: 0\r\n"
write h "\r\n"
listen h
--write
main = do
h <- connectTo server (PortNumber (fromInteger port))
hSetBuffering h NoBuffering
write h $ "OPTIONS sip:1234@someserver.com SIP/2.0\r\n"
++ "Via: SIP/2.0/TCP 192.168.0.153;branch-z9hg4bK4b1234\r\n"
++ "To: sip:1234@someserver.com\r\n"
++ "From: <sip:1234@someserver.com>;tag=1234\r\n"
++ "CSeq: 1 OPTIONS\r\n"
++ "Call-ID: abcdefgh\r\n"
++ "Content-Length: 0\r\n\r\n"
listen h
And about the parrsing: Try Parsec for this.
PS: Doing IO with usual String
s is a bit slow. Try ByteString
and attoparsec
instead.
精彩评论