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
protocols = {}
def add_interface(ip):
global interfaces
if ip not in interfaces:
interface = Interface(ip) interface = Interface(ip)
self.interfaces[ip] = interface interfaces[ip] = interface
self.protocols[0].force_send(interface) protocols[0].force_send(interface)
# TODO: verificar melhor este metodo: # TODO: verificar melhor este metodo:
def remove_interface(self, ip): def remove_interface(ip):
# TODO remover neighbors desta interface # TODO remover neighbors desta interface
if ip in self.interfaces: global interfaces
for (ip_neighbor, neighbor) in list(self.neighbors.items()): global neighbors
if ip in interfaces:
for (ip_neighbor, neighbor) in list(neighbors.items()):
# TODO ver melhor este algoritmo # TODO ver melhor este algoritmo
if neighbor.contact_interface == self.interfaces[ip]: if neighbor.contact_interface == interfaces[ip]:
neighbor.remove() neighbor.remove()
self.protocols[0].force_send_remove(self.interfaces[ip]) protocols[0].force_send_remove(interfaces[ip])
self.interfaces[ip].remove() interfaces[ip].remove()
del self.interfaces[ip] del interfaces[ip]
print("removido interface") print("removido interface")
def add_neighbor(self, contact_interface, ip, random_number, keep_alive_period): def add_neighbor(contact_interface, ip, random_number, keep_alive_period):
if ip not in self.neighbors: global neighbors
if ip not in neighbors:
print("ADD NEIGHBOR") print("ADD NEIGHBOR")
self.neighbors[ip] = Neighbor(contact_interface, ip, random_number, keep_alive_period) neighbors[ip] = Neighbor(contact_interface, ip, random_number, keep_alive_period)
self.protocols[0].force_send(contact_interface) protocols[0].force_send(contact_interface)
def get_neighbor(self, ip) -> Neighbor: def get_neighbor(ip) -> Neighbor:
if ip not in self.neighbors: global neighbors
if ip not in neighbors:
return None return None
return self.neighbors[ip] return neighbors[ip]
def remove_neighbor(self, ip): def remove_neighbor(ip):
if ip in self.neighbors: global neighbors
del self.neighbors[ip] if ip in neighbors:
del neighbors[ip]
print("removido neighbor") print("removido neighbor")
def add_protocol(self, protocol_number, protocol_obj): def add_protocol(protocol_number, protocol_obj):
self.protocols[protocol_number] = protocol_obj global protocols
protocols[protocol_number] = protocol_obj
def list_neighbors(self): def list_neighbors():
global neighbors
t = PrettyTable(['Neighbor IP', 'KeepAlive', "Generation ID"]) t = PrettyTable(['Neighbor IP', 'KeepAlive', "Generation ID"])
for ip, neighbor in list(self.neighbors.items()): for ip, neighbor in list(neighbors.items()):
import socket, struct # TODO atualmente conversao manual de numero para string ip import socket, struct # TODO atualmente conversao manual de numero para string ip
ip = socket.inet_ntoa(struct.pack('!L', ip)) ip = socket.inet_ntoa(struct.pack('!L', ip))
t.add_row([ip, neighbor.keep_alive_period, neighbor.generation_id]) t.add_row([ip, neighbor.keep_alive_period, neighbor.generation_id])
print(t) print(t)
return str(t)
def list_enabled_interfaces(self): def list_enabled_interfaces():
global interfaces
t = PrettyTable(['Interface', 'IP', 'Enabled']) 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']
status = ip in self.interfaces status = ip in interfaces
t.add_row([interface, ip, status]) t.add_row([interface, ip, status])
print(t) print(t)
return str(t)
def main(self, ip_interfaces_to_add): def main(ip_interfaces_to_add=[]):
from Hello import Hello from Hello import Hello
Hello() Hello()
for ip in ip_interfaces_to_add: for ip in ip_interfaces_to_add:
self.add_interface(ip) add_interface(ip)
# MAIN SINGLETON
instance = None
def __new__(cls): # __new__ always a classmethod
if not Main.instance:
Main.instance = Main.__Main()
return Main.instance
def __getattr__(self, name):
return getattr(self.instance, name)
def __setattr__(self, name):
return setattr(self.instance, name)
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