コード例 #1
0
ファイル: LayerPhy.py プロジェクト: Miaxos/AJA
class LayerPhy(object):
    '''
    classdocs
    '''
    def __init__(self,
                 ownIdentifier,
                 upperLayerCallbackFunction,
                 masterHost='127.0.0.1',
                 baseport=10000,
                 autoEnter=True):
        '''
        Constructor
        '''
        self.__ownIdentifier = ownIdentifier
        self.__masterHost = masterHost
        self.__controlPort = baseport - 1

        self.__interfaceSendPort = [0, 0]
        self.__interfaceRecvPort = [0, 0]

        self.__incomingTcpServer = [None, None]
        self.__outgoingTcpClient = [None, None]

        self.__callLinkLayer = upperLayerCallbackFunction

        self.__debugOut = DebugOut()
        self.__openControl_connection()
        if autoEnter:
            self.API_enter()

    def API_enter(self):
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 1,
                                      self.__debugOut.INFO, "Sending ENTER")
        self.controlTcpClient.send("ENTER\n")

    def API_leave(self):
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 1,
                                      self.__debugOut.INFO, "Sending LEAVE")
        self.controlTcpClient.send("LEAVE\n")

    def API_sendData(self, interfaceNumber=0, data=""):
        if self.__outgoingTcpClient[interfaceNumber] is not None:
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                "PHY - PhysicalLayer, Interface %d, sending %s" %
                (interfaceNumber, data))
            self.__outgoingTcpClient[interfaceNumber].sendBytes(data)

    def API_subscribeDebug(self):
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 1,
                                      self.__debugOut.INFO,
                                      "Sending SUBSCRIBEDEBUG")
        self.controlTcpClient.send("SUBSCRIBEDEBUG\n")
        self.__debugOut.addLocalListenCallback(self.__sendDebugMsg)

    def __sendDebugMsg(self, eventTime, identifier, source, level, data):
        message = "DEBUGMSG,%.6f,%s,%s,%s,%s" % (eventTime, identifier, source,
                                                 level, data)
        self.controlTcpClient.send(message)

    def __handleDebugMsg(self, line):
        (eventTime, separator, line) = line.partition(",")
        eventTime = float(eventTime)
        (identifier, separator, line) = line.partition(",")
        (source, separator, line) = line.partition(",")
        source = int(source)
        (level, separator, line) = line.partition(",")
        level = int(level)
        self.__debugOut.globaldebugOutSource(eventTime, identifier, source,
                                             level, line)

    def __listenControl_connection(self, tcpClient, __connection, clientAddr,
                                   data):
        while data:
            (line, separator, data) = data.partition("\n")

            (command, separator, line) = line.partition(",")
            if command == "ADDINTERFACE":
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 1, self.__debugOut.INFO,
                    "PHY %s - __listenControl_connection - received %s" %
                    (clientAddr, line))
                (interfacenumber, separator, line) = line.partition(",")
                (listenport, separator, line) = line.partition(",")
                self.__addInterface(int(interfacenumber), int(listenport))
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 1, self.__debugOut.INFO,
                    "PHY %s done __addInterface" % (clientAddr, ))
            elif command == "DELINTERFACE":
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 1, self.__debugOut.INFO,
                    "PHY %s - __listenControl_connection - received %s" %
                    (clientAddr, line))
                (interfacenumber, separator, line) = line.partition(",")
                self.__delInterface(int(interfacenumber))
            elif command == "CONNECT":
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 1, self.__debugOut.INFO,
                    "PHY %s - __listenControl_connection - received %s" %
                    (clientAddr, line))
                (interfacenumber, separator, line) = line.partition(",")
                (ipAddress, separator, line) = line.partition(",")
                (listenport, separator, line) = line.partition(",")
                self.__connect(int(interfacenumber), ipAddress,
                               int(listenport))
            elif command == "DISCONNECT":
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 1, self.__debugOut.INFO,
                    "PHY %s - __listenControl_connection - received %s" %
                    (clientAddr, line))
                (interfacenumber, separator, line) = line.partition(",")
                self.__disconnect(int(interfacenumber))
            elif command == "DEBUGMSG":
                self.__handleDebugMsg(line)
            else:
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 1, self.__debugOut.INFO,
                    "PHY %s - listenControl_connection - Received unknown command %s."
                    % (clientAddr, command))

    def __openControl_connection(self):
        self.controlTcpClient = TCPClient(
            host=self.__masterHost,
            port=self.__controlPort,
            callBackReceive=self.__listenControl_connection)

    def __incomingData_connectionInterface0(self, tcpServer, __connection,
                                            clientAddr, data):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "PHY %s - ListenData_connection on interface 0 received %s" %
            (clientAddr, data))
        self.__callLinkLayer(0, data)

    def __incomingData_connectionInterface1(self, tcpServer, __connection,
                                            clientAddr, data):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "PHY %s - ListenData_connection on interface 1 received %s" %
            (clientAddr, data))
        self.__callLinkLayer(1, data)

    def __sendControl(self, data):
        self.controlTcpClient.send(data)

    def __addInterface(self, interfaceNumber=0, listenport=0):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "PHY - Adding interface number %d with listenport %d" %
            (interfaceNumber, listenport))

        if self.__incomingTcpServer[interfaceNumber] is None:
            self.__interfaceRecvPort[interfaceNumber] = listenport
            if interfaceNumber == 0:
                self.__incomingTcpServer[0] = TCPServer(
                    host='',
                    port=self.__interfaceRecvPort[0],
                    callBackReceiveBytes=self.
                    __incomingData_connectionInterface0)
            else:
                self.__incomingTcpServer[1] = TCPServer(
                    host='',
                    port=self.__interfaceRecvPort[1],
                    callBackReceiveBytes=self.
                    __incomingData_connectionInterface1)
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                'PHY - Tried to add interface, isServing is : %d' %
                self.__incomingTcpServer[interfaceNumber].isServing())
            if self.__incomingTcpServer[interfaceNumber].isServing():
                self.__sendControl("STATUS,ACK\n")
            else:
                self.__sendControl("STATUS,NACK,Interface open failed\n")
                self.__incomingTcpServer[interfaceNumber] = None
        else:
            self.__sendControl(
                "STATUS,NACK,Interface is already __connected\n")

    def __delInterface(self, interfaceNumber):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "Removing interface number %d with listenport %d" %
            (interfaceNumber, self.__interfaceRecvPort[interfaceNumber]))
        if self.__incomingTcpServer[interfaceNumber] is None:
            self.__sendControl("STATUS,NACK,Interface is not active\n")
        else:
            self.__incomingTcpServer[interfaceNumber].stopServer()
            self.__incomingTcpServer[interfaceNumber] = None
            self.__sendControl("STATUS,ACK\n")

    def __connect(self, interfaceNumber=0, ipAddress="127.0.0.1", sendport=0):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "PHY - __connecting interface %d to ip %s port %d" %
            (interfaceNumber, ipAddress, sendport))
        if self.__outgoingTcpClient[interfaceNumber] is None:
            self.__interfaceSendPort[interfaceNumber] = sendport
            self.__outgoingTcpClient[interfaceNumber] = TCPClient(
                host=ipAddress,
                port=self.__interfaceSendPort[interfaceNumber],
                callBackReceiveBytes=None)
            if self.__outgoingTcpClient[interfaceNumber].isConnected():
                self.__sendControl("STATUS,ACK\n")
            else:
                self.__sendControl("STATUS,NACK,Interface open failed\n")
        else:
            self.__sendControl(
                "STATUS,NACK,Interface is already __connected\n")

    def __disconnect(self, interfaceNumber=0):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "PHY - disconnecting interface %d from port %d" %
            (interfaceNumber, self.__interfaceSendPort[interfaceNumber]))
        if self.__outgoingTcpClient[interfaceNumber] is None:
            self.__sendControl("STATUS,NACK,Interface is not __connected\n")
        else:
            self.__outgoingTcpClient[interfaceNumber].stopClient()
            self.__outgoingTcpClient[interfaceNumber] = None
            self.__sendControl("STATUS,ACK\n")
