packages feed

Scurry-0.0.2: src/Scurry/Types/Network.hs

{-# OPTIONS -XGeneralizedNewtypeDeriving #-}

module Scurry.Types.Network (
    MACAddr(..),
    EthernetHeader(..),
    SrcMAC,
    DstMAC,
    EthType,
    EndPoint(..),
    ScurryAddress(..),
    ScurryMask,
    ScurryPort(..),
    epToSa,
    saToEp,
) where

import Data.Binary
import Numeric
import Network.Socket (inet_ntoa,HostAddress,PortNumber(..),SockAddr(..))
import Network.Util
import Control.Monad (liftM,liftM2)
import System.IO.Unsafe (unsafePerformIO)

-- | MAC Address (6 8-bit words)
data MACAddr = MACAddr (Word8,Word8,Word8,Word8,Word8,Word8)
    deriving (Eq,Ord)

instance Show MACAddr where
    show (MACAddr (a,b,c,d,e,f)) = let s = flip showHex ":"
                                       l = flip showHex ""
                                   in concat [s a, s b, s c,
                                              s d, s e, l f]

instance Binary MACAddr where
    get = do
        { o1 <- get ; o2 <- get ; o3 <- get 
        ; o4 <- get ; o5 <- get ; o6 <- get 
        ; return $ MACAddr (o1,o2,o3,o4,o5,o6) }
    put (MACAddr (o1,o2,o3,o4,o5,o6)) = do
        { put o1 ; put o2 ; put o3
        ; put o4 ; put o5 ; put o6 }

data EthernetHeader = EthernetHeader DstMAC SrcMAC EthType
type SrcMAC = MACAddr
type DstMAC = MACAddr
type EthType = Word16

instance Show EthernetHeader where
    show (EthernetHeader d s t) = concat ["{EthHdr ", (show s),
                                          " -> ", (show d),
                                          " :: 0x", (showHex t "}")]

instance Binary EthernetHeader where
    get = do
        { d <- get ; s <- get ; t <- get
        ; return $ EthernetHeader d s t }
    put (EthernetHeader d s t) = do
        { put d ; put s ; put t }

type ScurryMask = ScurryAddress

newtype ScurryAddress = ScurryAddress {
    scurryAddr :: HostAddress
} deriving (Eq,Ord)

instance Enum ScurryAddress where
    succ (ScurryAddress a) = ScurryAddress $ htonl $ ntohl a + 1
    pred (ScurryAddress a) = ScurryAddress $ htonl $ ntohl a - 1
    toEnum = ScurryAddress . htonl . fromIntegral
    fromEnum (ScurryAddress a) = fromEnum (ntohl a)

instance Show ScurryAddress where
    -- We use unsafePerformIO here to avoid referencing the
    -- version of inet_ntoa in Scurry.Util since this would
    -- cause a cycle. TODO: Fix this later.
    show (ScurryAddress ha) = unsafePerformIO $ inet_ntoa ha

newtype ScurryPort = ScurryPort PortNumber
    deriving (Eq,Ord)

instance Show ScurryPort where
    show (ScurryPort pn) = show pn

data EndPoint = EndPoint ScurryAddress ScurryPort
    deriving (Show,Eq,Ord)

epToSa :: EndPoint -> SockAddr
epToSa (EndPoint (ScurryAddress ha) (ScurryPort pn)) = SockAddrInet pn ha 

saToEp :: SockAddr -> EndPoint
saToEp (SockAddrInet pn ha) = EndPoint (ScurryAddress ha) (ScurryPort pn)
saToEp _ = error "ERROR: Only IPV4 addresses are supported for now."

instance Binary ScurryPort where
    get = liftM (ScurryPort . PortNum) get
    put (ScurryPort (PortNum p)) = put p

instance Binary ScurryAddress where
    get = liftM ScurryAddress get
    put (ScurryAddress ha) = put ha

instance Binary EndPoint where
    get = do tag <- getWord8
             case tag of
                  0 -> liftM2 EndPoint get get
                  -- 1 -> liftM4 SockAddrInet6 get get get get -- #Job removed, not compatable with windows
                  -- 2 -> liftM SockAddrUnix get
                  _ -> error "Not a EndPoint"
    put (EndPoint sa sp) =
        do putWord8 0
           put sa
           put sp
    -- #Job - removed, not compatable with windows
    -- put (SockAddrInet6 pn fi ha si) =
        -- do putWord8 1
           -- put pn
           -- put fi
           -- put ha
           -- put si
    -- put (SockAddrUnix s) =
        -- do putWord8 2
           -- put s