moesocks-1.0.0.44: src/Network/MoeSocks/Common.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Network.MoeSocks.Common where
import Control.Lens
import Control.Monad.Writer hiding (listen)
import Data.IP (IPRange, isMatchedTo)
import Data.Maybe (isJust)
import Data.Text.Lens
import Network.Socket (SockAddr(..), Socket(..), SocketType(..), Family(..))
import Network.Socket (setSocketOption, SocketOption(..))
import Network.MoeSocks.Type
import Network.MoeSocks.Helper ((-), tryIO, error_)
import Network.MoeSocks.Helper (setSocket_TCP_NOTSENT_LOWAT, getSocketWithHint)
import Prelude hiding ((-), take)
makePrisms ''IPRange
check_IP_List :: AddressType -> [IPRange] -> Bool
check_IP_List _address@(IPv4_Address _) a_IP_List =
isJust -
do
_ip <- show _address ^? _Show
findOf (each . _IPv4Range) (isMatchedTo _ip) a_IP_List
check_IP_List _address@(IPv6_Address _) a_IP_List =
isJust -
do
_ip <- show _address ^? _Show
findOf (each . _IPv6Range) (isMatchedTo _ip) a_IP_List
check_IP_List _ _ = False
withChecked_IP_List :: AddressType -> ([IPRange], Maybe [IPRange])
-> IO a -> IO ()
withChecked_IP_List aAddressType (aDenyList, aAllowList) aIO =
if check_IP_List aAddressType aDenyList
then error_ - show aAddressType
<> " is in the denied list"
else
case aAllowList of
Nothing -> () <$ aIO
Just _allowList ->
if not - check_IP_List aAddressType _allowList
then error_ - show aAddressType
<> " is NOT in the allowed list"
else
() <$ aIO
getIPLists :: Env -> ([IPRange], Maybe [IPRange])
getIPLists aEnv = (aEnv ^. denyList <> aEnv ^. forbidden_IPs, mempty)
showConnectionType :: ConnectionType -> String
showConnectionType TCP_IP_StreamConnection = "TCP_Stream"
-- showConnectionType TCP_IP_PortBinding = "TCP_Bind "
showConnectionType UDP_Port = "UDP "
showRequest :: ClientRequest -> String
showRequest _r =
_r ^. addressType . to show
<> ":"
<> _r ^. portNumber . to show
showRelay :: SockAddr -> ClientRequest -> String
showRelay aSockAddr aClientRequest =
show aSockAddr <> " -> " <> showRequest aClientRequest
addressType_To_Family :: AddressType -> Family
addressType_To_Family (IPv4_Address _) = AF_INET
addressType_To_Family (IPv6_Address _) = AF_INET6
addressType_To_Family _ = AF_UNSPEC
_SocketType :: Prism' SocketType ConnectionType
_SocketType = prism' connectionType_To_SocketType socketType_To_connectionType
where
connectionType_To_SocketType :: ConnectionType -> SocketType
connectionType_To_SocketType TCP_IP_StreamConnection = Stream
{-connectionType_To_SocketType TCP_IP_PortBinding = NoSocketType-}
connectionType_To_SocketType UDP_Port = Datagram
socketType_To_connectionType :: SocketType -> Maybe ConnectionType
socketType_To_connectionType Stream = Just TCP_IP_StreamConnection
socketType_To_connectionType Datagram = Just UDP_Port
socketType_To_connectionType _ = Nothing
initTarget :: ClientRequest -> IO (Socket, SockAddr)
initTarget _clientRequest = do
let
_socketType = _clientRequest ^. connectionType . re _SocketType
_hostName = _clientRequest ^. addressType . to show . re _Text
_port = _clientRequest ^. portNumber
_family = _clientRequest ^. addressType . to addressType_To_Family
getSocketWithHint _family _hostName _port _socketType
setSocketConfig:: Env -> Socket -> IO ()
setSocketConfig aEnv aSocket = do
setSocketOption aSocket NoDelay 1
-- keepalive
setSocketOption aSocket KeepAlive 1
when (aEnv ^. socketOption_TCP_NOTSENT_LOWAT) - do
tryIO "setSocket_TCP_NOTSENT_LOWAT" - setSocket_TCP_NOTSENT_LOWAT aSocket
pure ()