コード例 #2
0
class NetworkStack(object):
    def __init__(self,
                 masterHost='127.0.0.1',
                 baseport=10000,
                 ownIdentifier='x',
                 autoEnter=True):
        self.__debugOut = DebugOut()
        self.__applicationList = []
        self.__sendDelay = 0
        self.__layerDelay = 0
        self.__layerPhy = LayerPhy.LayerPhy(
            ownIdentifier,
            upperLayerCallbackFunction=self.layer2_incomingPDU,
            masterHost=masterHost,
            baseport=baseport,
            autoEnter=autoEnter)
        # You may want to change the following part
        self.__ownIdentifier = ownIdentifier
        self.outgoingPacketStack = []
        self.outgoingPacketStackLock = threading.Lock()

    def leaveNetwork(self):
        self.__layerPhy.API_leave()

    def enableGlobalDebug(self):
        self.__layerPhy.API_subscribeDebug()

    def configureDelay(self, sendDelay=None, layerDelay=None):
        if sendDelay != None:
            self.__sendDelay = sendDelay
        if layerDelay != None:
            self.__layerDelay = layerDelay

    # Do not change!
    # This is the application layer protocol part: Each application has its specific port
    # The application registers a callback function that is called when a packet arrives for that particular application
    def applicationAddCallback(self, applicationPort, callBack):
        self.__applicationList.append((applicationPort, callBack))

    # Do not change!
    # The application sends packets which are stored in a buffer before being submitted
    def applicationSend(self, destination, applicationPort, pdu):
        self.outgoingPacketStackLock.acquire()
        self.outgoingPacketStack.insert(0, (destination, applicationPort, pdu))
        self.outgoingPacketStackLock.release()

#############################################################################################################################################
#############################################################################################################################################

# Please change: This sends the first TOKEN to the ring
# In fact, sending a TOKEN requires the creation of a new thread

    def initiateToken(self):
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 2,
                                      self.__debugOut.INFO, "Initiating TOKEN")
        tokenThread = threading.Thread(
            target=self.application_layer_outgoingPDU, args=(True, ))
        tokenThread.start()

    # Please adapt if required : This is the top layer that usually sends the data to the application
    # If pdu is None, the packet is not valid
    # forceToken determines that the return packet needs to be a TOKEN
    def application_layer_incomingPDU(self, forceToken, source, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: application_layer_in: received (%s) " %
            (self.__ownIdentifier, pdu))

        if pdu != None:
            applicationPort = int.from_bytes(pdu[0:1],
                                             byteorder="little",
                                             signed=False)
            sdu = pdu[1:]

            # We deliver the SDU to the application that handles this message
            for (thisApplicationPort,
                 thisApplication) in self.__applicationList:
                if thisApplicationPort == applicationPort:
                    thisApplication(source, applicationPort,
                                    sdu.decode('UTF-8'))

        # We dive back down into the network stack
        self.application_layer_outgoingPDU(forceToken)

    # Please adapt if required: This is the top layer that retrieves one element from the application layer
    def application_layer_outgoingPDU(self, forceToken=False):
        time.sleep(self.__layerDelay)
        self.outgoingPacketStackLock.acquire()
        if len(self.outgoingPacketStack) == 0 or forceToken:
            destination = "X"
            applicationPort = 20
            sdu = "TOKEN"
        else:
            destination, applicationPort, sdu = self.outgoingPacketStack.pop()
        self.outgoingPacketStackLock.release()

        pdu = applicationPort.to_bytes(1, byteorder="little",
                                       signed=False) + sdu.encode("UTF-8")
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: application_layer_out: sending (%s) " %
            (self.__ownIdentifier, pdu))
        self.layer4_outgoingPDU(destination, applicationPort, pdu)

    # Please adapt!
    # Take care: The parameters of incoming (data packets arriving at the computer) and outgoing (data packets leaving from the computer)
    # should generally agree with one layer difference (i.e. here we treat the applicationPort, an identifier that knows which application
    # is asked to handle the traffic
    def layer4_incomingPDU(self, source, pdu):
        time.sleep(self.__layerDelay)
        # Let us assume that this is the layer where we determine the applicationPort
        # We also decide whether we can send immediately send a new packet or whether we need to be friendly and send a TOKEN
        # We are not friendly and send a packet if our application has one with 100% chance
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_in: Received (%s) from %s " %
            (self.__ownIdentifier, pdu, source))
        self.application_layer_incomingPDU(False, source, pdu)

    # Please adapt
    def layer4_outgoingPDU(self, destination, applicationPort, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_out: Sending (%s) to %s " %
            (self.__ownIdentifier, pdu, destination))
        self.layer3_outgoingPDU(destination, pdu)

    # Please adapt!
    # The current situation is that in this layer, the network stack takes the decision to forcibly keep the packet because it thinkgs that it is destined to this computer
    # It also authorizes immediately that a new packet can be put onto the network.
    def layer3_incomingPDU(self, interface, pdu):
        time.sleep(self.__layerDelay)
        # In this layer we know that the packet is addressed to us.
        # It may contain information that is valid or not
        # This is another point of this obscure network protocol
        # With a chance of 50%, the packet contains valid data for us
        # With a chance of 50%, the packet does not contain valid data for us
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 3, self.__debugOut.INFO,
            "%s: Layer3_in: Received (%s) on interface %d " %
            (self.__ownIdentifier, pdu, interface))
        if random.randint(0, 1):
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 3, self.__debugOut.INFO,
                "%s: Layer3_in: tirage (%s) -> layer4_in\n" %
                (self.__ownIdentifier, pdu))
            # That is, for example that the destination of the packet corresponds to us
            # We also set here the source of the packet, currently as fixed: "A"
            self.layer4_incomingPDU("A", pdu)
        else:
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 3, self.__debugOut.INFO,
                "%s: Layer3_in: tirage (%s) -> Packet to be destroyed\n" %
                (self.__ownIdentifier, pdu))
            self.layer4_incomingPDU(None, None)

    # Please adapt
    def layer3_outgoingPDU(self, destination, pdu):
        time.sleep(self.__layerDelay)
        # Here, we store the packet and wait until an empty token packet arrives

        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 3, self.__debugOut.INFO,
            "%s: Layer3_out: Sending out (%s) via interface %d " %
            (self.__ownIdentifier, pdu, 0))
        self.layer2_outgoingPDU(0, pdu)

    # Please adapt
    def layer2_incomingPDU(self, interface, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 2, self.__debugOut.INFO,
            "%s: Layer2_in: Received (%s) on Interface %d " %
            (self.__ownIdentifier, pdu, interface))
        if interface == 0:  # same ring
            # Let us assume that here we treat the question whether this packet is addressed to us or not
            # The answer may be based on some obscure network protocol
            # With a chance of 50%, we forward the packet
            # With a chance of 50%, we receive the packet and say that it comes the source "A"
            if random.randint(0, 1):
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 2, self.__debugOut.INFO,
                    "%s: Layer2_in: tirage (%s) -> layer2_out\n" %
                    (self.__ownIdentifier, pdu))
                self.layer2_outgoingPDU(interface, pdu)
            else:
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 2, self.__debugOut.INFO,
                    "%s: Layer2_in: tirage (%s) -> layer3_in\n" %
                    (self.__ownIdentifier, pdu))
                self.layer3_incomingPDU(interface, pdu)
        else:  # Another Ring, this is for routing, see later
            pass

    def layer2_outgoingPDU(self, interface, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 2, self.__debugOut.INFO,
            "%s: Layer2_out: Sending out (%s) via interface %d " %
            (self.__ownIdentifier, pdu, interface))
        if self.__sendDelay != 0:
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 2, self.__debugOut.INFO,
                "%s: Layer2_out: Sleeping for %ds" %
                (self.__ownIdentifier, self.__sendDelay))
            time.sleep(self.__sendDelay)
        self.__layerPhy.API_sendData(interface, pdu)
