moesocks-1.0.0.43: src/Network/MoeSocks/UDP.hs
{-# LANGUAGE OverloadedStrings #-}
module Network.MoeSocks.UDP where
import Control.Exception (throwIO)
import Control.Lens
import Control.Monad (when)
import Data.Monoid ((<>))
import Data.Attoparsec.ByteString (IResult(Done), parse)
import Data.ByteString (ByteString)
import qualified Data.ByteString as S
import qualified Data.Strict as S
import Data.Text (Text)
import Network.Socket (Socket, SockAddr)
import Network.Socket (connect, SocketType(Datagram))
import Network.Socket.ByteString (sendAllTo)
import Network.MoeSocks.BuilderAndParser (shadowSocksRequestParser)
import Network.MoeSocks.BuilderAndParser (shadowSocksRequestBuilder)
import Network.MoeSocks.BuilderAndParser (sockAddr_To_Pair)
import Network.MoeSocks.Common (withChecked_IP_List, showRelay, initTarget, getIPLists)
import Network.MoeSocks.Type
import Network.MoeSocks.Helper ((-), recv_UDP, info_, debug_, send_)
import Network.MoeSocks.Helper (logSA, getSocket, ParseException(ParseException))
import Network.MoeSocks.Helper (builder_To_ByteString)
import Prelude hiding ((-), take)
buildShadowSocksRequest :: ClientRequest -> ByteString -> ByteString
buildShadowSocksRequest aClientRequest aMessage =
let _header = shadowSocksRequestBuilder aClientRequest
in
builder_To_ByteString _header <> aMessage
parseShadowSocksRequest :: ByteString -> IO (ByteString, ClientRequest)
parseShadowSocksRequest aMessage =
case parse (shadowSocksRequestParser UDP_Port) aMessage of
Done _i _r -> pure (_i, _r)
_ -> throwIO - ParseException -
"R Failed to parse UDP request"
processAll :: Cipher -> ByteString -> IO ByteString
processAll f x =
(<>) <$> f (S.Just x) <*> f S.Nothing
local_UDP_ForwardRequestHandler :: Env
-> Text
-> Port
-> Forward
-> ByteString
-> (Socket,SockAddr)
-> IO ()
local_UDP_ForwardRequestHandler aEnv
aRemoteHost
aRemotePort
aForwarding
aMessage
(aSocket, aSockAddr) = do
let
_cipherBox = aEnv ^. cipherBox
let _clientRequest = ClientRequest
UDP_Port
(DomainName - aForwarding ^.
forwardTargetHost)
(aForwarding ^. forwardTargetPort)
{-debug_ - "L UDP: " <> show _clientRequest-}
let _addr = _clientRequest ^. addressType
_IPLists = getIPLists aEnv
debug_ - "checking: " <> show _addr
withChecked_IP_List _addr _IPLists - do
_sa <- getSocket aRemoteHost aRemotePort Datagram
logSA "L UDP -->:" (pure _sa) -
\(_remoteSocket, _remoteAddr) -> do
connect _remoteSocket _remoteAddr
_encodeIV <- _cipherBox ^. generate_IV
_encrypt <- _cipherBox ^. encryptBuilder - _encodeIV
{-let (_encrypt, _decrypt) = (pure, pure)-}
let _bytes = buildShadowSocksRequest _clientRequest aMessage
{-debug_ - "L UDP sending: " <> show _bytes-}
let _msg = showRelay aSockAddr _clientRequest
info_ - "LU: " <> _msg
_eMsg <- _encrypt (S.Just _bytes)
send_ _remoteSocket - _encodeIV <> _eMsg
_response <- recv_UDP _remoteSocket
let (_decodeIV, _responseMsg) = S.splitAt (_cipherBox ^. ivLength)
_response
_decrypt <- _cipherBox ^. decryptBuilder - _decodeIV
(_r, _) <- processAll _decrypt _responseMsg
>>= parseShadowSocksRequest
when (_r & isn't _Empty) - do
sendAllTo aSocket _r aSockAddr
remote_UDP_RequestHandler :: Env
-> ByteString
-> (Socket, SockAddr)
-> IO ()
remote_UDP_RequestHandler aEnv
aMessage
(aSocket, aSockAddr) = do
let _cipherBox = aEnv ^. cipherBox
let (_decodeIV, _eMsg) = S.splitAt (_cipherBox ^. ivLength)
aMessage
_decrypt <- _cipherBox ^. decryptBuilder - _decodeIV
_msg <- processAll _decrypt _eMsg
(_decryptedMessage, _clientRequest) <- parseShadowSocksRequest _msg
{-debug_ - "R UDP: " <> show _clientRequest-}
{-debug_ - "R UDP: " <> show _decryptedMessage-}
logSA "R UDP -->:" (initTarget _clientRequest) - \_r -> do
{-debug_ - "R UDP targetSocket: " <> show _r-}
let (_targetSocket, _targetSocketAddress) = _r
(_addr, _) = sockAddr_To_Pair _targetSocketAddress
_IPLists = getIPLists aEnv
debug_ - "checking: " <> show _addr
withChecked_IP_List _addr _IPLists - do
let _msg = showRelay aSockAddr _clientRequest
info_ - "RU: " <> _msg
connect _targetSocket _targetSocketAddress
send_ _targetSocket _decryptedMessage
_r <- buildShadowSocksRequest _clientRequest <$> recv_UDP _targetSocket
{-debug_ - "R UDP <--: " <> show _r-}
when (_r & isn't _Empty) - do
_encodeIV <- _cipherBox ^. generate_IV
_encrypt <- _cipherBox ^. encryptBuilder - _encodeIV
_encryptedMessage <- processAll _encrypt _r
sendAllTo aSocket (_encodeIV <> _encryptedMessage) aSockAddr