Example #1
0
class enlace(object):
    def __init__(self, name):
        self.fisica = fisica(
            name)  # é o serialName - nome da porta do computador
        self.rx = RX(self.fisica)  #inicializa o RX
        self.tx = TX(self.fisica)  #inicializa o TX
        self.connected = False

    def enable(self):
        self.fisica.open()
        self.rx.threadStart()
        self.tx.threadStart()

    def disable(self):
        self.rx.threadKill()
        self.tx.threadKill()
        time.sleep(1)
        self.fisica.close()

    # Método que recebe os dados em bytes (array) e envia os dados
    #usa a funcao sendBuffer do tx(pino de envio)
    def sendData(self, data):
        self.tx.sendBuffer(data)

    #Método que recebe o tamanho dos dados e retorna os dados e o len dos dados
    def getData(self, size):
        data = self.rx.getNData(size)
        return (data, len(data))

    #Método que recebe o tamanho dos dados e retorna os dados e o len dos dados apos um determinado tempo

    def getDataTime(self, size, t):
        while self.rx.getBufferLen() < size:
            if t <= 0:
                return False
            mins, secs = divmod(t, 60)  #calcula o n de min e seg
            timer = '{:02d}:{:02d}'.format(int(mins), int(secs))
            print(timer, end="\r")  #print q sobrepoe o anterior
            time.sleep(0.05)  #conta 0.05 seg
            t -= 0.05

        return self.rx.getBuffer(size)