コード例 #3
0
ファイル: NetworkStackAlternative.py プロジェクト: Miaxos/AJA
class NetworkStackAlternative(object):
    def __init__(self,
                 masterHost='127.0.0.1',
                 baseport=10000,
                 ownIdentifier='x',
                 autoEnter=True):
        self.__debugOut = DebugOut()
        self.__applicationList = []
        self.__sendDelay = 0
        self.__layerDelay = 0
        self.__layerPhy = LayerPhy.LayerPhy(
            ownIdentifier,
            upperLayerCallbackFunction=self.layer2_incomingPDU,
            masterHost=masterHost,
            baseport=baseport,
            autoEnter=autoEnter)
        # You may want to change the following part
        self.__ownIdentifier = ownIdentifier
        self.outgoingPacketStack = []
        self.outgoingPacketStackLock = threading.Lock()

    def leaveNetwork(self):
        self.__layerPhy.API_leave()

    def enableGlobalDebug(self):
        self.__layerPhy.API_subscribeDebug()

    def configureDelay(self, sendDelay=None, layerDelay=None):
        if sendDelay != None:
            self.__sendDelay = sendDelay
        if layerDelay != None:
            self.__layerDelay = layerDelay

    # Do not change!
    # This is the application layer protocol part: Each application has its specific port
    # The application registers a callback function that is called when a packet arrives for that particular application
    def applicationAddCallback(self, applicationPort, callBack):
        self.__applicationList.append((applicationPort, callBack))

    # Do not change!
    # The application sends packets which are stored in a buffer before being submitted
    def applicationSend(self, destination, applicationPort, pdu):
        self.outgoingPacketStackLock.acquire()
        self.outgoingPacketStack.insert(0, (destination, applicationPort, pdu))
        self.outgoingPacketStackLock.release()

#############################################################################################################################################
#############################################################################################################################################

# Please change: This sends the first TOKEN to the ring
# In fact, sending a TOKEN requires the creation of a new thread

    def initiateToken(self):
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 2,
                                      self.__debugOut.INFO, "Initiating TOKEN")
        tokenThread = threading.Thread(
            target=self.application_layer_outgoingPDU, args=(True, ))
        tokenThread.start()

    # Please adapt if required : This is the top layer that usually sends the data to the application
    # If pdu is None, the packet is not valid
    # forceToken determines that the return packet needs to be a TOKEN
    def application_layer_incomingPDU(self, forceToken, source, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: application_layer_in: received (%s) " %
            (self.__ownIdentifier, pdu))
        if pdu != None:
            applicationPort = int.from_bytes(pdu[0:1],
                                             byteorder="little",
                                             signed=False)
            sdu = pdu[1:]

            # We deliver the SDU to the application that handles this message
            for (thisApplicationPort,
                 thisApplication) in self.__applicationList:
                if thisApplicationPort == applicationPort:
                    thisApplication(source, applicationPort,
                                    sdu.decode('UTF-8'))

        # We dive back down into the network stack
        self.application_layer_outgoingPDU(forceToken)

    # Please adapt if required: This is the top layer that retrieves one element from the application layer
    def application_layer_outgoingPDU(self, forceToken=False):
        time.sleep(self.__layerDelay)
        self.outgoingPacketStackLock.acquire()
        if len(self.outgoingPacketStack) == 0 or forceToken:
            destination = "X"
            applicationPort = 20
            sdu = "TOKEN"
        else:
            destination, applicationPort, sdu = self.outgoingPacketStack.pop()
        self.outgoingPacketStackLock.release()

        pdu = applicationPort.to_bytes(1, byteorder="little",
                                       signed=False) + sdu.encode("UTF-8")
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: application_layer_out: sending (%s) " %
            (self.__ownIdentifier, pdu))
        self.layer4_outgoingPDU(destination, applicationPort, pdu)

    # Please adapt!
    # Take care: The parameters of incoming (data packets arriving at the computer) and outgoing (data packets leaving from the computer)
    # should generally agree with one layer difference (i.e. here we treat the applicationPort, an identifier that knows which application
    # is asked to handle the traffic
    def layer4_incomingPDU(self, source, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_in: Received (%s) from %s " %
            (self.__ownIdentifier, pdu, source))

    # Please adapt
    def layer4_outgoingPDU(self, destination, applicationPort, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_out: Sending (%s) to %s " %
            (self.__ownIdentifier, pdu, destination))

    def layer3_incomingPDU(self, interface, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 2, self.__debugOut.INFO,
            "%s: Layer3_in: tirage (%s) -> layer4_in\n" %
            (self.__ownIdentifier, pdu))

    # Please adapt
    def layer3_outgoingPDU(self, destination, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 3, self.__debugOut.INFO,
            "%s: Layer3_out: Sending out (%s) via interface %d " %
            (self.__ownIdentifier, pdu, 0))

    # Please adapt
    def layer2_incomingPDU(self, interface, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 2, self.__debugOut.INFO,
            "%s: Layer2_in: Received (%s) on Interface %d " %
            (self.__ownIdentifier, pdu, interface))

        self.layer2_outgoingPDU(interface, pdu)

    def layer2_outgoingPDU(self, interface, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 2, self.__debugOut.INFO,
            "%s: Layer2_out: Sending out (%s) via interface %d " %
            (self.__ownIdentifier, pdu, interface))
        if self.__sendDelay != 0:
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 2, self.__debugOut.INFO,
                "%s: Layer2_out: Sleeping for %ds" %
                (self.__ownIdentifier, self.__sendDelay))
            time.sleep(self.__sendDelay)
        self.__layerPhy.API_sendData(interface, pdu)
コード例 #4
0
class NetworkStack(object):
    def __init__(self,
                 masterHost='127.0.0.1',
                 baseport=10000,
                 ownIdentifier='x',
                 autoEnter=True):
        self.__debugOut = DebugOut()
        self.__applicationList = []
        self.__sendDelay = 0
        self.__layerDelay = 0
        self.__layerPhy = LayerPhy.LayerPhy(
            ownIdentifier,
            upperLayerCallbackFunction=self.layer2_incomingPDU,
            masterHost=masterHost,
            baseport=baseport,
            autoEnter=autoEnter)
        # You may want to change the following part
        self.__ownIdentifier = ownIdentifier
        self.outgoingPacketStack = []
        self.outgoingPacketStackLock = threading.Lock()

    def leaveNetwork(self):
        self.__layerPhy.API_leave()

    def enableGlobalDebug(self):
        self.__layerPhy.API_subscribeDebug()

    def configureDelay(self, sendDelay=None, layerDelay=None):
        if sendDelay != None:
            self.__sendDelay = sendDelay
        if layerDelay != None:
            self.__layerDelay = layerDelay

    # Do not change!
    # This is the application layer protocol part: Each application has its specific port
    # The application registers a callback function that is called when a packet arrives for that particular application
    def applicationAddCallback(self, applicationPort, callBack):
        self.__applicationList.append((applicationPort, callBack))

    # Do not change!
    # The application sends packets which are stored in a buffer before being submitted
    def applicationSend(self, destination, applicationPort, pdu):
        self.outgoingPacketStackLock.acquire()
        self.outgoingPacketStack.insert(0, (destination, applicationPort, pdu))
        self.outgoingPacketStackLock.release()

