Ejemplo n.º 1
0
class enlace(object):
    """ This class implements methods to the interface between Enlace and Application
    """

    max_pkt = 2048
    
    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

        construtor = packet.packet()
        
        nada = bytearray([])
        self.SYN = construtor.buildPacket(0, nada, 0, 0, 0, 0, 0)
        self.ACK = construtor.buildPacket(0, nada, 1, 0, 0, 0, 0)
        self.nACK = construtor.buildPacket(0, nada, 2, 0, 0, 0, 0)

    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 Handshake(self):#client
        
        print("Estabelecendo conexao...")
        timeout=2.0

        while self.connected == False:
          time.sleep(0.1)
          self.sendCmd(0)
          
          
          tempacote= self.getData(timeout)[2]
          if tempacote == 4:
              print("Nao recebi o Syn ainda")
          if tempacote == 0:
              print("Recebi o Syn!")
              tempacote= self.getData(timeout)[2]
              #print(tempacote)
              if tempacote == 4:
                  print("Recebi o Syn e ainda não recebi o Ack")
                  time.sleep(0.1)
                  self.sendCmd(2) #manda o nAck enquanto o Ack nao chega
              if tempacote == 1:
                  print("Recebi o Ack")
                  self.sendCmd(1)
                  print("Mandei o ultimo Ack")
                  self.connected = True
          
        print("Conectado com sucesso!")

    def waitingHandshake(self): #SERVER
        timeout= 2.0
        while True:    
    
            print("Esperando o Syn...")
            while(self.getData(timeout)[2] != 0):
                print("...")
                continue
            print("Recebi o Syn")
            time.sleep(0.1)
            self.sendCmd(0)
            print("enviei o Syn")
            time.sleep(0.1)
            self.sendCmd(1)
            print("enviei o Ack")
            time.sleep(0.1)
            print("Aguardando o Ack")
            tempacote= self.getData(timeout)[2]
            print("tempacote: "+str(tempacote))
            if tempacote == 4:
                print("Não recebi nada (timeout)")
            if tempacote == 2:
                print("Recebi nAck")
            if tempacote == 1:
                print("Recebi o ultimo Ack")
                print("Handshake ENCERRADO")
                break
        print("----")
        
    def sendData(self, data):
        """ Send data over the enlace interface
        """
        construtor = packet.packet()
        
        max_pkt = self.max_pkt
        qtdpartes = math.ceil(len(data)/max_pkt)
        atual = 1
        x = 0
        y = max_pkt
        while atual <= qtdpartes:
            data_cortada = data[x:y]
            pacote = construtor.buildPacket(len(data_cortada), data_cortada, 3, atual, qtdpartes, 0, 0) #constroi pacote falso
            crc_head = self.CRC(pacote[0:5]) #calcula crc pro pacote falso
            crc_payload = self.CRC(data_cortada)
            pacote_final = construtor.buildPacket(len(data_cortada), data_cortada, 3, atual, qtdpartes, crc_head, crc_payload)
            time.sleep(0.05)            
            self.tx.sendBuffer(pacote_final) #envia pacote verdadeiro            
            
            tmp= self.getData(0.5)
            if tmp[2] == 1: #10 é valor do timeout
                print("Recebi o Ack, vou enviar o proximo pacote")
                atual += 1
                x += max_pkt
                y += max_pkt
                print("Checagem pacote: "+str(len(pacote_final)))
                
            if tmp[2] == 2:
                print("Recebi um nAck, vou reenviar o ultimo pacote")
        

    def sendCmd(self, tipo):
        if tipo == 0:
            self.tx.sendBuffer(self.SYN)
        if tipo == 1:
            self.tx.sendBuffer(self.ACK)
        if tipo == 2:
            self.tx.sendBuffer(self.nACK)
    
    #

    def getData(self, timeout):
        """ Get n data over the enlace interface
        Return the byte array and the size of the buffer
        """
        print("Chamei o Get Data")
        payload = bytearray([])
        while True:
            
            pacote = self.rx.getPacket(timeout)
            construtor = packet.packet()          
            
            data, tipo, atual, total, crc_head, crc_payload = construtor.unpack(pacote)
            if data != None:
                print("Atual: ", atual)
                print("Total: ", total)
                crc_payload_2 = self.CRC(data)
                crc_head_2 = self.CRC(pacote[0:5])
                if crc_payload_2 == crc_payload and crc_head_2 == crc_head:
                    #comparação de crcs, se der certo, envia Ack
                    payload += data
                    time.sleep(0.05)
                    self.sendCmd(1)
                    print("Recebi o pacote, mandando o Ack")
                else:
                    time.sleep(0.1)
                    self.sendCmd(2)
                    print("Recebi o pacote corrompido, mandando nAck")
                last= atual
                ptotal=total
                while atual < ptotal:
                    pacote = self.rx.getPacket(timeout)
                    data, tipo, atual, total, crc_head, crc_payload = construtor.unpack(pacote)
                    
                    print("Recebi um pacote tipo: ", tipo)
                    if (tipo!=3):
                        continue
                    
                    print("Atual: ", atual)
                    print("Total: ", total)
                    
                    crc_payload_2 = self.CRC(data)
                    crc_head_2 = self.CRC(pacote[0:5])
                    if crc_payload_2 == crc_payload and crc_head_2 == crc_head and atual==(last+1):
                        #comparação de crcs, se der certo, envia Ack
                        last=atual
                        payload += data
                        time.sleep(0.1)
                        self.sendCmd(1)
                        print("Recebi o pacote, mandando o Ack")
                    elif(last==atual):
                        print("Recebi um pacote repetido")
                    else:
                        time.sleep(0.05)
                        self.sendCmd(2)
                        print("Last: ", last)
                        print("Atual: ", atual)
                        print("Recebi o pacote corrompido, mandando nAck")
                    
                return(payload, len(payload), 3)
                
            else:
                return(None, 0, tipo)
                
    
    def CRC(self,data):
        crc8 = crcmod.predefined.mkCrcFun("crc-8")

        CRC = (crc8(data))

        return CRC
