Commit 27e8f125 authored by Pedro Oliveira's avatar Pedro Oliveira

types, remove_interface and socket close

parent 2649abb6
import random import random
from threading import Timer from threading import Timer
from Packet.Packet import Packet from Packet.Packet import Packet
from Packet.ReceivedPacket import ReceivedPacket
from Packet.PacketPimOption import PacketPimOption from Packet.PacketPimOption import PacketPimOption
from Packet.PacketPimHeader import PacketPimHeader from Packet.PacketPimHeader import PacketPimHeader
from Interface import Interface
from Main import Main from Main import Main
from utils import KEEP_ALIVE_PERIOD_TIMEOUT from utils import KEEP_ALIVE_PERIOD_TIMEOUT
...@@ -18,7 +20,7 @@ class Hello: ...@@ -18,7 +20,7 @@ class Hello:
self.thread.start() self.thread.start()
def send_handle(self): def send_handle(self):
for (ip, interface) in Main().interfaces.items(): for (ip, interface) in list(Main().interfaces.items()):
self.force_send_handle(interface) self.force_send_handle(interface)
# reschedule timer # reschedule timer
...@@ -27,7 +29,7 @@ class Hello: ...@@ -27,7 +29,7 @@ class Hello:
self.thread = Timer(hello_timer, self.send_handle) self.thread = Timer(hello_timer, self.send_handle)
self.thread.start() self.thread.start()
def force_send_handle(self, interface): def force_send_handle(self, interface: Interface):
ph = PacketPimHeader(Hello.TYPE) ph = PacketPimHeader(Hello.TYPE)
ph.add_option(PacketPimOption(1, Hello.HELLO_HOLD_TIME)) ph.add_option(PacketPimOption(1, Hello.HELLO_HOLD_TIME))
ph.add_option(PacketPimOption(20, interface.generation_id)) ph.add_option(PacketPimOption(20, interface.generation_id))
...@@ -35,7 +37,7 @@ class Hello: ...@@ -35,7 +37,7 @@ class Hello:
interface.send(packet.bytes()) interface.send(packet.bytes())
# TODO: ver melhor este metodo # TODO: ver melhor este metodo
def force_send_remove_handle(self, interface): def force_send_remove_handle(self, interface: Interface):
ph = PacketPimHeader(Hello.TYPE) ph = PacketPimHeader(Hello.TYPE)
ph.add_option(PacketPimOption(1, KEEP_ALIVE_PERIOD_TIMEOUT)) ph.add_option(PacketPimOption(1, KEEP_ALIVE_PERIOD_TIMEOUT))
ph.add_option(PacketPimOption(20, interface.generation_id)) ph.add_option(PacketPimOption(20, interface.generation_id))
...@@ -43,10 +45,10 @@ class Hello: ...@@ -43,10 +45,10 @@ class Hello:
interface.send(packet.bytes()) interface.send(packet.bytes())
# receive handler # receive handler
def receive_handle(self, packet): def receive_handle(self, packet: ReceivedPacket):
if packet.ip_header is None: if packet.ip_header is None:
return # TODO: MAYBE EXCEPCAO?? return # TODO: MAYBE EXCEPCAO??
ip = packet.ip_header.ip ip = packet.ip_header.ip
print("ip = ", ip) print("ip = ", ip)
# Unknown Neighbor # Unknown Neighbor
...@@ -66,7 +68,7 @@ class Hello: ...@@ -66,7 +68,7 @@ class Hello:
if 1 in options and neighbor.keep_alive_period != options[1]: if 1 in options and neighbor.keep_alive_period != options[1]:
print("keep alive period diferente") print("keep alive period diferente")
neighbor.set_keep_alive_period(options[1]) neighbor.set_keep_alive_period(options[1])
if 20 in options and neighbor.random_number != options[20]: if 20 in options and neighbor.generation_id != options[20]:
print("neighbor reiniciado") print("neighbor reiniciado")
neighbor.remove() neighbor.remove()
main.add_neighbor(packet.interface, ip, options[20], options[1]) main.add_neighbor(packet.interface, ip, options[20], options[1])
...@@ -8,7 +8,7 @@ class Interface: ...@@ -8,7 +8,7 @@ class Interface:
MCAST_GRP = '224.0.0.13' MCAST_GRP = '224.0.0.13'
# substituir ip por interface ou algo parecido # substituir ip por interface ou algo parecido
def __init__(self, ip_interface): def __init__(self, ip_interface: str):
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_PIM) s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_PIM)
# allow other sockets to bind this port too # allow other sockets to bind this port too
...@@ -47,8 +47,9 @@ class Interface: ...@@ -47,8 +47,9 @@ class Interface:
print("generation id received = ", packet.pim_header.options[1].option_value) print("generation id received = ", packet.pim_header.options[1].option_value)
Main().protocols[packet.pim_header.msg_type].receive_handle(packet) # TODO: perceber se existe melhor maneira de fazer isto Main().protocols[packet.pim_header.msg_type].receive_handle(packet) # TODO: perceber se existe melhor maneira de fazer isto
def send(self, data): def send(self, data: bytes):
self.socket.sendto(data, (Interface.MCAST_GRP, 0)) self.socket.sendto(data, (Interface.MCAST_GRP, 0))
def remove(self): def remove(self):
self.interface_enabled = False self.interface_enabled = False
self.socket.close()
import netifaces import netifaces
from prettytable import PrettyTable from prettytable import PrettyTable
from Interface import Interface from Interface import Interface
from Neighbor import Neighbor from Neighbor import Neighbor
...@@ -15,12 +17,20 @@ class Main(object): ...@@ -15,12 +17,20 @@ class Main(object):
if ip not in self.interfaces: if ip not in self.interfaces:
interface = Interface(ip) interface = Interface(ip)
self.interfaces[ip] = interface self.interfaces[ip] = interface
#self.protocols[0].force_send_handle(interface) # force send hello packet to added interface #self.protocols[0].force_send_handle(interface) # TODO force send hello packet to added interface
# TODO: verificar melhor este metodo: # TODO: verificar melhor este metodo:
def remove_interface(self, ip): def remove_interface(self, ip):
self.protocols[0].force_send_remove_handle(self.interfaces[ip]) # TODO remover neighbors desta interface
del self.interfaces[ip] if ip in self.interfaces:
for (ip_neighbor, neighbor) in list(self.neighbors.items()):
# TODO ver melhor este algoritmo
if neighbor.contact_interface == self.interfaces[ip]:
self.remove_neighbor(ip_neighbor)
self.protocols[0].force_send_remove_handle(self.interfaces[ip])
self.interfaces[ip].remove()
del self.interfaces[ip]
print("removido neighbor")
def add_neighbor(self, contact_interface, ip, random_number, keep_alive_period): def add_neighbor(self, contact_interface, ip, random_number, keep_alive_period):
print("ADD NEIGHBOR") print("ADD NEIGHBOR")
...@@ -28,7 +38,7 @@ class Main(object): ...@@ -28,7 +38,7 @@ class Main(object):
self.neighbors[ip] = Neighbor(contact_interface, ip, random_number, keep_alive_period) self.neighbors[ip] = Neighbor(contact_interface, ip, random_number, keep_alive_period)
print(self.neighbors.keys()) print(self.neighbors.keys())
def get_neighbor(self, ip): def get_neighbor(self, ip) -> Neighbor:
if ip not in self.neighbors: if ip not in self.neighbors:
return None return None
return self.neighbors[ip] return self.neighbors[ip]
...@@ -41,13 +51,15 @@ class Main(object): ...@@ -41,13 +51,15 @@ class Main(object):
self.protocols[protocol_number] = protocol_obj self.protocols[protocol_number] = protocol_obj
def list_neighbors(self): def list_neighbors(self):
t = PrettyTable(['Neighbor IP', 'KeepAlive', "Random Number"]) t = PrettyTable(['Neighbor IP', 'KeepAlive', "Generation ID"])
for ip, neighbor in self.neighbors.items(): for ip, neighbor in list(self.neighbors.items()):
t.add_row([ip, neighbor.keep_alive_period, neighbor.random_number]) import socket, struct # TODO atualmente conversao manual de numero para string ip
ip = socket.inet_ntoa(struct.pack('!L', ip))
t.add_row([ip, neighbor.keep_alive_period, neighbor.generation_id])
print(t) print(t)
def list_enabled_interfaces(self): def list_enabled_interfaces(self):
t = PrettyTable(['Interface', 'IP', 'Status']) t = PrettyTable(['Interface', 'IP', 'Enabled'])
for interface in netifaces.interfaces(): for interface in netifaces.interfaces():
# TODO: fix same interface with multiple ips # TODO: fix same interface with multiple ips
ip = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr'] ip = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr']
......
from threading import Timer from threading import Timer
from utils import KEEP_ALIVE_PERIOD_NO_TIMEOUT, KEEP_ALIVE_PERIOD_TIMEOUT from utils import KEEP_ALIVE_PERIOD_NO_TIMEOUT, KEEP_ALIVE_PERIOD_TIMEOUT
from Interface import Interface
class Neighbor: class Neighbor:
def __init__(self, contact_interface, ip, random_number, keep_alive_period): def __init__(self, contact_interface: Interface, ip, generation_id: int, keep_alive_period: int):
self.contact_interface = contact_interface self.contact_interface = contact_interface
self.ip = ip self.ip = ip
self.random_number = random_number self.generation_id = generation_id
self.neighbor_liveness_timer = None self.neighbor_liveness_timer = None
self.set_keep_alive_period(keep_alive_period) self.set_keep_alive_period(keep_alive_period)
def set_keep_alive_period(self, keep_alive_period): def set_keep_alive_period(self, keep_alive_period: int):
self.keep_alive_period = keep_alive_period self.keep_alive_period = keep_alive_period
if self.neighbor_liveness_timer is not None: if self.neighbor_liveness_timer is not None:
self.neighbor_liveness_timer.cancel() self.neighbor_liveness_timer.cancel()
...@@ -32,9 +33,6 @@ class Neighbor: ...@@ -32,9 +33,6 @@ class Neighbor:
self.neighbor_liveness_timer = Timer(4 * self.keep_alive_period, self.remove) self.neighbor_liveness_timer = Timer(4 * self.keep_alive_period, self.remove)
self.neighbor_liveness_timer.start() self.neighbor_liveness_timer.start()
def send(self, packet):
self.contact_interface.send(self.ip, packet)
def remove(self): def remove(self):
from Main import Main from Main import Main
print('HELLO TIMER EXPIRED... remove neighbor') print('HELLO TIMER EXPIRED... remove neighbor')
......
from Packet.PacketIpHeader import PacketIpHeader
from Packet.PacketPimHeader import PacketPimHeader
from Packet.PacketPimOption import PacketPimOption
class Packet: class Packet:
# ter ip header # ter ip header
# pim header # pim header
# pim options # pim options
def __init__(self, ip_header=None, pim_header=None): def __init__(self, ip_header: PacketIpHeader = None, pim_header: PacketPimHeader = None):
self.ip_header = ip_header self.ip_header = ip_header
self.pim_header = pim_header self.pim_header = pim_header
# maybe remover # maybe remover
def add_option(self, option): '''def add_option(self, option: PacketPimOption):
self.pim_header.add_option(option) self.pim_header.add_option(option)
'''
def bytes(self): def bytes(self):
return self.pim_header.bytes() return self.pim_header.bytes()
import struct import struct
from utils import checksum from utils import checksum
from Packet.PacketPimOption import PacketPimOption
class PacketPimHeader: class PacketPimHeader:
...@@ -10,11 +11,11 @@ class PacketPimHeader: ...@@ -10,11 +11,11 @@ class PacketPimHeader:
# HELLO: type = 0 # HELLO: type = 0
# pim options # pim options
def __init__(self, msg_type): def __init__(self, msg_type: int):
self.options = [] self.options = []
self.msg_type = msg_type self.msg_type = msg_type
def add_option(self, option): def add_option(self, option: PacketPimOption):
self.options.append(option) self.options.append(option)
def get_options_bytes(self): def get_options_bytes(self):
...@@ -32,7 +33,7 @@ class PacketPimHeader: ...@@ -32,7 +33,7 @@ class PacketPimHeader:
dictionary[option.option_type] = option.option_value dictionary[option.option_type] = option.option_value
return dictionary return dictionary
def bytes(self): def bytes(self) -> bytes:
# obter mensagem e criar checksum # obter mensagem e criar checksum
pim_vrs_type = (PacketPimHeader.PIM_VERSION << 4) + self.msg_type pim_vrs_type = (PacketPimHeader.PIM_VERSION << 4) + self.msg_type
msg_without_chcksum = struct.pack(PacketPimHeader.PIM_HDR, pim_vrs_type, 0, 0) msg_without_chcksum = struct.pack(PacketPimHeader.PIM_HDR, pim_vrs_type, 0, 0)
......
...@@ -9,11 +9,11 @@ class PacketPimOption: ...@@ -9,11 +9,11 @@ class PacketPimOption:
20: 4, 20: 4,
} }
def __init__(self, option_type, option_value): def __init__(self, option_type: int, option_value: int):
self.option_type = option_type self.option_type = option_type
self.option_value = option_value self.option_value = option_value
def bytes(self): def bytes(self) -> bytes:
option_length = PacketPimOption.PIM_MSG_TYPES_LENGTH[self.option_type] option_length = PacketPimOption.PIM_MSG_TYPES_LENGTH[self.option_type]
msg = struct.pack(PacketPimOption.PIM_HDR_OPTS, self.option_type, option_length) msg = struct.pack(PacketPimOption.PIM_HDR_OPTS, self.option_type, option_length)
return msg + struct.pack("! " + str(option_length) + "s", self.option_value.to_bytes(option_length, byteorder='big')) return msg + struct.pack("! " + str(option_length) + "s", self.option_value.to_bytes(option_length, byteorder='big'))
......
...@@ -12,4 +12,10 @@ ph.add_option(po) ...@@ -12,4 +12,10 @@ ph.add_option(po)
ph.add_option(PacketPimOption(20, 813183289)) ph.add_option(PacketPimOption(20, 813183289))
packet = Packet(pim_header=ph) packet = Packet(pim_header=ph)
m.interfaces["10.0.0.1"].send(packet.bytes())''' m.interfaces["10.0.0.1"].send(packet.bytes())'''
'''for i in range(0, 5):
m.list_enabled_interfaces()
m.list_neighbors()
time.sleep(10)'''
time.sleep(30)
m.remove_interface("10.0.0.1")
time.sleep(100) time.sleep(100)
...@@ -26,7 +26,7 @@ KEEP_ALIVE_PERIOD = 160 ...@@ -26,7 +26,7 @@ KEEP_ALIVE_PERIOD = 160
KEEP_ALIVE_PERIOD_TIMEOUT = 0 KEEP_ALIVE_PERIOD_TIMEOUT = 0
def checksum(pkt): def checksum(pkt: bytes) -> bytes:
if len(pkt) % 2 == 1: if len(pkt) % 2 == 1:
pkt += "\0" pkt += "\0"
s = sum(array.array("H", pkt)) s = sum(array.array("H", pkt))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment