From b4d3b295f75538234d82025617bc7cad6b4e9d19 Mon Sep 17 00:00:00 2001 From: Sam Truzjan Date: Thu, 26 Dec 2013 00:47:10 +0400 Subject: Add IsString instance to NodeInfos --- src/Network/BitTorrent/Core/Node.hs | 58 +++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) (limited to 'src/Network/BitTorrent/Core/Node.hs') diff --git a/src/Network/BitTorrent/Core/Node.hs b/src/Network/BitTorrent/Core/Node.hs index 0cb95dd2..f6ab7d82 100644 --- a/src/Network/BitTorrent/Core/Node.hs +++ b/src/Network/BitTorrent/Core/Node.hs @@ -1,4 +1,21 @@ +-- | +-- Module : Network.BitTorrent.Core.Node +-- Copyright : (c) Sam Truzjan 2013 +-- (c) Daniel Gröber 2013 +-- License : BSD3 +-- Maintainer : pxqr.sta@gmail.com +-- Stability : experimental +-- Portability : portable +-- +-- A \"node\" is a client\/server listening on a UDP port +-- implementing the distributed hash table protocol. The DHT is +-- composed of nodes and stores the location of peers. BitTorrent +-- clients include a DHT node, which is used to contact other nodes +-- in the DHT to get the location of peers to download from using +-- the BitTorrent protocol. +-- {-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE DeriveDataTypeable #-} @@ -22,23 +39,29 @@ import Data.Bits import Data.ByteString as BS import Data.BEncode as BE import Data.Default +import Data.IP +import Data.List as L import Data.Ord -import Data.Typeable import Data.Serialize as S +import Data.String +import Data.Typeable import Data.Word import Network import System.Entropy import Data.Torrent.JSON -import Network.BitTorrent.Core.PeerAddr () +import Network.BitTorrent.Core.PeerAddr (PeerAddr (..)) {----------------------------------------------------------------------- -- Node id -----------------------------------------------------------------------} -- TODO more compact representation ('ShortByteString's?) --- | Normally, /this/ node id should we saved between invocations of --- the client software. +-- | Each node has a globally unique identifier known as the \"node +-- ID.\" +-- +-- Normally, /this/ node id should we saved between invocations +-- of the client software. newtype NodeId = NodeId ByteString deriving (Show, Eq, Ord, BEncode, FromJSON, ToJSON, Typeable) @@ -55,6 +78,13 @@ instance Serialize NodeId where put (NodeId bs) = putByteString bs {-# INLINE put #-} +-- | ASCII encoded. +instance IsString NodeId where + fromString str + | L.length str == nodeIdSize = NodeId (fromString str) + | otherwise = error "fromString: invalid NodeId length" + {-# INLINE fromString #-} + -- | Test if the nth bit is set. testIdBit :: NodeId -> Word -> Bool testIdBit (NodeId bs) i @@ -85,7 +115,9 @@ $(deriveJSON omitRecordPrefix ''NodeAddr) -- | KRPC compatible encoding. instance Serialize a => Serialize (NodeAddr a) where get = NodeAddr <$> get <*> get + {-# INLINE get #-} put NodeAddr {..} = put nodeHost >> put nodePort + {-# INLINE put #-} -- | Torrent file compatible encoding. instance BEncode a => BEncode (NodeAddr a) where @@ -94,6 +126,19 @@ instance BEncode a => BEncode (NodeAddr a) where fromBEncode b = uncurry NodeAddr <$> fromBEncode b {-# INLINE fromBEncode #-} +-- | Example: +-- +-- @nodePort \"127.0.0.1:6881\" == 6881@ +-- +instance IsString (NodeAddr IPv4) where + fromString = fromPeerAddr . fromString + +fromPeerAddr :: PeerAddr a -> NodeAddr a +fromPeerAddr PeerAddr {..} = NodeAddr + { nodeHost = peerHost + , nodePort = peerPort + } + {----------------------------------------------------------------------- -- Node info -----------------------------------------------------------------------} @@ -108,7 +153,10 @@ $(deriveJSON omitRecordPrefix ''NodeInfo) instance Eq a => Ord (NodeInfo a) where compare = comparing nodeId --- | KRPC 'compact list' compatible encoding. +-- | KRPC 'compact list' compatible encoding: contact information for +-- nodes is encoded as a 26-byte string. Also known as "Compact node +-- info" the 20-byte Node ID in network byte order has the compact +-- IP-address/port info concatenated to the end. instance Serialize a => Serialize (NodeInfo a) where get = NodeInfo <$> get <*> get put NodeInfo {..} = put nodeId >> put nodeAddr -- cgit v1.2.3