| @@ -1,72 +0,0 @@ | |||||
| ''' | |||||
| The MIT License (MIT) | |||||
| Copyright (c) 2013 Dave P. | |||||
| ''' | |||||
| import signal | |||||
| import sys | |||||
| import ssl | |||||
| from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer, SimpleSSLWebSocketServer | |||||
| from optparse import OptionParser | |||||
| class SimpleEcho(WebSocket): | |||||
| def handleMessage(self): | |||||
| print self.data | |||||
| self.sendMessage(self.data) | |||||
| def handleConnected(self): | |||||
| pass | |||||
| def handleClose(self): | |||||
| pass | |||||
| clients = [] | |||||
| class SimpleChat(WebSocket): | |||||
| def handleMessage(self): | |||||
| for client in clients: | |||||
| if client != self: | |||||
| client.sendMessage(self.address[0] + u' - ' + self.data) | |||||
| def handleConnected(self): | |||||
| print (self.address, 'connected') | |||||
| for client in clients: | |||||
| client.sendMessage(self.address[0] + u' - connected') | |||||
| clients.append(self) | |||||
| def handleClose(self): | |||||
| clients.remove(self) | |||||
| print (self.address, 'closed') | |||||
| for client in clients: | |||||
| client.sendMessage(self.address[0] + u' - disconnected') | |||||
| if __name__ == "__main__": | |||||
| parser = OptionParser(usage="usage: %prog [options]", version="%prog 1.0") | |||||
| parser.add_option("--host", default='', type='string', action="store", dest="host", help="hostname (localhost)") | |||||
| parser.add_option("--port", default=8000, type='int', action="store", dest="port", help="port (8000)") | |||||
| parser.add_option("--example", default='echo', type='string', action="store", dest="example", help="echo, chat") | |||||
| parser.add_option("--ssl", default=0, type='int', action="store", dest="ssl", help="ssl (1: on, 0: off (default))") | |||||
| parser.add_option("--cert", default='./cert.pem', type='string', action="store", dest="cert", help="cert (./cert.pem)") | |||||
| parser.add_option("--ver", default=ssl.PROTOCOL_TLSv1, type=int, action="store", dest="ver", help="ssl version") | |||||
| (options, args) = parser.parse_args() | |||||
| cls = SimpleEcho | |||||
| if options.example == 'chat': | |||||
| cls = SimpleChat | |||||
| if options.ssl == 1: | |||||
| server = SimpleSSLWebSocketServer(options.host, options.port, cls, options.cert, options.cert, version=options.ver) | |||||
| else: | |||||
| server = SimpleWebSocketServer(options.host, options.port, cls) | |||||
| def close_sig_handler(signal, frame): | |||||
| server.close() | |||||
| sys.exit() | |||||
| signal.signal(signal.SIGINT, close_sig_handler) | |||||
| server.serveforever() | |||||
| @@ -1,694 +0,0 @@ | |||||
| ''' | |||||
| The MIT License (MIT) | |||||
| Copyright (c) 2013 Dave P. | |||||
| ''' | |||||
| import sys | |||||
| VER = sys.version_info[0] | |||||
| if VER >= 3: | |||||
| import socketserver | |||||
| from http.server import BaseHTTPRequestHandler | |||||
| from io import StringIO, BytesIO | |||||
| else: | |||||
| import SocketServer | |||||
| from BaseHTTPServer import BaseHTTPRequestHandler | |||||
| from StringIO import StringIO | |||||
| import hashlib | |||||
| import base64 | |||||
| import socket | |||||
| import struct | |||||
| import ssl | |||||
| import errno | |||||
| import codecs | |||||
| from collections import deque | |||||
| from select import select | |||||
| __all__ = ['WebSocket', | |||||
| 'SimpleWebSocketServer', | |||||
| 'SimpleSSLWebSocketServer'] | |||||
| def _check_unicode(val): | |||||
| if VER >= 3: | |||||
| return isinstance(val, str) | |||||
| else: | |||||
| return isinstance(val, unicode) | |||||
| class HTTPRequest(BaseHTTPRequestHandler): | |||||
| def __init__(self, request_text): | |||||
| if VER >= 3: | |||||
| self.rfile = BytesIO(request_text) | |||||
| else: | |||||
| self.rfile = StringIO(request_text) | |||||
| self.raw_requestline = self.rfile.readline() | |||||
| self.error_code = self.error_message = None | |||||
| self.parse_request() | |||||
| _VALID_STATUS_CODES = [1000, 1001, 1002, 1003, 1007, 1008, | |||||
| 1009, 1010, 1011, 3000, 3999, 4000, 4999] | |||||
| HANDSHAKE_STR = ( | |||||
| "HTTP/1.1 101 Switching Protocols\r\n" | |||||
| "Upgrade: WebSocket\r\n" | |||||
| "Connection: Upgrade\r\n" | |||||
| "Sec-WebSocket-Accept: %(acceptstr)s\r\n\r\n" | |||||
| ) | |||||
| GUID_STR = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' | |||||
| STREAM = 0x0 | |||||
| TEXT = 0x1 | |||||
| BINARY = 0x2 | |||||
| CLOSE = 0x8 | |||||
| PING = 0x9 | |||||
| PONG = 0xA | |||||
| HEADERB1 = 1 | |||||
| HEADERB2 = 3 | |||||
| LENGTHSHORT = 4 | |||||
| LENGTHLONG = 5 | |||||
| MASK = 6 | |||||
| PAYLOAD = 7 | |||||
| MAXHEADER = 65536 | |||||
| MAXPAYLOAD = 33554432 | |||||
| class WebSocket(object): | |||||
| def __init__(self, server, sock, address): | |||||
| self.server = server | |||||
| self.client = sock | |||||
| self.address = address | |||||
| self.handshaked = False | |||||
| self.headerbuffer = bytearray() | |||||
| self.headertoread = 2048 | |||||
| self.fin = 0 | |||||
| self.data = bytearray() | |||||
| self.opcode = 0 | |||||
| self.hasmask = 0 | |||||
| self.maskarray = None | |||||
| self.length = 0 | |||||
| self.lengtharray = None | |||||
| self.index = 0 | |||||
| self.request = None | |||||
| self.usingssl = False | |||||
| self.frag_start = False | |||||
| self.frag_type = BINARY | |||||
| self.frag_buffer = None | |||||
| self.frag_decoder = codecs.getincrementaldecoder('utf-8')(errors='strict') | |||||
| self.closed = False | |||||
| self.sendq = deque() | |||||
| self.state = HEADERB1 | |||||
| # restrict the size of header and payload for security reasons | |||||
| self.maxheader = MAXHEADER | |||||
| self.maxpayload = MAXPAYLOAD | |||||
| def handleMessage(self): | |||||
| """ | |||||
| Called when websocket frame is received. | |||||
| To access the frame data call self.data. | |||||
| If the frame is Text then self.data is a unicode object. | |||||
| If the frame is Binary then self.data is a bytearray object. | |||||
| """ | |||||
| pass | |||||
| def handleConnected(self): | |||||
| """ | |||||
| Called when a websocket client connects to the server. | |||||
| """ | |||||
| pass | |||||
| def handleClose(self): | |||||
| """ | |||||
| Called when a websocket server gets a Close frame from a client. | |||||
| """ | |||||
| pass | |||||
| def _handlePacket(self): | |||||
| if self.opcode == CLOSE: | |||||
| pass | |||||
| elif self.opcode == STREAM: | |||||
| pass | |||||
| elif self.opcode == TEXT: | |||||
| pass | |||||
| elif self.opcode == BINARY: | |||||
| pass | |||||
| elif self.opcode == PONG or self.opcode == PING: | |||||
| if len(self.data) > 125: | |||||
| raise Exception('control frame length can not be > 125') | |||||
| else: | |||||
| # unknown or reserved opcode so just close | |||||
| raise Exception('unknown opcode') | |||||
| if self.opcode == CLOSE: | |||||
| status = 1000 | |||||
| reason = u'' | |||||
| length = len(self.data) | |||||
| if length == 0: | |||||
| pass | |||||
| elif length >= 2: | |||||
| status = struct.unpack_from('!H', self.data[:2])[0] | |||||
| reason = self.data[2:] | |||||
| if status not in _VALID_STATUS_CODES: | |||||
| status = 1002 | |||||
| if len(reason) > 0: | |||||
| try: | |||||
| reason = reason.decode('utf8', errors='strict') | |||||
| except: | |||||
| status = 1002 | |||||
| else: | |||||
| status = 1002 | |||||
| self.close(status, reason) | |||||
| return | |||||
| elif self.fin == 0: | |||||
| if self.opcode != STREAM: | |||||
| if self.opcode == PING or self.opcode == PONG: | |||||
| raise Exception('control messages can not be fragmented') | |||||
| self.frag_type = self.opcode | |||||
| self.frag_start = True | |||||
| self.frag_decoder.reset() | |||||
| if self.frag_type == TEXT: | |||||
| self.frag_buffer = [] | |||||
| utf_str = self.frag_decoder.decode(self.data, final = False) | |||||
| if utf_str: | |||||
| self.frag_buffer.append(utf_str) | |||||
| else: | |||||
| self.frag_buffer = bytearray() | |||||
| self.frag_buffer.extend(self.data) | |||||
| else: | |||||
| if self.frag_start is False: | |||||
| raise Exception('fragmentation protocol error') | |||||
| if self.frag_type == TEXT: | |||||
| utf_str = self.frag_decoder.decode(self.data, final = False) | |||||
| if utf_str: | |||||
| self.frag_buffer.append(utf_str) | |||||
| else: | |||||
| self.frag_buffer.extend(self.data) | |||||
| else: | |||||
| if self.opcode == STREAM: | |||||
| if self.frag_start is False: | |||||
| raise Exception('fragmentation protocol error') | |||||
| if self.frag_type == TEXT: | |||||
| utf_str = self.frag_decoder.decode(self.data, final = True) | |||||
| self.frag_buffer.append(utf_str) | |||||
| self.data = u''.join(self.frag_buffer) | |||||
| else: | |||||
| self.frag_buffer.extend(self.data) | |||||
| self.data = self.frag_buffer | |||||
| self.handleMessage() | |||||
| self.frag_decoder.reset() | |||||
| self.frag_type = BINARY | |||||
| self.frag_start = False | |||||
| self.frag_buffer = None | |||||
| elif self.opcode == PING: | |||||
| self._sendMessage(False, PONG, self.data) | |||||
| elif self.opcode == PONG: | |||||
| pass | |||||
| else: | |||||
| if self.frag_start is True: | |||||
| raise Exception('fragmentation protocol error') | |||||
| if self.opcode == TEXT: | |||||
| try: | |||||
| self.data = self.data.decode('utf8', errors='strict') | |||||
| except Exception as exp: | |||||
| raise Exception('invalid utf-8 payload') | |||||
| self.handleMessage() | |||||
| def _handleData(self): | |||||
| # do the HTTP header and handshake | |||||
| if self.handshaked is False: | |||||
| data = self.client.recv(self.headertoread) | |||||
| if not data: | |||||
| raise Exception('remote socket closed') | |||||
| else: | |||||
| # accumulate | |||||
| self.headerbuffer.extend(data) | |||||
| if len(self.headerbuffer) >= self.maxheader: | |||||
| raise Exception('header exceeded allowable size') | |||||
| # indicates end of HTTP header | |||||
| if b'\r\n\r\n' in self.headerbuffer: | |||||
| self.request = HTTPRequest(self.headerbuffer) | |||||
| # handshake rfc 6455 | |||||
| try: | |||||
| key = self.request.headers['Sec-WebSocket-Key'] | |||||
| k = key.encode('ascii') + GUID_STR.encode('ascii') | |||||
| k_s = base64.b64encode(hashlib.sha1(k).digest()).decode('ascii') | |||||
| hStr = HANDSHAKE_STR % {'acceptstr': k_s} | |||||
| self.sendq.append((BINARY, hStr.encode('ascii'))) | |||||
| self.handshaked = True | |||||
| self.handleConnected() | |||||
| except Exception as e: | |||||
| raise Exception('handshake failed: %s', str(e)) | |||||
| # else do normal data | |||||
| else: | |||||
| data = self.client.recv(8192) | |||||
| if not data: | |||||
| raise Exception("remote socket closed") | |||||
| if VER >= 3: | |||||
| for d in data: | |||||
| self._parseMessage(d) | |||||
| else: | |||||
| for d in data: | |||||
| self._parseMessage(ord(d)) | |||||
| def close(self, status = 1000, reason = u''): | |||||
| """ | |||||
| Send Close frame to the client. The underlying socket is only closed | |||||
| when the client acknowledges the Close frame. | |||||
| status is the closing identifier. | |||||
| reason is the reason for the close. | |||||
| """ | |||||
| try: | |||||
| if self.closed is False: | |||||
| close_msg = bytearray() | |||||
| close_msg.extend(struct.pack("!H", status)) | |||||
| if _check_unicode(reason): | |||||
| close_msg.extend(reason.encode('utf-8')) | |||||
| else: | |||||
| close_msg.extend(reason) | |||||
| self._sendMessage(False, CLOSE, close_msg) | |||||
| finally: | |||||
| self.closed = True | |||||
| def _sendBuffer(self, buff): | |||||
| size = len(buff) | |||||
| tosend = size | |||||
| already_sent = 0 | |||||
| while tosend > 0: | |||||
| try: | |||||
| # i should be able to send a bytearray | |||||
| sent = self.client.send(buff[already_sent:]) | |||||
| if sent == 0: | |||||
| raise RuntimeError('socket connection broken') | |||||
| already_sent += sent | |||||
| tosend -= sent | |||||
| except socket.error as e: | |||||
| # if we have full buffers then wait for them to drain and try again | |||||
| if e.errno in [errno.EAGAIN, errno.EWOULDBLOCK]: | |||||
| return buff[already_sent:] | |||||
| else: | |||||
| raise e | |||||
| return None | |||||
| def sendFragmentStart(self, data): | |||||
| """ | |||||
| Send the start of a data fragment stream to a websocket client. | |||||
| Subsequent data should be sent using sendFragment(). | |||||
| A fragment stream is completed when sendFragmentEnd() is called. | |||||
| If data is a unicode object then the frame is sent as Text. | |||||
| If the data is a bytearray object then the frame is sent as Binary. | |||||
| """ | |||||
| opcode = BINARY | |||||
| if _check_unicode(data): | |||||
| opcode = TEXT | |||||
| self._sendMessage(True, opcode, data) | |||||
| def sendFragment(self, data): | |||||
| """ | |||||
| see sendFragmentStart() | |||||
| If data is a unicode object then the frame is sent as Text. | |||||
| If the data is a bytearray object then the frame is sent as Binary. | |||||
| """ | |||||
| self._sendMessage(True, STREAM, data) | |||||
| def sendFragmentEnd(self, data): | |||||
| """ | |||||
| see sendFragmentEnd() | |||||
| If data is a unicode object then the frame is sent as Text. | |||||
| If the data is a bytearray object then the frame is sent as Binary. | |||||
| """ | |||||
| self._sendMessage(False, STREAM, data) | |||||
| def sendMessage(self, data): | |||||
| """ | |||||
| Send websocket data frame to the client. | |||||
| If data is a unicode object then the frame is sent as Text. | |||||
| If the data is a bytearray object then the frame is sent as Binary. | |||||
| """ | |||||
| opcode = BINARY | |||||
| if _check_unicode(data): | |||||
| opcode = TEXT | |||||
| self._sendMessage(False, opcode, data) | |||||
| def _sendMessage(self, fin, opcode, data): | |||||
| payload = bytearray() | |||||
| b1 = 0 | |||||
| b2 = 0 | |||||
| if fin is False: | |||||
| b1 |= 0x80 | |||||
| b1 |= opcode | |||||
| if _check_unicode(data): | |||||
| data = data.encode('utf-8') | |||||
| length = len(data) | |||||
| payload.append(b1) | |||||
| if length <= 125: | |||||
| b2 |= length | |||||
| payload.append(b2) | |||||
| elif length >= 126 and length <= 65535: | |||||
| b2 |= 126 | |||||
| payload.append(b2) | |||||
| payload.extend(struct.pack("!H", length)) | |||||
| else: | |||||
| b2 |= 127 | |||||
| payload.append(b2) | |||||
| payload.extend(struct.pack("!Q", length)) | |||||
| if length > 0: | |||||
| payload.extend(data) | |||||
| self.sendq.append((opcode, payload)) | |||||
| def _parseMessage(self, byte): | |||||
| # read in the header | |||||
| if self.state == HEADERB1: | |||||
| self.fin = byte & 0x80 | |||||
| self.opcode = byte & 0x0F | |||||
| self.state = HEADERB2 | |||||
| self.index = 0 | |||||
| self.length = 0 | |||||
| self.lengtharray = bytearray() | |||||
| self.data = bytearray() | |||||
| rsv = byte & 0x70 | |||||
| if rsv != 0: | |||||
| raise Exception('RSV bit must be 0') | |||||
| elif self.state == HEADERB2: | |||||
| mask = byte & 0x80 | |||||
| length = byte & 0x7F | |||||
| if self.opcode == PING and length > 125: | |||||
| raise Exception('ping packet is too large') | |||||
| if mask == 128: | |||||
| self.hasmask = True | |||||
| else: | |||||
| self.hasmask = False | |||||
| if length <= 125: | |||||
| self.length = length | |||||
| # if we have a mask we must read it | |||||
| if self.hasmask is True: | |||||
| self.maskarray = bytearray() | |||||
| self.state = MASK | |||||
| else: | |||||
| # if there is no mask and no payload we are done | |||||
| if self.length <= 0: | |||||
| try: | |||||
| self._handlePacket() | |||||
| finally: | |||||
| self.state = self.HEADERB1 | |||||
| self.data = bytearray() | |||||
| # we have no mask and some payload | |||||
| else: | |||||
| #self.index = 0 | |||||
| self.data = bytearray() | |||||
| self.state = PAYLOAD | |||||
| elif length == 126: | |||||
| self.lengtharray = bytearray() | |||||
| self.state = LENGTHSHORT | |||||
| elif length == 127: | |||||
| self.lengtharray = bytearray() | |||||
| self.state = LENGTHLONG | |||||
| elif self.state == LENGTHSHORT: | |||||
| self.lengtharray.append(byte) | |||||
| if len(self.lengtharray) > 2: | |||||
| raise Exception('short length exceeded allowable size') | |||||
| if len(self.lengtharray) == 2: | |||||
| self.length = struct.unpack_from('!H', self.lengtharray)[0] | |||||
| if self.hasmask is True: | |||||
| self.maskarray = bytearray() | |||||
| self.state = MASK | |||||
| else: | |||||
| # if there is no mask and no payload we are done | |||||
| if self.length <= 0: | |||||
| try: | |||||
| self._handlePacket() | |||||
| finally: | |||||
| self.state = HEADERB1 | |||||
| self.data = bytearray() | |||||
| # we have no mask and some payload | |||||
| else: | |||||
| #self.index = 0 | |||||
| self.data = bytearray() | |||||
| self.state = PAYLOAD | |||||
| elif self.state == LENGTHLONG: | |||||
| self.lengtharray.append(byte) | |||||
| if len(self.lengtharray) > 8: | |||||
| raise Exception('long length exceeded allowable size') | |||||
| if len(self.lengtharray) == 8: | |||||
| self.length = struct.unpack_from('!Q', self.lengtharray)[0] | |||||
| if self.hasmask is True: | |||||
| self.maskarray = bytearray() | |||||
| self.state = MASK | |||||
| else: | |||||
| # if there is no mask and no payload we are done | |||||
| if self.length <= 0: | |||||
| try: | |||||
| self._handlePacket() | |||||
| finally: | |||||
| self.state = HEADERB1 | |||||
| self.data = bytearray() | |||||
| # we have no mask and some payload | |||||
| else: | |||||
| #self.index = 0 | |||||
| self.data = bytearray() | |||||
| self.state = PAYLOAD | |||||
| # MASK STATE | |||||
| elif self.state == MASK: | |||||
| self.maskarray.append(byte) | |||||
| if len(self.maskarray) > 4: | |||||
| raise Exception('mask exceeded allowable size') | |||||
| if len(self.maskarray) == 4: | |||||
| # if there is no mask and no payload we are done | |||||
| if self.length <= 0: | |||||
| try: | |||||
| self._handlePacket() | |||||
| finally: | |||||
| self.state = HEADERB1 | |||||
| self.data = bytearray() | |||||
| # we have no mask and some payload | |||||
| else: | |||||
| #self.index = 0 | |||||
| self.data = bytearray() | |||||
| self.state = PAYLOAD | |||||
| # PAYLOAD STATE | |||||
| elif self.state == PAYLOAD: | |||||
| if self.hasmask is True: | |||||
| self.data.append( byte ^ self.maskarray[self.index % 4] ) | |||||
| else: | |||||
| self.data.append( byte ) | |||||
| # if length exceeds allowable size then we except and remove the connection | |||||
| if len(self.data) >= self.maxpayload: | |||||
| raise Exception('payload exceeded allowable size') | |||||
| # check if we have processed length bytes; if so we are done | |||||
| if (self.index+1) == self.length: | |||||
| try: | |||||
| self._handlePacket() | |||||
| finally: | |||||
| #self.index = 0 | |||||
| self.state = HEADERB1 | |||||
| self.data = bytearray() | |||||
| else: | |||||
| self.index += 1 | |||||
| class SimpleWebSocketServer(object): | |||||
| def __init__(self, host, port, websocketclass, selectInterval = 0.1): | |||||
| self.websocketclass = websocketclass | |||||
| self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |||||
| self.serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |||||
| self.serversocket.bind((host, port)) | |||||
| self.serversocket.listen(5) | |||||
| self.selectInterval = selectInterval | |||||
| self.connections = {} | |||||
| self.listeners = [self.serversocket] | |||||
| def _decorateSocket(self, sock): | |||||
| return sock | |||||
| def _constructWebSocket(self, sock, address): | |||||
| return self.websocketclass(self, sock, address) | |||||
| def close(self): | |||||
| self.serversocket.close() | |||||
| for desc, conn in self.connections.items(): | |||||
| conn.close() | |||||
| conn.handleClose() | |||||
| def serveforever(self): | |||||
| while True: | |||||
| writers = [] | |||||
| for fileno in self.listeners: | |||||
| if fileno == self.serversocket: | |||||
| continue | |||||
| client = self.connections[fileno] | |||||
| if client.sendq: | |||||
| writers.append(fileno) | |||||
| if self.selectInterval: | |||||
| rList, wList, xList = select(self.listeners, writers, self.listeners, self.selectInterval) | |||||
| else: | |||||
| rList, wList, xList = select(self.listeners, writers, self.listeners) | |||||
| for ready in wList: | |||||
| client = self.connections[ready] | |||||
| try: | |||||
| while client.sendq: | |||||
| opcode, payload = client.sendq.popleft() | |||||
| remaining = client._sendBuffer(payload) | |||||
| if remaining is not None: | |||||
| client.sendq.appendleft((opcode, remaining)) | |||||
| break | |||||
| else: | |||||
| if opcode == CLOSE: | |||||
| raise Exception('received client close') | |||||
| except Exception as n: | |||||
| client.client.close() | |||||
| client.handleClose() | |||||
| del self.connections[ready] | |||||
| self.listeners.remove(ready) | |||||
| for ready in rList: | |||||
| if ready == self.serversocket: | |||||
| try: | |||||
| sock, address = self.serversocket.accept() | |||||
| newsock = self._decorateSocket(sock) | |||||
| newsock.setblocking(0) | |||||
| fileno = newsock.fileno() | |||||
| self.connections[fileno] = self._constructWebSocket(newsock, address) | |||||
| self.listeners.append(fileno) | |||||
| except Exception as n: | |||||
| if sock is not None: | |||||
| sock.close() | |||||
| else: | |||||
| if ready not in self.connections: | |||||
| continue | |||||
| client = self.connections[ready] | |||||
| try: | |||||
| client._handleData() | |||||
| except Exception as n: | |||||
| client.client.close() | |||||
| client.handleClose() | |||||
| del self.connections[ready] | |||||
| self.listeners.remove(ready) | |||||
| for failed in xList: | |||||
| if failed == self.serversocket: | |||||
| self.close() | |||||
| raise Exception('server socket failed') | |||||
| else: | |||||
| if failed not in self.connections: | |||||
| continue | |||||
| client = self.connections[failed] | |||||
| client.client.close() | |||||
| client.handleClose() | |||||
| del self.connections[failed] | |||||
| self.listeners.remove(failed) | |||||
| class SimpleSSLWebSocketServer(SimpleWebSocketServer): | |||||
| def __init__(self, host, port, websocketclass, certfile, | |||||
| keyfile, version = ssl.PROTOCOL_TLSv1, selectInterval = 0.1): | |||||
| SimpleWebSocketServer.__init__(self, host, port, | |||||
| websocketclass, selectInterval) | |||||
| self.context = ssl.SSLContext(version) | |||||
| self.context.load_cert_chain(certfile, keyfile) | |||||
| def close(self): | |||||
| super(SimpleSSLWebSocketServer, self).close() | |||||
| def _decorateSocket(self, sock): | |||||
| sslsock = self.context.wrap_socket(sock, server_side=True) | |||||
| return sslsock | |||||
| def _constructWebSocket(self, sock, address): | |||||
| ws = self.websocketclass(self, sock, address) | |||||
| ws.usingssl = True | |||||
| return ws | |||||
| def serveforever(self): | |||||
| super(SimpleSSLWebSocketServer, self).serveforever() | |||||
| @@ -0,0 +1,199 @@ | |||||
| """ | |||||
| Copied from Anders' original C++ implementation | |||||
| S. Anders, H. J. Briegel: Fast Simulation of Stabilizer Circuits using a Graph State Formalism quant-ph/0504117 | |||||
| """ | |||||
| import numpy as np | |||||
| cz_table = ((((1, 0, 0), (1, 0, 0), (1, 0, 3), (1, 0, 3), (1, 0, 5), (1, 0, 5), | |||||
| (1, 0, 6), (1, 0, 6), (0, 3, 8), (0, 3, 8), (0, 0, 10), (0, 0, 10), | |||||
| (1, 0, 3), (1, 0, 3), (1, 0, 0), (1, 0, 0), (1, 0, 6), (1, 0, 6), | |||||
| (1, 0, 5), (1, 0, 5), (0, 0, 10), (0, 0, 10), (0, 3, 8), (0, 3, 8)), | |||||
| ((1, 0, 0), (1, 0, 0), (1, 0, 3), (1, 0, 3), (1, 0, 5), (1, 0, 5), | |||||
| (1, 0, 6), (1, 0, 6), (0, 2, 8), (0, 2, 8), (0, 0, 10), (0, 0, 10), | |||||
| (1, 0, 3), (1, 0, 3), (1, 0, 0), (1, 0, 0), (1, 0, 6), (1, 0, 6), | |||||
| (1, 0, 5), (1, 0, 5), (0, 0, 10), (0, 0, 10), (0, 2, 8), (0, 2, 8)), | |||||
| ((1, 2, 3), (1, 0, 1), (1, 0, 2), (1, 2, 0), (1, 0, 4), (1, 2, 6), | |||||
| (1, 2, 5), (1, 0, 7), (0, 0, 8), (0, 0, 8), (0, 2, 10), (0, 2, 10), | |||||
| (1, 0, 2), (1, 0, 2), (1, 0, 1), (1, 0, 1), (1, 0, 7), (1, 0, 7), | |||||
| (1, 0, 4), (1, 0, 4), (0, 2, 10), (0, 2, 10), (0, 0, 8), (0, 0, 8)), | |||||
| ((1, 3, 0), (1, 0, 1), (1, 0, 2), (1, 3, 3), (1, 0, 4), (1, 3, 5), | |||||
| (1, 3, 6), (1, 0, 7), (0, 0, 8), (0, 0, 8), (0, 3, 10), (0, 3, 10), | |||||
| (1, 0, 2), (1, 0, 2), (1, 0, 1), (1, 0, 1), (1, 0, 7), (1, 0, 7), | |||||
| (1, 0, 4), (1, 0, 4), (0, 3, 10), (0, 3, 10), (0, 0, 8), (0, 0, 8)), | |||||
| ((1, 4, 3), (1, 4, 3), (1, 4, 0), (1, 4, 0), (1, 4, 6), (1, 4, 6), | |||||
| (1, 4, 5), (1, 4, 5), (0, 6, 8), (0, 6, 8), (0, 4, 10), (0, 4, 10), | |||||
| (1, 4, 0), (1, 4, 0), (1, 4, 3), (1, 4, 3), (1, 4, 5), (1, 4, 5), | |||||
| (1, 4, 6), (1, 4, 6), (0, 4, 10), (0, 4, 10), (0, 6, 8), (0, 6, 8)), | |||||
| ((1, 5, 0), (1, 5, 0), (1, 5, 3), (1, 5, 3), (1, 5, 5), (1, 5, 5), | |||||
| (1, 5, 6), (1, 5, 6), (0, 6, 8), (0, 6, 8), (0, 5, 10), (0, 5, 10), | |||||
| (1, 5, 3), (1, 5, 3), (1, 5, 0), (1, 5, 0), (1, 5, 6), (1, 5, 6), | |||||
| (1, 5, 5), (1, 5, 5), (0, 5, 10), (0, 5, 10), (0, 6, 8), (0, 6, 8)), | |||||
| ((1, 6, 0), (1, 5, 1), (1, 5, 2), (1, 6, 3), (1, 5, 4), (1, 6, 5), | |||||
| (1, 6, 6), (1, 5, 7), (0, 5, 8), (0, 5, 8), (0, 6, 10), (0, 6, 10), | |||||
| (1, 5, 2), (1, 5, 2), (1, 5, 1), (1, 5, 1), (1, 5, 7), (1, 5, 7), | |||||
| (1, 5, 4), (1, 5, 4), (0, 6, 10), (0, 6, 10), (0, 5, 8), (0, 5, 8)), | |||||
| ((1, 6, 0), (1, 4, 2), (1, 4, 1), (1, 6, 3), (1, 4, 7), (1, 6, 5), | |||||
| (1, 6, 6), (1, 4, 4), (0, 4, 8), (0, 4, 8), (0, 6, 10), (0, 6, 10), | |||||
| (1, 4, 1), (1, 4, 1), (1, 4, 2), (1, 4, 2), (1, 4, 4), (1, 4, 4), | |||||
| (1, 4, 7), (1, 4, 7), (0, 6, 10), (0, 6, 10), (0, 4, 8), (0, 4, 8)), | |||||
| ((0, 8, 3), (0, 8, 2), (0, 8, 0), (0, 8, 0), (0, 8, 6), (0, 8, 6), | |||||
| (0, 8, 5), (0, 8, 4), (0, 8, 8), (0, 8, 8), (0, 8, 10), (0, 8, 10), | |||||
| (0, 8, 0), (0, 8, 0), (0, 8, 2), (0, 8, 2), (0, 8, 4), (0, 8, 4), | |||||
| (0, 8, 6), (0, 8, 6), (0, 8, 10), (0, 8, 10), (0, 8, 8), (0, 8, 8)), | |||||
| ((0, 8, 3), (0, 8, 2), (0, 8, 0), (0, 8, 0), (0, 8, 6), (0, 8, 6), | |||||
| (0, 8, 5), (0, 8, 4), (0, 8, 8), (0, 8, 8), (0, 8, 10), (0, 8, 10), | |||||
| (0, 8, 0), (0, 8, 0), (0, 8, 2), (0, 8, 2), (0, 8, 4), (0, 8, 4), | |||||
| (0, 8, 6), (0, 8, 6), (0, 8, 10), (0, 8, 10), (0, 8, 8), (0, 8, 8)), | |||||
| ((0, 10, 0), (0, 10, 0), (0, 10, 2), (0, 10, 3), (0, 10, 4), (0, 10, 5), | |||||
| (0, 10, 6), (0, 10, 6), (0, 10, 8), (0, 10, 8), (0, 10, 10), (0, 10, 10), | |||||
| (0, 10, 2), (0, 10, 2), (0, 10, 0), (0, 10, 0), (0, 10, 6), (0, 10, 6), | |||||
| (0, 10, 4), (0, 10, 4), (0, 10, 10), (0, 10, 10), (0, 10, 8), (0, 10, 8)), | |||||
| ((0, 10, 0), (0, 10, 0), (0, 10, 2), (0, 10, 3), (0, 10, 4), (0, 10, 5), | |||||
| (0, 10, 6), (0, 10, 6), (0, 10, 8), (0, 10, 8), (0, 10, 10), (0, 10, 10), | |||||
| (0, 10, 2), (0, 10, 2), (0, 10, 0), (0, 10, 0), (0, 10, 6), (0, 10, 6), | |||||
| (0, 10, 4), (0, 10, 4), (0, 10, 10), (0, 10, 10), (0, 10, 8), (0, 10, 8)), | |||||
| ((1, 2, 3), (1, 0, 1), (1, 0, 2), (1, 2, 0), (1, 0, 4), (1, 2, 6), | |||||
| (1, 2, 5), (1, 0, 7), (0, 0, 8), (0, 0, 8), (0, 2, 10), (0, 2, 10), | |||||
| (1, 0, 2), (1, 0, 2), (1, 0, 1), (1, 0, 1), (1, 0, 7), (1, 0, 7), | |||||
| (1, 0, 4), (1, 0, 4), (0, 2, 10), (0, 2, 10), (0, 0, 8), (0, 0, 8)), | |||||
| ((1, 2, 3), (1, 0, 1), (1, 0, 2), (1, 2, 0), (1, 0, 4), (1, 2, 6), | |||||
| (1, 2, 5), (1, 0, 7), (0, 0, 8), (0, 0, 8), (0, 2, 10), (0, 2, 10), | |||||
| (1, 0, 2), (1, 0, 2), (1, 0, 1), (1, 0, 1), (1, 0, 7), (1, 0, 7), | |||||
| (1, 0, 4), (1, 0, 4), (0, 2, 10), (0, 2, 10), (0, 0, 8), (0, 0, 8)), | |||||
| ((1, 0, 0), (1, 0, 0), (1, 0, 3), (1, 0, 3), (1, 0, 5), (1, 0, 5), | |||||
| (1, 0, 6), (1, 0, 6), (0, 2, 8), (0, 2, 8), (0, 0, 10), (0, 0, 10), | |||||
| (1, 0, 3), (1, 0, 3), (1, 0, 0), (1, 0, 0), (1, 0, 6), (1, 0, 6), | |||||
| (1, 0, 5), (1, 0, 5), (0, 0, 10), (0, 0, 10), (0, 2, 8), (0, 2, 8)), | |||||
| ((1, 0, 0), (1, 0, 0), (1, 0, 3), (1, 0, 3), (1, 0, 5), (1, 0, 5), | |||||
| (1, 0, 6), (1, 0, 6), (0, 2, 8), (0, 2, 8), (0, 0, 10), (0, 0, 10), | |||||
| (1, 0, 3), (1, 0, 3), (1, 0, 0), (1, 0, 0), (1, 0, 6), (1, 0, 6), | |||||
| (1, 0, 5), (1, 0, 5), (0, 0, 10), (0, 0, 10), (0, 2, 8), (0, 2, 8)), | |||||
| ((1, 6, 0), (1, 4, 2), (1, 4, 1), (1, 6, 3), (1, 4, 7), (1, 6, 5), | |||||
| (1, 6, 6), (1, 4, 4), (0, 4, 8), (0, 4, 8), (0, 6, 10), (0, 6, 10), | |||||
| (1, 4, 1), (1, 4, 1), (1, 4, 2), (1, 4, 2), (1, 4, 4), (1, 4, 4), | |||||
| (1, 4, 7), (1, 4, 7), (0, 6, 10), (0, 6, 10), (0, 4, 8), (0, 4, 8)), | |||||
| ((1, 6, 0), (1, 4, 2), (1, 4, 1), (1, 6, 3), (1, 4, 7), (1, 6, 5), | |||||
| (1, 6, 6), (1, 4, 4), (0, 4, 8), (0, 4, 8), (0, 6, 10), (0, 6, 10), | |||||
| (1, 4, 1), (1, 4, 1), (1, 4, 2), (1, 4, 2), (1, 4, 4), (1, 4, 4), | |||||
| (1, 4, 7), (1, 4, 7), (0, 6, 10), (0, 6, 10), (0, 4, 8), (0, 4, 8)), | |||||
| ((1, 4, 3), (1, 4, 3), (1, 4, 0), (1, 4, 0), (1, 4, 6), (1, 4, 6), | |||||
| (1, 4, 5), (1, 4, 5), (0, 6, 8), (0, 6, 8), (0, 4, 10), (0, 4, 10), | |||||
| (1, 4, 0), (1, 4, 0), (1, 4, 3), (1, 4, 3), (1, 4, 5), (1, 4, 5), | |||||
| (1, 4, 6), (1, 4, 6), (0, 4, 10), (0, 4, 10), (0, 6, 8), (0, 6, 8)), | |||||
| ((1, 4, 3), (1, 4, 3), (1, 4, 0), (1, 4, 0), (1, 4, 6), (1, 4, 6), | |||||
| (1, 4, 5), (1, 4, 5), (0, 6, 8), (0, 6, 8), (0, 4, 10), (0, 4, 10), | |||||
| (1, 4, 0), (1, 4, 0), (1, 4, 3), (1, 4, 3), (1, 4, 5), (1, 4, 5), | |||||
| (1, 4, 6), (1, 4, 6), (0, 4, 10), (0, 4, 10), (0, 6, 8), (0, 6, 8)), | |||||
| ((0, 10, 0), (0, 10, 0), (0, 10, 2), (0, 10, 3), (0, 10, 4), (0, 10, 5), | |||||
| (0, 10, 6), (0, 10, 6), (0, 10, 8), (0, 10, 8), (0, 10, 10), (0, 10, 10), | |||||
| (0, 10, 2), (0, 10, 2), (0, 10, 0), (0, 10, 0), (0, 10, 6), (0, 10, 6), | |||||
| (0, 10, 4), (0, 10, 4), (0, 10, 10), (0, 10, 10), (0, 10, 8), (0, 10, 8)), | |||||
| ((0, 10, 0), (0, 10, 0), (0, 10, 2), (0, 10, 3), (0, 10, 4), (0, 10, 5), | |||||
| (0, 10, 6), (0, 10, 6), (0, 10, 8), (0, 10, 8), (0, 10, 10), (0, 10, 10), | |||||
| (0, 10, 2), (0, 10, 2), (0, 10, 0), (0, 10, 0), (0, 10, 6), (0, 10, 6), | |||||
| (0, 10, 4), (0, 10, 4), (0, 10, 10), (0, 10, 10), (0, 10, 8), (0, 10, 8)), | |||||
| ((0, 8, 3), (0, 8, 2), (0, 8, 0), (0, 8, 0), (0, 8, 6), (0, 8, 6), | |||||
| (0, 8, 5), (0, 8, 4), (0, 8, 8), (0, 8, 8), (0, 8, 10), (0, 8, 10), | |||||
| (0, 8, 0), (0, 8, 0), (0, 8, 2), (0, 8, 2), (0, 8, 4), (0, 8, 4), | |||||
| (0, 8, 6), (0, 8, 6), (0, 8, 10), (0, 8, 10), (0, 8, 8), (0, 8, 8)), | |||||
| ((0, 8, 3), (0, 8, 2), (0, 8, 0), (0, 8, 0), (0, 8, 6), (0, 8, 6), | |||||
| (0, 8, 5), (0, 8, 4), (0, 8, 8), (0, 8, 8), (0, 8, 10), (0, 8, 10), | |||||
| (0, 8, 0), (0, 8, 0), (0, 8, 2), (0, 8, 2), (0, 8, 4), (0, 8, 4), | |||||
| (0, 8, 6), (0, 8, 6), (0, 8, 10), (0, 8, 10), (0, 8, 8), (0, 8, 8))), | |||||
| (((0, 0, 0), (0, 3, 0), (0, 3, 2), (0, 0, 3), (0, 3, 4), (0, 0, 5), | |||||
| (0, 0, 6), (0, 3, 6), (1, 5, 23), (1, 5, 22), (1, 5, 21), (1, 5, 20), | |||||
| (0, 5, 2), (0, 6, 2), (0, 5, 0), (0, 6, 0), (0, 6, 6), (0, 5, 6), | |||||
| (0, 6, 4), (0, 5, 4), (1, 5, 10), (1, 5, 11), (1, 5, 8), (1, 5, 9)), | |||||
| ((0, 0, 3), (0, 2, 2), (0, 2, 0), (0, 0, 0), (0, 2, 6), (0, 0, 6), | |||||
| (0, 0, 5), (0, 2, 4), (1, 4, 23), (1, 4, 22), (1, 4, 21), (1, 4, 20), | |||||
| (0, 6, 0), (0, 4, 0), (0, 6, 2), (0, 4, 2), (0, 4, 4), (0, 6, 4), | |||||
| (0, 4, 6), (0, 6, 6), (1, 4, 10), (1, 4, 11), (1, 4, 8), (1, 4, 9)), | |||||
| ((0, 2, 3), (0, 0, 2), (0, 0, 0), (0, 2, 0), (0, 0, 6), (0, 2, 6), | |||||
| (0, 2, 5), (0, 0, 4), (1, 4, 22), (1, 4, 23), (1, 4, 20), (1, 4, 21), | |||||
| (0, 4, 0), (0, 6, 0), (0, 4, 2), (0, 6, 2), (0, 6, 4), (0, 4, 4), | |||||
| (0, 6, 6), (0, 4, 6), (1, 4, 11), (1, 4, 10), (1, 4, 9), (1, 4, 8)), | |||||
| ((0, 3, 0), (0, 0, 0), (0, 0, 2), (0, 3, 3), (0, 0, 4), (0, 3, 5), | |||||
| (0, 3, 6), (0, 0, 6), (1, 5, 22), (1, 5, 23), (1, 5, 20), (1, 5, 21), | |||||
| (0, 6, 2), (0, 5, 2), (0, 6, 0), (0, 5, 0), (0, 5, 6), (0, 6, 6), | |||||
| (0, 5, 4), (0, 6, 4), (1, 5, 11), (1, 5, 10), (1, 5, 9), (1, 5, 8)), | |||||
| ((0, 4, 3), (0, 6, 2), (0, 6, 0), (0, 4, 0), (0, 6, 6), (0, 4, 6), | |||||
| (0, 4, 5), (0, 6, 4), (1, 0, 21), (1, 0, 20), (1, 0, 23), (1, 0, 22), | |||||
| (0, 0, 0), (0, 2, 0), (0, 0, 2), (0, 2, 2), (0, 2, 4), (0, 0, 4), | |||||
| (0, 2, 6), (0, 0, 6), (1, 0, 8), (1, 0, 9), (1, 0, 10), (1, 0, 11)), | |||||
| ((0, 5, 0), (0, 6, 0), (0, 6, 2), (0, 5, 3), (0, 6, 4), (0, 5, 5), | |||||
| (0, 5, 6), (0, 6, 6), (1, 0, 22), (1, 0, 23), (1, 0, 20), (1, 0, 21), | |||||
| (0, 3, 2), (0, 0, 2), (0, 3, 0), (0, 0, 0), (0, 0, 6), (0, 3, 6), | |||||
| (0, 0, 4), (0, 3, 4), (1, 0, 11), (1, 0, 10), (1, 0, 9), (1, 0, 8)), | |||||
| ((0, 6, 0), (0, 5, 0), (0, 5, 2), (0, 6, 3), (0, 5, 4), (0, 6, 5), | |||||
| (0, 6, 6), (0, 5, 6), (1, 0, 23), (1, 0, 22), (1, 0, 21), (1, 0, 20), | |||||
| (0, 0, 2), (0, 3, 2), (0, 0, 0), (0, 3, 0), (0, 3, 6), (0, 0, 6), | |||||
| (0, 3, 4), (0, 0, 4), (1, 0, 10), (1, 0, 11), (1, 0, 8), (1, 0, 9)), | |||||
| ((0, 6, 3), (0, 4, 2), (0, 4, 0), (0, 6, 0), (0, 4, 6), (0, 6, 6), | |||||
| (0, 6, 5), (0, 4, 4), (1, 0, 20), (1, 0, 21), (1, 0, 22), (1, 0, 23), | |||||
| (0, 2, 0), (0, 0, 0), (0, 2, 2), (0, 0, 2), (0, 0, 4), (0, 2, 4), | |||||
| (0, 0, 6), (0, 2, 6), (1, 0, 9), (1, 0, 8), (1, 0, 11), (1, 0, 10)), | |||||
| ((1, 22, 6), (1, 20, 5), (1, 20, 6), (1, 22, 5), (1, 20, 3), (1, 22, 0), | |||||
| (1, 22, 3), (1, 20, 0), (0, 0, 0), (0, 0, 2), (0, 2, 2), (0, 2, 0), | |||||
| (0, 6, 6), (0, 4, 4), (0, 6, 4), (0, 4, 6), (0, 4, 2), (0, 6, 0), | |||||
| (0, 4, 0), (0, 6, 2), (0, 2, 4), (0, 2, 6), (0, 0, 6), (0, 0, 4)), | |||||
| ((1, 22, 5), (1, 20, 6), (1, 20, 5), (1, 22, 6), (1, 20, 0), (1, 22, 3), | |||||
| (1, 22, 0), (1, 20, 3), (0, 2, 0), (0, 2, 2), (0, 0, 2), (0, 0, 0), | |||||
| (0, 4, 6), (0, 6, 4), (0, 4, 4), (0, 6, 6), (0, 6, 2), (0, 4, 0), | |||||
| (0, 6, 0), (0, 4, 2), (0, 0, 4), (0, 0, 6), (0, 2, 6), (0, 2, 4)), | |||||
| ((1, 20, 6), (1, 20, 7), (1, 20, 4), (1, 20, 5), (1, 20, 1), (1, 20, 0), | |||||
| (1, 20, 3), (1, 20, 2), (0, 2, 2), (0, 2, 0), (0, 0, 0), (0, 0, 2), | |||||
| (0, 6, 4), (0, 4, 6), (0, 6, 6), (0, 4, 4), (0, 4, 0), (0, 6, 2), | |||||
| (0, 4, 2), (0, 6, 0), (0, 0, 6), (0, 0, 4), (0, 2, 4), (0, 2, 6)), | |||||
| ((1, 20, 5), (1, 20, 4), (1, 20, 7), (1, 20, 6), (1, 20, 2), (1, 20, 3), | |||||
| (1, 20, 0), (1, 20, 1), (0, 0, 2), (0, 0, 0), (0, 2, 0), (0, 2, 2), | |||||
| (0, 4, 4), (0, 6, 6), (0, 4, 6), (0, 6, 4), (0, 6, 0), (0, 4, 2), | |||||
| (0, 6, 2), (0, 4, 0), (0, 2, 6), (0, 2, 4), (0, 0, 4), (0, 0, 6)), | |||||
| ((0, 2, 5), (0, 0, 6), (0, 0, 4), (0, 2, 6), (0, 0, 0), (0, 2, 3), | |||||
| (0, 2, 0), (0, 0, 2), (0, 6, 6), (0, 6, 4), (0, 4, 6), (0, 4, 4), | |||||
| (1, 16, 18), (1, 16, 19), (1, 16, 16), (1, 16, 17), (1, 16, 12), | |||||
| (1, 16, 13), (1, 16, 14), (1, 16, 15), (0, 4, 2), (0, 4, 0), (0, 6, 2), | |||||
| (0, 6, 0)), ((0, 2, 6), (0, 0, 4), (0, 0, 6), (0, 2, 5), (0, 0, 2), | |||||
| (0, 2, 0), (0, 2, 3), (0, 0, 0), (0, 4, 4), (0, 4, 6), (0, 6, 4), | |||||
| (0, 6, 6), (1, 16, 17), (1, 16, 16), (1, 16, 19), (1, 16, 18), | |||||
| (1, 16, 15), (1, 16, 14), (1, 16, 13), (1, 16, 12), (0, 6, 0), (0, 6, 2), | |||||
| (0, 4, 0), (0, 4, 2)), ((0, 0, 5), (0, 2, 6), (0, 2, 4), (0, 0, 6), | |||||
| (0, 2, 0), (0, 0, 3), (0, 0, 0), (0, 2, 2), (0, 4, 6), (0, 4, 4), | |||||
| (0, 6, 6), (0, 6, 4), (1, 16, 16), (1, 16, 17), (1, 16, 18), (1, 16, 19), | |||||
| (1, 16, 14), (1, 16, 15), (1, 16, 12), (1, 16, 13), (0, 6, 2), (0, 6, 0), | |||||
| (0, 4, 2), (0, 4, 0)), ((0, 0, 6), (0, 2, 4), (0, 2, 6), (0, 0, 5), | |||||
| (0, 2, 2), (0, 0, 0), (0, 0, 3), (0, 2, 0), (0, 6, 4), (0, 6, 6), | |||||
| (0, 4, 4), (0, 4, 6), (1, 16, 19), (1, 16, 18), (1, 16, 17), (1, 16, 16), | |||||
| (1, 16, 13), (1, 16, 12), (1, 16, 15), (1, 16, 14), (0, 4, 0), (0, 4, 2), | |||||
| (0, 6, 0), (0, 6, 2)), ((0, 6, 6), (0, 4, 4), (0, 4, 6), (0, 6, 5), | |||||
| (0, 4, 2), (0, 6, 0), (0, 6, 3), (0, 4, 0), (0, 2, 4), (0, 2, 6), | |||||
| (0, 0, 4), (0, 0, 6), (1, 12, 16), (1, 12, 17), (1, 12, 18), (1, 12, 19), | |||||
| (1, 12, 14), (1, 12, 15), (1, 12, 12), (1, 12, 13), (0, 0, 0), (0, 0, 2), | |||||
| (0, 2, 0), (0, 2, 2)), ((0, 6, 5), (0, 4, 6), (0, 4, 4), (0, 6, 6), | |||||
| (0, 4, 0), (0, 6, 3), (0, 6, 0), (0, 4, 2), (0, 0, 6), (0, 0, 4), | |||||
| (0, 2, 6), (0, 2, 4), (1, 12, 19), (1, 12, 18), (1, 12, 17), (1, 12, 16), | |||||
| (1, 12, 13), (1, 12, 12), (1, 12, 15), (1, 12, 14), (0, 2, 2), (0, 2, 0), | |||||
| (0, 0, 2), (0, 0, 0)), ((0, 4, 6), (0, 6, 4), (0, 6, 6), (0, 4, 5), | |||||
| (0, 6, 2), (0, 4, 0), (0, 4, 3), (0, 6, 0), (0, 0, 4), (0, 0, 6), | |||||
| (0, 2, 4), (0, 2, 6), (1, 12, 18), (1, 12, 19), (1, 12, 16), (1, 12, 17), | |||||
| (1, 12, 12), (1, 12, 13), (1, 12, 14), (1, 12, 15), (0, 2, 0), (0, 2, 2), | |||||
| (0, 0, 0), (0, 0, 2)), ((0, 4, 5), (0, 6, 6), (0, 6, 4), (0, 4, 6), | |||||
| (0, 6, 0), (0, 4, 3), (0, 4, 0), (0, 6, 2), (0, 2, 6), (0, 2, 4), | |||||
| (0, 0, 6), (0, 0, 4), (1, 12, 17), (1, 12, 16), (1, 12, 19), (1, 12, 18), | |||||
| (1, 12, 15), (1, 12, 14), (1, 12, 13), (1, 12, 12), (0, 0, 2), (0, 0, 0), | |||||
| (0, 2, 2), (0, 2, 0)), ((1, 10, 5), (1, 8, 6), (1, 8, 5), (1, 10, 6), | |||||
| (1, 8, 0), (1, 10, 3), (1, 10, 0), (1, 8, 3), (0, 4, 2), (0, 4, 0), | |||||
| (0, 6, 0), (0, 6, 2), (0, 2, 4), (0, 0, 6), (0, 2, 6), (0, 0, 4), | |||||
| (0, 0, 0), (0, 2, 2), (0, 0, 2), (0, 2, 0), (0, 6, 6), (0, 6, 4), | |||||
| (0, 4, 4), (0, 4, 6)), ((1, 10, 6), (1, 8, 5), (1, 8, 6), (1, 10, 5), | |||||
| (1, 8, 3), (1, 10, 0), (1, 10, 3), (1, 8, 0), (0, 6, 2), (0, 6, 0), | |||||
| (0, 4, 0), (0, 4, 2), (0, 0, 4), (0, 2, 6), (0, 0, 6), (0, 2, 4), | |||||
| (0, 2, 0), (0, 0, 2), (0, 2, 2), (0, 0, 0), (0, 4, 6), (0, 4, 4), | |||||
| (0, 6, 4), (0, 6, 6)), ((1, 8, 5), (1, 8, 4), (1, 8, 7), (1, 8, 6), | |||||
| (1, 8, 2), (1, 8, 3), (1, 8, 0), (1, 8, 1), (0, 6, 0), (0, 6, 2), | |||||
| (0, 4, 2), (0, 4, 0), (0, 2, 6), (0, 0, 4), (0, 2, 4), (0, 0, 6), | |||||
| (0, 0, 2), (0, 2, 0), (0, 0, 0), (0, 2, 2), (0, 4, 4), (0, 4, 6), | |||||
| (0, 6, 6), (0, 6, 4)), ((1, 8, 6), (1, 8, 7), (1, 8, 4), (1, 8, 5), | |||||
| (1, 8, 1), (1, 8, 0), (1, 8, 3), (1, 8, 2), (0, 4, 0), (0, 4, 2), | |||||
| (0, 6, 2), (0, 6, 0), (0, 0, 6), (0, 2, 4), (0, 0, 4), (0, 2, 6), | |||||
| (0, 2, 2), (0, 0, 0), (0, 2, 0), (0, 0, 2), (0, 6, 4), (0, 6, 6), | |||||
| (0, 4, 6), (0, 4, 4)))) | |||||
| cz_table = np.array(cz_table, dtype = int) | |||||
| @@ -1,92 +0,0 @@ | |||||
| import urlparse | |||||
| from BaseHTTPServer import BaseHTTPRequestHandler | |||||
| from SimpleHTTPServer import SimpleHTTPRequestHandler | |||||
| import SocketServer | |||||
| import sys | |||||
| import json | |||||
| import threading | |||||
| import time | |||||
| import os | |||||
| from graphstate import GraphState | |||||
| class VizHandler(SimpleHTTPRequestHandler): | |||||
| """ Handles requests to the server """ | |||||
| def __init__(self, *args, **kwargs): | |||||
| SimpleHTTPRequestHandler.__init__(self, *args, **kwargs) | |||||
| def get_state(self): | |||||
| """ Get the current graphstate state """ | |||||
| self.send_response(200) | |||||
| self.send_header('Content-Type', 'application/json') | |||||
| self.end_headers() | |||||
| state = self.server.state | |||||
| self.wfile.write(state.to_json()) | |||||
| def do_GET(self, *args, **kwargs): | |||||
| """ Someone belled the server """ | |||||
| parsed_path = urlparse.urlparse(self.path) | |||||
| if parsed_path.path == "/state": | |||||
| return self.get_state() | |||||
| else: | |||||
| return SimpleHTTPRequestHandler.do_GET(self, *args, **kwargs) | |||||
| class Server(SocketServer.TCPServer): | |||||
| """ Serves the good stuff """ | |||||
| allow_reuse_address = True | |||||
| def __init__(self, port=8000): | |||||
| self.port = port | |||||
| self.state = None | |||||
| SocketServer.TCPServer.__init__( | |||||
| self, ("127.0.0.1", self.port), VizHandler) | |||||
| def update(self, state): | |||||
| """ Update the in-memory state """ | |||||
| self.state = state | |||||
| def run(self): | |||||
| """ Run in such a way that keyboard interrupts are caught properly """ | |||||
| try: | |||||
| self.serve_forever() | |||||
| except KeyboardInterrupt: | |||||
| self.shutdown() | |||||
| def start(self): | |||||
| """ Start in a new thread """ | |||||
| thread = threading.Thread(None, self.run) | |||||
| thread.daemon = True | |||||
| thread.start() | |||||
| print "Server running at http://localhost:{}/".format(self.port) | |||||
| def demograph(): | |||||
| """ A graph for testing with """ | |||||
| g = GraphState() | |||||
| g.add_edge(0, 1) | |||||
| g.add_edge(1, 2) | |||||
| g.add_edge(2, 0) | |||||
| g.add_edge(0, 3) | |||||
| g.add_edge(100, 200) | |||||
| return g | |||||
| if __name__ == '__main__': | |||||
| where = os.path.join(sys.path[0], "../static") | |||||
| os.chdir(where) | |||||
| server = Server() | |||||
| server.start() | |||||
| g = demograph() | |||||
| g.layout() | |||||
| while True: | |||||
| server.update(g) | |||||
| time.sleep(1) | |||||
| server.shutdown() | |||||
| @@ -1,26 +0,0 @@ | |||||
| import networkx as nx | |||||
| from matplotlib import pyplot as plt | |||||
| import clifford | |||||
| import numpy as np | |||||
| from graphstate import GraphState | |||||
| VOP_COLORS = ["red", "green", "blue", "orange", "yellow", "purple", "black", "white"] | |||||
| def draw(state, filename="out.pdf", pos=None, ns=500): | |||||
| """ Draw a graph with networkx layout """ | |||||
| plt.clf() | |||||
| graph = nx.from_edgelist(state.edgelist()) | |||||
| pos = nx.spring_layout(graph) if pos==None else pos | |||||
| colors = [VOP_COLORS[vop % len(VOP_COLORS)] for vop in state.vops.values()] | |||||
| nx.draw_networkx_nodes(graph, pos, node_color="white", node_size=ns) | |||||
| nx.draw_networkx_nodes(graph, pos, node_color=colors, node_size=ns, alpha=.4) | |||||
| nx.draw_networkx_edges(graph, pos, edge_color="gray") | |||||
| nx.draw_networkx_labels(graph, pos, font_family="FreeSans") | |||||
| # tables.name_of(v) | |||||
| labels = {i: "no name" for i, v in state.vops.items()} | |||||
| pos = {k: v + np.array([0, -.1]) for k, v in pos.items()} | |||||
| nx.draw_networkx_labels(graph, pos, labels, font_family="FreeSans") | |||||
| plt.axis('off') | |||||
| plt.savefig(filename) | |||||
| return pos | |||||
| @@ -1,13 +0,0 @@ | |||||
| from abp.graphstate import GraphState | |||||
| from abp import viz | |||||
| def test_viz(): | |||||
| g = GraphState(range(4)+[100, 200]) | |||||
| g.add_edge(0, 1) | |||||
| g.add_edge(1, 2) | |||||
| g.add_edge(2, 0) | |||||
| g.add_edge(0, 3) | |||||
| g.add_edge(100, 200) | |||||
| # g.remove_vop(0, 1) | |||||
| viz.draw(g) | |||||