Serial interface implemented
This commit is contained in:
		
							parent
							
								
									9a9630cfd2
								
							
						
					
					
						commit
						be8fa4f7bb
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| *.pyc | ||||
| @ -1,4 +1,5 @@ | ||||
| import base64 | ||||
| from Transport import Transport | ||||
| from cryptography.fernet import Fernet | ||||
| from cryptography.hazmat.primitives import hashes | ||||
| from cryptography.hazmat.backends import default_backend | ||||
| @ -41,13 +42,13 @@ class Destination: | ||||
| 
 | ||||
| 
 | ||||
| 	def __init__(self, direction, type, app_name, *aspects): | ||||
| 
 | ||||
| 		# Check input values and build name string | ||||
| 		if "." in app_name: raise ValueError("Dots can't be used in app names")  | ||||
| 		if not type in Destination.types: raise ValueError("Unknown destination type") | ||||
| 		if not direction in Destination.directions: raise ValueError("Unknown destination direction") | ||||
| 		self.type = type | ||||
| 		self.direction = direction | ||||
| 		self.mtu = 0 | ||||
| 
 | ||||
| 		self.name = Destination.getDestinationName(app_name, *aspects)		 | ||||
| 		self.hash = Destination.getDestinationHash(app_name, *aspects) | ||||
| @ -61,6 +62,8 @@ class Destination: | ||||
| 		self.prv_bytes = None | ||||
| 		self.pub_bytes = None | ||||
| 
 | ||||
| 		Transport.registerDestination(self) | ||||
| 
 | ||||
| 
 | ||||
| 	def __str__(self): | ||||
| 		return "<"+self.name+"/"+self.hexhash+">" | ||||
| @ -158,7 +161,7 @@ class Destination: | ||||
| 
 | ||||
| 	def decrypt(self, ciphertext): | ||||
| 		if self.type == Destination.PLAIN: | ||||
| 			return plaintext | ||||
| 			return ciphertext | ||||
| 
 | ||||
