]> defiant.homedns.org Git - pyshared.git/commitdiff
added net, protocoll
authorErik Andresen <erik@vontaene.de>
Sat, 3 Jan 2015 11:44:07 +0000 (12:44 +0100)
committerErik Andresen <erik@vontaene.de>
Sat, 3 Jan 2015 11:44:07 +0000 (12:44 +0100)
net.py [new file with mode: 0755]
protocoll.py [new file with mode: 0644]

diff --git a/net.py b/net.py
new file mode 100755 (executable)
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 (file)
index 0000000..5beea6e
--- /dev/null
@@ -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("<BBB%ds" % len(msg), self.ENQ, msg_len, addr, msg)
+                       packet+=chr(self.crc.bit_by_bit_fast(packet))
+                       self.conn.write(packet)
+                       if not self.__get_ack():
+                               raise NAKReceived()
+               except:
+                       raise
+               finally:
+                       self.lock.release()
+
+       def write(self, addr, msg):
+               return self.send(addr, msg)
+
+       def __reply_ack(self):
+               self.conn.write(chr(self.ACK))
+       
+       def __reply_nak(self):
+               self.conn.write(chr(self.NAK))
+
+       def receive(self):
+               packet = ""
+               num = 0
+               state = self.STATE_DEFAULT
+               self.lock.acquire()
+               try:
+                       while(True):
+                               c = self.conn.read(1)
+                               if not c:
+                                       raise
+                               if state == self.STATE_DEFAULT:
+                                       if ord(c) != self.ENQ:
+                                               self.__reply_nak()
+                                               raise ByteError(ord(c))
+                                       state = self.STATE_LEN
+                                       packet = c
+                               elif state == self.STATE_LEN:
+                                       if ord(c) > 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("<BBB%dsB" % (len(packet)-3-1), packet)
+                                                       return addr, msg
+                                               else:
+                                                       self.__reply_nak()
+                                                       raise CRCError()
+               except:
+                       raise
+               finally:
+                       self.lock.release()
+       
+       def read(self):
+               addr, msg = self.receive()
+               if msg[0] == chr(self.DC1) and len(msg) > 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