diff options
Diffstat (limited to 'src/Network/BitTorrent/Peer.hs')
-rw-r--r-- | src/Network/BitTorrent/Peer.hs | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/src/Network/BitTorrent/Peer.hs b/src/Network/BitTorrent/Peer.hs index 9aa924d3..41630c6d 100644 --- a/src/Network/BitTorrent/Peer.hs +++ b/src/Network/BitTorrent/Peer.hs | |||
@@ -44,12 +44,14 @@ module Network.BitTorrent.Peer | |||
44 | 44 | ||
45 | -- ** Generation | 45 | -- ** Generation |
46 | , newPeerID, timestampByteString | 46 | , newPeerID, timestampByteString |
47 | |||
47 | -- ** Extra | 48 | -- ** Extra |
48 | , byteStringPadded | 49 | , byteStringPadded |
49 | 50 | ||
50 | -- * Peer address | 51 | -- * Peer address |
51 | , PeerAddr(..) | 52 | , PeerAddr(..) |
52 | , peerSockAddr, connectToPeer | 53 | , peerSockAddr |
54 | , connectToPeer, forkListener | ||
53 | , ppPeer | 55 | , ppPeer |
54 | 56 | ||
55 | -- * Client version detection | 57 | -- * Client version detection |
@@ -66,6 +68,8 @@ module Network.BitTorrent.Peer | |||
66 | 68 | ||
67 | 69 | ||
68 | import Control.Applicative | 70 | import Control.Applicative |
71 | import Control.Concurrent | ||
72 | import Control.Exception | ||
69 | import Data.BEncode | 73 | import Data.BEncode |
70 | import Data.Bits | 74 | import Data.Bits |
71 | import Data.Word | 75 | import Data.Word |
@@ -84,7 +88,7 @@ import Data.Time.Format (formatTime) | |||
84 | import Text.PrettyPrint (text, Doc, (<+>)) | 88 | import Text.PrettyPrint (text, Doc, (<+>)) |
85 | import System.Locale (defaultTimeLocale) | 89 | import System.Locale (defaultTimeLocale) |
86 | 90 | ||
87 | import Network | 91 | import Network hiding (accept) |
88 | import Network.Socket | 92 | import Network.Socket |
89 | 93 | ||
90 | 94 | ||
@@ -489,7 +493,8 @@ data PeerAddr = PeerAddr { | |||
489 | , peerIP :: HostAddress | 493 | , peerIP :: HostAddress |
490 | , peerPort :: PortNumber | 494 | , peerPort :: PortNumber |
491 | } deriving (Show, Eq, Ord) | 495 | } deriving (Show, Eq, Ord) |
492 | -- TODO verify semantic of ord and eq instances | 496 | |
497 | -- TODO check semantic of ord and eq instances | ||
493 | 498 | ||
494 | instance BEncodable PortNumber where | 499 | instance BEncodable PortNumber where |
495 | toBEncode = toBEncode . fromEnum | 500 | toBEncode = toBEncode . fromEnum |
@@ -535,6 +540,28 @@ connectToPeer p = do | |||
535 | connect sock (peerSockAddr p) | 540 | connect sock (peerSockAddr p) |
536 | return sock | 541 | return sock |
537 | 542 | ||
543 | |||
544 | forkListener :: ((PeerAddr, Socket) -> IO ()) -> IO PortNumber | ||
545 | forkListener action = do | ||
546 | sock <- socket AF_INET Stream defaultProtocol | ||
547 | bindSocket sock (SockAddrInet 0 0) | ||
548 | listen sock 1 | ||
549 | addr <- getSocketName sock | ||
550 | case addr of | ||
551 | SockAddrInet port _ -> do | ||
552 | forkIO (loop sock) | ||
553 | return port | ||
554 | _ -> do | ||
555 | throwIO $ userError "listener: impossible happened" | ||
556 | where | ||
557 | loop sock = do | ||
558 | (conn, addr) <- accept sock | ||
559 | case addr of | ||
560 | SockAddrInet port host -> | ||
561 | action (PeerAddr Nothing host port, conn) | ||
562 | _ -> return () | ||
563 | loop sock | ||
564 | |||
538 | -- | Pretty print peer address in human readable form. | 565 | -- | Pretty print peer address in human readable form. |
539 | ppPeer :: PeerAddr -> Doc | 566 | ppPeer :: PeerAddr -> Doc |
540 | ppPeer p @ PeerAddr {..} = case peerID of | 567 | ppPeer p @ PeerAddr {..} = case peerID of |