From 8af8ebcc6ba1dc5760244fbc31cbaf09be6d8bb8 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sat, 3 Jan 2015 12:44:07 +0100 Subject: [PATCH] added net, protocoll --- net.py | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++ protocoll.py | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 295 insertions(+) create mode 100755 net.py create mode 100644 protocoll.py diff --git a/net.py b/net.py new file mode 100755 index 0000000..9092936 --- /dev/null +++ b/net.py @@ -0,0 +1,147 @@ +#!/usr/bin/python + +import sys +import socket +import logging +import traceback +from threading import Thread +from time import sleep +from protocoll import * + +logger = logging.getLogger(__name__) + +class NetServer(Thread): + def __init__(self, handler=None, handler_connect=None, handler_disconnect=None): + Thread.__init__(self) + self.setDaemon(True) + self.sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sck.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.sck.bind(("", 10001)) + self.sck.listen(1) + self.sck.setblocking(0) + self.bRun = False + self.handler = handler + self.handler_connect = handler_connect + self.handler_disconnect = handler_disconnect + self.start() + + def run(self): + self.bRun = True + while(self.bRun): + sleep(0.01) + try: + conn, addr = self.sck.accept() + #conn.settimeout(0.01) + except: + continue + logger.debug("New Connection") + proto = Protocoll(NetWrapper(conn)) + if self.handler_connect: + self.handler_connect(proto) + while True: + try: + addr, msg = proto.receive() + except socket.error, e: + if e.errno == 11: + logger.debug("Connection lost") + elif e.errno: + logger.debug("Socket Error %d", e.errno) + traceback.print_exc(file=sys.stdout) + break + except TimeoutException: + continue + except ByteError: + continue + except NAKReceived: + continue + except: + traceback.print_exc(file=sys.stdout) + break + + if self.handler: + try: + self.handler(addr, msg) + except: + traceback.print_exc(file=sys.stdout) + logger.debug("Connection Ended") + if self.handler_disconnect: + self.handler_disconnect(proto) + conn.close() + + def stop(self): + self.bRun = False + + +class NetWrapper: + def __init__(self, sck): + self.sck = sck + + def write(self, s): + return self.sck.send(s) + + def read(self, i): + return self.sck.recv(i) + + def close(self): + return self.sck.close() + +class NetClient(Protocoll, Thread): + def __init__(self, kTarget, handler=None): + Thread.__init__(self) + self.setDaemon(True) + self.comm = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.comm.connect(kTarget) + self.comm.setblocking(0) + self.comm.settimeout(0.01) + Protocoll.__init__(self, NetWrapper(self.comm)) + self.handler = handler + self.bRun = False + + def run(self): + self.bRun = True + while(self.bRun): + sleep(0.01) + try: + addr, msg = self.receive() + if self.handler: + self.handler(addr, msg) + except socket.error, e: + if hasattr(e, "errno") and e.errno == 9: + #print "Connection lost" + break + elif e.message == "timed out": + pass + else: + traceback.print_exc(file=sys.stdout) + except TimeoutException: + pass + except: + traceback.print_exc(file=sys.stdout) + self.comm.close() + + def receive(self): + i = 0 + while True: + i+=1 + try: + return Protocoll.receive(self) + except: + if i > 300: + raise + sleep(0.01) + + def stop(self): + self.bRun = False + + +if __name__ == "__main__": + def handler(addr, s): + print addr, s + + if sys.argv[1] == "server": + pNet = NetServer(handler) + while(1): + sleep(1) + elif sys.argv[1] == "client": + pNet = NetClient(("192.168.36.14", 10001)) + pNet.send(0, "lights") diff --git a/protocoll.py b/protocoll.py new file mode 100644 index 0000000..5beea6e --- /dev/null +++ b/protocoll.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +# -*- coding: iso-8859-15 -*- + +import struct +import threading +import math +from pycrc.crc_algorithms import Crc + +class ByteError(Exception): + def __init__(self, value): + Exception.__init__(self) + self.value = value + def __str__(self): + return "Byte Error, got 0x%x" % self.value + +class CRCError(Exception): + def __str__(self): + return "CRC Error" + +class TimeoutException(Exception): + def __str__(self): + return "Timeout" + +class NAKReceived(Exception): + def __str__(self): + return "NAK received" + +class PackageTooBigException(Exception): + def __str__(self): + return "Package too long" + + +class Protocoll: + ENQ = 0x5 + ACK = 0x6 + DC1 = 0x11 + NAK = 0x21 + MAX_LEN = 128 + STATE_DEFAULT = 0 + STATE_LEN = 1 + STATE_READ = 2 + + def __init__(self, conn): + self.conn = conn + self.lock = threading.Lock() + self.crc = Crc(width = 8, poly = 0x07, reflect_in = False, xor_in = 0x0, reflect_out = False, xor_out = 0x00) + + def __get_ack(self): + c = "" + for i in range(60): + try: + c = self.conn.read(1) + except: + continue + if c: + break + if not c: + self.conn.close() + raise TimeoutException() + c = ord(c) + if c not in (self.ACK, self.NAK): + raise ByteError(c) + return c == self.ACK + + def send(self, addr, msg, bSlitMsg=False): + msg_len = 3 + len(msg) + 1 + if bSlitMsg and msg_len > self.MAX_LEN: + num_per_packet = self.MAX_LEN - 3 - 1 + num_packets = math.ceil(len(msg)/float(num_per_packet)) + self.send(addr, "%cSplit %d" % (self.DC1, num_packets)) + for i in range(0, len(msg), num_per_packet): + msg_part = msg[i:i+num_per_packet] + self.send(addr, msg_part) + return + self.lock.acquire() + try: + if msg_len > self.MAX_LEN: + raise PackageTooBigException() + packet = struct.pack(" self.MAX_LEN: + self.__reply_nak() + raise PackageTooBigException() + state = self.STATE_READ + packet += c + num = ord(c)-2 + elif state == self.STATE_READ: + packet += c + num-=1 + if num == 0: + if self.crc.bit_by_bit_fast(packet) == 0: + self.__reply_ack() + msgtype, msglen, addr, msg, crc = struct.unpack(" 1: + lCmd = msg[1:].split() + if len(lCmd) == 2 and lCmd[0] == "Split": + num = int(lCmd[1]) + msg = "" + for i in range(num): + addr_part, msg_part = self.receive() + if addr_part == addr: + msg+=msg_part + return addr, msg -- 2.39.2