{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -- |Routines for parsing and rendering the default directories included in this -- binary. module Tor.DataFormat.DefaultDirectory( DefaultDirectory(..) , parseDefaultDirectory ) where import Data.Attoparsec.ByteString import Data.ByteString(ByteString) import Data.Word import Tor.DataFormat.Helpers -- |A default directory for pulling consensus and other data. data DefaultDirectory = DefaultDirectory { ddirNickname :: String , ddirIsBridge :: Bool , ddirAddress :: String , ddirOnionPort :: Word16 , ddirDirPort :: Word16 , ddirV3Ident :: Maybe ByteString , ddirFingerprint :: ByteString } deriving (Show) -- FIXME: Make this handle partial input -- |Parse a directory structure. parseDefaultDirectory :: ByteString -> Either String DefaultDirectory parseDefaultDirectory bstr = case parse defaultDirectory bstr of Fail _ _ err -> Left err Partial _ -> Left "Incomplete default directory!" Done _ res -> Right res defaultDirectory :: Parser DefaultDirectory defaultDirectory = do ddirNickname <- nickname _ <- sp _ <- string "orport=" ddirOnionPort <- port False _ <- sp ddirV3Ident <- option Nothing $ do res <- v3Ident _ <- sp return (Just res) ddirIsBridge <- option False $ do _ <- string "bridge " return True (ddirAddress, ddirDirPort) <- addrPort ddirFingerprint <- fingerprint return DefaultDirectory{..} v3Ident :: Parser ByteString v3Ident = do _ <- string "v3ident=" hexDigest addrPort :: Parser (String, Word16) addrPort = do a <- ip4 _ <- char8 ':' p <- port False return (a, p) fingerprint :: Parser ByteString fingerprint = do parts <- count 10 (sp >> toString `fmap` count 4 hexDigit) return (readHex (concat parts))