| 		if self.type == Destination.SINGLE and self.prv != None: | ||||
| 			plaintext = self.prv.decrypt( | ||||
							
								
								
									
										111
									
								
								FPE/FlexPE.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								FPE/FlexPE.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| from Interfaces import * | ||||
| import ConfigParser | ||||
| import jsonpickle | ||||
| from vendor.configobj import ConfigObj | ||||
| import struct | ||||
| import array | ||||
| import os.path | ||||
| import os | ||||
| 
 | ||||
| class FlexPE: | ||||
| 	MTU          = 700 | ||||
| 	router       = None | ||||
| 	config       = None | ||||
| 	destinations = [] | ||||
| 	interfaces   = [] | ||||
| 	configdir = os.path.expanduser("~")+"/.flexpe" | ||||
| 	configpath   = configdir+"/config" | ||||
| 
 | ||||
| 
 | ||||
| 	def __init__(self): | ||||
| 		if os.path.isfile(FlexPE.configpath): | ||||
| 			self.config = ConfigObj(FlexPE.configpath) | ||||
| 		else: | ||||
| 			print("Could not load config file, creating default configuration...") | ||||
| 			self.createDefaultConfig() | ||||
| 
 | ||||
| 		self.applyConfig() | ||||
| 		print FlexPE.interfaces | ||||
| 
 | ||||
| 		FlexPE.router = self | ||||
| 
 | ||||
| 	@staticmethod | ||||
| 	def addDestination(destination): | ||||
| 		destination.MTU = FlexPE.MTU | ||||
| 		FlexPE.destinations.append(destination) | ||||
| 
 | ||||
| 	@staticmethod | ||||
| 	def incoming(data): | ||||
| 		 | ||||
| 		header = struct.unpack("B", data[0]) | ||||
| 
 | ||||
| 		hash = data[1:11] | ||||
| 		type = header[0] & 0x03 | ||||
| 
 | ||||
| 		for destination in FlexPE.destinations: | ||||
| 			if destination.hash == hash and destination.type == type: | ||||
| 				destination.receive(data[11:]) | ||||
| 
 | ||||
| 	@staticmethod | ||||
| 	def outbound(raw): | ||||
| 		for interface in FlexPE.interfaces: | ||||
| 			if interface.OUT: | ||||
| 				interface.processOutgoing(raw) | ||||
| 
 | ||||
| 	def applyConfig(self): | ||||
| 		for name in self.config["interfaces"]: | ||||
| 			c = self.config["interfaces"][name] | ||||
| 			try: | ||||
| 				if c["type"] == "UdpInterface": | ||||
| 					interface = UdpInterface.UdpInterface( | ||||
| 						self, | ||||
| 						c["listen_ip"], | ||||
| 						int(c["listen_port"]), | ||||
| 						c["forward_ip"], | ||||
| 						int(c["forward_port"]) | ||||
| 					) | ||||
| 
 | ||||
| 					if c["use_as_outgoing"].lower() == "true": | ||||
| 						interface.OUT = True | ||||
| 
 | ||||
| 					interface.name = name | ||||
| 					FlexPE.interfaces.append(interface) | ||||
| 
 | ||||
| 				if c["type"] == "SerialInterface": | ||||
| 					interface = SerialInterface.SerialInterface( | ||||
| 						self, | ||||
| 						c["port"], | ||||
| 						int(c["speed"]), | ||||
| 						int(c["databits"]), | ||||
| 						c["parity"], | ||||
| 						int(c["stopbits"]) | ||||
| 					) | ||||
| 
 | ||||
| 					if c["use_as_outgoing"].lower() == "true": | ||||
| 						interface.OUT = True | ||||
| 
 | ||||
| 					interface.name = name | ||||
| 					FlexPE.interfaces.append(interface) | ||||
| 
 | ||||
| 			except Exception as e: | ||||
| 				print("The interface \""+name+"\" could not be created. Check your configuration file for errors!") | ||||
| 				print("The contained error was: "+str(e)) | ||||
| 				 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	def createDefaultConfig(self): | ||||
| 		self.config = ConfigObj() | ||||
| 		self.config.filename = FlexPE.configpath | ||||
| 		self.config["interfaces"] = {} | ||||
| 		self.config["interfaces"]["Default UDP Interface"] = {} | ||||
| 		self.config["interfaces"]["Default UDP Interface"]["type"] = "UdpInterface" | ||||
| 		self.config["interfaces"]["Default UDP Interface"]["listen_ip"] = "0.0.0.0" | ||||
| 		self.config["interfaces"]["Default UDP Interface"]["listen_port"] = 7777 | ||||
| 		self.config["interfaces"]["Default UDP Interface"]["forward_ip"] = "255.255.255.255" | ||||
| 		self.config["interfaces"]["Default UDP Interface"]["forward_port"] = 7777 | ||||
| 		self.config["interfaces"]["Default UDP Interface"]["use_as_outgoing"] = "true" | ||||
| 		if not os.path.isdir(FlexPE.configdir): | ||||
| 			os.makedirs(FlexPE.configdir) | ||||
| 		self.config.write() | ||||
| 		self.applyConfig() | ||||
							
								
								
									
										9
									
								
								FPE/Interfaces/Interface.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								FPE/Interfaces/Interface.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| class Interface: | ||||
|     IN  = False | ||||
|     OUT = False | ||||
|     FWD = False | ||||
|     RPT = False | ||||
|     name = None | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         pass | ||||
							
								
								
									
										76
									
								
								FPE/Interfaces/SerialInterface.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								FPE/Interfaces/SerialInterface.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| from __future__ import print_function | ||||
| from Interface import Interface | ||||
| import sys | ||||
| import serial | ||||
| import threading | ||||
| 
 | ||||
| class SerialInterface(Interface): | ||||
| 	MAX_CHUNK = 32768 | ||||
| 	TIMEOUT_SECONDS = 0.15 | ||||
| 
 | ||||
| 	owner    = None | ||||
| 	port     = None | ||||
| 	speed    = None | ||||
| 	databits = None | ||||
| 	parity   = None | ||||
| 	stopbits = None | ||||
| 	serial   = None | ||||
| 
 | ||||
| 	def __init__(self, owner, port, speed, databits, parity, stopbits): | ||||
| 		self.owner    = owner | ||||
| 		self.port     = port | ||||
| 		self.speed    = speed | ||||
| 		self.databits = databits | ||||
| 		self.parity   = serial.PARITY_NONE | ||||
| 		self.stopbits = stopbits | ||||
| 
 | ||||
| 		if parity.lower() == "e" or parity.lower() == "even": | ||||
| 			self.parity = serial.PARITY_EVEN | ||||
| 
 | ||||
| 		if parity.lower() == "o" or parity.lower() == "odd": | ||||
| 			self.parity = serial.PARITY_ODD | ||||
| 
 | ||||
| 		try: | ||||
| 			self.serial = serial.Serial( | ||||
| 				port = self.port, | ||||
| 				baudrate = self.speed, | ||||
| 				bytesize = self.databits, | ||||
| 				parity = self.parity, | ||||
| 				stopbits = self.stopbits, | ||||
| 				timeout = SerialInterface.TIMEOUT_SECONDS, | ||||
| 				xonxoff = False, | ||||
| 				rtscts = False, | ||||
| 				write_timeout = None, | ||||
| 				dsrdtr = False, | ||||
| 			) | ||||
| 			print(self.serial.inter_byte_timeout) | ||||
| 		except Exception as e: | ||||
| 			print("Could not create serial port", file=sys.stderr) | ||||
| 			raise e | ||||
| 
 | ||||
| 		#self.serial.open() | ||||
| 		if self.serial.is_open: | ||||
| 			thread = threading.Thread(target=self.readLoop) | ||||
| 			thread.setDaemon(True) | ||||
| 			thread.start() | ||||
| 		else: | ||||
| 			raise IOError("Could not open serial port") | ||||
| 
 | ||||
| 
 | ||||
| 	def processIncoming(self, data): | ||||
| 		self.owner.__class__.incoming(data) | ||||
| 
 | ||||
| 
 | ||||
| 	def processOutgoing(self,data): | ||||
| 		self.serial.write(data) | ||||
| 
 | ||||
| 
 | ||||
| 	def readLoop(self): | ||||
| 		while self.serial.is_open: | ||||
| 			data = self.serial.read(size=self.owner.__class__.MTU) | ||||
| 			if not data == "": | ||||
| 				self.processIncoming(data) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										56
									
								
								FPE/Interfaces/UdpInterface.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								FPE/Interfaces/UdpInterface.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| from Interface import Interface | ||||
| import SocketServer | ||||
| import threading | ||||
| import socket | ||||
| import sys | ||||
| 
 | ||||
| class UdpInterface(Interface): | ||||
|     bind_ip = None | ||||
|     bind_port = None | ||||
|     forward_ip = None | ||||
|     forward_port = None | ||||
|     owner = None | ||||
| 
 | ||||
|     def __init__(self, owner, bindip=None, bindport=None, forwardip=None, forwardport=None): | ||||
|         self.IN  = True | ||||
|         self.OUT = False | ||||
| 
 | ||||
|         if (bindip != None and bindport != None): | ||||
|             self.receives = True | ||||
|             self.bind_ip = bindip | ||||
|             self.bind_port = bindport | ||||
| 
 | ||||
|             UdpInterfaceHandler.interface = self | ||||
|             self.owner = owner | ||||
|             address = (self.bind_ip, self.bind_port) | ||||
|             self.server = SocketServer.UDPServer(address, UdpInterfaceHandler) | ||||
| 
 | ||||
|             thread = threading.Thread(target=self.server.serve_forever) | ||||
|             thread.setDaemon(True) | ||||
|             thread.start() | ||||
| 
 | ||||
|         if (forwardip != None and forwardport != None): | ||||
|             self.forwards = True | ||||
|             self.forward_ip = forwardip | ||||
|             self.forward_port = forwardport | ||||
| 
 | ||||
| 
 | ||||
|     def processIncoming(self, data): | ||||
|         self.owner.__class__.incoming(data) | ||||
| 
 | ||||
|     def processOutgoing(self,data): | ||||
|         udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | ||||
|         udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) | ||||
|         udp_socket.sendto(data, (self.forward_ip, self.forward_port)) | ||||
| 
 | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "UdpInterface["+self.bind_ip+":"+str(self.bind_port)+"]" | ||||