Ejemplo n.º 2
0
class enlace(object):
    """ This class implements methods to the interface between Enlace and Application
    """
    def __init__(self, app):
        """ Initializes the enlace class
        """
        self.app = app
        self.fisica = fisica(app.serialName)
        self.rx = RX(self.fisica)
        self.tx = TX(self.fisica)
        self.connected = False
        self.ph = PacketHandler()
        self.label = '[ENLACE]'
        self.idle = True

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

    def connect(self, client):
        """ Bloqueia a execução do programa até que uma conexão confiável
        com o servidor seja estabelecida """
        print(self.label, "Iniciando Handshake como Cliente")
        while client.handshake == False:
            if client.state == 'INICIAL':
                client.setState('ENVIANDO_SYN')

            elif client.state == 'ENVIANDO_SYN':
                self.sendSyn()
                client.setState('AGUARDANDO_SYN')

            elif client.state == 'AGUARDANDO_SYN':
                data = self.getData()
                if data != False:
                    p = self.ph.unpack(data)
                    if p['type'] == 'SYN':
                        client.setState('AGUARDANDO_ACK')
                    else:
                        client.setState('ENVIANDO_SYN')
                else:
                    client.setState('ENVIANDO_SYN')

            elif client.state == 'AGUARDANDO_ACK':
                data = self.getData()
                if data != False:
                    p = self.ph.unpack(data)
                    if p['type'] == 'ACK':
                        client.setState('ENVIANDO_ACK')
                        self.sendAck()
                        print(self.label, '\n ~~~ HANDSHAKE EFETUADO ~~~ \n')
                        client.setState('CONECTADO')
                        client.handshake = True
                else:
                    client.setState('INICIAL')

    def bind(self, server):
        """ Bloqueia a execução do programa até que uma conexão confiável
        com o cliente seja estabelecida """
        print(self.label, "Iniciando Handshake como Servidor")
        while server.handshake == False:
            if server.state == 'INICIAL':
                server.setState('AGUARDANDO_SYN')

            elif server.state == 'AGUARDANDO_SYN':
                print(self.label, 'Aguardando pedidos SYN...')
                data = self.getData()
                if data:
                    p = self.ph.unpack(data)
                    if p['type'] == 'SYN':
                        server.setState('ENVIANDO_SYN')

            elif server.state == 'ENVIANDO_SYN':
                self.sendSyn()
                time.sleep(0.05)
                server.setState('ENVIANDO_ACK')

            elif server.state == 'ENVIANDO_ACK':
                self.sendAck()
                time.sleep(0.05)
                server.setState('AGUARDANDO_ACK')

            elif server.state == 'AGUARDANDO_ACK':
                data = self.getData()
                if data:
                    p = self.ph.unpack(data)
                    if p['type'] == 'ACK':
                        print(self.label, '\n ~~~ HANDSHAKE EFETUADO ~~~ \n')
                        server.setState('CONECTADO')
                        server.handshake = True

    def startServerStateMachine(self, server):
        """Máquina de Estados para envio de ACK e NACK ao receber payloads"""
        currentSize = 0

        while server.stateMachineRunning:
            # Checa se o handshake já foi efetuado, caso contrário, o faz
            if server.handshake == False:
                server.setState('INICIAL')
                server.app.com.bind(server)

            elif server.state == 'CONECTADO':
                time.sleep(0.05)
                server.setState('AGUARDANDO_PACOTE')

            elif server.state == 'AGUARDANDO_PACOTE':
                file = self.getData()
                if file != False:
                    self.idle = False
                    p = server.ph.unpack(file)
                    headchecksum = server.ph.generateHeadChecksum(p['head'])
                    payloadchecksum = server.ph.generatePayloadChecksum(
                        p['payload'])
                    # print('HOLYYYYYYYYY', p['headchecksum'],'\n',headchecksum)
                    if (p['headchecksum']
                            == headchecksum) and (p['payloadchecksum']
                                                  == payloadchecksum):
                        index = p['index']
                        currentSize += p['slicesize']
                        print(
                            '[ServerStateMachine] Recebido pacote {}/{} com {} bytes | Recebido : {}/{} bytes'
                            .format(index[0], index[1], p['slicesize'],
                                    currentSize, p['size']))

                        server.setState('ENVIANDO_ACK')

                        if index[0] == index[1] and currentSize == p['size']:
                            self.sendAck()
                            currentSize = 0
                            print(
                                '[ServerStateMachine] Arquivo recebido com sucesso! '
                            )
                            server.ph.writeFile()
                            self.idle = True
                            server.setState('CONECTADO')

                    else:
                        server.setState('ENVIANDO_NACK')

                else:
                    server.setState('ENVIANDO_NACK')

            elif server.state == 'ENVIANDO_ACK':
                self.sendAck()
                server.setState('AGUARDANDO_PACOTE')

            elif server.state == 'ENVIANDO_NACK':
                self.sendNack()
                server.setState('AGUARDANDO_PACOTE')

    def startClientStateMachine(self, client):
        """Máquina de Estados para envio e recepcao de ACKS e NACKS ao enviar
        payloads"""

        packets = client.filePackets
        currentPacket = 0

        while client.stateMachineRunning:
            # Checa se o handshake já foi efetuado, caso contrário, o faz
            if client.handshake == False:
                client.setState('INICIAL')
                client.app.com.connect(client)

            elif client.state == 'CONECTADO':
                time.sleep(0.05)
                client.setState('ENVIANDO_PACOTE')

            elif client.state == 'ENVIANDO_PACOTE':
                print(
                    '[ClientStateMachine] Enviando pacote {}/{} com {} bytes'.
                    format(currentPacket + 1, len(packets),
                           packets[currentPacket]['packetSize']))

                self.sendData(packets[currentPacket]['packet'])
                client.setState('AGUARDANDO_ACK')

            elif client.state == 'AGUARDANDO_ACK':
                data = client.app.com.getData()
                if data != False:
                    p = client.app.ph.unpack(data)
                    if p['type'] == 'ACK':
                        print('[ClientStateMachine] -> Pacote {}/{} -> ACK'.
                              format(currentPacket + 1, len(packets)))
                        currentPacket += 1
                        if currentPacket == len(packets):
                            client.setState('ENCERRANDO_COMUNICACAO')
                        else:
                            client.setState('ENVIANDO_PACOTE')

                    elif p['type'] == 'NACK':
                        print(
                            '[ClientStateMachine] -> Pacote {}/{} -> NACK !!!'.
                            format(currentPacket + 1, len(packets)))
                        client.setState('ENVIANDO_PACOTE')

                else:
                    print(
                        '[ClientStateMachine] -> Pacote {}/{} -> TIMEOUT !!!'.
                        format(currentPacket + 1, len(packets)))
                    client.setState('ENVIANDO_PACOTE')

            elif client.state == 'ENCERRANDO_COMUNICACAO':
                print('[Client] Sucesso no envio, encerrando comunicação')
                print('Fim de Transmissão. Arquivo enviado com sucesso!')
                client.setState('CONECTADO')
                currentPacket = 0
                client.stateMachineRunning = False

    def sendSyn(self):
        p = self.ph.buildCommandPacket("SYN")
        self.sendData(p)

    def sendAck(self):
        p = self.ph.buildCommandPacket("ACK")
        self.sendData(p)

    def sendNack(self):
        p = self.ph.buildCommandPacket("NACK")
        if self.app.role == 'server' and self.idle == False:
            self.sendData(p)

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

    def sendData(self, data):
        """ Send data over the enlace interface
        """
        self.tx.sendBuffer(data)

    def getData(self):
        """ Get n data over the enlace interface
        """
        packet = self.rx.getPacket()
        # print('--> DATA RECEIVED : ', packet)

        if packet != False:
            p = PacketHandler().unpack(packet)
            # if p['type'] == 'PAYLOAD' and p['slicesize'] != len(p['payload']):
            #     print(self.label,'Pacote corrompido, enviando NACK')
            #     self.sendNack()
            #     return False
            return packet

        else:
            return False