Example #2
0
class enlace(object):
    """ This class implements methods to the interface between Enlace and Application
    """
    def __init__(self, name):
        """ Initializes the enlace class
        """
        self.fisica = fisica(name)
        self.rx = RX(self.fisica)
        self.tx = TX(self.fisica)
        self.connected = False
        self.queuedPck = []
        self.receivedPck = []
        self.meta = None

    def enable(self):
        """ Enable reception and transmission
        """
        self.fisica.open()
        self.rx.threadStart()
        self.tx.threadStart()

    def disable(self):
        """ Disable reception and transmission
        """
        self.rx.threadKill()
        self.tx.threadKill()
        time.sleep(1)
        self.fisica.close()

    ################################
    # Application  interface       #
    ################################

    def listenPacket(self, timeout, size):  #valor -1111 desativa o timeout
        label = 85
        packet = None

        dic = {
            'small': 17,
            'medium':
            544,  #signature + label + thresh + pckAmount + filenameSize + content + checksum + signature : +8 +1 +2 +3 +2 +512 +8 +8
            'big': 14 + 2**10 + 16
        }  #header + payload + eop
        size = dic[size]

        while timeout > 0 or timeout == -1111:
            if (timeout != -1111):
                timeout -= 100
            time.sleep(0.1)
            if (self.rx.getBufferLen() >= size):
                packet = self.rx.getBuffer(size)
                label = packet[8]
                break

        if (packet != None and
            (packet[0:8] != 'F.A.S.T.'.encode() or packet[-8:] !=
             'S.L.O.W.'.encode())):  #confere as assinaturas de header e eop
            label = 170

        if ((label == 0 or label == 131)
                and self.checksum(packet[0:-16]) != packet[-16:-8]
            ):  #confere o checksum de header+payload contra o checksum no eop
            label = 151

        if (label == 0
                and self.getPayloadCounter(packet) != len(self.receivedPck)):
            print(self.getPayloadCounter(packet))
            label = 222

        dic = {
            255: 'SYN',
            240: 'ACK',
            222: 'MISCOUNT',
            170: 'MALFORMED',
            151: 'CORRUPTED',
            131: 'META',
            85: 'TIMEOUT',
            15: 'NACK',
            0: 'DATA'
        }

        label = dic[label]
        print("Resultado do packet ouvido: " + label)
        self.rx.clearBufferUntilSignature('F.A.S.T.'.encode())
        return (label, packet)

    def getMetaName(self, packet):
        trailingfilename = packet[16:16 + 512]
        filenamelength = int.from_bytes(packet[14:16], byteorder='big')
        filename = trailingfilename[0:filenamelength]
        return filename.decode(
            'utf-8'
        )  #torcemos para que não tenhamos que nos preocupar algo que não utf-8

    def getMetaPacketAmount(self, packet):
        return int.from_bytes(packet[11:14], byteorder='big')

    def getMetaThreshold(self, packet):
        return int.from_bytes(packet[9:11], byteorder='big')

    def getPayloadCounter(self, packet):
        return int.from_bytes(packet[11:14], byteorder='little')

    def collapseData(self):
        data = bytes(bytearray())
        i = 0
        while (i != len(self.receivedPck)):
            data += self.receivedPck[i][13:-16]
            print('azul ', self.getPayloadCounter(self.receivedPck[i]))
            i += 1
        self.receivedPck = []
        cut = (2**10 - self.getMetaThreshold(self.meta)) % (2**10)
        return data[:-cut]

    def sendPacket(self, label, number=0):
        time.sleep(
            0.2
        )  #pra dar tempo do outro se preparar pra receber, testar diminuir ou remover este valor depois

        print("Enviando packet tipo ", label)

        dic = {
            'SYN': bytes([255]),
            'ACK': bytes([240]),
            'NACK': bytes([15]),
            'META': bytes([131]),
            'DATA': bytes([0])
        }
        label = dic[label]

        if (label == bytes([255]) or label == bytes([240])
                or label == bytes([15])):

            signature = 'F.A.S.T.'.encode()

            header = signature + label

            signature = 'S.L.O.W.'.encode()

            eop = signature
            packet = header + eop

        elif (label == bytes([131])):
            packet = self.meta

        elif (label == bytes([0])):
            packet = self.queuedPck[number]

        self.tx.sendBuffer(packet)

    def packageData(self, data, filename):

        self.queuedPck = []

        #bytes do payload de cada packet: 2**10
        payloadsize = 2**10
        packetamount = ((len(data) - 1) // payloadsize) + 1

        #TODO: editar o metadata para suportar mais packets por comunicação

        ##Fazer metadata
        #Para suportar o maior número possível de filesystems, suportaremos filenames de até 512 bytes
        #tamanho máximo de um arquivo transferido por uma sprint apenas, 4Gb = 2^32, 4 bytes
        signature = 'F.A.S.T.'.encode()
        label = bytes([131])
        thresh = len(data) % payloadsize
        thresh = bytes([((thresh // 256) % 256), (thresh % 256)])
        content = filename.encode()
        filenameSize = bytes([(((len(content) // 256) % 256)),
                              (len(content) % 256)])
        pckAmount = bytes([((packetamount // (256**2)) % 256),
                           ((packetamount // 256) % 256),
                           (packetamount % 256)])
        header = signature + label + thresh + pckAmount + filenameSize

        content = content + bytes([0]) * (512 - len(content))

        signature = 'S.L.O.W.'.encode()
        eop = self.checksum(header + content) + signature

        self.meta = (header + content + eop)

        #Fazer o packaging

        data += (((2**10) - (len(data) % 2**10)) % 2**10) * bytes([0])  #oh god

        counter = 0
        while (counter != packetamount):
            thisdata = data[counter * (2**10):(counter + 1) * (2**10)]
            self.queuedPck.append(self.createPacket(thisdata, counter))
            counter += 1

    def createPacket(self, payload, counter):

        signature = 'F.A.S.T.'.encode()
        label = bytes([0])
        #size= 2**10 #size do payload, constante para packets com payload
        size = bytes([0, 0])  #TODO: consertar
        counter = bytes([((counter // (256**2)) % 256),
                         ((counter // 256) % 256), (counter % 256)])

        header = signature + label + counter + size
        #14 bytes

        signature = 'S.L.O.W.'.encode()

        eop = self.checksum(header + payload) + signature
        #16 bytes

        return header + payload + eop

    def checksum(self, data):
        #Implementação nossa de um CRC-64 bits

        data = int.from_bytes(data, 'big')
        data = data * (2**64)  #append com zeros
        while (data.bit_length() > 64):
            sumNum = 2**(data.bit_length() - 65)
            key = 18601846741563846107  #um int aleatoriamente selecionado de 65 bits
            powerkey = key * sumNum

            data ^= powerkey

        return bytes([(data // (256**7)) % 256, (data // (256**6)) % 256,
                      (data // (256**5)) % 256, (data // (256**4)) % 256,
                      (data // (256**3)) % 256, (data // (256**2)) % 256,
                      (data // 256) % 256, data % 256])