def _rdt_rcv(self, seq_no, ack_no, flags, payload): src_addr, src_port, dst_addr, dst_port = self.id_conexao if self.ack_no == seq_no: if DEBUG: print(f'{src_addr}:{src_port}', 'receiving: seq->', seq_no, 'ack->', ack_no, 'bytes->', len(payload)) if (flags & FLAGS_FIN) == FLAGS_FIN and not self.closing: self.closing = True self.callback(self, b'') self.ack_no += 1 src_addr, src_port, dst_addr, dst_port = self.id_conexao cabecalho = make_header(dst_port, src_port, self.seq_no, self.ack_no, FLAGS_FIN | FLAGS_ACK) cabecalho = fix_checksum(cabecalho, dst_addr, src_addr) self.servidor.rede.enviar(cabecalho, src_addr) return elif (flags & FLAGS_ACK) == FLAGS_ACK and self.closing: print(f'Fechada a conexão com {src_addr}:{src_port}') self.servidor.conexoes.pop(self.id_conexao) return if ack_no > self.send_base and (flags & FLAGS_ACK) == FLAGS_ACK: self.nao_confirmados = self.nao_confirmados[ack_no - self.send_base:] self.send_base = ack_no if self.nao_confirmados: if DEBUG: print('++Timer restarted++') self._start_timer() else: if DEBUG: print('++Timer stopped++') self._stop_timer() if not self.retransmitindo: self.final_moment = time.time() self.calc_rtt() if self.last_seq == ack_no: self.janela += 1 if DEBUG: print('Updated window', self.janela, 'MSS') self._send_pending() self.retransmitindo = False self.ack_no += len(payload) if len(payload) > 0: # Só Deus sabe, mas funciona dados = make_header(src_port, dst_port, self.seq_no, self.ack_no, flags) dados = fix_checksum(dados, src_addr, dst_addr) self.servidor.rede.enviar(dados, src_addr) self.callback(self, payload)
def fechar(self): """ Usado pela camada de aplicação para fechar a conexão """ src_addr, src_port, dst_addr, dst_port = self.id_conexao cabecalho = make_header(dst_port, src_port, self.seq_no, self.seq_no, FLAGS_FIN) cabecalho = fix_checksum(cabecalho, dst_addr, src_addr) self.servidor.rede.enviar(cabecalho, src_addr)
def _start_connection(self): src_addr, src_port, dst_addr, dst_port = self.id_conexao cabecalho = make_header(dst_port, src_port,self.seq_no,self.ack_no,FLAGS_SYN | FLAGS_ACK) cabecalho = fix_checksum(cabecalho, src_addr, dst_addr) self.servidor.rede.enviar(cabecalho,src_addr) self.seq_no += 1 self.send_base = self.seq_no if DEBUG: print(f'{src_addr}:{src_port}', 'connected with', f'{dst_addr}:{dst_port}') print('handshaking: seq->',self.seq_no,'ack->',self.ack_no)
def start_connection(self, dst_addr, dst_port): src_addr = self.rede.meu_endereco src_port = self.porta ack_no = 0 seq_no = 0 cabecalho = make_header(src_port, dst_port, seq_no, ack_no, FLAGS_SYN) cabecalho = fix_checksum(cabecalho, src_addr, dst_addr) self.rede.enviar(cabecalho, dst_addr) print(f'{src_addr}:{src_port}', 'connecting with', f'{dst_addr}:{dst_port}') print('handshaking: seq->', seq_no, 'ack->', ack_no) self.status_conexao = 1
def _start_connection(self, id_conexao, segment): src_port, dst_port, seq_no, ack_no, \ flags, _, _, _ = read_header(segment) src_addr, src_port, dst_addr, dst_port = id_conexao ack_no = seq_no + 1 seq_no = random.randint(40, 0xfff) cabecalho = make_header(dst_port, src_port, seq_no, ack_no, FLAGS_SYN | FLAGS_ACK) cabecalho = fix_checksum(cabecalho, src_addr, dst_addr) self.rede.enviar(cabecalho, src_addr) print(f'{src_addr}:{src_port}', 'connected with', f'{dst_addr}:{dst_port}') print('handshaking: seq->', seq_no, 'ack->', ack_no) return Conexao(self, id_conexao, seq_no + 1, ack_no)
def _send_ack_segment(self, payload): src_addr, src_port, dst_addr, dst_port = self.id_conexao seq_no = None if self.retransmitindo: seq_no = self.send_base else: seq_no = self.seq_no self.seq_no += len(payload) self.nao_confirmados = self.nao_confirmados + payload cabecalho = make_header(dst_port, src_port, seq_no, self.ack_no, FLAGS_ACK) segmento = fix_checksum(cabecalho + payload, dst_addr, src_addr) self.servidor.rede.enviar(segmento, src_addr) if self.timer is None: self.initial_moment = time.time() self._start_timer()
def _rdt_rcv(self, seq_no, ack_no, flags, payload): src_addr, src_port, dst_addr, dst_port = self.id_conexao if self.ack_no == seq_no: if DEBUG: print(src_addr, 'receiving: seq->', seq_no, 'ack->', ack_no, 'bytes->', len(payload)) if ack_no > self.send_base and (flags & FLAGS_ACK) == FLAGS_ACK: self.nao_confirmados = self.nao_confirmados[ack_no - self.send_base:] self.send_base = ack_no if self.nao_confirmados: if DEBUG: print('++Timer restarted++') self._start_timer() else: if DEBUG: print('++Timer stopped++') self._stop_timer() if not self.retransmitindo: self.final_moment = time.time() self.calc_rtt() self.retransmitindo = False self.ack_no += len(payload) if (flags & FLAGS_FIN) == FLAGS_FIN: self.ack_no += 1 # É preciso somar, pois quando é enviada a flag FIN não há payload flags = FLAGS_FIN | FLAGS_ACK if ((flags & FLAGS_FIN) == FLAGS_FIN ) or len(payload) > 0: # Só Deus sabe, mas funciona dados = make_header(src_port, dst_port, self.seq_no, self.ack_no, flags) dados = fix_checksum(dados, src_addr, dst_addr) self.servidor.rede.enviar(dados, src_addr) self.callback(self, payload)
def _rdt_rcv(self, src_addr, dst_addr, segment): src_port, dst_port, seq_no, ack_no, \ flags, _, _, _ = read_header(segment) if dst_port != self.porta: # Ignora segmentos que não são destinados à porta do nosso servidor return payload = segment[4 * (flags >> 12):] id_conexao = (src_addr, src_port, dst_addr, dst_port) if (flags & FLAGS_SYN) == FLAGS_SYN and self.status_conexao == 1: tmp = ack_no ack_no = seq_no + 1 seq_no = tmp self.id_conexao = id_conexao cabecalho = make_header(dst_port, src_port, seq_no, ack_no, FLAGS_ACK) cabecalho = fix_checksum(cabecalho, src_addr, dst_addr) self.rede.enviar(cabecalho, src_addr) self.conexao = Conexao(self, id_conexao, seq_no, ack_no) self.status_conexao = 2 if self.callback: self.callback(self.conexao) elif id_conexao == self.id_conexao and self.status_conexao == 2: # Passa para a conexão adequada se ela já estiver estabelecida self.conexao._rdt_rcv(seq_no, ack_no, flags, payload) elif self.status_conexao != 2: print('%s:%d -> %s:%d (conexão não estabelecida)' % (src_addr, src_port, dst_addr, dst_port)) else: print('%s:%d -> %s:%d (pacote associado a conexão desconhecida)' % (src_addr, src_port, dst_addr, dst_port))