packages feed

ntrip-client (empty) → 0.1.0

raw patch · 3 files changed

+85/−0 lines, 3 filesdep +asyncdep +attoparsecdep +basesetup-changed

Dependencies added: async, attoparsec, base, base64-bytestring, basic-prelude, case-insensitive, conduit, conduit-extra, http-types

Files

+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ ntrip-client.cabal view
@@ -0,0 +1,27 @@+name:                  ntrip-client+version:               0.1.0+synopsis:              NTRIP client.+description:           Networked Transport of RTCM via Internet Protocol client.+license:               BSD3+author:                Swift Navigation Inc.+maintainer:            Mark Fine <dev@swiftnav.com>+copyright:             Copyright (C) 2016 Swift Navigation, Inc.+category:              Network+build-type:            Simple+cabal-version:         >=1.10++library+  hs-source-dirs:      src+  exposed-modules:     Network.Ntrip.Client+  ghc-options:         -Wall+  default-language:    Haskell2010+  build-depends:       async,+                       async,+                       attoparsec,+                       base >= 4.7 && < 5,+                       base64-bytestring,+                       basic-prelude,+                       case-insensitive,+                       conduit,+                       conduit-extra,+                       http-types
+ src/Network/Ntrip/Client.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Network.Ntrip.Client where++import BasicPrelude+import Control.Concurrent.Async+import Data.Attoparsec.ByteString+import Data.Attoparsec.ByteString.Char8  (decimal, endOfLine, isEndOfLine)+import Data.ByteString.Base64+import Data.CaseInsensitive+import Data.Conduit+import Data.Conduit.Attoparsec+import Data.Conduit.Network+import Network.HTTP.Types++tcpClient :: ByteString -> Int -> Source IO ByteString -> Sink ByteString IO () -> IO ()+tcpClient host port source sink =+  runTCPClient (clientSettings port host) $ \ad ->+    void $ concurrently (source $$ appSink ad) (appSource ad $$ sink)++sourceNtrip :: ByteString -> ByteString -> ByteString -> Source IO ByteString -> Source IO ByteString+sourceNtrip path user password source = do+  yield $ intercalate "\r\n" $+    [ methodGet <> " " <> path <> " HTTP/1.0"+    , original hUserAgent <> ": NTRIP ntrip-client/0.0"+    , original hAuthorization <> ": " <> encode (user <> ":" <> password)+    , ""+    , ""+    ]+  source++parseNtrip :: Parser (ByteString, Status)+parseNtrip = do+  format   <- parseFormat+  code     <- parseCode+  message <- parseMessage+  return (format, Status code message)+  where+    takeSpace      = takeWhile1 (== 32)+    takeInClass    = takeWhile1 . inClass+    takeEndOfLine1 = takeWhile1 (not . isEndOfLine)+    parseFormat    = takeInClass "a-zA-Z0-9/." <* takeSpace+    parseCode      = decimal <* takeSpace+    parseMessage   = takeEndOfLine1 <* endOfLine++sinkNtrip :: Sink ByteString IO () -> Sink ByteString IO ()+sinkNtrip sink = do+  (format, status) <- sinkParser parseNtrip+  unless (format == "ICY") $ throwIO $ userError "Unsupported format"+  unless (status == status200) $ throwIO $ userError "Bad status"+  sink++runNtrip :: ByteString -> Int -> ByteString -> ByteString -> ByteString -> Source IO ByteString -> Sink ByteString IO () -> IO ()+runNtrip host port path user password source sink =+  tcpClient host port (sourceNtrip path user password source) (sinkNtrip sink)