packages feed

mptcp-pm-0.0.5: src/Net/Mptcp/PathManager/Upstream/NdiffPorts.hs

{-|
Description : Implementation of mptcp netlink path manager
module: Net.Mptcp.PathManager.V1.NdiffPorts
Maintainer  : matt
Portability : Linux
-}
module Net.Mptcp.PathManager.Upstream.NdiffPorts (
  -- TODO don't export / move to its own file
    ndiffports
  , meshPathManager
  , nportsOnMasterEstablishement
) where

import Data.Maybe (fromJust)
-- import qualified Data.Set as Set
import Debug.Trace
import Net.Mptcp
import Net.Stream
import Net.Mptcp.PathManager
-- import Net.Mptcp.Types
import Net.Tcp.Connection
import Net.Mptcp.Upstream.Commands
import Net.Mptcp.Netlink


-- These should be plugins

ndiffports :: PathManager
ndiffports = PathManager {
    name = "ndiffports"
  , onMasterEstablishement = nportsOnMasterEstablishement
}

{-
  Generate requests
TODO it iterates over local interfaces but not
-}
nportsOnMasterEstablishement :: MptcpSocket -> MptcpConnection -> ExistingInterfaces -> [MptcpPacket]
nportsOnMasterEstablishement mptcpSock mptcpCon paths = do
  map (newSublowPacketFromPort ) [3456]
  where
    generatedCon port = let
        master = fromJust (getMasterSubflow mptcpCon)
      in
        master { sfConn = (sfConn master) { conTcpClientPort = port } }
    newSublowPacketFromPort port = newSubflowPkt mptcpSock mptcpCon (generatedCon port)

  -- TODO create #X subflows
  -- iterate

-- | Creates a subflow between each pair of (client, server) interfaces
meshPathManager :: PathManager
meshPathManager = PathManager {
  name = "mesh"
  , onMasterEstablishement = meshOnMasterEstablishement
}



-- per interface
--  TODO check if there is already an interface with this connection
meshGenPkt :: MptcpSocket -> MptcpConnection -> NetworkInterface -> [MptcpPacket] -> [MptcpPacket]
meshGenPkt mptcpSock mptcpCon intf pkts =

    if traceShow (intf) (interfaceId intf == (fromJust $ sfInterface masterSf)) then
        pkts
    else
        pkts ++ [newSubflowPkt mptcpSock mptcpCon generatedSf]
    where
        generatedSf = MptcpSubflow {
            sfConn = generatedCon
          , sfJoinToken = Nothing
          , sfPriority = Nothing
          -- TODO fix this
          , sfLocalId = fromIntegral $ interfaceId intf    -- how to get it ? or do I generate it ?
          , sfRemoteId = sfRemoteId masterSf
          , sfInterface = Just $ interfaceId intf
        }
        generatedCon = (sfConn masterSf) {
            conTcpClientPort = 0  -- let the kernel handle it
          -- , conTcpServerPort = (conTcpServerPort . sfConn) masterSf
          , conTcpClientIp = ipAddress intf
          -- , conTcpServerIp =  (conTcpServerIp . sfConn) masterSf  -- same as master
          , conTcpStreamId = StreamId 0
          }

        masterSf = (fromJust . getMasterSubflow) mptcpCon


{-
  Generate requests
it iterates over local interfaces and try to connect
-}
meshOnMasterEstablishement :: MptcpSocket -> MptcpConnection -> ExistingInterfaces -> [MptcpPacket]
meshOnMasterEstablishement mptcpSock con paths = do
  foldr (meshGenPkt mptcpSock con) [] paths