summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Core.hs
blob: 6024f5a5b5b72ab3677cf40a56e367f0778fdf49 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
-- |
--   Copyright   :  (c) Sam Truzjan 2013
--   License     :  BSD3
--   Maintainer  :  pxqr.sta@gmail.com
--   Stability   :  experimental
--   Portability :  portable
--
--   Re-export every @Network.BitTorrent.Core.*@ module.
--
module Network.BitTorrent.Core
       ( module Core
       , Address (..)

         -- * Re-exports from Data.IP
       , IPv4
       , IPv6
       , IP (..)
       ) where

import Control.Applicative
import Data.IP
import Data.Serialize
import Data.Typeable
import Network.Socket (SockAddr (..), PortNumber)

import Network.BitTorrent.Core.Fingerprint as Core
import Network.BitTorrent.Core.Node        as Core
import Network.BitTorrent.Core.PeerId      as Core
import Network.BitTorrent.Core.PeerAddr    as Core


class (Eq a, Serialize a, Typeable a) => Address a where
  toSockAddr   :: a        -> SockAddr
  fromSockAddr :: SockAddr -> Maybe a

-- | Note that port is zeroed.
instance Address IPv4 where
  toSockAddr = SockAddrInet 0 . toHostAddress
  fromSockAddr (SockAddrInet _ h) = Just (fromHostAddress h)
  fromSockAddr  _                 = Nothing

-- | Note that port is zeroed.
instance Address IPv6 where
  toSockAddr h = SockAddrInet6 0 0 (toHostAddress6 h) 0
  fromSockAddr (SockAddrInet6 _ _ h _) = Just (fromHostAddress6 h)
  fromSockAddr  _                      = Nothing

-- | Note that port is zeroed.
instance Address IP where
  toSockAddr (IPv4 h) = toSockAddr h
  toSockAddr (IPv6 h) = toSockAddr h
  fromSockAddr sa =
        IPv4 <$> fromSockAddr sa
    <|> IPv6 <$> fromSockAddr sa

setPort :: PortNumber -> SockAddr -> SockAddr
setPort port (SockAddrInet  _   h  ) = SockAddrInet  port   h
setPort port (SockAddrInet6 _ f h s) = SockAddrInet6 port f h s
setPort _    (SockAddrUnix  s      ) = SockAddrUnix  s
{-# INLINE setPort #-}

getPort :: SockAddr -> Maybe PortNumber
getPort (SockAddrInet  p   _  ) = Just p
getPort (SockAddrInet6 p _ _ _) = Just p
getPort (SockAddrUnix  _      ) = Nothing
{-# INLINE getPort #-}

instance Address a => Address (NodeAddr a) where
  toSockAddr NodeAddr {..} = setPort nodePort $ toSockAddr nodeHost
  fromSockAddr sa = NodeAddr <$> fromSockAddr sa <*> getPort sa

instance Address a => Address (PeerAddr a) where
  toSockAddr PeerAddr {..} = setPort peerPort $ toSockAddr peerHost
  fromSockAddr sa = PeerAddr Nothing <$> fromSockAddr sa <*> getPort sa