@@ -3,62 +3,89 @@ module Main where
3import Network.Transport
3import Network.Transport
4import Network.Transport.TCP
4import Network.Transport.TCP
6−import System.Environment
7import Control.Monad
6import Control.Monad
7+import Network.Socket (HostName, ServiceName)
8+import System.Environment
8import qualified Data.ByteString.Char8 as BS
10import qualified Data.ByteString.Char8 as BS
10type ChanId = Int
14type ChanId = Int
12-- | This example demonstrates how a master can be connected to slaves using
16-- | This example demonstrates how a master can be connected to slaves using
13-- the transport layer.
17-- the transport layer.
14main :: IO ()
18main :: IO ()
16− [mode, numberStr, host, service, chanId] <- getArgs
20+ args <- getArgs
17− case mode of
21+ case args of
18− "master" -> do
22+ -- Master:
19− let number = read numberStr
23+ -- The master only provides the host, service, and slaves to expect.
24+ [host, service, sendAddrFilePath, number] -> do
25+ let numSlaves = read number
20 transport <- mkTransport $ TCPConfig defaultHints host service
26 transport <- mkTransport $ TCPConfig defaultHints host service
22− (clients, masterReceiveEnd) <- demoMaster number transport host service
27+ (clientSendEnds, masterReceiveEnd) <- demoMaster transport sendAddrFilePath numSlaves
24 (\clientSendEnd clientId -> send clientSendEnd [BS.pack . show $ clientId])
29 (\clientSendEnd clientId -> send clientSendEnd [BS.pack . show $ clientId])
25− clients [0 .. number-1]
30+ clientSendEnds [0 .. numSlaves-1]
26− replicateM_ number $ do
31+ replicateM_ numSlaves $ do
27 [clientMessage] <- receive masterReceiveEnd
32 [clientMessage] <- receive masterReceiveEnd
28 print clientMessage
33 print clientMessage
30− "slave" -> do
35+ -- Slave:
36+ -- Each slave provides its own host and service, as well as details of
37+ -- the master it wishes to connect to.
38+ [host, service, sendAddrFilePath] -> do
39+ transport <- mkTransport $ TCPConfig defaultHints host service
31− (masterSendEnd, slaveReceiveEnd) <- demoSlave transport host service
40+ (masterSendEnd, slaveReceiveEnd) <- demoSlave transport sendAddrFilePath
32 [clientId] <- receive slaveReceiveEnd
41 [clientId] <- receive slaveReceiveEnd
42+ putStrLn $ "slave: received clientId: " ++ show clientId
33 let message = "Connected to slave: " ++ BS.unpack clientId
43 let message = "Connected to slave: " ++ BS.unpack clientId
34 send masterSendEnd [BS.pack message]
45 send masterSendEnd [BS.pack message]
46+ putStrLn "slave: sent message to master"
48+ _ -> error "Unexpected arguments"
50+demoMaster :: Transport -- ^ Transport
51+ -> FilePath -- ^ File to write SendAddr
36−demoMaster :: Int -- ^ Number of slaves
52+ -> Int -- ^ Number of slaves to expect
37− -> Transport -- ^ Transport
38− -> HostName -- ^ HostName of the master node
39− -> ServiceName -- ^ ServiceName of the master node
40 -> IO ([SendEnd], ReceiveEnd)
53 -> IO ([SendEnd], ReceiveEnd)
41−demoMaster numSlaves transport host service = do
54+demoMaster transport sendAddrFilePath numSlaves = do
42− trans <- mkTransport defaultHints host service
55+ -- Establish an initial transport
43− (sendAddr, receiveEnd) <- connect trans
56+ (sendAddr, receiveEnd) <- newConnection transport
58+ -- Write a file containing the sendAddr
44− putStrLn $ "Master sendAddr:" ++ show . serialize $ sendAddr
59+ putStrLn $ "master: writing sendAddr file:" ++ (show . serialize $ sendAddr)
60+ BS.writeFile sendAddrFilePath $ serialize sendAddr
62+ -- Deserialize each of the sendEnds received by the slaves
46 sendEnds <- replicateM numSlaves $ do
63 sendEnds <- replicateM numSlaves $ do
47 [bytes] <- receive receiveEnd
64 [bytes] <- receive receiveEnd
65+ putStrLn "master: received connection."
48 case deserialize transport bytes of
66 case deserialize transport bytes of
49− Nothing -> fail "Garbage message from slave"
67+ Nothing -> fail "Garbage message from slave!"
50 Just sendAddr -> connect sendAddr
68 Just sendAddr -> connect sendAddr
51 return (sendEnds, receiveEnd)
69 return (sendEnds, receiveEnd)
53demoSlave :: Transport -- ^ Transport
71demoSlave :: Transport -- ^ Transport
54− -> HostName -- ^ The master HostName
72+ -> FilePath -- ^ File to read SendAddr
55− -> ServiceName -- ^ The master ServiceName
56− -> ChanId -- ^ The master ChanId
57 -> IO (SendEnd, ReceiveEnd)
73 -> IO (SendEnd, ReceiveEnd)
58−demoSlave transport host service chanId = do
74+demoSlave transport masterSendAddrFilePath = do
59− sendAddr <- mkSendAddr host service chanId
75+ -- Create a new connection on the transport
60− (selfSendAddr, selfReceiveEnd) <- newConnection transport
76+ (sendAddr, receiveEnd) <- newConnection transport
61− sendEnd <- connect (newSendAddr host service)
77+
62− send sendEnd [serialize selfSendAddr]
78+ -- Establish connection with the master
63− return (sendEnd, selfReceiveEnd)
79+ bytes <- BS.readFile masterSendAddrFilePath
80+ case deserialize transport bytes of
81+ Just masterSendAddr -> do
82+ putStrLn $ "slave: connecting to sendAddr: " ++ (show . serialize $ masterSendAddr)
83+ masterSendEnd <- connect masterSendAddr
85+ -- Send the serialized address of this slave
86+ send masterSendEnd [serialize sendAddr]
87+ putStrLn "slave: sent sendAddr"
88+ return (masterSendEnd, receiveEnd)
90+ Nothing -> error "slave: Unable to deserialize master SendAddr!"