def setupWebsocket(self, status): from txws import WebSocketFactory f = Factory() f.protocol = websocketstatus.WSBuildHandler f.status = status service = strports.service(self.dashboard, WebSocketFactory(f)) service.setServiceParent(self)
def on_load(self): self.config = self.server.config.web with open('./web/js/init.js', 'w') as f: port = self.config.web_interface_port2 auth = self.config.auth_key f.write('var server_port = "%s";\n var auth_key = "%s"' % (port, auth)) root = File('./web') root.indexNames = ['index.html'] root.putChild('css', static.File("./web/css")) root.putChild('js', static.File("./web/js")) root.putChild('img', static.File("./web/img")) checker = PasswordDictChecker(self.config) realm = HttpPasswordRealm(root) p = portal.Portal(realm, [checker]) credentialFactory = DigestCredentialFactory("md5", "Cuwo Interface Login") protected_resource = HTTPAuthSessionWrapper(p, [credentialFactory]) auth_resource = resource.Resource() auth_resource.putChild("", protected_resource) site = SiteOverride(auth_resource) reactor.listenTCP(self.config.web_interface_port1, site) self.web_factory = WebFactory(self) reactor.listenTCP(self.config.web_interface_port2, WebSocketFactory(self.web_factory))
def lineReceived(self, line): log.msg("Received line %s" % line) try: d = loads(line) # Required names. host = d["daddr"] dport = d["dport"] password = d["password"] # Optional names. sport = d.get("sport") ws = d.get("ws", False) tls = d.get("tls", False) client_opts = d.get("client", {}) # Allocate the source port. sport = self.factory.allocate_port(sport) factory = VNCProxy(host, dport, password, client_opts) if ws: factory = WebSocketFactory(factory) if tls: context = DefaultOpenSSLContextFactory("keys/vncap.key", "keys/vncap.crt") listening = reactor.listenSSL(sport, factory, context) else: listening = reactor.listenTCP(sport, factory) # Set up our timeout. def timeout(): log.msg("Timed out connection on port %d" % sport) listening.stopListening() self.factory.free_port(sport) reactor.callLater(30, timeout) log.msg("New forwarder (%d->%s:%d)" % (sport, host, dport)) self.sendLine("%d" % sport) except (KeyError, ValueError): log.msg("Couldn't handle line %s" % line) self.sendLine("FAILED") except CannotListenError: # Couldn't bind the port. Don't free it, as it's probably not # available to us. log.msg("Couldn't bind port %d" % sport) self.sendLine("FAILED") self.transport.loseConnection()
def serveWS(cls, port=9999, setupFcn=None, cleanupFcn=None, durable=True, SSL=False, *args, **kwargs): # websocket server print "Listening at port %s.\n" % str(port) # build protocol try: if SSL and SSL_OK: raise NotImplementedError, "Websocket server over SSL not yet implemented." # sslFactory = ssl.DefaultOpenSSLContextFactory('D:\\cert\\server.key', 'D:\\cert\\server.crt') # listener = reactor.listenSSL(port, WebSocketFactory(WSFactory(cls, *args, **kwargs)), sslFactory) else: listener = reactor.listenTCP( port, WebSocketFactory(WSFactory(cls, durable, *args, **kwargs))) except Exception: print "Protocol not built." print traceback.format_exc() return # run setup code before starting reactor (e.g. start browser) if setupFcn is not None: setupFcn() # run reactor try: reactor.run() except Exception: print "Reactor stopped." print traceback.format_exc() time.sleep(2) reactor.stop() time.sleep(2) # run cleanup after reactor is stopped (e.g. close browser) if cleanupFcn is not None: cleanupFcn() print "Stopped listening."
def main(): """ Routing: ws://127.0.0.1:5600/bar -> BarResource ws://127.0.0.1:5600/foo/baz -> BazResource ws://127.0.0.1:5600/foo/qux -> QuxResource """ log.startLogging(stdout) root = WebSocketResource() root.putChild("bar", BarResource()) foo = WebSocketResource() root.putChild("foo", foo) foo.putChild("baz", BazResource()) foo.putChild("qux", QuxResource()) reactor.listenTCP(5600, WebSocketFactory(root)) reactor.run()
from twisted.python import log from sys import stdout log.startLogging(stdout) from twisted.internet.protocol import Protocol, Factory class EchoProtocol(Protocol): def dataReceived(self, data): self.transport.write(data) class EchoFactory(Factory): protocol = EchoProtocol from txws import WebSocketFactory from twisted.application.strports import listen port = listen("tcp:5600", WebSocketFactory(EchoFactory())) from twisted.internet import reactor reactor.run()
""" Utility function that the client can use to shutdown the server. """ connector.stopListening() try: reactor.stop() except: pass print "DISCONNECTED" class VSFactory(protocol.Factory): def buildProtocol(self, addr): return VS() if __name__ == '__main__': try: ip_addr, port = "127.0.0.1", 9001 device = None print "LISTENING AT %s:%s" % (ip_addr, port) connector = reactor.listenTCP(port, WebSocketFactory(VSFactory())) reactor.run() except Exception as e: print traceback.format_exc()
def __init_websocket_server(self): from moksha.hub.reactor import reactor if self.config.get('moksha.livesocket.backend', 'amqp') != 'websocket': return log.info("Enabling websocket server") port = int(self.config.get('moksha.livesocket.websocket.port', 0)) if not port: raise ValueError("websocket is backend, but no port set") interface = self.config.get('moksha.livesocket.websocket.interface') interface = interface or '' class RelayProtocol(protocol.Protocol): moksha_hub = self def dataReceived(self, data): """ Messages sent from the browser arrive here. This hook: 1) Acts on any special control messages 2) Forwards messages onto the zeromq hub """ try: json = JSON.loads(data) if json['topic'] == '__topic_subscribe__': # If this is a custom control message, then subscribe. def send_to_websocket(zmq_message): """ Callback. Sends a message to the browser """ msg = JSON.dumps({ 'topic': zmq_message.topic, 'body': JSON.loads(zmq_message.body), }) self.transport.write(msg) _topic = json['body'] log.info("Websocket subscribing to %r." % _topic) self.moksha_hub.subscribe( _topic, send_to_websocket, ) else: # FIXME - The following is disabled temporarily until # we can devise a secure method of "firewalling" where # messages can and can't go. See the following for # more info: # https://fedorahosted.org/moksha/ticket/245 # https://github.com/gregjurman/zmqfirewall key = 'moksha.livesocket.websocket.client2server' if asbool(self.moksha_hub.config.get(key, False)): # Simply forward on the message through the hub. self.moksha_hub.send_message( json['topic'], json['body'], ) except Exception as e: import traceback log.error(traceback.format_exc()) class RelayFactory(protocol.Factory): def buildProtocol(self, addr): return RelayProtocol() self.websocket_server = reactor.listenTCP( port, WebSocketFactory(RelayFactory()), interface=interface, ) log.info("Websocket server set to run on port %r" % port)
from twisted.internet.reactor import listenTCP, run from twisted.internet.protocol import Protocol, Factory from txws import WebSocketFactory from prefork import prefork, cpu_count class Echo(Protocol): def dataReceived(self, data): self.transport.write(data) class EchoFactory(Factory): def buildProtocol(self, addr): return Echo() if __name__ == "__main__": listenTCP(8000, WebSocketFactory(EchoFactory()), backlog=768) num = cpu_count() print "Twisted + txWS (%s workers)" % num if prefork(num): exit() run()
def websocket(): factory = protocol.ServerFactory() factory.protocol = Sub reactor.listenTCP(6666, factory) reactor.listenTCP(9898, WebSocketFactory(factory)) reactor.run()
from atom.ws import WSRouterFactory from atom.web import MainElement app = Klein() @app.route('/') def home(request, name=''): return MainElement(name) @app.route('/static/', branch=True) def static(request): return File("./static") from txws import WebSocketFactory from twisted.internet import reactor wsFactory = WSRouterFactory() usbClient = USBRouterProtocol() reactor.listenTCP(5600, WebSocketFactory(wsFactory)) SerialPort(usbClient, '/dev/ttyUSB0', reactor, baudrate='9600') wsFactory.setSrcClients(usbClient.getClients()) resource = app.resource
#!/usr/bin/python from twisted.internet import protocol, reactor from txws import WebSocketFactory import socket class Echo(protocol.Protocol): def dataReceived(self, data): #global s print data #s.send(data) class EchoFactory(protocol.Factory): def buildProtocol(self, addr): return Echo() #global s #s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #s.connect(("witestlab.poly.edu", 3003)) reactor.listenTCP(9080, WebSocketFactory(EchoFactory())) reactor.run()
def dataReceived(self, data): if data == 'whoami': self.transport.write('{"host": "'+hostname+'"}'); elif data == 'gimmiescripts': codeToSend = open('JS/Padside.js','r').read(); self.transport.write(codeToSend); else: global instructionBuffer datadict = eval(data) if datadict['mode'] == 'read': for instruction in instructionBuffer: self.transport.write('{"update":'+str(instruction).replace("'",'"')+'}') instructionBuffer = [] if datadict['mode'] == 'update': print data del datadict['mode'] instructionBuffer += [datadict] class Factory(protocol.Factory): def buildProtocol(self, addr): return Replier() reactor.listenTCP(8080, WebSocketFactory(Factory())) reactor.run()
topik = dict_pesan["topik"] if topik in subs: subs[topik].append(self) else: subs[topik] = [] subs[topik].append(self) for cl in clients: cl.transport.write("OK") if tipe == "PUB": pesan = dict_pesan["pesan"][0] topik = dict_pesan["topik"][0] if topik in subs: list_subs = subs[topik] for cl in list_subs: cl.transport.write(pesan) else: for cl in clients: cl.transport.write("ERROR") for cl in clients: cl.transport.write("OK") class EchoFactory(protocol.Factory): def buildProtocol(self, address): return EchoServer() factory = EchoFactory() reactor.listenTCP(8002, WebSocketFactory(factory)) reactor.run()
root = Stuff("web") application = service.Application('web-ui') site = server.Site(root) sc = service.IServiceCollection(application) i = internet.TCPServer(80, site) proto = MonitorFactory() def intr(which): threads.deferToThread(hardware.check).addCallback(intr) for target in which: for client in list(proto.clients): client.send(cmd='int', target=target) for client in list(matlab.clients): client.intr(target) for client in list(matlabasync.clients): client.intr(target) intr(()) w = internet.TCPServer(8080, WebSocketFactory(proto)) matlab = MatlabFactory() m = internet.TCPServer(8000, matlab) matlabasync = MatlabAsyncFactory() ma = internet.TCPServer(8001, matlabasync) m.setServiceParent(sc) ma.setServiceParent(sc) i.setServiceParent(sc) w.setServiceParent(sc)
return if socket in self._sockets[socket_type][socket_id]: self._sockets[socket_type][socket_id].remove(socket) if socket_id in self._sockets[socket_type]\ and len(self._sockets[socket_type][socket_id]) == 0: del self._sockets[socket_type][socket_id] @property def sockets(self): return self._sockets def emit(self, socket_type, session_id, emmission, msg, token=None, bit_ac=None, bit={}, omit=[]): log.msg('bit.bot.http.socket: Sockets.emit') if not session_id in self.sockets[socket_type]: return for socket in self.sockets[socket_type][session_id]: if bit_ac: socket.transport.write(json.dumps(dict(emit={emmission: msg}, bit=bit, token=bit_ac, ))) else: socket.transport.write(json.dumps(dict(emit={emmission: msg}, bit=bit ))) WebBotSocketFactory = lambda: WebSocketFactory(BotSocketFactory()) sockets = Sockets()
def connectionLost(self, reason): self.pp.transport.loseConnection() def _send(self, data): self.transport.write(data) class ProcessProtocol(protocol.ProcessProtocol): def connectionMade(self): log.msg("connectionMade") log.msg("processExited") def processEnded(self, reason): log.msg("processEnded") def _sendback(self, data): self.factory._send(data) application = service.Application("ws-cli") _echofactory = protocol.Factory() _echofactory.protocol = Protocol strports.service("tcp:8076:interface=127.0.0.1", WebSocketFactory(_echofactory)).setServiceParent(application) resource = File('.') strports.service("tcp:8080:interface=127.0.0.1", Site(resource)).setServiceParent(application)
class ClientProtocol(protocol.Protocol): def __init__(self, factory): self.factory = factory def dataReceived(self, data): self.factory.sendMessage(data) def connectionLost(self, reason): self.factory.clients.remove(self) def connectionMade(self): self.factory.clients.add(self) class ClientFactory(protocol.Factory): def __init__(self): self.clients = set() def buildProtocol(self, addr): return ClientProtocol(self) def sendMessage(self, message): for client in self.clients: client.transport.write(message) endpoints.serverFromString(reactor, "tcp:9998").listen( WebSocketFactory(ClientFactory())) reactor.run()
def run(*args): TESTNET = args[0] LOGLEVEL = args[1] PORT = args[2] ALLOWIP = args[3] RESTPORT = args[4] WSPORT = args[5] HEARTBEATPORT = args[6] def start_server(keys, first_startup=False): # logging logFile = logfile.LogFile.fromFullPath(os.path.join( DATA_FOLDER, "debug.log"), rotateLength=15000000, maxRotatedFiles=1) log.addObserver(FileLogObserver(logFile, level=LOGLEVEL).emit) log.addObserver(FileLogObserver(level=LOGLEVEL).emit) logger = Logger(system="OpenBazaard") # NAT traversal p = PortMapper() p.add_port_mapping(PORT, PORT, "UDP") logger.info("Finding NAT Type...") response = looping_retry(stun.get_ip_info, "0.0.0.0", PORT) logger.info("%s on %s:%s" % (response[0], response[1], response[2])) ip_address = response[1] port = response[2] if response[0] == "Full Cone": nat_type = FULL_CONE elif response[0] == "Restric NAT": nat_type = RESTRICTED else: nat_type = SYMMETRIC def on_bootstrap_complete(resp): logger.info("bootstrap complete") task.LoopingCall(mserver.get_messages, mlistener).start(3600) task.LoopingCall(check_unfunded_for_payment, db, libbitcoin_client, nlistener, TESTNET).start(600) task.LoopingCall(rebroadcast_unconfirmed, db, libbitcoin_client, TESTNET).start(600) protocol = OpenBazaarProtocol( db, (ip_address, port), nat_type, testnet=TESTNET, relaying=True if nat_type == FULL_CONE else False) # kademlia SEED_URLS = SEEDS_TESTNET if TESTNET else SEEDS relay_node = None if nat_type != FULL_CONE: for seed in SEED_URLS: try: relay_node = (socket.gethostbyname(seed[0].split(":")[0]), 28469 if TESTNET else 18469) break except socket.gaierror: pass try: kserver = Server.loadState( os.path.join(DATA_FOLDER, 'cache.pickle'), ip_address, port, protocol, db, nat_type, relay_node, on_bootstrap_complete, storage) except Exception: node = Node(keys.guid, ip_address, port, keys.verify_key.encode(), relay_node, nat_type, Profile(db).get().vendor) protocol.relay_node = node.relay_node kserver = Server(node, db, keys.signing_key, KSIZE, ALPHA, storage=storage) kserver.protocol.connect_multiplexer(protocol) kserver.bootstrap(kserver.querySeed(SEED_URLS)).addCallback( on_bootstrap_complete) kserver.saveStateRegularly(os.path.join(DATA_FOLDER, 'cache.pickle'), 10) protocol.register_processor(kserver.protocol) # market mserver = network.Server(kserver, keys.signing_key, db) mserver.protocol.connect_multiplexer(protocol) protocol.register_processor(mserver.protocol) looping_retry(reactor.listenUDP, port, protocol) interface = "0.0.0.0" if ALLOWIP != ["127.0.0.1"] else "127.0.0.1" # websockets api authenticated_sessions = [] ws_api = WSFactory(mserver, kserver, only_ip=ALLOWIP) ws_factory = AuthenticatedWebSocketFactory(ws_api) ws_factory.authenticated_sessions = authenticated_sessions ws_factory.protocol = AuthenticatedWebSocketProtocol if SSL: reactor.listenSSL(WSPORT, ws_factory, ChainedOpenSSLContextFactory(SSL_KEY, SSL_CERT), interface=interface) else: reactor.listenTCP(WSPORT, ws_factory, interface=interface) # rest api rest_api = RestAPI(mserver, kserver, protocol, username, password, authenticated_sessions, only_ip=ALLOWIP) if SSL: reactor.listenSSL(RESTPORT, rest_api, ChainedOpenSSLContextFactory(SSL_KEY, SSL_CERT), interface=interface) else: reactor.listenTCP(RESTPORT, rest_api, interface=interface) # blockchain if TESTNET: libbitcoin_client = LibbitcoinClient( LIBBITCOIN_SERVERS_TESTNET, log=Logger(service="LibbitcoinClient")) else: libbitcoin_client = LibbitcoinClient( LIBBITCOIN_SERVERS, log=Logger(service="LibbitcoinClient")) heartbeat_server.libbitcoin = libbitcoin_client # listeners nlistener = NotificationListenerImpl(ws_api, db) mserver.protocol.add_listener(nlistener) mlistener = MessageListenerImpl(ws_api, db) mserver.protocol.add_listener(mlistener) blistener = BroadcastListenerImpl(ws_api, db) mserver.protocol.add_listener(blistener) protocol.set_servers(ws_api, libbitcoin_client) if first_startup: heartbeat_server.push( json.dumps({ "status": "GUID generation complete", "username": username, "password": password })) heartbeat_server.set_status("online") logger.info("startup took %s seconds" % str(round(time.time() - args[7], 2))) def shutdown(): logger.info("shutting down server") for vendor in protocol.vendors.values(): db.vendors.save_vendor(vendor.id.encode("hex"), vendor.getProto().SerializeToString()) PortMapper().clean_my_mappings(PORT) protocol.shutdown() reactor.addSystemEventTrigger('before', 'shutdown', shutdown) # database db = Database(TESTNET) storage = ForgetfulStorage() # client authentication username, password = get_credentials(db) # heartbeat server interface = "0.0.0.0" if ALLOWIP != ["127.0.0.1"] else "127.0.0.1" heartbeat_server = HeartbeatFactory(only_ip=ALLOWIP) if SSL: reactor.listenSSL(HEARTBEATPORT, WebSocketFactory(heartbeat_server), ChainedOpenSSLContextFactory(SSL_KEY, SSL_CERT), interface=interface) else: reactor.listenTCP(HEARTBEATPORT, WebSocketFactory(heartbeat_server), interface=interface) btcPrice = BtcPrice() btcPrice.start() # key generation KeyChain(db, start_server, heartbeat_server) reactor.run() btcPrice.closethread() btcPrice.join(1)
def run(*args): TESTNET = args[0] LOGLEVEL = args[1] PORT = args[2] ALLOWIP = args[3] SSL = args[4] RESTPORT = args[5] WSPORT = args[6] # database db = Database(TESTNET) # key generation keys = KeyChain(db) # logging logFile = logfile.LogFile.fromFullPath(DATA_FOLDER + "debug.log", rotateLength=15000000, maxRotatedFiles=1) log.addObserver(FileLogObserver(logFile, level=LOGLEVEL).emit) log.addObserver(FileLogObserver(level=LOGLEVEL).emit) logger = Logger(system="OpenBazaard") # NAT traversal p = PortMapper() p.add_port_mapping(PORT, PORT, "UDP") logger.info("Finding NAT Type...") response = looping_retry(stun.get_ip_info, "0.0.0.0", PORT) logger.info("%s on %s:%s" % (response[0], response[1], response[2])) ip_address = response[1] port = response[2] if response[0] == "Full Cone": nat_type = FULL_CONE elif response[0] == "Restric NAT": nat_type = RESTRICTED else: nat_type = SYMMETRIC def on_bootstrap_complete(resp): logger.info("bootstrap complete") mserver.get_messages(mlistener) task.LoopingCall(check_unfunded_for_payment, db, libbitcoin_client, nlistener, TESTNET).start(600) protocol = OpenBazaarProtocol( (ip_address, port), nat_type, testnet=TESTNET, relaying=True if nat_type == FULL_CONE else False) # kademlia storage = ForgetfulStorage() if TESTNET else PersistentStorage( db.get_database_path()) relay_node = None if nat_type != FULL_CONE: for seed in SEEDS: try: relay_node = (socket.gethostbyname(seed[0].split(":")[0]), 28469 if TESTNET else 18469) break except socket.gaierror: pass try: kserver = Server.loadState(DATA_FOLDER + 'cache.pickle', ip_address, port, protocol, db, nat_type, relay_node, on_bootstrap_complete, storage) except Exception: node = Node(keys.guid, ip_address, port, keys.verify_key.encode(), relay_node, nat_type, Profile(db).get().vendor) protocol.relay_node = node.relay_node kserver = Server(node, db, keys.signing_key, KSIZE, ALPHA, storage=storage) kserver.protocol.connect_multiplexer(protocol) kserver.bootstrap( kserver.querySeed(SEEDS)).addCallback(on_bootstrap_complete) kserver.saveStateRegularly(DATA_FOLDER + 'cache.pickle', 10) protocol.register_processor(kserver.protocol) # market mserver = network.Server(kserver, keys.signing_key, db) mserver.protocol.connect_multiplexer(protocol) protocol.register_processor(mserver.protocol) looping_retry(reactor.listenUDP, port, protocol) interface = "0.0.0.0" if ALLOWIP not in ("127.0.0.1", "0.0.0.0") else ALLOWIP # websockets api ws_api = WSFactory(mserver, kserver, only_ip=ALLOWIP) if SSL: reactor.listenSSL(WSPORT, WebSocketFactory(ws_api), ChainedOpenSSLContextFactory(SSL_KEY, SSL_CERT), interface=interface) else: reactor.listenTCP(WSPORT, WebSocketFactory(ws_api), interface=interface) # rest api rest_api = RestAPI(mserver, kserver, protocol, only_ip=ALLOWIP) if SSL: reactor.listenSSL(RESTPORT, rest_api, ChainedOpenSSLContextFactory(SSL_KEY, SSL_CERT), interface=interface) else: reactor.listenTCP(RESTPORT, rest_api, interface=interface) # blockchain if TESTNET: libbitcoin_client = LibbitcoinClient( LIBBITCOIN_SERVER_TESTNET, log=Logger(service="LibbitcoinClient")) else: libbitcoin_client = LibbitcoinClient( LIBBITCOIN_SERVER, log=Logger(service="LibbitcoinClient")) # listeners nlistener = NotificationListenerImpl(ws_api, db) mserver.protocol.add_listener(nlistener) mlistener = MessageListenerImpl(ws_api, db) mserver.protocol.add_listener(mlistener) blistener = BroadcastListenerImpl(ws_api, db) mserver.protocol.add_listener(blistener) protocol.set_servers(ws_api, libbitcoin_client) logger.info("Startup took %s seconds" % str(round(time.time() - args[7], 2))) reactor.run()
protocol = WSProtocol class PbConnection( pb.Referenceable ): def __init__( self, client, data ): controllers[ data['id'] ] = self self.controller = data self.client = client def remote_data( self, data ): for device in data['devices']: for prop in data['devices'][device]: self.controller['devices'][device][prop] = data['devices'][device][prop] class PbServer( pb.Root ): def remote_connect( self, client, data ): pbc = PbConnection( client, data ) print "pb client connected" return pbc #d = json.loads( data ) #client.callRemote( "cmd", { "cmd": "set", "state": 1 } ) siteRoot = static.File(conf['site']['root']) reactor.listenTCP( conf['site']['port'], server.Site( siteRoot ) ) reactor.listenTCP( conf['pb']['port'], pb.PBServerFactory( PbServer() ) ) reactor.listenTCP( conf['ws']['port'], WebSocketFactory( WSFactory() ) ) pingCall = task.LoopingCall( sendIds ) pingCall.start( 5 ) reactor.run()
dict_subs[topik].append(self) # Tambahkan key 'stataus' dan value 'succecs' ke dict_data dict_data['status'] = 'success' # Encode dict_data pada var data data = json.dumps(dict_data) # Kirim data ke subscriber sebagai notifikasi sukses self.transport.write(data) elif dict_data['id'] == 'pub': topik = dict_data['topik'] pesan = dict_data['pesan'] # Jika topik ada di dict_subs if topik in dict_subs: list_subs = dict_subs[topik] # Buat dictionary data yang akan dikirim, data = {'topik': topik, 'pesan': pesan} # Kirimkan ke semua subscriber dengan topik tersebut for sub in list_subs: str_data = json.dumps(data) sub.transport.write(str_data) class EchoFactory(protocol.Factory): def buildProtocol(self, address): return EchoServer() factory = EchoFactory() reactor.listenTCP(8877, WebSocketFactory(factory)) reactor.run()
self.broadcast('user_joined', {'handle': self.handle, 'id': self.id}) def connectionLost(self, reason): params = {'handle': self.handle, 'id': self.id} self.factory.remove(self) self.broadcast('user_left', params) class ChatterFactory(protocol.Factory): chatters = [] next_id = 0 def buildProtocol(self, addr): self.next_id += 1 chatter = Chatter(self, self.next_id) self.chatters.append(chatter) return chatter def broadcast(self, message): for chatter in self.chatters: chatter._write(message) def remove(self, chatter): self.chatters.remove(chatter) print("Starting reactor...") reactor.listenTCP(PORT, WebSocketFactory(ChatterFactory())) print("Listening on port %d..." % PORT) reactor.run()