Commit f91a2e1a authored by Pedro Oliveira's avatar Pedro Oliveira

deamonized program and can interact with daemon program

parent 4e436aa9
"""Generic linux daemon base class for python 3.x."""
import sys, os, time, atexit, signal
class Daemon:
"""A generic Daemon class.
Usage: subclass the Daemon class and override the run() method."""
def __init__(self, pidfile): self.pidfile = pidfile
def daemonize(self):
"""Deamonize class. UNIX double fork mechanism."""
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError as err:
sys.stderr.write('fork #1 failed: {0}\n'.format(err))
sys.exit(1)
# decouple from parent environment
#os.chdir('/')
#os.setsid()
#os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError as err:
sys.stderr.write('fork #2 failed: {0}\n'.format(err))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = open(os.devnull, 'r')
so = open('stdout', 'a+')
se = open(os.devnull, 'a+')
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# write pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
with open(self.pidfile, 'w+') as f:
f.write(pid + '\n')
def delpid(self):
os.remove(self.pidfile)
def start(self):
"""Start the Daemon."""
# Check for a pidfile to see if the Daemon already runs
try:
with open(self.pidfile,'r') as pf:
pid = int(pf.read().strip())
except IOError:
pid = None
if pid:
message = "pidfile {0} already exist. " + \
"Daemon already running?\n"
sys.stderr.write(message.format(self.pidfile))
sys.exit(1)
# Start the Daemon
self.daemonize()
print("daemonize")
self.run()
def stop(self):
"""Stop the Daemon."""
# Get the pid from the pidfile
try:
with open(self.pidfile,'r') as pf:
pid = int(pf.read().strip())
except IOError:
pid = None
if not pid:
message = "pidfile {0} does not exist. " + \
"Daemon not running?\n"
sys.stderr.write(message.format(self.pidfile))
return # not an error in a restart
# Try killing the Daemon process
try:
while 1:
os.kill(pid, signal.SIGTERM)
time.sleep(0.1)
except OSError as err:
e = str(err.args)
if e.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print (str(err.args))
sys.exit(1)
def restart(self):
"""Restart the Daemon."""
self.stop()
self.start()
def run(self):
"""You should override this method when you subclass Daemon.
It will be called after the process has been daemonized by
start() or restart()."""
\ No newline at end of file
...@@ -5,7 +5,7 @@ from Packet.ReceivedPacket import ReceivedPacket ...@@ -5,7 +5,7 @@ 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 Interface import Interface
from Main import Main import Main
from utils import KEEP_ALIVE_PERIOD_TIMEOUT from utils import KEEP_ALIVE_PERIOD_TIMEOUT
...@@ -14,13 +14,13 @@ class Hello: ...@@ -14,13 +14,13 @@ class Hello:
TRIGGERED_HELLO_DELAY = 16 # TODO: configure via external file?? TRIGGERED_HELLO_DELAY = 16 # TODO: configure via external file??
def __init__(self): def __init__(self):
Main().add_protocol(Hello.TYPE, self) Main.add_protocol(Hello.TYPE, self)
self.thread = Timer(Hello.TRIGGERED_HELLO_DELAY, self.send_handle) self.thread = Timer(Hello.TRIGGERED_HELLO_DELAY, self.send_handle)
self.thread.start() self.thread.start()
def send_handle(self): def send_handle(self):
for (ip, interface) in list(Main().interfaces.items()): for (ip, interface) in list(Main.interfaces.items()):
self.packet_send_handle(interface) self.packet_send_handle(interface)
# reschedule timer # reschedule timer
...@@ -55,19 +55,18 @@ class Hello: ...@@ -55,19 +55,18 @@ class Hello:
ip = packet.ip_header.ip ip = packet.ip_header.ip
print("ip = ", ip) print("ip = ", ip)
main = Main()
options = packet.pim_header.get_options() options = packet.pim_header.get_options()
if main.get_neighbor(ip) is None: if Main.get_neighbor(ip) is None:
# Unknown Neighbor # Unknown Neighbor
if (1 in options) and (20 in options): if (1 in options) and (20 in options):
print("non neighbor and options inside") print("non neighbor and options inside")
main.add_neighbor(packet.interface, ip, options[20], options[1]) Main.add_neighbor(packet.interface, ip, options[20], options[1])
return return
print("non neighbor and required options not inside") print("non neighbor and required options not inside")
else: else:
# Already know Neighbor # Already know Neighbor
print("neighbor conhecido") print("neighbor conhecido")
neighbor = main.get_neighbor(ip) neighbor = Main.get_neighbor(ip)
neighbor.heartbeat() neighbor.heartbeat()
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")
...@@ -75,4 +74,4 @@ class Hello: ...@@ -75,4 +74,4 @@ class Hello:
if 20 in options and neighbor.generation_id != 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])
...@@ -2,6 +2,7 @@ import socket ...@@ -2,6 +2,7 @@ import socket
import threading import threading
import random import random
from Packet.ReceivedPacket import ReceivedPacket from Packet.ReceivedPacket import ReceivedPacket
import Main
class Interface: class Interface:
#IF_IP = "10.0.0.1" #IF_IP = "10.0.0.1"
...@@ -38,7 +39,6 @@ class Interface: ...@@ -38,7 +39,6 @@ class Interface:
receive_thread.start() receive_thread.start()
def receive(self): def receive(self):
from Main import Main
while self.interface_enabled: while self.interface_enabled:
try: try:
(raw_packet, (ip, p)) = self.socket.recvfrom(256 * 1024) (raw_packet, (ip, p)) = self.socket.recvfrom(256 * 1024)
...@@ -46,7 +46,7 @@ class Interface: ...@@ -46,7 +46,7 @@ class Interface:
#print("packet received bytes: ", packet.bytes()) #print("packet received bytes: ", packet.bytes())
#print("pim type received = ", packet.pim_header.msg_type) #print("pim type received = ", packet.pim_header.msg_type)
#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
except Exception: except Exception:
pass pass
......
...@@ -4,85 +4,81 @@ from Interface import Interface ...@@ -4,85 +4,81 @@ from Interface import Interface
from Neighbor import Neighbor from Neighbor import Neighbor
class Main(object):
class __Main:
def __init__(self):
self.interfaces = {} # interfaces with multicast routing enabled
self.neighbors = {} # multicast router neighbors
self.protocols = {}
def add_interface(self, ip): interfaces = {} # interfaces with multicast routing enabled
if ip not in self.interfaces: neighbors = {} # multicast router neighbors
interface = Interface(ip) protocols = {}
self.interfaces[ip] = interface
self.protocols[0].force_send(interface)
def add_interface(ip):
# TODO: verificar melhor este metodo: global interfaces
def remove_interface(self, ip): if ip not in interfaces:
# TODO remover neighbors desta interface interface = Interface(ip)
if ip in self.interfaces: interfaces[ip] = interface
for (ip_neighbor, neighbor) in list(self.neighbors.items()): protocols[0].force_send(interface)
# TODO ver melhor este algoritmo
if neighbor.contact_interface == self.interfaces[ip]: # TODO: verificar melhor este metodo:
neighbor.remove() def remove_interface(ip):
self.protocols[0].force_send_remove(self.interfaces[ip]) # TODO remover neighbors desta interface
self.interfaces[ip].remove() global interfaces
del self.interfaces[ip] global neighbors
print("removido interface") if ip in interfaces:
for (ip_neighbor, neighbor) in list(neighbors.items()):
def add_neighbor(self, contact_interface, ip, random_number, keep_alive_period): # TODO ver melhor este algoritmo
if ip not in self.neighbors: if neighbor.contact_interface == interfaces[ip]:
print("ADD NEIGHBOR") neighbor.remove()
self.neighbors[ip] = Neighbor(contact_interface, ip, random_number, keep_alive_period) protocols[0].force_send_remove(interfaces[ip])
self.protocols[0].force_send(contact_interface) interfaces[ip].remove()
del interfaces[ip]
def get_neighbor(self, ip) -> Neighbor: print("removido interface")
if ip not in self.neighbors:
return None def add_neighbor(contact_interface, ip, random_number, keep_alive_period):
return self.neighbors[ip] global neighbors
if ip not in neighbors:
def remove_neighbor(self, ip): print("ADD NEIGHBOR")
if ip in self.neighbors: neighbors[ip] = Neighbor(contact_interface, ip, random_number, keep_alive_period)
del self.neighbors[ip] protocols[0].force_send(contact_interface)
print("removido neighbor")
def get_neighbor(ip) -> Neighbor:
def add_protocol(self, protocol_number, protocol_obj): global neighbors
self.protocols[protocol_number] = protocol_obj if ip not in neighbors:
return None
def list_neighbors(self): return neighbors[ip]
t = PrettyTable(['Neighbor IP', 'KeepAlive', "Generation ID"])
for ip, neighbor in list(self.neighbors.items()): def remove_neighbor(ip):
import socket, struct # TODO atualmente conversao manual de numero para string ip global neighbors
ip = socket.inet_ntoa(struct.pack('!L', ip)) if ip in neighbors:
t.add_row([ip, neighbor.keep_alive_period, neighbor.generation_id]) del neighbors[ip]
print(t) print("removido neighbor")
def list_enabled_interfaces(self): def add_protocol(protocol_number, protocol_obj):
t = PrettyTable(['Interface', 'IP', 'Enabled']) global protocols
for interface in netifaces.interfaces(): protocols[protocol_number] = protocol_obj
# TODO: fix same interface with multiple ips
ip = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr'] def list_neighbors():
status = ip in self.interfaces global neighbors
t.add_row([interface, ip, status]) t = PrettyTable(['Neighbor IP', 'KeepAlive', "Generation ID"])
print(t) for ip, neighbor in list(neighbors.items()):
import socket, struct # TODO atualmente conversao manual de numero para string ip
def main(self, ip_interfaces_to_add): ip = socket.inet_ntoa(struct.pack('!L', ip))
from Hello import Hello t.add_row([ip, neighbor.keep_alive_period, neighbor.generation_id])
Hello() print(t)
return str(t)
for ip in ip_interfaces_to_add:
self.add_interface(ip) def list_enabled_interfaces():
global interfaces
# MAIN SINGLETON t = PrettyTable(['Interface', 'IP', 'Enabled'])
instance = None for interface in netifaces.interfaces():
# TODO: fix same interface with multiple ips
def __new__(cls): # __new__ always a classmethod ip = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr']
if not Main.instance: status = ip in interfaces
Main.instance = Main.__Main() t.add_row([interface, ip, status])
return Main.instance print(t)
return str(t)
def __getattr__(self, name):
return getattr(self.instance, name) def main(ip_interfaces_to_add=[]):
from Hello import Hello
def __setattr__(self, name): Hello()
return setattr(self.instance, name)
for ip in ip_interfaces_to_add:
add_interface(ip)
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 from Interface import Interface
import Main
class Neighbor: class Neighbor:
def __init__(self, contact_interface: Interface, ip, generation_id: int, keep_alive_period: int): def __init__(self, contact_interface: Interface, ip, generation_id: int, keep_alive_period: int):
...@@ -34,8 +34,7 @@ class Neighbor: ...@@ -34,8 +34,7 @@ class Neighbor:
self.neighbor_liveness_timer.start() self.neighbor_liveness_timer.start()
def remove(self): def remove(self):
from Main import Main
print('HELLO TIMER EXPIRED... remove neighbor') print('HELLO TIMER EXPIRED... remove neighbor')
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()
Main().remove_neighbor(self.ip) Main.remove_neighbor(self.ip)
import time #!/usr/bin/env python
from Main import Main
from Daemon.Daemon import Daemon
#indicar ips das interfaces pim import Main
m = Main() import _pickle as pickle
m.main(["10.0.0.1"]) import socket
''' import sys
from Packet.PacketPimHeader import * import os
ph = PacketPimHeader(0) import argparse
po = PacketPimOption(1, 12408)
ph.add_option(po)
ph.add_option(PacketPimOption(20, 813183289)) class MyDaemon(Daemon):
packet = Packet(pim_header=ph) def run(self):
m.interfaces["10.0.0.1"].send(packet.bytes())''' Main.main()
'''for i in range(0, 5): server_address = './uds_socket'
m.list_enabled_interfaces()
m.list_neighbors()
time.sleep(10)''' # Make sure the socket does not already exist
time.sleep(30) try:
m.remove_interface("10.0.0.1") os.unlink(server_address)
time.sleep(100) except OSError:
if os.path.exists(server_address):
raise
# Create a UDS socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
# Bind the socket to the port
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
while True:
try:
connection, client_address = sock.accept()
data = connection.recv(256 * 1024)
print(sys.stderr, 'sending data back to the client')
print(pickle.loads(data))
args = pickle.loads(data)
if args.list_interfaces:
connection.sendall(pickle.dumps(Main.list_enabled_interfaces()))
elif args.list_neighbors:
connection.sendall(pickle.dumps(Main.list_neighbors()))
elif args.add_interface:
Main.add_interface(args.add_interface[0])
connection.sendall(pickle.dumps(''))
elif args.remove_interface:
Main.remove_interface(args.remove_interface[0])
connection.sendall(pickle.dumps(''))
finally:
# Clean up the connection
connection.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='PIM')
parser.add_argument("-li", "--list_interfaces", action="store_true", default=False,
help="List All PIM Interfaces")
parser.add_argument("-ln", "--list_neighbors", action="store_true", default=False,
help="List All PIM Neighbors")
parser.add_argument("-ai", "--add_interface", nargs=1,
help="Add PIM interface")
parser.add_argument("-ri", "--remove_interface", nargs=1,
help="Remove PIM interface")
parser.add_argument("-start", "--start", action="store_true", default=False,
help="Start PIM")
parser.add_argument("-stop", "--stop", action="store_true", default=False,
help="Stop PIM")
parser.add_argument("-restart", "--restart", action="store_true", default=False,
help="Restart PIM")
parser.add_argument("-v", "--verbose", action="store_true", default=False,
help="Verbose (print all debug messages)")
args = parser.parse_args()
print(parser.parse_args())
daemon = MyDaemon('/tmp/Daemon-pim.pid')
if args.start:
print("start")
daemon.start()
print("start")
sys.exit(0)
elif args.stop:
daemon.stop()
sys.exit(0)
elif args.restart:
daemon.restart()
sys.exit(0)
elif args.verbose:
os.system("tailf stdout")
sys.exit(0)
# Create a UDS socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
server_address = './uds_socket'
print('connecting to %s' % server_address)
try:
sock.connect(server_address)
except (socket.error):
print("erro socket")
print(sys.stderr)
sys.exit(1)
try:
sock.sendall(pickle.dumps(args))
data = sock.recv(1024 * 256)
print(pickle.loads(data))
finally:
print('closing socket')
sock.close()
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