Serial interface implemented

This commit is contained in:
Mark Qvist 2016-06-03 19:02:02 +02:00
parent 9a9630cfd2
commit be8fa4f7bb
15 changed files with 2789 additions and 30 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.pyc

View File

@ -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
View 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()

View File

@ -0,0 +1,9 @@
class Interface:
IN = False
OUT = False
FWD = False
RPT = False
name = None
def __init__(self):
pass

View 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)

View 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)

View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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)

3
README Normal file
View File

@ -0,0 +1,3 @@
Dependencies:
- cryptography.io
- pyserial 3.1

View File

@ -1,4 +0,0 @@
class Transport:
@staticmethod
def outbound(raw):
pass