@@ -25,9 +25,10 @@ generator with a psuedo-random number.
25module Data.UUID.V1(nextUUID)
25module Data.UUID.V1(nextUUID)
30import Data.Bits
29import Data.Bits
31import Data.Word
32import Data.Word
33import Control.Applicative ((<$>),(<*>))
34import Control.Applicative ((<$>),(<*>))
@@ -36,8 +37,7 @@ import System.IO.Unsafe
37import qualified System.Random as R
38import qualified System.Random as R
39−import qualified System.Info.MAC as SysMAC
40+import Network.Info
42import Data.UUID.Builder
42import Data.UUID.Builder
43import Data.UUID.Internal
43import Data.UUID.Internal
@@ -52,13 +52,13 @@ nextUUID :: IO (Maybe UUID)
52nextUUID = do
52nextUUID = do
53 res <- stepTime
53 res <- stepTime
54 case res of
54 case res of
55− Just (mac, c, t) -> return $ Just $ makeUUID t c mac
55+ Just (mac', c, t) -> return $ Just $ makeUUID t c mac'
56 _ -> return Nothing
56 _ -> return Nothing
59makeUUID :: Word64 -> Word16 -> MAC -> UUID
59makeUUID :: Word64 -> Word16 -> MAC -> UUID
60−makeUUID time clock mac =
60+makeUUID time clock mac' =
61− buildFromBytes 1 /-/ tLow /-/ tMid /-/ tHigh /-/ clock /-/ (MACSource mac)
61+ buildFromBytes 1 /-/ tLow /-/ tMid /-/ tHigh /-/ clock /-/ (MACSource mac')
62 where tLow = (fromIntegral time) :: Word32
62 where tLow = (fromIntegral time) :: Word32
63 tMid = (fromIntegral (time `shiftR` 32)) :: Word16
63 tMid = (fromIntegral (time `shiftR` 32)) :: Word16
64 tHigh = (fromIntegral (time `shiftR` 48)) :: Word16
64 tHigh = (fromIntegral (time `shiftR` 48)) :: Word16
@@ -75,17 +75,17 @@ type instance ByteSink MACSource g = Takes3Bytes (Takes3Bytes g)
75stepTime :: IO (Maybe (MAC, Word16, Word64))
75stepTime :: IO (Maybe (MAC, Word16, Word64))
76stepTime = do
76stepTime = do
77 h1 <- fmap hundredsOfNanosSinceGregorianReform getCurrentTime
77 h1 <- fmap hundredsOfNanosSinceGregorianReform getCurrentTime
78− modifyMVar state $ \s@(State mac c0 h0) ->
78+ modifyMVar state $ \s@(State mac' c0 h0) ->
79 if h1 > h0
79 if h1 > h0
81− return (State mac c0 h1, Just (mac, c0, h1))
81+ return (State mac' c0 h1, Just (mac', c0, h1))
84 c1 = succ c0
84 c1 = succ c0
85 in if c1 <= 0x3fff -- when clock is initially randomized,
85 in if c1 <= 0x3fff -- when clock is initially randomized,
86 -- then this test will need to change
86 -- then this test will need to change
88− return (State mac c1 h1, Just (mac, c1, h1))
88+ return (State mac' c1 h1, Just (mac', c1, h1))
90 return (s, Nothing)
90 return (s, Nothing)
@@ -94,16 +94,17 @@ stepTime = do
94state :: MVar State
94state :: MVar State
95state = unsafePerformIO $ do
95state = unsafePerformIO $ do
96 h0 <- fmap hundredsOfNanosSinceGregorianReform getCurrentTime
96 h0 <- fmap hundredsOfNanosSinceGregorianReform getCurrentTime
97− mac <- getMac
97+ mac' <- getMac
98− newMVar $ State mac 0 h0 -- the 0 should be a random number
98+ newMVar $ State mac' 0 h0 -- the 0 should be a random number
100-- SysMAC.mac can fail on some machines.
100-- SysMAC.mac can fail on some machines.
101-- In those cases we fake it with a random
101-- In those cases we fake it with a random
102-- 6 bytes seed.
102-- 6 bytes seed.
103getMac :: IO MAC
103getMac :: IO MAC
105− SysMAC.mac >>= \macM ->
105+ getNetworkInterfaces >>=
106+ return . listToMaybe . filter (minBound /=) . map mac >>=
106− case macM of
107+ \macM -> case macM of
107 Just m -> return m
108 Just m -> return m
108 Nothing -> randomMac
109 Nothing -> randomMac
@@ -112,7 +113,7 @@ randomMac =
112 -- I'm too lazy to thread through
113 -- I'm too lazy to thread through
113 -- the random state ...
114 -- the random state ...
115− <$> R.randomIO
116+ <$> (R.randomIO >>= return . (1 .|.)) -- We must set the multicast bit to True. See section 4.5 of the RFC.
116 <*> R.randomIO
117 <*> R.randomIO
117 <*> R.randomIO
118 <*> R.randomIO
118 <*> R.randomIO
119 <*> R.randomIO