Ejemplo n.º 3
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.enviardata  = False
        self.corrupt     = False
        self.bufferdata  = bytes(bytearray())
        self.sizeselect  = 2048
        self.datasize    = 0
        self.sizepack    = 0
        self.numberpack  = 0
        self.numberpackrecive = 1
        self.tamanhoenviado   = 0

    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()
        
    def fragment(self):
        self.numberpack += 1
        if (len(self.bufferdata) >= self.sizeselect):
            b           = self.bufferdata[:self.sizeselect]
            self.bufferdata = self.bufferdata[self.sizeselect:]
        else:
            b           = self.bufferdata[:]
            self.bufferdata = b""
        self.tamanhoenviado = len(b) 
        return self.buildDataPacket(b)

    def connect(self,data):
        self.constructado()
        self.bufferdata = data[:]
        self.datasize = len(data)
        """ Estabelece um conexão confiável com o Servidor - Máquina de Estados Client """
        print("Client - Iniciando Handshake")

        while(self.connected == False):
            print("Enviando SYN...")
            self.sendData(self.buildSynPacket())
            print("SYN Enviado!")
            print("Esperando pelo ACK + SYN do Servidor...")
            time.sleep(0.5) 
            if(self.getCommandType() == "ACK"):
                print("Ack recebido")
                time.sleep(0.15)
                while(self.connected == False):
                    if (self.getCommandType() == "SYN"): 
                        print("SYN Recebido!")
                        print("Confirmando recebimento do SYN...")
                        self.sendData(self.buildAckPacket())    
                        print("Conexão estabelecida!")
                        self.connected = True
            elif(self.getCommandType() == "Erro"):
                print("Erro na transmissão de dados. Reconectando...")
            else:
                print("Time out")
                print("Reiniciando conexão")
                time.sleep(0.2)
        
        packtotal = (len(data) // self.sizeselect) + 1
        while(len(self.bufferdata)!= 0):
            pack = self.fragment()
            while(self.enviardata == False):
                print("Enviado: pacote ",self.numberpack,"/",packtotal," : ",self.tamanhoenviado, "Bytes")
                self.sendData(pack)
                if (self.getCommandType() == "ACK"):
                    self.enviardata = True
                elif(self.getCommandType() == "nACK"):
                    self.enviardata = False 
                time.sleep(1)
            self.enviardata = False
            time.sleep(1)
            print("Proximo Pacote")
            
    def bind(self):
        self.constructado()
        """ Estabelece um conexão confiável com o Client - Máquina de Estados Servidor """
        print("Servidor - Iniciando Handshake")
        while(self.connected == False):
            print("Aguardando um Comando do Client")
            if(self.getCommandType() == "SYN"):
                print("SYN Recebido!")
    
                self.sendData(self.buildAckPacket())
                print("ACK Enviado")
                time.sleep(0.01)
                                
                self.sendData(self.buildSynPacket())
                print("SYN Enviado")
                time.sleep(0.01)
                
                cont = 0
                while(self.connected == False):    
                    cont += 1
                    if(self.getCommandType() == "ACK"):
                        print("ACK Recebido!")
                        self.connected = True
                        print("Conexão estabelecida!")

                    time.sleep(0.15)
                    if(cont == 9):
                        break

            elif(self.getCommandType() == "nACK"):
                print("Conexão não estabelecida, erro!")
                self.sendData(self.buildNackPacket())


            elif(self.getCommandType() == "Erro"):
                print("Erro na transmissão de dados.")
                self.sendData(self.buildNackPacket())

            else:
                print("Timeout! O Client não respondeu no tempo hábil. Reiniciando Conexão.")
                self.sendData(self.buildNackPacket())
            time.sleep(1)

    def constructado(self):
        self.StructEop()
        self.StructHead()

    def sendData(self, pack):
        self.tx.sendBuffer(pack)
            
    def getData(self):
        """ Get n data over the enlace interface
        Return the byte array and the size of the buffer
        """
        byterecebido = 0
        bytetotal = 1
        f = bytes(bytearray())
        
        while(byterecebido != bytetotal):
            head, data = self.rx.getPacket()
            size = int(binascii.hexlify(head[2:4]), 16)
            CRC_Head = self.getCRC(head[:8])
            CRC_Data = self.getCRC(data)
            packtotal = int(binascii.hexlify(head[4:6]), 16) // self.sizeselect  
            
            if(size != len(data) or (CRC_Head != head[8]) or (CRC_Data != head[9]) ):
                print("Size: ",size,"/",len(data))
                print("CRC_HEAD: ",CRC_Head,"/",head[8])
                print("CRC_DATA: ",CRC_Data,"/",head[9])
                print("nAck (Arquivo corrompido)")
                self.sendData(self.buildNackPacket())
                time.sleep(0.2)

            else:
                print("ACK Enviado")
                self.sendData(self.buildAckPacket())

                if(self.numberpackrecive == head[7]): 
                    byterecebido += len(data) 
                    bytetotal = int(binascii.hexlify(head[4:6]), 16)
                    print("Recebido: pacote", head[7],"/",packtotal ," : ",byterecebido,"/",bytetotal)
                    f += data
                    self.numberpackrecive += 1
                    time.sleep(0.1)
                else:
                    print("nAck Enviado")
                    self.sendData(self.buildNackPacket())
        return f
#---------------------------------------------#
    #Define a estrutura do HEAD.
    def StructHead(self):
        self.headStart = 0xFF
        self.headStruct = Struct("start"        / Int16ub, #Como é 16, o Head começará com \x00\xff + size 
                                "size"          / Int16ub,
                                "totaldatasize" / Int16ub,
                                "typecommand"   / Int8ub,
                                "number"        /Int8ub,
                                "crc_head"      / Int8ub,
                                "crc_payload"   / Int8ub
                                )
        
    #Implementa o head
    def buildHead(self, dataLen, totalsize, command, packnumber, crc_head_value, crc_payload_value):
        head = self.headStruct.build(dict(
                                start           = self.headStart,
                                size            = dataLen,
                                totaldatasize   = totalsize,
                                typecommand     = command,
                                number          = packnumber,
                                crc_head        = crc_head_value,
                                crc_payload     = crc_payload_value))
        return head

#---------------------------------------------#
    #Define a estrutura do EOP.
    def StructEop(self):
        self.endStart = 0xFF
        self.endStruct = Struct("c1" / Int8ub,
                                "c2" / Int8ub,
                                "c3" / Int8ub,
                                "c4" / Int8ub)

    #Implementa o EOP.
    def buildEop(self):
        end = self.endStruct.build(dict(
                                c1 = 0x01,
                                c2 = 0x02,
                                c3 = 0x03,
                                c4 = 0x04))
        return end

#---------------------------------------------#
    #Cria o Pacote de Dados.
    def buildDataPacket(self,data):
        size = len(data)       
        head = self.buildHead(size,self.datasize,0,self.numberpack,0,0)
        CRC_Head = self.getCRC(head[:8])
        CRC_Data = self.getCRC(data)

        head = self.buildHead(size,self.datasize,0,self.numberpack,CRC_Head,CRC_Data)

        pack = head + data
        pack += self.buildEop()
        return pack
#---------------------------------------------#
    #Cria o Pacote Comando Syn
    def buildSynPacket(self):
        SYN = 0x10
        pack = self.buildHead(0,0,SYN,0,0,0)
        pack += self.buildEop()
        return pack

    #Cria o Pacote Comando Ack
    def buildAckPacket(self):
        ACK = 0x11  
        pack = self.buildHead(0,0,ACK,0,0,0)
        pack += self.buildEop()
        return pack

    #Cria o Pacote Comando nAck
    def buildNackPacket(self):
        NACK = 0x12
        pack = self.buildHead(0,0,NACK,0,0,0)
        pack += self.buildEop()
        return pack

#---------------------------------------------#
    #Classifica o pacote em Commandos ou Dado
    def getPacketType(self):
        head, _= self.rx.getPacket()
        if head.endswith(b'\x00'):
            return ("Dado")
        elif head.endswith(b'\x10') or head.endswith(b'\x11') or head.endswith(b'\x12'):
            return ("Comando")
        else:
            return ("Buffer vazio")

    #Classifica o comando em Syn, Ack ou nAck
    def getCommandType(self):
        if (self.rx.getIsEmpty() == False):
            head, _= self.rx.getPacket()
            if (len(head) > 6):
                if (head[6] == 16):
                    return ("SYN")
                elif (head[6] == 17):
                    return ("ACK")
                elif (head[6] == 18):
                    return ("nACK")
                else:
                    return ("Erro")
        else:
            time.sleep(0.3)
            return("Erro")

    #Pega o size expresso no Head
    def getSize(self,data):
        size = int(binascii.hexlify(data[2:4]), 16)
        return (size)         

#---------------------------------------------#
    #CALCULAR OVERHEAD
    def CalcularOverhead(self, pack, data):
        overhead = len(pack)/len(data) 
        print("Overhead:" , overhead)
        return (overhead)

#---------------------------------------------#
    #Calcula CRC
    def getCRC(self, data):
        crc8_func = crcmod.predefined.mkCrcFun('crc-8')
        crc = crc8_func(data)
        return(crc)
Ejemplo n.º 4
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.enviardata = False

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

    def connect(self, data):
        self.constructado()
        """ Estabelece um conexão confiável com o Servidor - Máquina de Estados Client """
        print("Client - Iniciando Handshake")
        while (self.connected == False):
            print("Enviando SYN...")
            self.sendData(self.buildSynPacket())
            print("SYN Enviado!")
            print("Esperando pelo ACK + SYN do Servidor...")
            time.sleep(0.15)
            if (self.getCommandType() == "ACK"):
                time.sleep(0.15)
                if (self.getCommandType() == "SYN"):
                    print("SYN + ACK Recebido!")
                    print("Confirmando recebimento do SYN...")
                    self.sendData(self.buildAckPacket())
                    print("Conexão estabelecida!")
                    self.connected = True
            elif (self.getCommandType() == "Erro"):
                print("Erro na transmissão de dados. Reconectando...")
            else:
                print("Time out")
                print("Reiniciando conexão")
                time.sleep(0.15)
        pack = self.buildDataPacket(data)
        while (self.enviardata == False):
            self.sendData(pack)
            time.sleep(0.2)
            if (self.getCommandType() == "ACK"):
                self.enviardata = True
            elif (self.getCommandType() == "nACK"):
                self.enviardata = False

    def bind(self):
        self.constructado()
        """ Estabelece um conexão confiável com o Client - Máquina de Estados Servidor """
        print("Servidor - Iniciando Handshake")
        while (self.connected == False):
            print("Aguardando um Comando do Client")
            if (self.getCommandType() == "SYN"):
                print("SYN Recebido!")

                self.sendData(self.buildAckPacket())
                print("ACK Enviado")
                time.sleep(0.1)

                self.sendData(self.buildSynPacket())
                print("SYN Enviado")

                if (self.getCommandType() == "ACK"):
                    print("ACK Recebido!")
                    self.connected = True
                    print("Conexão estabelecida!")

                time.sleep(0.4)

            elif (self.getCommandType() == "nACK"):
                print("Conexão não estabelecida, erro!")
                self.sendData(self.buildNackPacket())

            elif (self.getCommandType() == "Erro"):
                print("Erro na transmissão de dados.")
                self.sendData(self.buildNackPacket())

            else:
                print(
                    "Timeout! O Client não respondeu no tempo hábil. Reiniciando Conexão."
                )
                self.sendData(self.buildNackPacket())
            time.sleep(0.15)

    def constructado(self):
        self.StructEop()
        self.StructHead()

    def sendData(self, pack):
        self.tx.sendBuffer(pack)

    def getData(self):
        """ Get n data over the enlace interface
        Return the byte array and the size of the buffer
        """
        _, data = self.rx.getPacket()
        size = len(data)

        while (size != len(data)):
            print("nack enviado")
            self.sendData(self.buildNackPacket())
            time.sleep(0.2)

        print("ack enviado")
        self.sendData(self.buildAckPacket())
        return (data)

#---------------------------------------------#
#Define a estrutura do HEAD.

    def StructHead(self):
        self.headStart = 0xFF
        self.headStruct = Struct(
            "start" /
            Int16ub,  #Como é 16, o Head começará com \x00\xff + size 
            "size" / Int16ub,
            "typecommand" / Int8ub)

    #Implementa o head
    def buildHead(self, dataLen, command):
        head = self.headStruct.build(
            dict(start=self.headStart, size=dataLen, typecommand=command))
        return head

#---------------------------------------------#
#Define a estrutura do EOP.

    def StructEop(self):
        self.endStart = 0xFF
        self.endStruct = Struct("c1" / Int8ub, "c2" / Int8ub, "c3" / Int8ub,
                                "c4" / Int8ub)

    #Implementa o EOP.
    def buildEop(self):
        end = self.endStruct.build(dict(c1=0x01, c2=0x02, c3=0x03, c4=0x04))
        return end

#---------------------------------------------#
#Cria o Pacote de Dados.

    def buildDataPacket(self, data):
        pack = self.buildHead(len(data), 0x00)
        pack += data
        pack += self.buildEop()
        print(len(data))
        return pack

#---------------------------------------------#
#Cria o Pacote Comando Syn

    def buildSynPacket(self):
        SYN = 0x10
        pack = self.buildHead(0, SYN)
        pack += self.buildEop()
        return pack

    #Cria o Pacote Comando Ack
    def buildAckPacket(self):
        ACK = 0x11
        pack = self.buildHead(0, ACK)
        pack += self.buildEop()
        return pack

    #Cria o Pacote Comando nAck
    def buildNackPacket(self):
        NACK = 0x12
        pack = self.buildHead(0, NACK)
        pack += self.buildEop()
        return pack

#---------------------------------------------#
#Classifica o pacote em Commandos ou Dado

    def getPacketType(self):
        head, _ = self.rx.getPacket()
        if head.endswith(b'\x00'):
            return ("Dado")
        elif head.endswith(b'\x10') or head.endswith(b'\x11') or head.endswith(
                b'\x12'):
            return ("Comando")
        else:
            return ("Buffer vazio")

    #Classifica o comando em Syn, Ack ou nAck
    def getCommandType(self):
        if (self.rx.getIsEmpty() == False):
            head, _ = self.rx.getPacket()
            if head.endswith(b'\x10'):
                return ("SYN")
            elif head.endswith(b'\x11'):
                return ("ACK")
            elif head.endswith(b'\x12'):
                return ("nACK")
            else:
                return ("Erro")
        else:
            time.sleep(0.5)
            return ("Erro")

    #Pega o size expresso no Head
    def getSize(self):
        head, _ = self.rx.getPacket()
        size = int(binascii.hexlify(head[2:4]), 16)
        return (size)

#---------------------------------------------#
#CALCULAR OVERHEAD

    def CalcularOverhead(self, pack, data):
        overhead = len(pack) / len(data)
        print("Overhead:", overhead)
        return (overhead)