| 
 | ||||
| class UdpInterfaceHandler(SocketServer.BaseRequestHandler): | ||||
|     interface = None | ||||
| 
 | ||||
|     def handle(self): | ||||
|         if (UdpInterfaceHandler.interface != None): | ||||
|             data = self.request[0].strip() | ||||
|             UdpInterfaceHandler.interface.processIncoming(data) | ||||
							
								
								
									
										5
									
								
								FPE/Interfaces/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								FPE/Interfaces/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| import os | ||||
| import glob | ||||
| 
 | ||||
| modules = glob.glob(os.path.dirname(__file__)+"/*.py") | ||||
| __all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')] | ||||
							
								
								
									
										35
									
								
								FPE/Packet.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								FPE/Packet.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| import struct | ||||
| from Transport import * | ||||
| 
 | ||||
| class Packet: | ||||
| 
 | ||||
| 	def __init__(self, destination, data): | ||||
| 		self.destination = destination | ||||
| 		self.data   = data | ||||
| 		self.flags  = 0x00 | ||||
| 		self.header = 0x00 | ||||
| 		self.raw	= None | ||||
| 		self.sent   = False | ||||
| 		self.mtu    = 0 | ||||
| 
 | ||||
| 	def send(self): | ||||
| 		if not self.sent: | ||||
| 			self.MTU = self.destination.MTU | ||||
| 			self.header =  struct.pack("!B", self.header ^ self.destination.type ^ self.flags) | ||||
| 			self.header += self.destination.hash | ||||
| 			self.ciphertext = self.destination.encrypt(self.data) | ||||
| 			self.raw = self.header + self.ciphertext | ||||
| 
 | ||||