#############################################################################################################################################
#############################################################################################################################################

# Please change: This sends the first TOKEN to the ring
# In fact, sending a TOKEN requires the creation of a new thread

    def initiateToken(self):
        # On définit le maître par un envoie d'un token
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 2,
                                      self.__debugOut.INFO, "Initiating TOKEN")
        tokenThread = threading.Thread(
            target=self.application_layer_outgoingPDU, args=(0, ))
        tokenThread.start()

    # Please adapt if required : This is the top layer that usually sends the data to the application
    # If pdu is None, the packet is not valid
    # forceToken determines that the return packet needs to be a TOKEN
    def application_layer_incomingPDU(self, localtype, source, pdu):
        # Layer 5 dans l'application (Le premier element du paquet se trouve dedans)
        # Les données sont toutes seules pour le moment.
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: application_layer_in: received (%s) " %
            (self.__ownIdentifier, pdu))

        if pdu != None:
            applicationPort = int.from_bytes(pdu[0:1],
                                             byteorder="little",
                                             signed=False)
            sdu = pdu[1:]

            # We deliver the SDU to the application that handles this message
            for (thisApplicationPort,
                 thisApplication) in self.__applicationList:
                if thisApplicationPort == applicationPort:
                    thisApplication(source, applicationPort,
                                    sdu.decode('UTF-8'))

        # We dive back down into the network stack
        if (localtype == 2):
            self.application_layer_outgoingPDU(3)

    # Please adapt if required: This is the top layer that retrieves one element from the application layer
    def application_layer_outgoingPDU(self, localtype=0):
        # Layer 5 dans l'application (Le premier element du paquet se trouve dedans)
        # On récupère les infos de l'application, dont le type de paquet qu'on balance, pour qui, avec les données.
        time.sleep(self.__layerDelay)
        self.outgoingPacketStackLock.acquire()
        if localtype == 0:
            destination = 1
            applicationPort = 20
            sdu = "TOKEN"
            type = 0
        else:
            if (localtype == 1):
                # Après l'accusé de réception
                if (len(self.outgoingPacketStack) == 0):
                    # On balance le token
                    destination = 1
                    applicationPort = 20
                    sdu = "TOKEN"
                    type = 0
                else:
                    destination, applicationPort, sdu = self.outgoingPacketStack.pop(
                    )
                    type = 2
            elif (localtype == 2):
                # Type message
                # Il s'agit d'envoyer un message comme quoi elle a bien reçu les données.
                None
            elif (localtype == 3):
                # Il s'agit de recevoir l'accusé de réception.
                # On balance donc le token des qu'on a reçu l'accusé de reception
                destination = 1
                applicationPort = 20
                sdu = "TOKEN"
                type = 0

        self.outgoingPacketStackLock.release()

        # Data
        pdu = sdu.encode("UTF-8")

        #Dest
        pdu = applicationPort.to_bytes(1, byteorder="little",
                                       signed=False) + pdu

        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: application_layer_out: sending (%s) " %
            (self.__ownIdentifier, pdu))
        self.layer7_outgoingPDU(DestinationtoID(destination),
                                ord(self.__ownIdentifier), type, pdu, 255)

# --------- ENCAPSULAGE --------

    def layer7_outgoingPDU(self, destination, source, type, pdu, TTL=255):
        # encapsulage du checksum
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 7, self.__debugOut.INFO,
            "%s: Layer7_out: Sending (%s) to %s " %
            (self.__ownIdentifier, pdu, destination))

        pdu = HashageAJA(pdu).to_bytes(2, byteorder="little") + pdu

        self.layer6_outgoingPDU(destination, source, type, pdu, TTL)

    def layer6_outgoingPDU(self, destination, source, type, pdu, TTL=255):
        # encapsulage source
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 6, self.__debugOut.INFO,
            "%s: Layer6_out: Sending (%s) to %s " %
            (self.__ownIdentifier, pdu, destination))
        pdu = source.to_bytes(1, byteorder="little") + pdu
        self.layer5_outgoingPDU(destination, type, pdu, TTL)

    def layer5_outgoingPDU(self, destination, type, pdu, TTL=255):
        # encapsulage destination
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: Layer5_out: Sending (%s) to %s " %
            (self.__ownIdentifier, pdu, destination))
        pdu = destination.to_bytes(1, byteorder="little") + pdu
        self.layer4_outgoingPDU(type, pdu, TTL)

    def layer4_outgoingPDU(self, type, pdu, TTL=255):
        # encapsulage TTL
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_out: Sending (%s)" % (self.__ownIdentifier, pdu))
        pdu = TTL.to_bytes(1, byteorder="little") + pdu
        self.layer3_outgoingPDU(type, pdu)

    def layer3_outgoingPDU(self, type, pdu):
        # encapsulage Type
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 3, self.__debugOut.INFO,
            "%s: Layer3_out: Sending (%s)" % (self.__ownIdentifier, pdu))
        pdu = type.to_bytes(1, byteorder="little") + pdu
        self.layer2_outgoingPDU(0, pdu)

    #4 -> TTL

    def layer2_outgoingPDU(self, interface, pdu):
        # encapsulage Protocol
        time.sleep(self.__layerDelay)
        proto = 26
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 2, self.__debugOut.INFO,
            "%s: Layer2_out: Sending (%s) via interface %d " %
            (self.__ownIdentifier, pdu, interface))
        pdu = proto.to_bytes(1, byteorder="little") + pdu
        if self.__sendDelay != 0:
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 2, self.__debugOut.INFO,
                "%s: Layer2_out: Sleeping for %ds" %
                (self.__ownIdentifier, self.__sendDelay))
            time.sleep(self.__sendDelay)
        self.__layerPhy.API_sendData(interface, pdu)


# ----------------------------------- END NEW ------------------

