11module Comm
22 ( IPPeer (.. ), parseHeader , localServer , serverDispatch , tunnel ,
3- toCharArray , fromCharArray
3+ buildHeader , toCharArray , fromCharArray
44 ) where
55
66import Network.Socket
@@ -21,7 +21,7 @@ import Debug.Trace
2121
2222import KTable
2323import Globals
24- import Kad (storeReceive , nodeLookupReceive , nodeLookupCallback , valueLookupCallback )
24+ import Kad -- (storeReceive, nodeLookupReceive, nodeLookupCallback, valueLookupCallback)
2525
2626-- TODO shut out nodes that are too chatty
2727-- Header: version - 1 byte
@@ -48,6 +48,13 @@ instance Peer IPPeer where
4848 sendLookupReply = sendLookupReplyIP
4949 sendStore = sendStoreIP
5050 sendValueReply = sendValueReplyIP
51+ sendToPeer = sendToPeerIP
52+ serPeer p = (serIP $ host p) ++ (serPort $ port p) ++ toCharArray (nodeId p) 20
53+
54+ deserIP = intercalate " ." . map (show . ord)
55+ serIP = map (chr . read ) . split ' .'
56+ deserPort = (show :: Int -> String ) . fromCharArray
57+ serPort = (flip toCharArray 2 ) . read
5158
5259instance Node IPPeer where
5360 nodeId = ipNodeId
@@ -65,35 +72,35 @@ data Header = Header { msgVersion ::Int, msgOp ::KadOp, msgUid ::Word64, sender
6572-- operation itself is tracked by a secondary id stored locally. Supports both
6673-- node and value lookup using the last boolean
6774sendLookupIP peers nid lookupId valL = forM peers (\ p -> do
68- msgId <- liftIO newUid
75+ msgId <- newUid
6976 me <- askLocalId
7077 let msg = buildHeader (if valL then ValueLookupOp else NodeLookupOp ) msgId me ++ toCharArray nid 20
7178
7279 newWaitingReply p (if valL then ValueLookupReplyOp else NodeLookupReplyOp ) msgId lookupId
73- liftIO $ sendToPeer msg p ) >> return ()
80+ liftIO $ sendToPeerIP msg p ) >> return ()
7481
7582-- Sends the reply to a node lookup query, sending k nodes and reproducing the
7683-- received message id.
7784sendLookupReplyIP peer nodes msgId valL = do
7885 me <- askLocalId
7986 let msg = buildHeader (if valL then ValueLookupReplyOp else NodeLookupReplyOp ) msgId me ++ serPeers nodes
80- liftIO $ sendToPeer msg peer
87+ liftIO $ sendToPeerIP msg peer
8188
8289sendValueReplyIP peer val msgId = do
8390 me <- askLocalId
8491 let msg = buildHeader ValueLookupReplyOp msgId me ++
8592 if length val `mod` 26 == 0 then val ++ " " else val
86- liftIO $ sendToPeer msg peer
93+ liftIO $ sendToPeerIP msg peer
8794
8895sendStoreIP peers key value storeId = forM peers (\ p -> do
89- msgId <- liftIO newUid
96+ msgId <- newUid
9097 me <- askLocalId
9198 let msg = buildHeader StoreOp msgId me ++ toCharArray key 20 ++ value
9299
93100 newWaitingReply p StoreReplyOp msgId storeId
94- liftIO $ sendToPeer msg p ) >> return ()
101+ liftIO $ sendToPeerIP msg p ) >> return ()
95102
96- sendToPeer msg peer = do
103+ sendToPeerIP msg peer = do
97104 phandle <- openPeerHandle (host peer) (port peer)
98105 sendstr phandle msg
99106 closePeerHandle phandle
@@ -176,6 +183,16 @@ parseHeader msg = runState parseHeader' msg
176183 put r
177184 return $ fn v
178185
186+ -- Deserializes peers from message strings using the opposite transformation from ser
187+ deserPeers = map deserPeer . splitEvery 26
188+ deserPeer s =
189+ let (h,rest) = splitAt 4 s
190+ (p,nid) = splitAt 2 rest
191+ in IPPeer (deserIP h) (deserPort p) (fromCharArray nid)
192+
193+ split delim = unfoldr (\ b -> fmap (const . (second $ drop 1 ) . break (== delim) $ b) . listToMaybe $ b)
194+ splitEvery n = takeWhile (not . null ) . unfoldr (Just . splitAt n)
195+
179196tunnel :: (SockAddr -> String -> ServerState p () ) -> ((SockAddr -> String -> IO () ) -> IO () ) -> ServerState p ()
180197tunnel f k = do
181198 gs <- ask
@@ -196,61 +213,11 @@ localServer port handlerFn = do
196213 handlerFn addr msg
197214 procMessages sock
198215
199-
200- -- Utility functions to serialize messages
201- --
202-
203- buildHeader optype msgId sender =
204- (chr 1 ) : optypeStr : toCharArray (toInteger msgId) 8 ++ serPeer sender
205- where optypeStr = case optype of
206- PingOp -> chr 1
207- PingReplyOp -> chr 2
208- NodeLookupOp -> chr 3
209- NodeLookupReplyOp -> chr 4
210- StoreOp -> chr 5
211- StoreReplyOp -> chr 6
212- ValueLookupOp -> chr 7
213- ValueLookupReplyOp -> chr 8
214-
215- -- Convert an integer to a string of n bytes
216- toCharArray :: Integer -> Int -> [Char ]
217- toCharArray num depth = map (chr . fromInteger ) (toBytes num $ toInteger depth)
218-
219- -- Converts a string to its numeric value by considering that each character is a
220- -- byte in a n byte number
221- fromCharArray :: (Bits a ) => [Char ] -> a
222- fromCharArray str = foldl (\ acc ch -> shift acc 8 + fromIntegral (ord ch)) 0 str
223-
224- -- Serializes peers
225- serPeers = concat . map serPeer
226- serPeer p = (serIP $ host p) ++ (serPort $ port p) ++ toCharArray (nodeId p) 20
227-
228- -- Deserializes peers from message strings using the opposite transformation from ser
229- deserPeers = map deserPeer . splitEvery 26
230- deserPeer s =
231- let (h,rest) = splitAt 4 s
232- (p,nid) = splitAt 2 rest
233- in IPPeer (deserIP h) (deserPort p) (fromCharArray nid)
234-
235- deserIP = intercalate " ." . map (show . ord)
236- serIP = map (chr . read ) . split ' .'
237- deserPort = (show :: Int -> String ) . fromCharArray
238- serPort = (flip toCharArray 2 ) . read
239-
240- split delim = unfoldr (\ b -> fmap (const . (second $ drop 1 ) . break (== delim) $ b) . listToMaybe $ b)
241- splitEvery n = takeWhile (not . null ) . unfoldr (Just . splitAt n)
242-
243- -- Decomposes a number into its successive byte values or, said differently, converts
244- -- a number to base 2^8.
245- toBytes :: Integer -> Integer -> [Integer ]
246- toBytes num depth = unfoldr byteMod (num,depth- 1 )
247- where byteMod (num,exp ) = let (d,m) = divMod num (2 ^ (exp * 8 ))
248- in if exp < 0 then Nothing else Just (d, (m,exp - 1 ))
249-
250216-- Build a new peer from packet address and header peer info
251217toPeer addr pr = let (h,p) = span (/= ' :' ) (show addr)
252218 in IPPeer h (port pr) (nodeId pr)
253219
220+
254221-- Tried below but host is a Word 32...
255222-- case addr of
256223-- SockAddrInet port host -> Peer (show host) (show port) (-1)
0 commit comments