#!/usr/bin/env python3 # Antes de usar, execute o seguinte comando para evitar que o Linux feche # as conexões TCP que o seu programa estiver tratando: # # sudo iptables -I OUTPUT -p tcp --tcp-flags RST RST -j DROP # Este é um exemplo de um programa que faz eco, ou seja, envia de volta para # o cliente tudo que for recebido em uma conexão. import asyncio from camadarede import CamadaRedeLinux from mytcp import Servidor def dados_recebidos(conexao, dados): if dados == b'': conexao.fechar() else: conexao.enviar(dados) # envia de volta def conexao_aceita(conexao): conexao.registrar_recebedor(dados_recebidos) # usa esse mesmo recebedor para toda conexão aceita rede = CamadaRedeLinux() servidor = Servidor(rede, 7000) servidor.registrar_monitor_de_conexoes_aceitas(conexao_aceita) asyncio.get_event_loop().run_forever()
def main(): global recebido, conexao rede = CamadaRede() dst_port = random.randint(10, 1023) servidor = Servidor(rede, dst_port) servidor.registrar_monitor_de_conexoes_aceitas(conexao_aceita) src_port = random.randint(1024, 0xffff) seq_no = random.randint(0, 0xffff) src_addr, dst_addr = '10.%d.1.%d'%(random.randint(1, 10), random.randint(0,255)), '10.%d.1.%d'%(random.randint(11, 20), random.randint(0, 255)) rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, 0, FLAGS_SYN), src_addr, dst_addr)) segmento, _ = rede.fila[0] _, _, ack_no, ack, flags, _, _, _ = read_header(segmento) assert 4*(flags>>12) == len(segmento), 'O SYN+ACK não deveria ter payload' assert (flags & FLAGS_ACK) == FLAGS_ACK rede.fila.clear() seq_no += 1 ack_no += 1 assert ack == seq_no rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) rede.fila.clear() payload = os.urandom(MSS) conexao.enviar(payload) assert len(rede.fila) == 1 yield from asyncio.sleep(0.2) while len(rede.fila) > 0: segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) payload = os.urandom(MSS) conexao.enviar(payload) assert len(rede.fila) == 1 rede.fila.clear() # descarta yield from asyncio.sleep(1.5) while len(rede.fila) > 0: segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) payload = os.urandom(2*MSS) conexao.enviar(payload) rede.fila.clear() # descarta yield from asyncio.sleep(1.5) while len(rede.fila) > 0: segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) print("ack "+str(ack_no)+" seq "+str(seq)) # Apenas o segmento mais antigo deve ser reenviado no timeout assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload[:MSS] ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) yield from asyncio.sleep(1.5) segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) # Agora deve vir o segundo segmento assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload[MSS:] ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr))
server = Server() # Integração com as demais camadas driver = ZyboSerialDriver() linha_serial = driver.obter_porta(4) pty = driver.expor_porta_ao_linux(5) outra_ponta = '192.168.123.1' nossa_ponta = '192.168.123.2' porta_tcp = 7000 print('Conecte o RX da porta 4 com o TX da porta 5 e vice-versa.') print('Para conectar a outra ponta da camada física, execute:') print() print('sudo slattach -vLp slip {}'.format(pty.pty_name)) print('sudo ifconfig sl0 {} pointopoint {} mtu 1500'.format( outra_ponta, nossa_ponta)) print() print('Acesse o serviço com o comando: nc {} {}'.format(nossa_ponta, porta_tcp)) print() enlace = CamadaEnlace({outra_ponta: linha_serial}) rede = CamadaRede(enlace) rede.definir_endereco_host(nossa_ponta) rede.definir_tabela_encaminhamento([ ('0.0.0.0/0', outra_ponta) ]) tcp = Tcp(rede, porta_tcp) tcp.registrar_monitor_de_conexoes_aceitas(server.conexao_aceita) asyncio.get_event_loop().run_forever()
conexao.registrar_recebedor(dados_recebidos) # usa esse mesmo recebedor para toda conexão aceita # Integração com as demais camadas driver = ZyboSerialDriver() linha_serial = driver.obter_porta(4) pty = driver.expor_porta_ao_linux(5) outra_ponta = '192.168.123.1' nossa_ponta = '192.168.123.2' porta_tcp = 7000 print('Conecte o RX da porta 4 com o TX da porta 5 e vice-versa.') print('Para conectar a outra ponta da camada física, execute:') print() print('sudo slattach -vLp slip {}'.format(pty.pty_name)) print('sudo ifconfig sl0 {} pointopoint {} mtu 1500'.format(outra_ponta, nossa_ponta)) print() print('Acesse o serviço com o comando: nc {} {}'.format(nossa_ponta, porta_tcp)) print() enlace = CamadaEnlace({outra_ponta: linha_serial}) rede = CamadaRede(enlace) rede.definir_endereco_host(nossa_ponta) rede.definir_tabela_encaminhamento([ ('0.0.0.0/0', outra_ponta) ]) servidor = Servidor(rede, porta_tcp) servidor.registrar_monitor_de_conexoes_aceitas(conexao_aceita) asyncio.get_event_loop().run_forever()
def main(): global recebido, conexao rede = CamadaRede() dst_port = random.randint(10, 1023) servidor = Servidor(rede, dst_port) servidor.registrar_monitor_de_conexoes_aceitas(conexao_aceita) src_port = random.randint(1024, 0xffff) seq_no = random.randint(0, 0xffff) src_addr, dst_addr = '10.%d.%d.%d'%(random.randint(1, 10), random.randint(0,255), random.randint(0,255)), '10.%d.%d.%d'%(random.randint(11,20), random.randint(0,255), random.randint(0,255)) rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, 0, FLAGS_SYN), src_addr, dst_addr)) segmento, _ = rede.fila[0] _, _, ack_no, ack, flags, _, _, _ = read_header(segmento) assert 4*(flags>>12) == len(segmento), 'O SYN+ACK não deveria ter payload' assert (flags & FLAGS_ACK) == FLAGS_ACK rede.fila.clear() seq_no += 1 ack_no += 1 assert ack == seq_no rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) rede.fila.clear() payload = os.urandom(MSS) conexao.enviar(payload) assert len(rede.fila) == 1 yield from asyncio.sleep(0.1) while len(rede.fila) > 0: segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload ack_no += len(payload) rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) payload = os.urandom(14*MSS) conexao.enviar(payload) for winsize in (2, 3, 4, 5): assert len(rede.fila) == winsize, 'A janela neste momento deveria ser de %d MSS, mas foi de %d MSS' % (winsize, len(rede.fila)) for _ in range(winsize): segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload[:MSS] payload = payload[MSS:] ack_no += MSS if winsize == 5: # Causa um timeout yield from asyncio.sleep(0.25) assert len(rede.fila) == 1, 'Deveria ter acontecido a retransmissão de um segmento' rede.fila.clear() else: yield from asyncio.sleep(0.1) rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) payload = os.urandom(12*MSS) conexao.enviar(payload) for winsize in (3, 4, 5): assert len(rede.fila) == winsize, 'A janela neste momento deveria ser de %d MSS, mas foi de %d MSS' % (winsize, len(rede.fila)) for _ in range(winsize): segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload[:MSS] payload = payload[MSS:] ack_no += MSS yield from asyncio.sleep(0.1) rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr))
def main(): global recebido, conexao rede = CamadaRede() dst_port = random.randint(10, 1023) servidor = Servidor(rede, dst_port) servidor.registrar_monitor_de_conexoes_aceitas(conexao_aceita) src_port = random.randint(1024, 0xffff) seq_no = random.randint(0, 0xffff) src_addr, dst_addr = '10.%d.%d.%d'%(random.randint(1, 10), random.randint(0,255), random.randint(0,255)), '10.%d.%d.%d'%(random.randint(11,20), random.randint(0,255), random.randint(0,255)) rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, 0, FLAGS_SYN), src_addr, dst_addr)) segmento, _ = rede.fila[0] _, _, ack_no, ack, flags, _, _, _ = read_header(segmento) assert 4*(flags>>12) == len(segmento), 'O SYN+ACK não deveria ter payload' assert (flags & FLAGS_ACK) == FLAGS_ACK rede.fila.clear() seq_no += 1 ack_no += 1 assert ack == seq_no rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) rede.fila.clear() payload = os.urandom(MSS) conexao.enviar(payload) assert len(rede.fila) == 1 yield from asyncio.sleep(0.1) while len(rede.fila) > 0: segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) payload = os.urandom(MSS) conexao.enviar(payload) assert len(rede.fila) == 1 rede.fila.clear() # descarta # sample_rtt = 0.1 # estimated_rtt = sample_rtt = 0.1 # dev_rtt = sample_rtt/2 = 0.05 # timeout_interval = estimated_rtt + 4*dev_rtt = 0.3 # 0.29 < timeout_interval < 0.31 yield from asyncio.sleep(0.29) assert len(rede.fila) == 0, 'Não deveria ter retransmitido ainda' yield from asyncio.sleep(0.02) assert len(rede.fila) == 1, 'Já deveria ter retransmitido' segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload # Verifica se o tempo de segmentos retransmitidos está sendo ignorado yield from asyncio.sleep(2) rede.fila.clear() ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) payload = os.urandom(MSS) conexao.enviar(payload) assert len(rede.fila) == 1 rede.fila.clear() # descarta yield from asyncio.sleep(0.25) assert len(rede.fila) == 0, 'Não deveria ter retransmitido ainda' yield from asyncio.sleep(0.06) assert len(rede.fila) == 1, 'Já deveria ter retransmitido' segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) payload = os.urandom(MSS) conexao.enviar(payload) yield from asyncio.sleep(0.001) assert len(rede.fila) == 1 segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr)) payload = os.urandom(MSS) conexao.enviar(payload) assert len(rede.fila) == 1 rede.fila.clear() # descarta # sample_rtt = 0.001 # estimated_rtt = (1-0.125)*0.1 + 0.125*0.001 = 0.087625 # dev_rtt = (1-0.25)*0.05 + 0.25*abs(0.001-0.1) = 0.06225 # timeout_interval = estimated_rtt + 4*dev_rtt = 0.336625 # 0.32 < timeout_interval < 0.34 yield from asyncio.sleep(0.32) assert len(rede.fila) == 0, 'Não deveria ter retransmitido ainda' yield from asyncio.sleep(0.02) assert len(rede.fila) == 1, 'Já deveria ter retransmitido' segmento, _ = rede.fila.pop(0) _, _, seq, ack, flags, _, _, _ = read_header(segmento) assert seq == ack_no assert (flags & FLAGS_ACK) == FLAGS_ACK and ack == seq_no assert segmento[4*(flags>>12):] == payload ack_no += MSS rede.callback(src_addr, dst_addr, fix_checksum(make_header(src_port, dst_port, seq_no, ack_no, FLAGS_ACK), src_addr, dst_addr))