# ------- DECAPSULAGE -------

    def layer2_incomingPDU(self, interface, pdu):
        # On doit décider si le paquet est pour nous ou pas.
        # On doit pour cela verifier si le protocole est le notre.
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 2, self.__debugOut.INFO,
            "%s: Layer2_in: Received (%s) on Interface %d " %
            (self.__ownIdentifier, pdu, interface))
        if interface == 0:  # same ring
            # On doit décapsuler le paquet pour check le protocole.
            if pdu != None:
                # On prend le premier octet pour check si c'est notre protocol !
                protocol = int.from_bytes(pdu[0:1],
                                          byteorder="little",
                                          signed=False)
                pdu = pdu[1:]
            if protocol == 26:
                # Numero du protocol AJA
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 2, self.__debugOut.INFO,
                    "%s: Layer2_in: [AJA] (%s) -> Check Type\n" %
                    (self.__ownIdentifier, pdu))
                self.layer3_incomingPDU(pdu)
            else:
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 2, self.__debugOut.INFO,
                    "%s: Layer2_in: [Not AJA] (%s) -> layer2_out\n" %
                    (self.__ownIdentifier, pdu))
                self.layer2_outgoingPDU(interface, pdu)
        else:
            pass

    def layer3_incomingPDU(self, pdu):
        # Type
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 3, self.__debugOut.INFO,
            "%s: Layer3_in: Received (%s)" % (self.__ownIdentifier, pdu))
        if pdu != None:
            localtype = int.from_bytes(pdu[0:1],
                                       byteorder="little",
                                       signed=False)
            pdu = pdu[1:]
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 3, self.__debugOut.INFO,
            "%s: Layer3_in: Type: (%s)" %
            (self.__ownIdentifier, str(localtype)))
        if localtype == 0:
            # Token
            self.layer4_incomingPDU(localtype, pdu)
        elif localtype == 1:
            # Type Accusé de reception
            # Il s'agit de voir si on a fait le tour.
            self.layer4_incomingPDU(localtype, pdu)
        elif localtype == 2:
            # Type Données
            # Message
            self.layer4_incomingPDU(localtype, pdu)
        elif localtype == 3:
            # accusé message reçu
            self.layer4_incomingPDU(localtype, pdu)
        elif localtype == 4:
            # Type RetId
            None
        elif localtype == 5:
            # Type Update TTL
            None
        elif localtype == 6:
            # Type CountTTl
            None
        else:
            # Type invalide, destruction du paquet.
            pass

    def layer4_incomingPDU(self, localtype, pdu):
        # TTL
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_in: Received (%s) type (%s)" %
            (self.__ownIdentifier, pdu, str(localtype)))
        if pdu != None:
            TTL = int.from_bytes(pdu[0:1], byteorder="little", signed=False)
            pdu = pdu[1:]
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_in: TTL (%s)" % (self.__ownIdentifier, str(TTL)))
        if localtype == 0:
            self.layer5_incomingPDU(localtype, TTL, pdu)
        elif localtype == 1:
            # Type Accusé de reception
            # On decrease le TTL
            TTL = TTL - 1
            self.layer5_incomingPDU(localtype, TTL, pdu)
        elif localtype == 2:
            # Type Données
            # On decrease le TTL
            TTL = TTL - 1
            self.layer5_incomingPDU(localtype, TTL, pdu)
        elif localtype == 3:
            TTL = TTL - 1
            self.layer5_incomingPDU(localtype, TTL, pdu)
        elif localtype == 4:
            # Type RetId
            None
        elif localtype == 5:
            # Type Update TTL
            None
        elif localtype == 6:
            # Type CountTTl
            None
        else:
            # Type invalide, destruction du paquet.
            pass
        # self.layer5_outgoingPDU(localtype, pdu, TTL)

    def layer5_incomingPDU(self, localtype, TTL, pdu):
        # destination
        time.sleep(self.__layerDelay)
        if pdu != None:
            destination = int.from_bytes(pdu[0:1],
                                         byteorder="little",
                                         signed=False)
            pdu = pdu[1:]
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: Layer5_in: Destination (%s)" %
            (self.__ownIdentifier, str(destination)))
        if localtype == 0:
            self.layer6_incomingPDU(destination, localtype, TTL, pdu)
        elif localtype == 1:
            # Type Accusé de reception
            if destination != ord(self.__ownIdentifier):
                # Si c'est pas nous alors
                # On fait tourner.
                self.layer5_outgoingPDU(destination, localtype, pdu, TTL)
            else:
                # On a terminé le tour donc on diffuse un message.
                self.layer6_incomingPDU(destination, localtype, TTL, pdu)
        elif localtype == 2:
            # Type Données
            # Message
            if destination != ord(self.__ownIdentifier):
                # Si c'est pas nous alors
                # On fait tourner.
                self.layer5_outgoingPDU(destination, localtype, pdu, TTL)
            else:
                # On a terminé le tour donc on diffuse un message.
                self.layer6_incomingPDU(destination, localtype, TTL, pdu)
        elif localtype == 3:
            # Accusé de réception message
            if destination != ord(self.__ownIdentifier):
                self.layer5_outgoingPDU(destination, localtype, pdu, TTL)
            else:
                self.application_layer_outgoingPDU(0)
        elif localtype == 4:
            # Type RetId
            None
        elif localtype == 5:
            # Type Update TTL
            None
        elif localtype == 6:
            # Type CountTTl
            None
        else:
            # Type invalide, destruction du paquet.
            pass

    def layer6_incomingPDU(self, destination, localtype, TTL, pdu):
        # source
        time.sleep(self.__layerDelay)
        if pdu != None:
            source = int.from_bytes(pdu[0:1], byteorder="little", signed=False)
            pdu = pdu[1:]
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 6, self.__debugOut.INFO,
            "%s: Layer6_in: Source (%s)" %
            (self.__ownIdentifier, str(destination)))
        if localtype == 0:
            # On balance un accusé de reception
            self.layer6_outgoingPDU(DestinationtoID(self.__ownIdentifier),
                                    ord(self.__ownIdentifier), 1, pdu, 255)
        elif localtype == 1:
            # Type Accusé de reception
            self.application_layer_outgoingPDU(localtype)
        elif localtype == 2:
            # Type Données
            # Rien de particulier avec la source
            self.layer7_incomingPDU(localtype, source, pdu)
        elif localtype == 3:
            # Reception message accusé
            None
        elif localtype == 4:
            # Type RetId
            None
        elif localtype == 5:
            # Type Update TTL
            None
        elif localtype == 6:
            # Type CountTTl
            None
        else:
            # Type invalide, destruction du paquet.
            pass

    def layer7_incomingPDU(self, localtype, source, pdu):
        time.sleep(self.__layerDelay)
        if pdu != None:
            checksum = int.from_bytes(pdu[0:2],
                                      byteorder="little",
                                      signed=False)
            pdu = pdu[2:]
        if (HashageAJA(pdu) == checksum):
            self.application_layer_incomingPDU(localtype, source, pdu)
        else:
            # Destruction du paquet
            None
コード例 #5
0
class NetworkStack(object):
    def __init__(self,
                 masterHost='127.0.0.1',
                 baseport=10000,
                 ownIdentifier='x',
                 autoEnter=True):
        self.__debugOut = DebugOut()
        self.__applicationList = []
        self.__sendDelay = 0
        self.__layerDelay = 0
        self.__layerPhy = LayerPhy.LayerPhy(
            ownIdentifier,
            upperLayerCallbackFunction=self.layer2_incomingPDU,
            masterHost=masterHost,
            baseport=baseport,
            autoEnter=autoEnter)
        # You may want to change the following part
        self.__ownIdentifier = ownIdentifier
        self.outgoingPacketStack = []
        self.outgoingPacketStackLock = threading.Lock()

        #SN TB ETAPE DE L'INITIALISATION DU TOKEN
        self.initToken = 2

        #SN TB compteur -> compteur pour le nombre de slot (couche 2)
        self.compteur = 2
        self.indice = 0
        self.paquetRecu = ""
        self.paquetAEnvoyer = "".encode("UTF-8")

    def leaveNetwork(self):
        self.__layerPhy.API_leave()

    def enableGlobalDebug(self):
        self.__layerPhy.API_subscribeDebug()

    def configureDelay(self, sendDelay=None, layerDelay=None):
        if sendDelay != None:
            self.__sendDelay = sendDelay
        if layerDelay != None:
            self.__layerDelay = layerDelay

    # Do not change!
    # This is the application layer protocol part: Each application has its specific port
    # The application registers a callback function that is called when a packet arrives for that particular application
    def applicationAddCallback(self, applicationPort, callBack):
        self.__applicationList.append((applicationPort, callBack))

    # Do not change!
    # The application sends packets which are stored in a buffer before being submitted
    def applicationSend(self, destination, applicationPort, pdu):
        self.outgoingPacketStackLock.acquire()
        self.outgoingPacketStack.insert(0, (destination, applicationPort, pdu))
        self.outgoingPacketStackLock.release()

#############################################################################################################################################
#############################################################################################################################################