| 			if len(self.raw) > self.MTU: | ||||
| 				raise IOError("Packet size exceeds MTU of "+Packet.MTU+" bytes") | ||||
| 
 | ||||
| 			Transport.outbound(self.raw) | ||||
| 			self.sent = True | ||||
| 		else: | ||||
| 			raise IOError("Packet was already sent") | ||||
| 
 | ||||
| 	def resend(self): | ||||
| 		if self.sent: | ||||
| 			Transport.outbound(self.raw) | ||||
| 		else: | ||||
| 			raise IOError("Packet was not sent yet") | ||||
							
								
								
									
										10
									
								
								FPE/Transport.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								FPE/Transport.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| from FlexPE import FlexPE | ||||
| 
 | ||||
| class Transport: | ||||
| 	@staticmethod | ||||
| 	def outbound(raw): | ||||
| 		FlexPE.outbound(raw) | ||||
| 
 | ||||
| 	@staticmethod | ||||
| 	def registerDestination(destination): | ||||
| 		FlexPE.addDestination(destination) | ||||
							
								
								
									
										5
									
								
								FPE/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								FPE/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| import os | ||||
| import glob | ||||
| 
 | ||||
| modules = glob.glob(os.path.dirname(__file__)+"/*.py") | ||||
| __all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')] | ||||
							
								
								
									
										5
									
								
								FPE/vendor/__init__.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								FPE/vendor/__init__.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| import os | ||||
| import glob | ||||
| 
 | ||||
| modules = glob.glob(os.path.dirname(__file__)+"/*.py") | ||||
| __all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')] | ||||
							
								
								
									
										2468
									
								
								FPE/vendor/configobj.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2468
									
								
								FPE/vendor/configobj.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										24
									
								
								Packet.py
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								Packet.py
									
									
									
									
									
								
							| @ -1,24 +0,0 @@ | ||||
| import struct | ||||
| from Transport import * | ||||
| 
 | ||||
| class Packet: | ||||
| 	MTU = 960 | ||||
| 
 | ||||
| 	def __init__(self, destination, data): | ||||
| 		self.destination = destination | ||||
| 		self.data   = data | ||||
| 		self.flags  = 0x00 | ||||
| 		self.header = 0x00 | ||||
| 		self.raw	= None | ||||
| 		self.sent   = False | ||||
| 
 | ||||
| 	def send(self): | ||||
| 		self.header =  struct.pack("!B", self.header ^ self.destination.type ^ self.flags) | ||||
| 		self.header += self.destination.hash | ||||
| 		self.ciphertext = self.destination.encrypt(self.data) | ||||
| 		self.raw = self.header + self.ciphertext | ||||
| 
 | ||||
| 		if len(self.raw) > Packet.MTU: | ||||
| 			raise IOError("Packet size exceeds MTU of "+Packet.MTU+" bytes") | ||||
| 
 | ||||
| 		Transport.outbound(self.raw) | ||||
| @ -1,4 +0,0 @@ | ||||
| class Transport: | ||||
| 	@staticmethod | ||||
| 	def outbound(raw): | ||||
| 		pass | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user