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)
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])