# Please change: This sends the first TOKEN to the ring
# In fact, sending a TOKEN requires the creation of a new thread

    def initiateToken(self):
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 2,
                                      self.__debugOut.INFO, "Initiating TOKEN")
        tokenThread = threading.Thread(
            target=self.application_layer_outgoingPDU, args=(True, ))
        tokenThread.start()

    # Please adapt if required : This is the top layer that usually sends the data to the application
    # If pdu is None, the packet is not valid
    # forceToken determines that the return packet needs to be a TOKEN
    def application_layer_incomingPDU(self, forceToken, source, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: application_layer_in: received (%s) " %
            (self.__ownIdentifier, pdu))

        if pdu != None:
            applicationPort = int.from_bytes(pdu[0:1],
                                             byteorder="little",
                                             signed=False)
            sdu = pdu[1:]

            # We deliver the SDU to the application that handles this message
            for (thisApplicationPort,
                 thisApplication) in self.__applicationList:
                if thisApplicationPort == applicationPort:
                    thisApplication(source, applicationPort,
                                    sdu.decode('UTF-8'))

        # We dive back down into the network stack
        self.application_layer_outgoingPDU(forceToken)

    # Please adapt if required: This is the top layer that retrieves one element from the application layer
    def application_layer_outgoingPDU(self, forceToken=False):
        time.sleep(self.__layerDelay)
        self.outgoingPacketStackLock.acquire()

        #TB SN on compare le initToken et le ownIdentifier pour initialiser le paquet avec le computeur 'A'

        if (self.initToken != 0 and self.__ownIdentifier == 'A') or forceToken:
            destination = "X"
            applicationPort = 20
            sdu = "TOKEN"

        else:
            if self.outgoingPacketStack != []:
                destination, applicationPort, sdu = self.outgoingPacketStack.pop(
                )
            else:
                destination = "X"
                applicationPort = 20
                sdu = "TOKEN"

        self.outgoingPacketStackLock.release()

        pdu = applicationPort.to_bytes(1, byteorder="little",
                                       signed=False) + sdu.encode("UTF-8")
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 5, self.__debugOut.INFO,
            "%s: application_layer_out: sending (%s) " %
            (self.__ownIdentifier, pdu))
        self.layer4_outgoingPDU(destination, applicationPort, pdu)

    # Please adapt!
    # Take care: The parameters of incoming (data packets arriving at the computer) and outgoing (data packets leaving from the computer)
    # should generally agree with one layer difference (i.e. here we treat the applicationPort, an identifier that knows which application
    # is asked to handle the traffic
    def layer4_incomingPDU(self, source, pdu):
        time.sleep(self.__layerDelay)
        # Let us assume that this is the layer where we determine the applicationPort
        # We also decide whether we can send immediately send a new packet or whether we need to be friendly and send a TOKEN
        # We are not friendly and send a packet if our application has one with 100% chance
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_in: Received (%s) from %s " %
            (self.__ownIdentifier, pdu, source))
        self.application_layer_incomingPDU(False, source, pdu)

    # Please adapt
    def layer4_outgoingPDU(self, destination, applicationPort, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 4, self.__debugOut.INFO,
            "%s: Layer4_out: Sending (%s) to %s " %
            (self.__ownIdentifier, pdu, destination))
        self.layer3_outgoingPDU(destination, pdu)

    # Please adapt!
    # The current situation is that in this layer, the network stack takes the decision to forcibly keep the packet because it thinkgs that it is destined to this computer
    # It also authorizes immediately that a new packet can be put onto the network.
    def layer3_incomingPDU(self, interface, pdu):
        time.sleep(self.__layerDelay)

        #TB SN On va recuperer l'expéditeur et le destinaire du pdu grâce au code fournit dans les annexes

        expediteur = pdu[0:1].decode('UTF-8')
        destinataire = pdu[1:2].decode('UTF-8')

        if destinataire == 'X':
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 3, self.__debugOut.INFO,
                "%s: Layer3_in: tirage (%s) -> layer4_in\n" %
                (self.__ownIdentifier, pdu))
            self.layer4_incomingPDU(None, None)

        #SN TB Test pour savoir si le paquet reçus est celui qu'on à envoyer
        elif expediteur == self.__ownIdentifier:
            self.layer4_incomingPDU(None, None)

        #SN TB Test pour savoir si on est le destinaire
        elif destinataire == self.__ownIdentifier:
            print("Nice ca")
            #SN TB Si oui, on envoie à la couche 4 incoming
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 3, self.__debugOut.INFO,
                "%s: Layer3_in: tirage (%s) -> layer4_in\n" %
                (self.__ownIdentifier, pdu))
            self.layer4_incomingPDU(expediteur, pdu[2:])
        else:
            #SN TB Si non, on renvoie le paquet à la couche 2 outgoing pour transmettre le paquet au computer suivant
            taille = len(pdu)
            if taille < 10:
                taille = '0' + str(taille)
            else:
                taille = str(len(pdu))
            pdu = taille.encode("UTF-8") + pdu
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 3, self.__debugOut.INFO,
                "%s: Layer3_in: tirage (%s) -> Packet to be destroyed\n" %
                (self.__ownIdentifier, pdu))
            self.layer2_outgoingPDU(interface, pdu)

    # Please adapt
    def layer3_outgoingPDU(self, destination, pdu):
        time.sleep(self.__layerDelay)
        # Here, we store the packet and wait until an empty token packet arrives

        #SN TB On récupère l'expéditeur et la destination, que l'on encode et ajoute au PDU
        expediteur = self.__ownIdentifier
        pdu = expediteur.encode("UTF-8") + destination.encode("UTF-8") + pdu

        #TB SN On récupère la taille et on l'ajoute au pdu
        taille = len(pdu)
        if taille < 10:
            taille = '0' + str(taille)
        else:
            taille = str(len(pdu))
        pdu = taille.encode("UTF-8") + pdu

        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 3, self.__debugOut.INFO,
            "%s: Layer3_out: Sending out (%s) via interface %d " %
            (self.__ownIdentifier, pdu, 0))
        self.layer2_outgoingPDU(0, pdu)

    # Please adapt
    def layer2_incomingPDU(self, interface, pdu):
        time.sleep(self.__layerDelay)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 2, self.__debugOut.INFO,
            "%s: Layer2_in: Received (%s) on Interface %d " %
            (self.__ownIdentifier, pdu, interface))

        if interface == 0:  # same ring

            print(pdu)
            self.paquetRecu = pdu

            if self.compteur <= 0:
                self.compteur = 2
                self.indice = 0
                self.paquetAEnvoyer = "".encode("UTF-8")
                #self.paquetRecu = pdu
            taille = self.paquetRecu[self.indice:self.indice + 2]
            taille = int(taille.decode('UTF-8'))

            self.indice += 2
            pdu = self.paquetRecu[self.indice:self.indice + taille]
            self.indice += taille
            self.compteur -= 1

            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 2, self.__debugOut.INFO,
                "%s: Layer2_in: tirage (%s) -> layer3_in\n" %
                (self.__ownIdentifier, pdu))
            self.layer3_incomingPDU(interface, pdu)
        else:  # Another Ring, this is for routing, see later
            pass

    def layer2_outgoingPDU(self, interface, pdu):
        if self.initToken > 0 and self.__ownIdentifier == 'A':  #TB SN On regarde si on continue d'initialiser le paquet
            print('lol')
            if self.initToken >= 2:  #TB SN on est pas sur le dernier slot donc on continue d'initialiser
                self.initToken -= 1
                self.paquetAEnvoyer += pdu
                self.compteur -= 1
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 2, self.__debugOut.INFO,
                    "%s: Layer2_out: Sending in (%s) via interface %d " %
                    (self.__ownIdentifier, self.paquetAEnvoyer, interface))
                self.application_layer_outgoingPDU(True)
            #TB SN On initialise le dernier slot du paquet, donc on envoie le paquet initialisé au noeud suivant
            elif self.initToken == 1:
                self.initToken -= 1
                self.paquetAEnvoyer += pdu
                self.compteur -= 1
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 2, self.__debugOut.INFO,
                    "%s: Layer2_out: Sending in (%s) via interface %d " %
                    (self.__ownIdentifier, self.paquetAEnvoyer, interface))
                self.__layerPhy.API_sendData(interface, self.paquetAEnvoyer)
                #self.layer2_incomingPDU(interface,self.paquetRecu)
        #SN TB Tant que tous les slots n'ont pas été traités
        elif self.compteur > 0:
            self.paquetAEnvoyer += pdu
            time.sleep(self.__layerDelay)
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 2, self.__debugOut.INFO,
                "%s: Layer2_out: Sending out (%s) via interface %d " %
                (self.__ownIdentifier, self.paquetAEnvoyer, interface))
            if self.__sendDelay != 0:
                self.__debugOut.debugOutLayer(
                    self.__ownIdentifier, 2, self.__debugOut.INFO,
                    "%s: Layer2_out: Sleeping for %ds" %
                    (self.__ownIdentifier, self.__sendDelay))
                time.sleep(self.__sendDelay)
            #SN TB On envoie en couche 2 incoming pour traiter le slot suivant
            self.layer2_incomingPDU(interface, self.paquetRecu)
        #SN TB tous les slots ont été traités
        else:
            self.paquetAEnvoyer += pdu
            #SN TB on envoie au noeud suivant
            self.__layerPhy.API_sendData(interface, self.paquetAEnvoyer)
