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
from Packet.PacketPimOption import PacketPimOption
from Packet.PacketPimHeader import PacketPimHeader
from Interface import Interface
from Main import Main
import Main
from utils import KEEP_ALIVE_PERIOD_TIMEOUT
......@@ -14,13 +14,13 @@ class Hello:
TRIGGERED_HELLO_DELAY = 16 # TODO: configure via external file??
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.start()
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)
# reschedule timer
......@@ -55,19 +55,18 @@ class Hello:
ip = packet.ip_header.ip
print("ip = ", ip)
main = Main()
options = packet.pim_header.get_options()
if main.get_neighbor(ip) is None:
if Main.get_neighbor(ip) is None:
# Unknown Neighbor
if (1 in options) and (20 in options):
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
print("non neighbor and required options not inside")
else:
# Already know Neighbor
print("neighbor conhecido")
neighbor = main.get_neighbor(ip)
neighbor = Main.get_neighbor(ip)
neighbor.heartbeat()
if 1 in options and neighbor.keep_alive_period != options[1]:
print("keep alive period diferente")
......@@ -75,4 +74,4 @@ class Hello:
if 20 in options and neighbor.generation_id != options[20]:
print("neighbor reiniciado")
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
import threading
import random
from Packet.ReceivedPacket import ReceivedPacket
import Main
class Interface:
#IF_IP = "10.0.0.1"
......@@ -38,7 +39,6 @@ class Interface:
receive_thread.start()
def receive(self):
from Main import Main
while self.interface_enabled:
try:
(raw_packet, (ip, p)) = self.socket.recvfrom(256 * 1024)
......@@ -46,7 +46,7 @@ class Interface:
#print("packet received bytes: ", packet.bytes())
#print("pim type received = ", packet.pim_header.msg_type)
#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:
pass
......
......@@ -4,85 +4,81 @@ from Interface import Interface
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):
if ip not in self.interfaces:
interface = Interface(ip)
self.interfaces[ip] = interface
self.protocols[0].force_send(interface)
# TODO: verificar melhor este metodo:
def remove_interface(self, ip):
# TODO remover neighbors desta interface
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]:
neighbor.remove()
self.protocols[0].force_send_remove(self.interfaces[ip])
self.interfaces[ip].remove()
del self.interfaces[ip]
print("removido interface")
def add_neighbor(self, contact_interface, ip, random_number, keep_alive_period):
if ip not in self.neighbors:
print("ADD NEIGHBOR")
self.neighbors[ip] = Neighbor(contact_interface, ip, random_number, keep_alive_period)
self.protocols[0].force_send(contact_interface)
def get_neighbor(self, ip) -> Neighbor:
if ip not in self.neighbors:
return None
return self.neighbors[ip]
def remove_neighbor(self, ip):
if ip in self.neighbors:
del self.neighbors[ip]
print("removido neighbor")
def add_protocol(self, protocol_number, protocol_obj):
self.protocols[protocol_number] = protocol_obj
def list_neighbors(self):
t = PrettyTable(['Neighbor IP', 'KeepAlive', "Generation ID"])
for ip, neighbor in list(self.neighbors.items()):
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)
def list_enabled_interfaces(self):
t = PrettyTable(['Interface', 'IP', 'Enabled'])
for interface in netifaces.interfaces():
# TODO: fix same interface with multiple ips
ip = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr']
status = ip in self.interfaces
t.add_row([interface, ip, status])
print(t)
def main(self, ip_interfaces_to_add):
from Hello import Hello
Hello()
for ip in ip_interfaces_to_add:
self.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)
interfaces = {} # interfaces with multicast routing enabled
neighbors = {} # multicast router neighbors
protocols = {}
def add_interface(ip):
global interfaces
if ip not in interfaces:
interface = Interface(ip)
interfaces[ip] = interface
protocols[0].force_send(interface)
# TODO: verificar melhor este metodo:
def remove_interface(ip):
# TODO remover neighbors desta interface
global interfaces
global neighbors
if ip in interfaces:
for (ip_neighbor, neighbor) in list(neighbors.items()):
# TODO ver melhor este algoritmo
if neighbor.contact_interface == interfaces[ip]:
neighbor.remove()
protocols[0].force_send_remove(interfaces[ip])
interfaces[ip].remove()
del interfaces[ip]
print("removido interface")
def add_neighbor(contact_interface, ip, random_number, keep_alive_period):
global neighbors
if ip not in neighbors:
print("ADD NEIGHBOR")
neighbors[ip] = Neighbor(contact_interface, ip, random_number, keep_alive_period)
protocols[0].force_send(contact_interface)
def get_neighbor(ip) -> Neighbor:
global neighbors
if ip not in neighbors:
return None
return neighbors[ip]
def remove_neighbor(ip):
global neighbors
if ip in neighbors:
del neighbors[ip]
print("removido neighbor")
def add_protocol(protocol_number, protocol_obj):
global protocols
protocols[protocol_number] = protocol_obj
def list_neighbors():
global neighbors
t = PrettyTable(['Neighbor IP', 'KeepAlive', "Generation ID"])
for ip, neighbor in list(neighbors.items()):
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)
return str(t)
def list_enabled_interfaces():
global interfaces
t = PrettyTable(['Interface', 'IP', 'Enabled'])
for interface in netifaces.interfaces():
# TODO: fix same interface with multiple ips
ip = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr']
status = ip in interfaces
t.add_row([interface, ip, status])
print(t)
return str(t)
def main(ip_interfaces_to_add=[]):
from Hello import Hello
Hello()
for ip in ip_interfaces_to_add:
add_interface(ip)
from threading import Timer
from utils import KEEP_ALIVE_PERIOD_NO_TIMEOUT, KEEP_ALIVE_PERIOD_TIMEOUT
from Interface import Interface
import Main
class Neighbor:
def __init__(self, contact_interface: Interface, ip, generation_id: int, keep_alive_period: int):
......@@ -34,8 +34,7 @@ class Neighbor:
self.neighbor_liveness_timer.start()
def remove(self):
from Main import Main
print('HELLO TIMER EXPIRED... remove neighbor')
if self.neighbor_liveness_timer is not None:
self.neighbor_liveness_timer.cancel()
Main().remove_neighbor(self.ip)
Main.remove_neighbor(self.ip)
import time
from Main import Main
#indicar ips das interfaces pim
m = Main()
m.main(["10.0.0.1"])
'''
from Packet.PacketPimHeader import *
ph = PacketPimHeader(0)
po = PacketPimOption(1, 12408)
ph.add_option(po)
ph.add_option(PacketPimOption(20, 813183289))
packet = Packet(pim_header=ph)
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)
#!/usr/bin/env python
from Daemon.Daemon import Daemon
import Main
import _pickle as pickle
import socket
import sys
import os
import argparse
class MyDaemon(Daemon):
def run(self):
Main.main()
server_address = './uds_socket'
# Make sure the socket does not already exist
try:
os.unlink(server_address)
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