コード例 #6
0
class PhyMaster(object):
    '''
    classdocs
    '''
    def __init__(self, phyNetwork, ownIdentifier):
        self.__ownIdentifier = ownIdentifier
        self.__host = ''  # We are listening on any incoming connection
        self.__phyNetwork = phyNetwork
        self.__receivedMessage = threading.Condition()
        self.__debugOut = DebugOut(phyNetwork)
        self.__globalDebugHistory = []
        self.__debugSubscribers = []
        self.active = False
        self.__commandlist = []
        try:
            self.__masterServer = TCPServer(
                host=self.__host,
                port=self.__phyNetwork.baseport - 1,
                callBackReceive=self.__masterListen,
                callBackConnect=self.__masterConnect,
                callBackHandleSocketError=self.__masterSocketError)
            self.active = True
        except:
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                "PhyMaster : Master Server seems to be already running")

        if self.active:
            # This is the serialized dispatch thread
            self.__dispatchThread = threading.Thread(
                target=self.__dispatchCommands)
            self.__dispatchThread.start()

    def __waitForAcknowledge(self, connection):
        found = False
        while not found:
            index = 0
            for (thisConnection, clientAddr, line) in self.__commandlist:
                if thisConnection == connection:
                    (command, separator, line) = line.partition(",")
                    (result, separator, line) = line.partition(",")
                    if command == "STATUS":
                        found = True
                        self.__commandlist.pop(index)
                        self.__debugOut.debugOutLayer(
                            self.__ownIdentifier, 1, self.__debugOut.INFO,
                            "PhyMaster %s - Waited for Acknowledge and got: %s %s"
                            % (clientAddr, result, line))
                        if result == "ACK":
                            result = True
                        else:
                            result = False
                index = index + 1
            if not found:
                numberOfCommandsPriorToWait = len(self.__commandlist)
                self.__receivedMessage.wait(0.1)
                # Check for timeout
                if numberOfCommandsPriorToWait == len(self.__commandlist):
                    result = False
                    break
        return result

    def __nodeConnect(self, node, connectNode, clientAddr, listenPort,
                      interfaceNumber):
        self.__masterServer.sendConnection(
            connectNode.connection,
            ('CONNECT,%d,%s,%d\n' %
             (interfaceNumber, clientAddr[0], listenPort)))
        retval = False
        if not self.__waitForAcknowledge(connectNode.connection):
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                "DEBUG: PhyMaster %s - connect for previous node %s failed" %
                (clientAddr, connectNode.clientAddr))
        else:
            connectNode.sendInterfaceConfig[interfaceNumber] = (clientAddr[0],
                                                                listenPort)
            retval = True
        return retval

    def __nodeDisconnect(self, node, disconnectNode, interfaceNumber):
        # We can also safely disconnect the current node
        self.__masterServer.sendConnection(
            disconnectNode.connection, ("DISCONNECT,%d\n" % interfaceNumber))
        retval = False
        if not self.__waitForAcknowledge(disconnectNode.connection):
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                "DEBUG: PhyMaster %s - disconnect for current node %s failed" %
                (node.clientAddr, disconnectNode.clientAddr))
        else:
            disconnectNode.sendInterfaceConfig[interfaceNumber] = ('', 0)
            retval = True

        return retval

    def __nodeAddInterface(self, node, addInterfaceNode, interfaceNumber):
        (addInterfaceRingNumber, addInterfaceNodeNumber
         ) = self.__phyNetwork.getNodePositionByConnection(
             addInterfaceNode.connection)
        listenPort = self.__phyNetwork.getListenInterfacePort(
            interfaceNumber, addInterfaceRingNumber, addInterfaceNodeNumber)
        acknowledge = False
        while not acknowledge:
            self.__masterServer.sendConnection(addInterfaceNode.connection,
                                               ("ADDINTERFACE,%d,%d\n" %
                                                (interfaceNumber, listenPort)))
            acknowledge = self.__waitForAcknowledge(
                addInterfaceNode.connection)
            if not acknowledge:
                listenPort = listenPort + 1
        addInterfaceNode.listenInterfacePorts[interfaceNumber] = listenPort
        return True

    def __nodeDelInterface(self, node, delInterfaceNode, interfaceNumber):
        self.__masterServer.sendConnection(
            delInterfaceNode.connection,
            ("DELINTERFACE,%d\n" % interfaceNumber))
        retval = False
        if not self.__waitForAcknowledge(delInterfaceNode.connection):
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                "DEBUG: PhyMaster %s - delinterface for current node %s failed"
                % (node.clientAddr, delInterfaceNode.clientAddr))
        else:
            delInterfaceNode.listenInterfacePorts[interfaceNumber] = 0
            retval = True
        return retval

    def __handleLeave(self, connection, clientAddr, assumeDisconnect=False):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "LEAVE : Entering configuration section")
        thisNode = self.__phyNetwork.getNodeByConnection(connection)
        (ringNumber, nodeNumber
         ) = self.__phyNetwork.getNodePositionByConnection(connection)
        (previousNode,
         previousInterfaceNumber) = self.__phyNetwork.getPreviousNode(
             ringNumber, nodeNumber)
        (nextNode, nextInterfaceNumber) = self.__phyNetwork.getNextNode(
            ringNumber, nodeNumber)
        ringHandoverNode = None
        if thisNode is None:
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                "DEBUG: PhyMaster %s received LEAVE request from unknown client"
                % (clientAddr, ))
        else:
            # We first treat interface 0 : Reconnect previous and next node
            # Assume, B is to be removed from the middle of A and C

            # We can disconnect the previous node in any case
            self.__nodeDisconnect(thisNode, previousNode,
                                  previousInterfaceNumber)

            # We can also safely disconnect the current node
            if not assumeDisconnect:
                self.__nodeDisconnect(thisNode, thisNode, 0)

            # We shutdown the current interface 0 which should no longer be connected in any case (even if immediate loop)
            if not assumeDisconnect:
                self.__nodeDelInterface(thisNode, thisNode, 0)

            # Check whether we are the last node on the ring
            if ringNumber > 0 and self.__phyNetwork.getRingLength(
                    ringNumber) == 1:
                # then the previousNode (and the nextNode should be the connection to the lower ring
                if previousInterfaceNumber != 1:
                    self.__debugOut.debugOutLayer(
                        self.__ownIdentifier, 1, self.__debugOut.INFO,
                        "DEBUG: PhyMaster %s - Something is strange, only one node left but previous is not on interface 1"
                        % (clientAddr, ))
                else:
                    ringHandoverNode = previousNode
                    self.__nodeDelInterface(thisNode, previousNode,
                                            previousInterfaceNumber)

            else:  # This is the normal case, we have at least 2 nodes left
                self.__nodeConnect(
                    thisNode, previousNode, nextNode.clientAddr,
                    nextNode.listenInterfacePorts[nextInterfaceNumber],
                    previousInterfaceNumber)

            # Check whether we are the uplink node
            if thisNode.listenInterfacePorts[1] != 0:
                if self.__phyNetwork.getRingLength(ringNumber) > 1:
                    if previousNode.listenInterfacePorts[1] != 0:
                        self.__debugOut.debugOutLayer(
                            self.__ownIdentifier, 1, self.__debugOut.INFO,
                            "DEBUG: PhyMaster %s - Something is strange, there is a previous node which is an uplink but the current is uplink, too"
                            % (clientAddr, ))
                    else:
                        # We need to do a Ring Handover here: Imagine, we have D2 -> D1 -> A2 with D1 being in Ring 1, the rest in Ring 2
                        # Then we want to handover from D1 to C1 because we remove D1
                        if ringHandoverNode == None:
                            ringHandoverNode = previousNode
                        (handoverRingNumber, handoverNodeNumber
                         ) = self.__phyNetwork.getNodePositionByConnection(
                             ringHandoverNode.connection)

                        # We first enable the interface 1 on C1
                        self.__nodeAddInterface(thisNode, ringHandoverNode, 1)

                        # Now we need to hand over the upper ring to the previous Node
                        predecessorNode = self.__phyNetwork.getNodeByIndex(
                            ringNumber + 1, -1)
                        sucessorNode = self.__phyNetwork.getNodeByIndex(
                            ringNumber + 1, 0)

                        # Then we connect D2 to C1
                        self.__nodeDisconnect(thisNode, predecessorNode, 0)
                        self.__nodeConnect(
                            thisNode, predecessorNode,
                            ringHandoverNode.clientAddr,
                            ringHandoverNode.listenInterfacePorts[1], 0)

                        # Now we connect C1 to A2
                        self.__nodeDisconnect(thisNode, thisNode, 1)
                        self.__nodeConnect(
                            thisNode, ringHandoverNode,
                            sucessorNode.clientAddr,
                            sucessorNode.listenInterfacePorts[0], 1)

        self.__phyNetwork.delNode(ringNumber, nodeNumber)
        self.__phyNetwork.API_dumpPhyNetworkState()
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 1,
                                      self.__debugOut.INFO,
                                      "LEAVE : Leaving configuration section")

    def __handleEnter(self, connection, clientAddr):
        self.__phyNetwork.addNode(connection, clientAddr)
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "ENTER : Entering configuration section")
        thisNode = self.__phyNetwork.getNodeByConnection(connection)
        if thisNode is None:
            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                "DEBUG: PhyMaster %s received ENTER request from unknown client"
                % (clientAddr, ))
        else:
            (ringNumber, nodeNumber
             ) = self.__phyNetwork.getNodePositionByConnection(connection)
            # If this is the first node of a new Ring, we need to connect it downwards by enabling interface 1 of the lowerRing Node
            if nodeNumber == 0 and ringNumber > 0:
                lowerRingRouterNode = self.__phyNetwork.getLowerRingRouterNode(
                    ringNumber)
                (lowerRingNumber, lowerRingNodeNumber
                 ) = self.__phyNetwork.getNodePositionByConnection(
                     lowerRingRouterNode.connection)
                self.__nodeAddInterface(thisNode, lowerRingRouterNode, 1)

            # Let's imagine we want to insert B between A and C
            self.__nodeAddInterface(thisNode, thisNode, 0)

            (previousNode,
             previousInterfaceNumber) = self.__phyNetwork.getPreviousNode(
                 ringNumber, nodeNumber)
            # We are disconnecting A from C
            self.__nodeDisconnect(thisNode, previousNode,
                                  previousInterfaceNumber)

            # We are connecting A to B
            self.__nodeConnect(thisNode, previousNode, clientAddr,
                               thisNode.listenInterfacePorts[0],
                               previousInterfaceNumber)

            # We are connecting B to C
            (nextNode, nextInterfaceNumber) = self.__phyNetwork.getNextNode(
                ringNumber, nodeNumber)

            self.__debugOut.debugOutLayer(
                self.__ownIdentifier, 1, self.__debugOut.INFO,
                "Trying to connect %s %d " %
                (nextNode.clientAddr[0], nextNode.listenInterfacePorts[0]))

            self.__nodeConnect(
                thisNode, thisNode, nextNode.clientAddr,
                nextNode.listenInterfacePorts[nextInterfaceNumber], 0)

        self.__phyNetwork.API_dumpPhyNetworkState()
        self.__debugOut.debugOutLayer(self.__ownIdentifier, 1,
                                      self.__debugOut.INFO,
                                      "ENTER : Leaving configuration section")

    def __handleDebugMsg(self, connection, clientAddr, line):
        self.__globalDebugHistory.append(line)
        for (sendConnection, sendClientAddr) in self.__debugSubscribers:
            try:
                self.__masterServer.sendConnection(sendConnection,
                                                   ("DEBUGMSG," + line))
            except socket.error as msg:
                print("HandleDebugMsg - Exception caught: ", msg)
                self.__debugSubscribers.remove(
                    (sendConnection, sendClientAddr))

    def __handleSubscribeDebug(self, connection, clientAddr):
        subscribeOk = True
        for line in self.__globalDebugHistory:
            try:
                self.__masterServer.sendConnection(connection,
                                                   ("DEBUGMSG," + line))
            except socket.error as msg:
                print("HandleDebugMsg - Exception caught: ", msg)
                subscribeOk = False
        if subscribeOk:
            self.__debugSubscribers.append((connection, clientAddr))

    def __dispatchCommands(self):
        while True:
            self.__receivedMessage.acquire()
            while len(self.__commandlist) > 0:
                (connection, clientAddr,
                 thisCommand) = self.__commandlist.pop(0)
                (command, separator, line) = thisCommand.partition(",")
                if command == "ENTER":
                    self.__handleEnter(connection, clientAddr)
                elif command == "LEAVE":
                    self.__handleLeave(connection, clientAddr)
                elif command == "DEBUGMSG":
                    self.__handleDebugMsg(connection, clientAddr, line)
                elif command == "SUBSCRIBEDEBUG":
                    self.__handleSubscribeDebug(connection, clientAddr)
                else:
                    self.__debugOut.debugOutLayer(
                        self.__ownIdentifier, 1, self.__debugOut.INFO,
                        "DEBUG: PhyMaster %s - Unknown Command %s" %
                        (clientAddr, line))
            self.__receivedMessage.wait()

    def __masterListen(self, tcpServer, connection, clientAddr, data):
        self.__receivedMessage.acquire()
        while data:
            (line, separator, data) = data.partition("\n")
            #            self.__debugOut.debugOutLayer(self.__ownIdentifier,1,self.__debugOut.INFO,"DEBUG: PhyMaster %s - received %s" % (clientAddr,line))
            self.__commandlist.append((connection, clientAddr, line))
            self.__receivedMessage.notify()
        self.__receivedMessage.release()

    def __masterConnect(self, tcpServer, connection, clientAddr):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "PhyMaster %s - Incoming connection" % (clientAddr, ))

    def __masterSocketError(self, tcpServer, connection, clientAddr):
        self.__debugOut.debugOutLayer(
            self.__ownIdentifier, 1, self.__debugOut.INFO,
            "PhyMaster %s - Received SocketError assuming disconnect" %
            (clientAddr, ))
        self.__receivedMessage.acquire()
        self.__handleLeave(connection, clientAddr, True)
        self.__receivedMessage.release()