class client(): def __init__(self): self.ws = WebSocket() def __enter__(self): self.ws.connect(WS_PATH) return self def __exit__(self, *exc): self.ws.close() def send(self, commands): list(map(self.ws.send, commands)) def daylight(self, level): self.send(dimmer(level)) self.send(led(level, 1, 0.75, 0.5)) def house(self, level): self.send(dimmer(level * 0.2)) self.send(led(level * 0.4, 1, 0.25, 0.02)) def flash(self): self.send(dimmer(0)) self.send(led(1, 1, 1, 1)) time.sleep(0.1) self.send(led(0, 0, 0, 0)) def end(self, level): self.send(dimmer(0)) self.send(led(level * .5, 0, 0, 1)) def blackout(self): self.send(dimmer(0)) self.send(led(0, 0, 0, 0))
class TestAuthentication(TestCase): def setUp(self): self.ws = WebSocket(sslopt={'check_hostname': False}) self.ws.connect(url='wss://sim.smogon.com/showdown/websocket') msg = '' while not msg.startswith('|challstr|'): msg = self.ws.recv() self.challstr = msg[msg.find('|challstr|') + len('|challstr|'):] self.ws.settimeout(.5) def test_auth_temp_user(self): username = generate_username() assertion = auth_temp_user(self.challstr, username) login_cmd = f'|/trn {username},0,{assertion}' self.ws.send(login_cmd) self._username_in_msg(username) def test_login(self): with open('ts_auth.txt', 'r') as file: username, password = file.read().splitlines() assertion = login(self.challstr, username, password) login_cmd = f'|/trn {username},0,{assertion}' self.ws.send(login_cmd) self._username_in_msg(username) def _username_in_msg(self, username): msg = '' while not msg.startswith('|updateuser|'): msg = self.ws.recv() self.assertIn(username, msg) def tearDown(self): self.ws.close()
class WSS: url: str = settings.WEB_SOCKET_SERVER wss: WebSocket = field(init=False) def __post_init__(self): self.wss = WebSocket() def connect(self): self.wss.connect(self.url) message = "Открываем соединение с Web Socket Server" logger.debug(message) self.wss.send(message) def publish(self, message: str, is_mute=False) -> None: is_test = settings.TEST is False is_debug = settings.DEBUG is False is_wss_mute = is_mute is False if is_test and is_debug and is_wss_mute: if self.wss.sock is None: self.connect() self.wss.send(message) def close(self): try: message = "Закрываем соеденение с Web Socket Server" self.wss.send(message) logger.debug(message) self.wss.close() except WebSocketConnectionClosedException: pass
class Slack(object): """Simple class which just allows sending of messages via Slack""" base_url = "https://slack.com/api/" def __init__(self, token=irakli_is_bad): self.token = token response = requests.get(Slack.base_url + 'rtm.start', params={"token": token}) body = response.json() self.channels = {c["name"]: c for c in chain(body["channels"], body["groups"])} url = body["url"] self.socket = WebSocket() self.socket.connect(url) self.socket.settimeout(5) self.message_id = 0 def send_message(self, channel_name, text): """Send a message TODO:? Verify success """ message = json.dumps({"id": self.message_id, "type": "message", "channel": self.channels[channel_name]["id"], "text": text}) self.message_id += 1 self.socket.send(message) def close(self): self.socket.close()
class RPANChat: def __init__(self, user_agent: str): self._header = {'User-Agent': user_agent} self._websocket = WebSocket() def __iter__(self): while True: try: comment_data = self._websocket.recv() except WebSocketConnectionClosedException: return comment_json = json.loads(comment_data) if comment_json['type'] != 'new_comment': continue payload = comment_json['payload'] author = payload['author'] body = payload['body'] created_utc = payload['created_utc'] id = payload['_id36'] yield RPANComment(author, body, created_utc, id) def connect(self, stream_id: str) -> None: strapi_request = requests.get( f'https://strapi.reddit.com/videos/t3_{stream_id}', headers=self._header) if strapi_request.status_code != 200: raise ConnectionError stream_json = strapi_request.json() live_comments_websocket = stream_json['data']['post'][ 'liveCommentsWebsocket'] self._websocket.connect(live_comments_websocket, header=self._header) def disconnect(self) -> None: self._websocket.close()
def send_transaction(self, message: ExonumMessage) -> str: """ Sends a transaction into an Exonum node via WebSocket. Example: >>> response = client.send_websocket_transaction(message) >>> print(response) {"result":"success","response":{"tx_hash":"48b7d71d388f3c2dfa665bcf837e1fa0417ca559fb0163533ea72de6319e61ca"}} Parameters ---------- message: ExonumMessage Prepared and signed an Exonum message. Returns ------- result: str Result of the WebSocket request. If a transaction is correct and it is accepted, it will contain a JSON with a hash of the transaction. """ body_raw = message.signed_raw() if body_raw is None: logger.critical("Attempt to send an unsigned message through websocket.") raise RuntimeError("Attempt to send an unsigned message.") data = json.dumps({"type": "transaction", "payload": {"tx_body": body_raw.hex()}}) ws_client = WebSocket() ws_client.connect(self._address) ws_client.send(data) response = ws_client.recv() ws_client.close() return response
def proxy_socket(ws, path): # create connection to the remote: keep_headers = ['cookie'] request_headers = { name: value for (name, value) in request.headers.items() if name.lower() in keep_headers } pws = WebSocket(enable_multithread=True) pws.connect(f"ws://{SITE_NAME}flexx/ws/{path}", header=request_headers) # start remote handler: remote_handler_thread = threading.Thread(target=remote_handler, args=(ws, pws)) remote_handler_thread.start() # pws = create_connection(f"ws://{SITE_NAME}flexx/{request.full_path}", header=request_headers, class_=MyWebSocket) while not ws.closed: message = ws.receive() if isinstance(message, (bytearray, bytes)): opcode = ABNF.OPCODE_BINARY elif isinstance(message, str): opcode = ABNF.OPCODE_TEXT elif message is None: assert ws.closed break else: raise ValueError('Unknown message type') pws.send(message, opcode=opcode) pws.close() return
def send_message(msg_type, data): panel_config = load_config() ws = WebSocket() ws.connect("ws://" + panel_config['uri'][0] + "/core") message = '{"type": "' + msg_type + '", "data":' + data + '}' ws.send(message) ws.recv() ws.close()
class WebSocketApp(object): """ Higher level of APIs are provided. The interface is like JavaScript WebSocket object. """ def __init__(self, url, on_open = None, on_message = None, on_error = None, on_close = None, symbol='btc_cny'): """ url: websocket url. on_open: callable object which is called at opening websocket. this function has one argument. The arugment is this class object. on_message: callbale object which is called when recieved data. on_message has 2 arguments. The 1st arugment is this class object. The passing 2nd arugment is utf-8 string which we get from the server. on_error: callable object which is called when we get error. on_error has 2 arguments. The 1st arugment is this class object. The passing 2nd arugment is exception object. on_close: callable object which is called when closed the connection. this function has one argument. The arugment is this class object. """ self.url = url self.sock = WebSocket() self.sock.connect(self.url) self.symbol = ''.join(symbol.split('_')) self.send("{'event':'addChannel','channel':'ok_%s_depth'}" % self.symbol) def send(self, data): """ send message. data must be utf-8 string or unicode. """ self.sock.send(data) def close(self): """ close websocket connection. """ self.sock.close() def depth(self, symbol='btc_cny'): try: data = self.sock.recv() resp = json.loads(data) return resp[0]['data'] except Exception as e: logging.info("except[%s]" % e) def _run_with_no_err(self, callback, *args): if callback: try: callback(self, *args) except Exception as e: if logger.isEnabledFor(logging.DEBUG): logger.error(e)
def test_socket(self): mock_socket = MockSocket() c = WebSocket('ws://localhost:1234/', MockSocketFactory(mock_socket)) c.connect() c.send("Rock it with HTML5 WebSocket") msg = c.receive() c.close() print(msg)
def pi_boot_fn(): def my_msg_handler(msg): print 'Got "%s"!' % msg socket = WebSocket('ws://localhost:8888/enginebus/were', onmessage=my_msg_handler) socket.onopen = lambda: socket.send('Hello world!') try: asyncore.loop() except KeyboardInterrupt: socket.close()
class Client(): _instance = None @staticmethod def Get(): if Client._instance is None: Client._instance = Client() return Client._instance def __init__(self): self.socket = WebSocket() self.userId = random.randint(0, 65536) def Start(self): import configReader serverIp = configReader.ConfigReader.GetVariable('SERVER_IP') serverPort = configReader.ConfigReader.GetVariable('PORT') self.socket.connect('ws://' + serverIp + ':' + serverPort + '/') messageData = {'user_id' : self.userId} message = '[playerJoined, ' + json.dumps(messageData) + ']' self.socket.send(message) engine.Engine.Get().Start() self.Close() def GetMessage(self): messageData = self.socket.recv() return json.loads(messageData) def SendPlayerMovedMessage(self, factor): messageData = {'user_id' : self.userId, 'factor' : factor} message = '[playerMoved, ' + json.dumps(messageData) + ']' self.socket.send(message) def SendPlayerTurnedMessage(self, factor): messageData = {'user_id' : self.userId, 'factor' : factor} message = '[playerTurned, ' + json.dumps(messageData) + ']' self.socket.send(message) def SendPlayerFiredMessage(self): messageData = {'user_id' : self.userId} message = '[playerFired, ' + json.dumps(messageData) + ']' self.socket.send(message) def Close(self): self.socket.close()
class Gateway: def __init__(self, url): self.url = url self.ws = WebSocket() self.close_reason = None self.limiter = GatewayRateLimiter() def __iter__(self): try: self.ws.connect(self.url) except WebSocketError as e: logger.debug("Exception connecting to gateway.", exc_info=True) self.close_reason = CloseReason.exception(e) while self.ws.connected: try: with self.ws.readlock: opcode, data = self.ws.recv_data() except WebSocketError as e: logger.debug("Exception receiving gateway data.", exc_info=True) self.close_reason = CloseReason.exception(e) break if data and opcode == ABNF.OPCODE_CLOSE: self.close_reason = CloseReason.parse(data) break if data and opcode == ABNF.OPCODE_TEXT: decoded_data = data.decode("utf-8") logger.debug("Gateway payload received: %s", decoded_data) yield JsonObject(json.loads(decoded_data)) logger.info("Gateway Closed: %s", self.close_reason) def send(self, data): self.limiter.on_send() payload = json.dumps(data) logger.debug("Gateway payload sent: %s", payload) try: self.ws.send(payload) except WebSocketError: logger.debug("Error sending payload.", exc_info=True) raise NetworkError def close(self, status=1000): # An error is output be websocket-client for non-1000 statuses. # During normal operation we use non-1000 statuses and don't want an error logged. with suppress_logging("websocket"): self.ws.close(status=status)
class client(object): stopping = False greenlets = None def __init__(self, args, url): self.args = args self.tuntap = tuntap.tuntap(args.tuntap) self.ws = WebSocket() self.ws.connect(url) self.greenlets = [ gevent.spawn(self.read_ws), gevent.spawn(self.read_fd) ] def read_fd(self): while not self.stopping: try: msg = os.tp_read(self.tuntap.fd, 1500) if not self.ws.connected: break if not msg: self.stopping = True self.ws.close() break except IOError: break self.ws.send_binary(msg) def read_ws(self): while not self.stopping: try: msg = self.ws.recv() if not msg: break except websocket.WebSocketConnectionClosedException: self.stopping = True self.greenlets[1].kill() break except: continue os.tp_write(self.tuntap.fd, bytes(msg)) def join(self): gevent.joinall(self.greenlets)
def listen_and_forward_to_websocket(client: socket, ws: websocket.WebSocket): message = ' ' while message: # log.info(client) message = client.recv(pw.tcp_bufsize) if message: # log.info(type(message)) try: ws.send_binary(message) except: pass else: shutdown_socket(client) try: ws.close() except: pass break
class WSTunnel: def __init__(self, *args, **kwargs): self.ws = WebSocket(*args, **kwargs) def send(self, data): return self.ws.send_binary(data) def recv(self): return self.ws.recv() def connect(self, *args, **kwargs): self.ws.connect(*args, **kwargs) def up(self): pass def down(self): self.ws.close()
def callback(self, instance, value): print('O switch', instance, 'is', value) app = App.get_running_app() client = WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE}) try: app.start(1000, 0) client.connect(address.ADDRESS_WEBSOCKET) time.sleep(5) client.send(app.gps_location + "\n" + app.username) except Exception as e: print(e) finally: app.stop() client.close() value = False
class Gateway: def __init__(self, url): self.url = url self.ws = WebSocket() def __iter__(self): self.ws.connect(self.url) for data in self.ws: if data: yield data if not self.ws.connected: break def send(self, data): self.ws.send(data) def close(self): self.ws.close()
def reset_timer(ws: websocket.WebSocket) -> None: # reset the keep alive timeout daemon thread global timeout_timer global timeout_interval if timeout_timer: timeout_timer.cancel() timeout_timer = threading.Timer(timeout_interval, lambda: ws.close()) timeout_timer.daemon = True timeout_timer.start()
class UDPLikeWebSocketClient: def __init__(self, url) -> None: self.ws = WebSocket() self.url = url def try_to_connect(self): try: self.ws.connect(url=self.url) except ConnectionRefusedError: pass def try_to_send(self, d): try: self.ws.send(extend_dumps(d)) except BrokenPipeError: self.ws.close() def silent_send(self, channel, msg): if not self.ws.connected: self.try_to_connect() if not self.ws.connected: return self.try_to_send(dict(msg=msg, channel=channel))
def test_websocket(app: Flask, aio: AioHTTP): """Test for websocket""" @app.route('/echo') @websocket def echo(): while True: msg = yield from aio.ws.receive_msg() if msg.tp == aiohttp.MsgType.text: aio.ws.send_str(msg.data) elif msg.tp == aiohttp.MsgType.close: break elif msg.tp == aiohttp.MsgType.error: break with Server(app, aio) as server: ws = WebSocket() ws.connect(server.ws_url('/echo')) try: ws.send('foo') assert 'foo' == ws.recv() finally: ws.close()
class WebSocketThread(StoppableThread): """Base class for running WebSocket connection. It has .do_heartbeat, .init_connection, .cleanup method to be overriden by inherited client, for defining desired behaviour depending on clients. This class inherits from Thread, and is running as a separate thread. To start the client, you have to invoke .start method as you would with typical threads. Attributes: url: URL of the gateway for this client to connect to. dispatcher: Handler to be called when the event has been received. It should recieve a single argument with type of dict. ready_to_run: Event object indicating if the event is ready to be used. This event must be set manually by the inherited class. _sock: internal WebSocket object to be used to communicate with gateway. heartbeat_thread: Thread where .do_heartbeat method runs. This thread runs throughout the lifetime of this thread, so .do_heartbeat should be written with continuability in mind. init_thread: Thread where init_thread method runs. It runs in thread so that ._event_loop method could run parellelly. This thread is expected to run quick and quit shortly after. """ def __init__(self, url, dispatcher, name): """ Args: url: same as .url attribute dispatcher: same as .dispatcher attribute name: same as name argument in threading.Thread """ super(WebSocketThread, self).__init__() self.url = url self.dispatcher = dispatcher self.ready_to_run = Event() self.name = str(name) self._sock = None self.heartbeat_thread = None self.init_thread = None def run(self): """Start the heartbeat and run _event_loop in a loop until .stop calls. heartbeat_thread, init_thread gets created in this method, as well as .cleanup method which gets called after the socket disconnects. Since the connection restarts after the socket has been disconnected, if a problem occurs from eg. heartbeat thread or init thread, you can call ._sock.stop method to stop the socket and reconnect. """ self._sock = WebSocket(enable_multithread=True, skip_utf8_validation=True) self.run_heartbeat() while True: logger.info("Connecting to Gateway...") try: self._sock.connect(self.url) except Exception: logger.exception("Failed to connect to Gateway.") continue self.run_init_connection() self._event_loop() logger.warning("Gateway connection is lost!") self.ready_to_run.clear() try: self.cleanup() except Exception: logger.exception("Exception occured while cleaning up.") if self.stop_flag.is_set(): break else: time.sleep(random.randint(1, 5)) logger.info("Stopping thread...") self.heartbeat_thread.stop() self.ready_to_run.clear() def run_heartbeat(self): logger.info("Starting heartbeat thread.") self.heartbeat_thread = StoppableThread(target=self.do_heartbeat, name=f"{self.name}_heartbeat") self.heartbeat_thread.start() def run_init_connection(self): logger.info("Starting init thread.") self.init_thread = StoppableThread(target=self.init_connection, name=f"{self.name}_init") self.init_thread.start() def _event_loop(self): """ Receives from _socket, parses it to JSON and passes it to dispatcher. """ while self._sock.connected: rl, _, _ = select.select((self._sock.sock, ), (), (), SELECT_TIMEOUT) if self._sock.sock not in rl: if not self._sock.sock: logger.warning("Gateway connection severed!") break else: continue try: opcode, data = self._sock.recv_data() if opcode == ABNF.OPCODE_TEXT: data = data.decode() elif opcode == ABNF.OPCODE_CLOSE: code, reason = self._get_close_args(data) if code: logger.warning("Gateway connection closed with Code " f"{code}: {reason}") self.on_close(code, reason) break elif not data: logger.warning("No Data! Gateway Connection Dropped?") break parsed_data = json.loads(data) except json.JSONDecodeError: logger.error(f"Gateway returned invalid JSON data:\n{data}") except WebSocketConnectionClosedException: break except OSError as e: if e.args[0] != 9: raise except Exception: logger.exception( "Exception occured while receiving data from the gateway.") try: logger.debug("Received " + data) self.dispatcher(parsed_data) except Exception: logger.exception( "Exception occured while running dispatcher function.") def _get_close_args(self, close_frame): if close_frame is None: return [None, None] if close_frame and len(close_frame) >= 2: close_status_code = 256 * close_frame[0] + close_frame[1] reason = close_frame[2:].decode("utf-8") return [close_status_code, reason] else: # Most likely reached this because len(close_frame_data.data) < 2 return [None, None] def send(self, data, retry=5, i=0): """serializes data to json if dict, and send it through the socket. I strongly encourage you to use this method instead of _sock.send, because this method is meant to solve the SSLError caused by ssl module by catching the exception and running the method recursively. """ if i == retry: return False if isinstance(data, dict): data = json.dumps(data) try: logger.debug("Sent " + data) return self._sock.send(data) except SSLError: logger.exception("SSLError while sending data! retrying...") time.sleep(3) return self.send(data, retry, i + 1) except Exception: logger.exception("Unexpected error while sending data!") def is_ready(self): return self.ready_to_run.is_set() def reconnect(self, status=1006, *args, **kwargs): logger.info(f"Attempting reconnect: code {status}") self._sock.close(status=1006, *args, **kwargs) def stop(self, status=1000): """Stops the gateway connection. This client cannot be started after this method has been called, since .start method in Thread object can only be called once per instances. if you have to restart the client, you have to create a new instance. """ super(WebSocketThread, self).stop() self._sock.close(status=status) def init_connection(self): """Method to be run when websocket connection establishes. This method is expected to run shortly, if a problem occurs during the procedure, run .reconnect method which will reestablish the connection. This method should be implemented by the inherited client. """ raise NotImplementedError() def do_heartbeat(self): """Method to be run when websocket connection establishes. This method runs throughout the main thread's lifetime, so you should consider that while overriding the method. This method should be implemented by the inherited class. """ raise NotImplementedError() def on_close(self, code, reason): """Method to be run when websocket connection closes. This method is made to handle Websocket connection close codes accordingly. Whether to override this method or not is your choice. Args: code: """ pass def cleanup(self): """Method to be called after the client disconnects. This method exists to reset the attributes when needed. if not, you can just leave this method as is. Whether to override this method or not is your choice. """ pass
class Wdb(object, Bdb): """Wdb debugger main class""" __metaclass__ = MetaWdb @property def html(self): with open(os.path.join(RES_PATH, 'wdb.html')) as f: return f.read() def __init__(self, app, skip=None): try: Bdb.__init__(self, skip=skip) except TypeError: Bdb.__init__(self) self.begun = False self.app = app self.ws = WebSocket('0.0.0.0', randint(10000, 60000)) self.connected = False tries = 1 while self.ws == 'FAIL' and tries < 10: tries += 1 self.ws = WebSocket('0.0.0.0', randint(10000, 60000)) def __call__(self, environ, start_response): path = environ.get('PATH_INFO', '') if path.startswith('/__wdb/'): filename = path.replace('/__wdb/', '') log.debug('Getting static "%s"' % filename) return self.static_request( environ, start_response, filename) elif 'text/html' in environ.get('HTTP_ACCEPT', ''): log.debug('Sending fake page (%s) for %s' % ( environ['HTTP_ACCEPT'], path)) return self.first_request(environ, start_response) else: log.debug('Sending real page (%s) for %s' % ( environ.get('HTTP_ACCEPT', ''), path)) return self.handled_request(environ, start_response) def static_request(self, environ, start_response, filename): start_response('200 OK', [('Content-Type', guess_type(filename)[0])]) with open(os.path.join(RES_PATH, filename)) as f: yield f.read() def handled_request(self, environ, start_response): self.quitting = 0 appiter = None try: appiter = self.app(environ, start_response) for item in appiter: yield item if hasattr(appiter, 'close'): appiter.close() except Exception: log.exception('wdb') if hasattr(appiter, 'close'): appiter.close() self.handle_connection() type_, value, tb = exc_info() exception = type_.__name__ exception_description = str(value) self.interaction(None, tb, exception, exception_description) try: start_response('500 INTERNAL SERVER ERROR', [ ('Content-Type', 'text/html')]) yield ( '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">' '<title>500 Internal Server Error</title>' '<h1>Internal Server Error</h1>' '<p>There was an error in your request.</p>') except: pass def first_request(self, environ, start_response): post = 'null' if environ.get('REQUEST_METHOD', '') == 'POST': post = {} body = '' try: length = int(environ.get('CONTENT_LENGTH', '0')) except ValueError: pass else: body = environ['wsgi.input'].read(length) post['enctype'] = environ.get('CONTENT_TYPE', '') if not 'multipart/form-data' in post['enctype']: post['data'] = parse_qs(body) else: post['data'] = body post = dump(post) start_response('200 OK', [('Content-Type', 'text/html')]) yield self.html%dict(port=self.ws.port, post=post) def get_file(self, filename): checkcache(filename) return escape(''.join(getlines(filename))) # WDB def handle_connection(self): if self.connected: ret = None try: self.ws.send('Ping') ret = self.ws.receive() except: log.exception('Ping Failed') self.connected = ret == 'Pong' if not self.connected: self.ws.wait_for_connect() self.connected = True def get_trace(self, frame, tb, w_code=None): frames = [] stack, current = self.get_stack(frame, tb) for i, (frame, lno) in enumerate(stack): code = frame.f_code filename = code.co_filename if filename == '<wdb>' and w_code: line = w_code else: checkcache(filename) line = getline(filename, lno, frame.f_globals) line = line and line.strip() frames.append({ 'file': filename, 'function': code.co_name, 'flno': code.co_firstlineno, 'lno': lno, 'code': escape(line), 'level': i }) return stack, frames, current def interaction( self, frame, tb=None, exception='Wdb', exception_description='Set Trace'): try: self._interaction( frame, tb, exception, exception_description) except WsError: log.exception('Websocket Error during interaction. Starting again') self.handle_connection() self.interaction( frame, tb, exception, exception_description) def _interaction( self, frame, tb, exception, exception_description): stack, trace, current_index = self.get_trace(frame, tb) current = trace[current_index] locals = stack[current_index][0].f_locals if self.begun: self.ws.send('Trace|%s' % dump({ 'trace': trace })) current_file = current['file'] self.ws.send('Check|%s' % dump({ 'name': current_file, 'sha512': sha512(self.get_file(current_file)).hexdigest() })) else: self.begun = True while True: message = self.ws.receive() if '|' in message: pipe = message.index('|') cmd = message[:pipe] data = message[pipe + 1:] else: cmd = message data = '' log.info('Cmd %s #Data %d' % (cmd, len(data))) if cmd == 'Start': self.ws.send('Title|%s' % dump({ 'title': exception, 'subtitle': exception_description })) self.ws.send('Trace|%s' % dump({ 'trace': trace })) current_file = current['file'] self.ws.send('Check|%s' % dump({ 'name': current_file, 'sha512': sha512(self.get_file(current_file)).hexdigest() })) elif cmd == 'Select': current_index = int(data) current = trace[current_index] current_file = current['file'] locals = stack[current_index][0].f_locals self.ws.send('Check|%s' % dump({ 'name': current_file, 'sha512': sha512(self.get_file(current_file)).hexdigest() })) elif cmd == 'File': current_file = current['file'] self.ws.send('File|%s' % dump({ 'file': self.get_file(current_file), 'name': current_file, 'sha512': sha512(self.get_file(current_file)).hexdigest() })) self.ws.send('Select|%s' % dump({ 'frame': current })) elif cmd == 'NoFile': self.ws.send('Select|%s' % dump({ 'frame': current })) elif cmd == 'Inspect': thing = reverse_id(int(data)) self.ws.send('Dump|%s' % dump({ 'for': escape(repr(thing)), 'val': escape(pformat(dict( (key, getattr(thing, key)) for key in dir(thing)))) })) elif cmd == 'Trace': self.ws.send('Trace|%s' % dump(trace)) elif cmd == 'Eval': globals = dict(stack[current_index][0].f_globals) # Hack for function scope eval globals.update(locals) globals.setdefault('pprint', pprint) with capture_output() as (out, err): try: compiled_code = compile(data, '<stdin>', 'single') exec compiled_code in globals, locals except Exception: type_, value, tb = exc_info() print '%s: %s' % (type_.__name__, str(value)) self.ws.send('Print|%s' % dump({ 'result': escape('\n'.join(out) + '\n'.join(err)) })) elif cmd == 'Ping': self.ws.send('Pong') elif cmd == 'Step': if hasattr(self, 'botframe'): self.set_step() break elif cmd == 'Next': if hasattr(self, 'botframe'): self.set_next(stack[current_index][0]) break elif cmd == 'Continue': if hasattr(self, 'botframe'): self.set_continue() break elif cmd == 'Return': if hasattr(self, 'botframe'): self.set_return(stack[current_index][0]) break elif cmd == 'Quit': if hasattr(self, 'botframe'): self.set_continue() self.ws.close() break else: log.warn('Unknown command %s' % cmd) def user_call(self, frame, argument_list): """This method is called when there is the remote possibility that we ever need to stop in this function.""" if self.stop_here(frame): log.warn('CALL') self.handle_connection() self.ws.send('Echo|%s' % dump({ 'for': '__call__', 'val': frame.f_code.co_name})) # self.interaction(frame, first_step=False) def user_line(self, frame): """This function is called when we stop or break at this line.""", if self.stop_here(frame): log.warn('LINE') self.handle_connection() self.interaction(frame) def user_return(self, frame, return_value): """This function is called when a return trap is set here.""" if self.stop_here(frame): log.warn('RETURN') frame.f_locals['__return__'] = return_value self.handle_connection() self.ws.send('Echo|%s' % dump({ 'for': '__return__', 'val': return_value })) self.interaction(frame) def user_exception(self, frame, exc_info): """This function is called if an exception occurs, but only if we are to stop at or just below this level.""" log.error('EXCEPTION', exc_info=exc_info) type_, value, tb = exc_info frame.f_locals['__exception__'] = type_, value exception = type_.__name__ exception_description = str(value) self.handle_connection() self.ws.send('Echo|%s' % dump({ 'for': '__exception__', 'val': '%s: %s' % ( exception, exception_description)})) self.interaction(frame, tb, exception, exception_description)
class ShowdownSimulator(BattleSimulator): """A :class:`pokebattle_rl_env.battle_simulator.BattleSimulator` using `Pokemon Showdown <https://pokemonshowdown.com>`_ as backend. View ongoing battles at https://play.pokemonshowdown.com/:attr:`room_id` if :attr:`local` is False or at http://localhost:8000/:attr:`room_id` if otherwise. Attributes: state (:class:`pokebattle_rl_env.game_state.GameState`): The current state of the battle. auth (str): The authentication method to use to log into https://pokemonshowdown.com. Options: * empty string: Log into a temporary account. * `'register'`: Generate a username and password to register an account. The credentials will be output on the console. * path to authentication file: Logs into an account specified in a text file, where the first line specifies the username and the second line specifies the password. self_play (bool): Whether to use self play. Note that this is a naive self play-implementation. In fact, agents simply play against other agents - a temporary text file keeps track of the battles. Thus, self play only works if `number of agents % 2 == 0`. If :attr:`self_play` is false, the agent will battle against random human opponents. Keep in mind that this self-play implementation is redundant if multiple agents are deployed on a local Pokemon Showdown instance (see :attr:`connection`) without human players. If https://github.com/Zarel/Pokemon-Showdown/blob/master/ladders.js#L470 and https://github.com/Zarel/Pokemon-Showdown/blob/master/ladders.js#L470 is removed, they will battle against each other automatically. connection (:class:`pokebattle_rl_env.showdown_simulator.ShowdownConnection`): Details which Pokemon Showdown connection to use. The default connection is to the local instance at https://localhost:8000. Use a local instance of Pokemon Showdown whenever possible. See https://github.com/Zarel/Pokemon-Showdown for installation instructions. Obviously, if self play is not desired, using a local/custom instance is only recommended if there are human players on it. Otherwise, set :attr:`connection` to :const:`DEFAULT_PUBLIC_CONNECTION` to use the public connection at https://play.pokemonshowdown.com. logging_file (bool): Specify the path to a file to log debug output. room_id (str): The string used to identify the current battle (room). """ def __init__(self, auth='', self_play=False, connection=DEFAULT_LOCAL_CONNECTION, logging_file=None): info('Using Showdown backend') self.state = GameState() self.auth = auth self.self_play = self_play self.connection = connection if logging_file is not None: logger = getLogger() logger.removeHandler(logger.handlers[0]) logger.setLevel(DEBUG) handler = FileHandler(filename=logging_file, mode='w', encoding='utf-8') logger.addHandler(handler) self.room_id = None self.ws = None if self_play: self.self_play_opponent = None super().__init__() def _connect(self, auth): self.ws = WebSocket(sslopt={'check_hostname': False}) self.ws.connect(url=self.connection.ws_url) debug('Connected to Showdown socket') msg = '' while not msg.startswith('|challstr|'): msg = self.ws.recv() challstr = msg[msg.find('|challstr|') + len('|challstr|'):] if auth == 'register': self.username = generate_username() self.password = generate_token(16) assertion = register(challstr=challstr, username=self.username, password=self.password) elif isfile(auth): with open(auth, 'r') as file: self.username, password = file.read().splitlines() self.password = None assertion = login(challstr=challstr, username=self.username, password=password) else: self.username = generate_username() self.password = None assertion = auth_temp_user(challstr=challstr, username=self.username) login_cmd = f'|/trn {self.username},0,{assertion}' self.ws.send(login_cmd) msg = '' while not msg.startswith('|updateuser|') and self.username not in msg: msg = self.ws.recv() debug(msg) def _attack(self, move, mega=False, z=False): cmd = f'{self.room_id}|/move {move}' cmd += ' mega' if mega else '' cmd += ' zmove' if z else '' debug(cmd) self.ws.send(cmd) def _switch(self, pokemon): cmd = f'{self.room_id}|/switch {pokemon}' debug(cmd) self.ws.send(cmd) pokemon_list = self.state.player.pokemon pokemon_list[0], pokemon_list[pokemon - 1] = pokemon_list[pokemon - 1], pokemon_list[0] counter = 0 def _update_state(self): self.counter += 1 debug('%s, %s, %s', self.username, self.state.player.name, self.counter) end = False while not end: msg = self.ws.recv() end = self._parse_message(msg) def _parse_message(self, msg): if self.room_id is None and '|init|battle' in msg: self.room_id = msg.split('\n')[0][1:] end = False if not msg.startswith(f'>{self.room_id}'): return False debug(msg) msgs = msg.split('\n') for msg in msgs: info = msg.split('|') if len(info) < 2: continue if info[1] == 'player': if info[3] == self.username: self.player_short = info[2] self.state.player.name = info[3] else: self.opponent = info[3] self.state.opponent.name = self.opponent self.opponent_short = info[2] elif info[1] == 'win': winner = msg[len('|win|'):] self.state.state = 'win' if winner == self.state.player.name else 'loss' end = True elif info[1] == 'tie': self.state.state = 'tie' end = True elif info[1] == 'turn': self.state.turn = int(info[2]) if self.state.turn == 1: self.state.state = 'ongoing' end = True elif info[1] == 'html': if info[2] == "<div class=\"broadcast-red\"><b>The battle crashed</b><br />Don't worry, we're working on fixing it.</div>": self.state.state = 'tie' end = True elif info[1] == 'request': if info[2].startswith( '{"wait":true' ) and False: # ToDo: Start battle on first action? end = True elif info[2] != '' and not info[2].startswith('{"wait":true'): read_state_json(info[2], self.state) end = self.state.player.force_switch elif info[1] == 'replace': parse_replace(info, self.state, self.opponent_short) elif info[1] == 'move': parse_move(info, self.state, self.opponent_short) elif info[1] == 'upkeep': for effect in self.state.field_effects + self.state.player_conditions + self.state.opponent_conditions: effect.turn += 1 for pokemon in self.state.player.pokemon + self.state.opponent.pokemon: for status in pokemon.statuses: status.turn += 1 pass elif info[1] == 'error': warning(msg) elif info[1] == 'switch' or info[1] == 'drag': parse_switch(info, self.state, self.opponent_short) elif info[1] == '-boost': parse_boost(info, self.state, self.opponent_short) elif info[1] == '-unboost': parse_boost(info, self.state, self.opponent_short, unboost=True) elif info[1] == '-damage' or info[1] == '-heal': parse_damage_heal(info, self.state, self.opponent_short) elif info[1] == '-status': parse_status(info, self.state, self.opponent_short) elif info[1] == '-curestatus': parse_status(info, self.state, self.opponent_short, cure=True) elif info[1] == '-message': if 'lost due to inactivity.' in info[ 2] or 'forfeited.' in info[2]: self.state.forfeited = True elif info[1] == '-start': parse_start_end(info, self.state, self.opponent_short) elif info[1] == '-end': parse_start_end(info, self.state, self.opponent_short, start=False) elif info[1] == '-sidestart': parse_sideeffect(info, self.state, self.opponent_short) elif info[1] == '-sideend': parse_sideeffect(info, self.state, self.opponent_short, start=False) elif info[1] == '-weather': if info[2] == 'none': self.state.weather = None else: if self.state.weather is not None and info[2] == self.state.weather.name and len(info) > 3 and\ info[3] == '[upkeep]': self.state.weather.turn += 1 else: self.state.weather = BattleEffect(info[2]) elif info[1] == '-fieldstart': parse_field(info, self.state) elif info[1] == '-fieldend': parse_field(info, self.state, start=False) elif info[1] == '-ability': pokemon = ident_to_pokemon(info[2], self.state, self.opponent_short) ability = ability_name_to_id(info[3]) pokemon.ability = ability elif info[1] == 'endability': pokemon = ident_to_pokemon(info[2], self.state, self.opponent_short) pokemon.ability = None elif info[1] == 'detailschange': parse_specieschange(info, self.state, self.opponent_short) elif info[1] == '-formechange': parse_specieschange(info, self.state, self.opponent_short, details=True) elif info[1] == '-transform': pokemon = ident_to_pokemon(info[2], self.state, self.opponent_short) to_pokemon = ident_to_pokemon(info[3], self.state, self.opponent_short) pokemon.change_species(to_pokemon.species) pokemon.transformed = True elif info[1] == '-mega': parse_mega(info, self.state, self.opponent_short) elif info[1] == '-item': parse_item(info, self.state, self.opponent_short) elif info[1] == '-enditem': parse_item(info, self.state, self.opponent_short, start=False) elif info[1] == '-zpower': if self.opponent_short in msg: self.state.opponent.z_used = True else: self.state.player.z_used = True # ToDo: |-zpower|POKEMON |move|POKEMON|MOVE|TARGET|[zeffect] if '[of]' in msg: parse_auxiliary_info(info, self.state, self.opponent_short) return end def render(self, mode='human'): """Renders the ongoing battle, if there is any. Args: mode (str): Details the rendering mode. Currently, only mode `human` is supported. `human` will simply open the ongoing battle in a web browser (if one exists). Therefore, it is advised to call :meth:`render` only once per battle. """ if mode == 'human' and self.room_id is not None: browser_url = f'{self.connection.web_url}/{self.room_id}' webbrowser.open(browser_url) def reset(self): """Resets the simulator to its initial state. Call this function prior to calling :meth:`act`. It automatically sets up a new battle, even if there exists an ongoing battle. """ debug('Reset %s', self.state.player.name) if self.state.state == 'ongoing': cmd = f'{self.room_id}|/forfeit' self.ws.send(cmd) debug(cmd) if self.room_id is not None: cmd = f'|/leave {self.room_id}' self.ws.send(cmd) debug(cmd) self.room_id = None self.state = GameState() msg = '' while 'deinit' not in msg: msg = self.ws.recv() debug(msg) if self.ws is None: self._connect(self.auth) info('Using username %s with password %s', self.username, self.password) self.ws.send('|/utm null') # Team if self.self_play: self.ws.settimeout(None) # Naive self play with open('usernames', 'a') as file: file.write(self.username + '\n') lines = [] while len(lines) < 2: with open('usernames', 'r') as file: lines = file.readlines() usernames = [line[:-1] for line in lines] print(self.counter, self.username, lines, usernames) username_index = usernames.index(self.username) if username_index % 2 == 0: opponent = usernames[username_index + 1] cmd = f'|/challenge {opponent}, gen7unratedrandombattle' self.ws.send(cmd) debug(cmd) else: while True: msg = self.ws.recv() debug(msg) if msg.startswith('|updatechallenges|'): json = loads(msg.split('|')[2]) if 'challengesFrom' in json and json['challengesFrom']: opponent = next(iter(json['challengesFrom'])) cmd = f'|/accept {opponent}' self.ws.send(cmd) debug(cmd) del lines[username_index - 1] del lines[username_index - 1] with open('usernames', 'w') as file: file.writelines(lines) break # if self.self_play_opponent is None: # with open('usernames', 'a') as file: # file.write(self.username + '\n') # sleep(1 + random()) # with open('usernames', 'r') as file: # lines = file.readlines() # usernames = [line[:-1] for line in lines] # username_index = usernames.index(self.username) # if username_index % 2 == 0: # self.self_play_opponent = usernames[username_index + 1] # self.ws.send(f'|/challenge {self.self_play_opponent}, gen7randombattle') # print(f'|/challenge {self.self_play_opponent}, gen7randombattle') # else: # self.self_play_opponent = self.username # while True: # msg = self.ws.recv() # if self.debug_output: # print(msg) # if msg.startswith('|updatechallenges|'): # json = loads(msg.split('|')[2]) # if 'challengesFrom' in json and json['challengesFrom']: # self.self_play_opponent = next(iter(json['challengesFrom'])) # self.ws.send(f'|/accept {self.self_play_opponent}') # if self.debug_output: # print(f'|/accept {self.self_play_opponent}') # del lines[username_index - 1] # del lines[username_index - 1] # with open('usernames', 'w') as file: # file.writelines(lines) # break # elif self.self_play_opponent == self.username: # while True: # msg = self.ws.recv() # if self.debug_output: # print(msg) # if msg.startswith('|updatechallenges|'): # json = loads(msg.split('|')[2]) # if 'challengesFrom' in json and json['challengesFrom']: # opponent = next(iter(json['challengesFrom'])) # self.ws.send(f'|/accept {opponent}') # if self.debug_output: # print(f'|/accept {opponent}') # break # else: # self.ws.send(f'|/challenge {self.self_play_opponent}, gen7randombattle') # print(f'|/challenge {self.self_play_opponent}, gen7randombattle') # p >> |/challenge [OPPONENT], gen7randombattle # p << |updatechallenges|{"challengesFrom":{},"challengeTo":{"to":"[OPPONENT]","format":"gen7randombattle"}} # o << |updatechallenges|{"challengesFrom":{"[PLAYER]":"gen7randombattle"},"challengeTo":null} # o >> |/accept [PLAYER] # - << |updatechallenges|{"challengesFrom":{},"challengeTo":null} # - << |updatesearch|{"searching":[],"games":null} # - << |updatesearch|{"searching":[],"games":{"battle-gen7randombattle-706502869":"[Gen 7] Random Battle"}} else: # Against human players or other agents self.ws.send('|/search gen7unratedrandombattle') # Tier self._update_state() if not self.self_play: self.ws.send(f'{self.room_id}|/timer on') debug('Playing against %s', self.opponent) def close(self): """Closes the connection to the WebSocket endpoint.""" self.ws.close() info('Connection to Showdown Socket closed')
class CloudClient: """Spokestack client for cloud based speech to text Args: key_id (str): identity from spokestack api credentials key_secret (str): secret key from spokestack api credentials socket_url (str): url for socket connection audio_format (str): format of input audio sample_rate (int): audio sample rate (kHz) language (str): language for recognition limit (int): Limit of messages per api response idle_timeout (Any): Time before client timeout. Defaults to None """ def __init__( self, key_id: str, key_secret: str, socket_url: str = "wss://api.spokestack.io", audio_format: str = "PCM16LE", sample_rate: int = 16000, language: str = "en", limit: int = 10, idle_timeout: Union[float, None] = None, ) -> None: self._body: str = json.dumps({ "format": audio_format, "rate": sample_rate, "language": language, "limit": limit, }) self._socket_url: str = socket_url self._key_id: str = key_id self._key: bytes = key_secret.encode("utf-8") signature = hmac.new(self._key, self._body.encode("utf-8"), hashlib.sha256).digest() self._signature = base64.b64encode(signature).decode("utf-8") self._socket: Any = None self._response: Dict[str, Any] = { "error": None, "final": True, "hypotheses": [], "status": None, } self._sample_rate: int = sample_rate self._idle_timeout = idle_timeout self._idle_count: int = 0 def __call__(self, audio: Union[bytes, np.ndarray], limit: int = 1) -> List[str]: """Audio to text interface for the cloud client Args: audio (bytes|np.ndarray): input audio can be in the form of bytes or np.float, np.int16 array with conversions handled. other types with produce a TypeError limit (int): number of predictions to return Returns: list of transcripts, and their confidence values of size limit """ if isinstance(audio, bytes): audio = np.frombuffer(audio, np.int16) elif np.issubdtype(audio.dtype, np.floating): # convert and rescale to PCM-16 audio = (audio * (2**15 - 1)).astype(np.int16) elif not np.issubdtype(audio.dtype, np.int16): raise TypeError("invalid_audio") chunk_size = self._sample_rate self.connect() self.initialize() for i in range(0, len(audio), chunk_size): frame = audio[i:][:chunk_size] self.send(frame) self.receive() self.end() while not self._response["final"]: self.receive() self.disconnect() hypotheses = self._response.get("hypotheses", []) return hypotheses[:limit] @property def is_connected(self) -> bool: """ status of the socket connection """ if self._socket: return True return False def connect(self) -> None: """ connects to websocket """ if self._socket is None: self._socket = WebSocket() self._socket.connect(f"{self._socket_url}/v1/asr/websocket") def initialize(self) -> None: """ sends/receives the initial api request """ if not self._socket: raise ConnectionError("Not Connected") message = { "keyId": self._key_id, "signature": self._signature, "body": self._body, } self._socket.send(json.dumps(message)) self._response = json.loads(self._socket.recv()) if not self._response["status"] == "ok": raise APIError(self._response) def disconnect(self) -> None: """ disconnects client socket connection """ if self._socket: self._socket.close() self._socket = None def send(self, frame: np.ndarray) -> None: """sends a single frame of audio Args: frame (np.ndarray): segment of PCM-16 encoded audio """ if self._socket: self._socket.send_binary(frame.tobytes()) else: raise ConnectionError("Not Connected") def end(self) -> None: """ sends empty string in binary to indicate last frame """ if self._socket: self._socket.send_binary(b"") else: raise ConnectionError("Not Connected") def receive(self) -> None: """ receives the api response """ if self._socket: timeout = self._socket.timeout try: self._socket.timeout = 0 response = self._socket.recv() self._response = json.loads(response) except Exception: pass self._socket.timeout = timeout else: raise ConnectionError("Not Connected") @property def response(self) -> dict: """ current response message""" return self._response @property def is_final(self) -> bool: """ status of most recent sever response """ return self._response["final"] @property def idle_timeout(self) -> Any: """ property for maximum idle time """ return self._idle_timeout @property def idle_count(self) -> int: """ current counter of idle time """ return self._idle_count @idle_count.setter def idle_count(self, value: int) -> None: """ sets the idle counter""" self._idle_count = value
class WebSocketApp(object): """ Higher level of APIs are provided. The interface is like JavaScript WebSocket object. """ def __init__(self, url, on_open=None, on_message=None, on_error=None, on_close=None, symbol='btc_cny'): """ url: websocket url. on_open: callable object which is called at opening websocket. this function has one argument. The arugment is this class object. on_message: callbale object which is called when recieved data. on_message has 2 arguments. The 1st arugment is this class object. The passing 2nd arugment is utf-8 string which we get from the server. on_error: callable object which is called when we get error. on_error has 2 arguments. The 1st arugment is this class object. The passing 2nd arugment is exception object. on_close: callable object which is called when closed the connection. this function has one argument. The arugment is this class object. """ self.url = url self.sock = WebSocket() self.sock.connect(self.url) self.symbol = ''.join(symbol.split('_')) self.send("{'event':'addChannel','channel':'ok_%s_depth'}" % self.symbol) def send(self, data): """ send message. data must be utf-8 string or unicode. """ self.sock.send(data) def close(self): """ close websocket connection. """ self.sock.close() def depth(self, symbol='btc_cny'): try: data = self.sock.recv() resp = json.loads(data) return resp[0]['data'] except Exception as e: logging.info("except[%s]" % e) def _run_with_no_err(self, callback, *args): if callback: try: callback(self, *args) except Exception as e: if logger.isEnabledFor(logging.DEBUG): logger.error(e)
class Subscriber: """ Subscriber objects are used to subscribe to Exonum blocks via websockets. """ # constants SUBSCRIPTION_WEBSOCKET_URI = "ws://{}:{}/api/explorer/v1/{}/subscribe" SENDING_WEBSOCKET_URI = "ws://{}:{}/api/explorer/v1/ws" SUBSCRIPTION_TYPES = ["blocks", "transactions"] # Type of the received data (it can be either bytes or a string). ReceiveType = Union[bytes, str] # Type of the `Callback` (`Callable` that takes `ReceiveType` as an argument and produces nothing). CallbackType = Callable[[ReceiveType], None] def __init__( self, address: str, port: int, subscription_type: Optional[str] = None, filters: Optional[Dict[str, Any]] = None ): """Subscriber constructor. Parameters ---------- address: str IP address of the Exonum node. port: int Port of the exonum node. subscription_type: Optional[str] Type of subscription: "blocks" or "transactions". If not given, it is assumed that subscriber is used to send transactions. filters: Optional[Dict[str, Any]] Dictionary of filters, such as 'service_id' and 'tx_id' for transactions. """ if not subscription_type: self._address = self.SENDING_WEBSOCKET_URI.format(address, port) else: if subscription_type not in Subscriber.SUBSCRIPTION_TYPES: err = ValueError( f"Subscription type must be one of these: {self.SUBSCRIPTION_TYPES}, " f"while {subscription_type} is given." ) logger.error("Error occurred during subscriber initialization: %s", err) raise err parameters = "?" + urlencode(filters) if filters else "" self._address = self.SUBSCRIPTION_WEBSOCKET_URI.format(address, port, subscription_type) + parameters self._is_running = False self._connected = False self._ws_client = WebSocket() self._thread = Thread(target=self._event_processing) self._handler: Optional[Subscriber.CallbackType] = None def __enter__(self) -> "Subscriber": self.connect() return self def __exit__(self, exc_type: Optional[type], exc_value: Optional[Any], exc_traceback: Optional[object]) -> None: self.stop() def connect(self) -> None: """Connects the subscriber to the Exonum, so it will be able to receive events. """ self._ws_client.connect(self._address) self._connected = True def set_handler(self, handler: "Subscriber.CallbackType") -> None: """Sets the handler """ self._handler = handler def run(self) -> None: """Runs the subscriber thread. It will call the provided handler on every new block. """ try: self._is_running = True self._thread.setDaemon(True) self._thread.start() logger.debug("Subscriber thread started successfully.") except RuntimeError as error: logger.error("Error occurred during running subscriber thread: %s", error) def _event_processing(self) -> None: while self._is_running: data = self._ws_client.recv() if data and self._handler: self._handler(data) def wait_for_new_event(self) -> None: """ Waits until a new event (block or transaction) is ready. Please note that this method is a blocking one. """ if self._is_running: print("Subscriber is already running...") else: self._ws_client.recv() def stop(self) -> None: """Closes connection with the websocket and, if the thread is running, joins it. """ if self._is_running: self._is_running = False if self._connected: self._ws_client.close() self._connected = False if self._thread.is_alive(): self._thread.join() def send_transaction(self, message: ExonumMessage) -> str: """ Sends a transaction into an Exonum node via WebSocket. Example: >>> response = client.send_websocket_transaction(message) >>> print(response) {"result":"success","response":{"tx_hash":"48b7d71d388f3c2dfa665bcf837e1fa0417ca559fb0163533ea72de6319e61ca"}} Parameters ---------- message: ExonumMessage Prepared and signed an Exonum message. Returns ------- result: str Result of the WebSocket request. If a transaction is correct and it is accepted, it will contain a JSON with a hash of the transaction. """ body_raw = message.signed_raw() if body_raw is None: logger.critical("Attempt to send an unsigned message through websocket.") raise RuntimeError("Attempt to send an unsigned message.") data = json.dumps({"type": "transaction", "payload": {"tx_body": body_raw.hex()}}) ws_client = WebSocket() ws_client.connect(self._address) ws_client.send(data) response = ws_client.recv() ws_client.close() return response
ws = WebSocket() ws.connect("ws://lab.algonics.net/anticaptcha/ws") # Super print(ws.recv()) while True: msg = " ".join(argv[1:]) m = "{{\"message\": \"{}\"}}".format(msg) ws.send(m) r = ws.recv() r = loads(r) challenge = r["challenge"] response = int(challenge, 13) # print("Challenge: {}, reponse: {}".format(challenge, response)) m = "{{\"reponse\": \"{}\"}}".format(response) ws.send(m) r = ws.recv() r = loads(r) cipher = r["ciphertext"] if cipher[0] == L: print(cipher) break ws.close()
class WSClient: def __init__(self, configuration, url, headers): """A websocket client with support for channels. Exec command uses different channels for different streams. for example, 0 is stdin, 1 is stdout and 2 is stderr. Some other API calls like port forwarding can forward different pods' streams to different channels. """ enableTrace(False) header = [] self._connected = False self._channels = {} self._all = "" # We just need to pass the Authorization, ignore all the other # http headers we get from the generated code if headers and 'authorization' in headers: header.append("authorization: %s" % headers['authorization']) if headers and 'sec-websocket-protocol' in headers: header.append("sec-websocket-protocol: %s" % headers['sec-websocket-protocol']) else: header.append("sec-websocket-protocol: v4.channel.k8s.io") if url.startswith('wss://') and configuration.verify_ssl: ssl_opts = { 'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': configuration.ssl_ca_cert or certifi.where(), } if configuration.assert_hostname is not None: ssl_opts['check_hostname'] = configuration.assert_hostname else: ssl_opts = {'cert_reqs': ssl.CERT_NONE} if configuration.cert_file: ssl_opts['certfile'] = configuration.cert_file if configuration.key_file: ssl_opts['keyfile'] = configuration.key_file self.sock = WebSocket(sslopt=ssl_opts, skip_utf8_validation=False) self.sock.connect(url, header=header) self._connected = True def peek_channel(self, channel, timeout=0): """Peek a channel and return part of the input, empty string otherwise.""" self.update(timeout=timeout) if channel in self._channels: return self._channels[channel] return "" def read_channel(self, channel, timeout=0): """Read data from a channel.""" if channel not in self._channels: ret = self.peek_channel(channel, timeout) else: ret = self._channels[channel] if channel in self._channels: del self._channels[channel] return ret def readline_channel(self, channel, timeout=None): """Read a line from a channel.""" if timeout is None: timeout = float("inf") start = time.time() while self.is_open() and time.time() - start < timeout: if channel in self._channels: data = self._channels[channel] if "\n" in data: index = data.find("\n") ret = data[:index] data = data[index+1:] if data: self._channels[channel] = data else: del self._channels[channel] return ret self.update(timeout=(timeout - time.time() + start)) def write_channel(self, channel, data): """Write data to a channel.""" self.sock.send(chr(channel) + data) def peek_stdout(self, timeout=0): """Same as peek_channel with channel=1.""" return self.peek_channel(STDOUT_CHANNEL, timeout=timeout) def read_stdout(self, timeout=None): """Same as read_channel with channel=1.""" return self.read_channel(STDOUT_CHANNEL, timeout=timeout) def readline_stdout(self, timeout=None): """Same as readline_channel with channel=1.""" return self.readline_channel(STDOUT_CHANNEL, timeout=timeout) def peek_stderr(self, timeout=0): """Same as peek_channel with channel=2.""" return self.peek_channel(STDERR_CHANNEL, timeout=timeout) def read_stderr(self, timeout=None): """Same as read_channel with channel=2.""" return self.read_channel(STDERR_CHANNEL, timeout=timeout) def readline_stderr(self, timeout=None): """Same as readline_channel with channel=2.""" return self.readline_channel(STDERR_CHANNEL, timeout=timeout) def read_all(self): """Return buffered data received on stdout and stderr channels. This is useful for non-interactive call where a set of command passed to the API call and their result is needed after the call is concluded. Should be called after run_forever() or update() TODO: Maybe we can process this and return a more meaningful map with channels mapped for each input. """ out = self._all self._all = "" self._channels = {} return out def is_open(self): """True if the connection is still alive.""" return self._connected def write_stdin(self, data): """The same as write_channel with channel=0.""" self.write_channel(STDIN_CHANNEL, data) def update(self, timeout=0): """Update channel buffers with at most one complete frame of input.""" if not self.is_open(): return if not self.sock.connected: self._connected = False return r, _, _ = select.select( (self.sock.sock, ), (), (), timeout) if r: op_code, frame = self.sock.recv_data_frame(True) if op_code == ABNF.OPCODE_CLOSE: self._connected = False return elif op_code == ABNF.OPCODE_BINARY or op_code == ABNF.OPCODE_TEXT: data = frame.data if six.PY3: data = data.decode("utf-8") if len(data) > 1: channel = ord(data[0]) data = data[1:] if data: if channel in [STDOUT_CHANNEL, STDERR_CHANNEL]: # keeping all messages in the order they received for # non-blocking call. self._all += data if channel not in self._channels: self._channels[channel] = data else: self._channels[channel] += data def run_forever(self, timeout=None): """Wait till connection is closed or timeout reached. Buffer any input received during this time.""" if timeout: start = time.time() while self.is_open() and time.time() - start < timeout: self.update(timeout=(timeout - time.time() + start)) else: while self.is_open(): self.update(timeout=None) def close(self, **kwargs): """ close websocket connection. """ self._connected = False if self.sock: self.sock.close(**kwargs)
class Subscriber: """ Subscriber objects are used to subscribe to Exonum blocks via websockets. """ # Type of the received data (it can be either bytes or a string). ReceiveType = Union[bytes, str] # Type of the `Callback` (`Callable` that takes `ReceiveType` as an argument and produces nothing). CallbackType = Callable[[ReceiveType], None] def __init__(self, address: str, port: int): """Subscriber constructor. Parameters ---------- address: str IP address of the Exonum node. post: int Port of the exonum node. """ self._address = _WEBSOCKET_URI.format(address, port) self._is_running = False self._connected = False self._ws_client = WebSocket() self._thread = Thread(target=self._event_processing) self._handler: Optional[Subscriber.CallbackType] = None def __enter__(self) -> "Subscriber": self.connect() return self def __exit__(self, exc_type: Optional[type], exc_value: Optional[Any], exc_traceback: Optional[object]) -> None: self.stop() def connect(self) -> None: """Connects the subscriber to the Exonum, so it will be able to receive events. """ self._ws_client.connect(self._address) self._connected = True def set_handler(self, handler: "Subscriber.CallbackType") -> None: """Sets the handler """ self._handler = handler def run(self) -> None: """Runs the subscriber thread. It will call the provided handler on every new block. """ try: self._is_running = True self._thread.setDaemon(True) self._thread.start() except RuntimeError as error: print(f"Error occured during running subscriber thread: {error}") def _event_processing(self) -> None: while self._is_running: data = self._ws_client.recv() if data and self._handler: self._handler(data) def wait_for_new_block(self) -> None: """ Waits until a new block is ready. Please note that this method is a blocking one. """ if self._is_running: print("Subscriber is already running...") else: self._ws_client.recv() def stop(self) -> None: """Closes connection with the websocket and, if the thread is running, joins it. """ if self._connected: self._ws_client.close() self._connected = False if self._is_running: if self._thread.isAlive(): self._thread.join() self._is_running = False
def on_message(socket: websocket.WebSocket, message: str): config["token"] = json.loads(message)["data"]["token"] socket.close()
class WSClient: def __init__(self, configuration, url, headers): """A websocket client with support for channels. Exec command uses different channels for different streams. for example, 0 is stdin, 1 is stdout and 2 is stderr. Some other API calls like port forwarding can forward different pods' streams to different channels. """ enableTrace(False) header = [] self._connected = False self._channels = {} self._all = "" # We just need to pass the Authorization, ignore all the other # http headers we get from the generated code if headers and 'authorization' in headers: header.append("authorization: %s" % headers['authorization']) if headers and 'sec-websocket-protocol' in headers: header.append("sec-websocket-protocol: %s" % headers['sec-websocket-protocol']) else: header.append("sec-websocket-protocol: v4.channel.k8s.io") if url.startswith('wss://') and configuration.verify_ssl: ssl_opts = { 'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': configuration.ssl_ca_cert or certifi.where(), } if configuration.assert_hostname is not None: ssl_opts['check_hostname'] = configuration.assert_hostname else: ssl_opts = {'cert_reqs': ssl.CERT_NONE} if configuration.cert_file: ssl_opts['certfile'] = configuration.cert_file if configuration.key_file: ssl_opts['keyfile'] = configuration.key_file self.sock = WebSocket(sslopt=ssl_opts, skip_utf8_validation=False) self.sock.connect(url, header=header) self._connected = True def peek_channel(self, channel, timeout=0): """Peek a channel and return part of the input, empty string otherwise.""" self.update(timeout=timeout) if channel in self._channels: return self._channels[channel] return "" def read_channel(self, channel, timeout=0): """Read data from a channel.""" if channel not in self._channels: ret = self.peek_channel(channel, timeout) else: ret = self._channels[channel] if channel in self._channels: del self._channels[channel] return ret def readline_channel(self, channel, timeout=None): """Read a line from a channel.""" if timeout is None: timeout = float("inf") start = time.time() while self.is_open() and time.time() - start < timeout: if channel in self._channels: data = self._channels[channel] if "\n" in data: index = data.find("\n") ret = data[:index] data = data[index + 1:] if data: self._channels[channel] = data else: del self._channels[channel] return ret self.update(timeout=(timeout - time.time() + start)) def write_channel(self, channel, data): """Write data to a channel.""" self.sock.send(chr(channel) + data) def peek_stdout(self, timeout=0): """Same as peek_channel with channel=1.""" return self.peek_channel(STDOUT_CHANNEL, timeout=timeout) def read_stdout(self, timeout=None): """Same as read_channel with channel=1.""" return self.read_channel(STDOUT_CHANNEL, timeout=timeout) def readline_stdout(self, timeout=None): """Same as readline_channel with channel=1.""" return self.readline_channel(STDOUT_CHANNEL, timeout=timeout) def peek_stderr(self, timeout=0): """Same as peek_channel with channel=2.""" return self.peek_channel(STDERR_CHANNEL, timeout=timeout) def read_stderr(self, timeout=None): """Same as read_channel with channel=2.""" return self.read_channel(STDERR_CHANNEL, timeout=timeout) def readline_stderr(self, timeout=None): """Same as readline_channel with channel=2.""" return self.readline_channel(STDERR_CHANNEL, timeout=timeout) def read_all(self): """Return buffered data received on stdout and stderr channels. This is useful for non-interactive call where a set of command passed to the API call and their result is needed after the call is concluded. Should be called after run_forever() or update() TODO: Maybe we can process this and return a more meaningful map with channels mapped for each input. """ out = self._all self._all = "" self._channels = {} return out def is_open(self): """True if the connection is still alive.""" return self._connected def write_stdin(self, data): """The same as write_channel with channel=0.""" self.write_channel(STDIN_CHANNEL, data) def update(self, timeout=0): """Update channel buffers with at most one complete frame of input.""" if not self.is_open(): return if not self.sock.connected: self._connected = False return r, _, _ = select.select((self.sock.sock, ), (), (), timeout) if r: op_code, frame = self.sock.recv_data_frame(True) if op_code == ABNF.OPCODE_CLOSE: self._connected = False return elif op_code == ABNF.OPCODE_BINARY or op_code == ABNF.OPCODE_TEXT: data = frame.data if six.PY3: data = data.decode("utf-8", "replace") if len(data) > 1: channel = ord(data[0]) data = data[1:] if data: if channel in [STDOUT_CHANNEL, STDERR_CHANNEL]: # keeping all messages in the order they received # for non-blocking call. self._all += data if channel not in self._channels: self._channels[channel] = data else: self._channels[channel] += data def run_forever(self, timeout=None): """Wait till connection is closed or timeout reached. Buffer any input received during this time.""" if timeout: start = time.time() while self.is_open() and time.time() - start < timeout: self.update(timeout=(timeout - time.time() + start)) else: while self.is_open(): self.update(timeout=None) @property def returncode(self): """ The return code, A None value indicates that the process hasn't terminated yet. """ if self.is_open(): return None else: err = self.read_channel(ERROR_CHANNEL) err = yaml.safe_load(err) if err['status'] == "Success": return 0 return int(err['details']['causes'][0]['message']) def close(self, **kwargs): """ close websocket connection. """ self._connected = False if self.sock: self.sock.close(**kwargs)
class GameClient(object): def __init__(self, server, connection): super(GameClient, self).__init__() # internals self.number = None self.teamid = None self.buffer = [] self.x = 0 self.y = 0 self.r = 0 self.server = server # io initialisation self.io = WebSocket(connection) self.io.on('data', self._onData) self.io.on('close', self._onClose) self.io.on('pause', self._onPause) self.io.pause(False) def _onData(self, data): try: for d in data: if d.startswith('iwannaplay'): self._register() elif d.startswith('pos'): self._position(d) elif d.startswith('fire'): self._fire() elif d.startswith('hit'): self._hit(d) else: print "UNKNOWN ACTION", d except: print 'It was nasty:', data self.io.close() def _onClose(self): print 'client gone' if self.number: self.server.unregister(self) def _onPause(self, pause): if pause == False: for d in self.buffer: self.io.write(d) def _write(self, data): if self.io.w_paused: if len(self.buffer) > 70: # Sloooowpoke self.io.close() return self.buffer.append(data) else: self.io.write(data) def _register(self): self.server.register(self) if not self.number: self._write('fuckoff') print 'we are not in mood', self.number else: self._write('level:%s' % self.server.getLevel(self)) self._write('okay:%d:%d' % (self.teamid, self.number)) stats = self.server.getStats() self._write('stats:%d:%d:%d:%d' % (stats[0], stats[1], stats[2], stats[3])) self.server.updatePosClient(self) print 'client registred', self.number def _position(self, d): (x,y,r) = d.split(':')[1:] x = int(x) y = int(y) r = int(r) if self.x!=x or self.y!=y or self.r!=r: self.x = x self.y = y self.r = r self.server.updateClientPos(self) def _fire(self): self.server.updateFire(self) def _hit(self, d): (who, by) = d.split(':')[1:] who = int(who) by = int(by) self.server.updateHit(who, by) def anyHit(self, who, by): self._write('hit:%d:%d' % (who, by)) def updateOpponent(self, client): self._write('op_update:%d:%d:%d:%d' % (client.teamid, client.x, client.y, client.r)) def updateOpponentFire(self, client): self._write('op_fire:%d' % (client.teamid)) def removeOpponent(self, client): self._write('op_remove:%d' % client.teamid)
class WSClient: def __init__(self, configuration, url, headers, capture_all): """A websocket client with support for channels. Exec command uses different channels for different streams. for example, 0 is stdin, 1 is stdout and 2 is stderr. Some other API calls like port forwarding can forward different pods' streams to different channels. """ enableTrace(False) header = [] self._connected = False self._channels = {} self._ordered_all = [] if capture_all: self._all = StringIO() else: self._all = _IgnoredIO() # We just need to pass the Authorization, ignore all the other # http headers we get from the generated code if headers and 'authorization' in headers: header.append("authorization: %s" % headers['authorization']) if headers and 'sec-websocket-protocol' in headers: header.append("sec-websocket-protocol: %s" % headers['sec-websocket-protocol']) else: header.append("sec-websocket-protocol: v4.channel.k8s.io") if url.startswith('wss://') and configuration.verify_ssl: ssl_opts = { 'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': configuration.ssl_ca_cert or certifi.where(), } if configuration.assert_hostname is not None: ssl_opts['check_hostname'] = configuration.assert_hostname else: ssl_opts = {'cert_reqs': ssl.CERT_NONE} if configuration.cert_file: ssl_opts['certfile'] = configuration.cert_file if configuration.key_file: ssl_opts['keyfile'] = configuration.key_file self.sock = WebSocket(sslopt=ssl_opts, skip_utf8_validation=False) if configuration.proxy: proxy_url = urlparse(configuration.proxy) self.sock.connect(url, header=header, http_proxy_host=proxy_url.hostname, http_proxy_port=proxy_url.port) else: self.sock.connect(url, header=header) self._connected = True def peek_channel(self, channel, timeout=0): """Peek a channel and return part of the input, empty string otherwise.""" self.update(timeout=timeout) if channel in self._channels: return self._channels[channel] return "" def read_channel(self, channel, timeout=0): """Read data from a channel.""" if channel not in self._channels: ret = self.peek_channel(channel, timeout) else: ret = self._channels[channel] if channel in self._channels: del self._channels[channel] return ret def readline_channel(self, channel, timeout=None): """Read a line from a channel.""" if timeout is None: timeout = float("inf") start = time.time() while self.is_open() and time.time() - start < timeout: if channel in self._channels: data = self._channels[channel] if "\n" in data: index = data.find("\n") ret = data[:index] data = data[index+1:] if data: self._channels[channel] = data else: del self._channels[channel] return ret self.update(timeout=(timeout - time.time() + start)) def readline_any(self, timeout=None): """Read a line from any output channel.""" import logging from datetime import datetime logging.basicConfig(level=logging.INFO) logger = logging.getLogger('kubernetes.client.rest') if timeout is None: timeout = float("inf") start = time.time() chunks = {STDOUT_CHANNEL : "", STDERR_CHANNEL : ""} while self.is_open() and time.time() - start < timeout: for position, entry in enumerate(self._ordered_all): index = entry["data"].find("\n") if index == -1: chunks[entry["channel"]] += entry["data"] del self._ordered_all[position] else: chunks[entry["channel"]] += entry["data"][:index] ret = {"channel": entry["channel"], "data": chunks[entry["channel"]]} entry["data"] = entry["data"][index+1:] if not entry["data"]: del self._ordered_all[position] if ret["data"]: chunks[entry["channel"]] = "" return ret self.update(timeout=(timeout - time.time() + start)) # def readline_any(self, channels=[STDOUT_CHANNEL, STDERR_CHANNEL], timeout=None): # """Read a line from any output channel.""" # if timeout is None: # timeout = float("inf") # start = time.time() # while self.is_open() and time.time() - start < timeout: # for channel in channels: # if channel in self._channels: # data = self._channels[channel] # if not data: # continue # if "\n" in data: # index = data.find("\n") # ret = {"channel": channel, "data": data[:index]} # data = data[index+1:] # if data: # self._channels[channel] = data # else: # del self._channels[channel] # return ret # self.update(timeout=(timeout - time.time() + start)) def write_channel(self, channel, data): """Write data to a channel.""" # check if we're writing binary data or not binary = six.PY3 and type(data) == six.binary_type opcode = ABNF.OPCODE_BINARY if binary else ABNF.OPCODE_TEXT channel_prefix = chr(channel) if binary: channel_prefix = six.binary_type(channel_prefix, "ascii") payload = channel_prefix + data self.sock.send(payload, opcode=opcode) def peek_stdout(self, timeout=0): """Same as peek_channel with channel=1.""" return self.peek_channel(STDOUT_CHANNEL, timeout=timeout) def read_stdout(self, timeout=None): """Same as read_channel with channel=1.""" return self.read_channel(STDOUT_CHANNEL, timeout=timeout) def readline_stdout(self, timeout=None): """Same as readline_channel with channel=1.""" return self.readline_channel(STDOUT_CHANNEL, timeout=timeout) def peek_stderr(self, timeout=0): """Same as peek_channel with channel=2.""" return self.peek_channel(STDERR_CHANNEL, timeout=timeout) def read_stderr(self, timeout=None): """Same as read_channel with channel=2.""" return self.read_channel(STDERR_CHANNEL, timeout=timeout) def readline_stderr(self, timeout=None): """Same as readline_channel with channel=2.""" return self.readline_channel(STDERR_CHANNEL, timeout=timeout) def read_all(self): """Return buffered data received on stdout and stderr channels. This is useful for non-interactive call where a set of command passed to the API call and their result is needed after the call is concluded. Should be called after run_forever() or update() TODO: Maybe we can process this and return a more meaningful map with channels mapped for each input. """ out = self._all.getvalue() self._all = self._all.__class__() self._channels = {} return out def is_open(self): """True if the connection is still alive.""" return self._connected def write_stdin(self, data): """The same as write_channel with channel=0.""" self.write_channel(STDIN_CHANNEL, data) def update(self, timeout=0): """Update channel buffers with at most one complete frame of input.""" if not self.is_open(): return if not self.sock.connected: self._connected = False return r, _, _ = select.select( (self.sock.sock, ), (), (), timeout) if r: op_code, frame = self.sock.recv_data_frame(True) if op_code == ABNF.OPCODE_CLOSE: self._connected = False return elif op_code == ABNF.OPCODE_BINARY or op_code == ABNF.OPCODE_TEXT: data = frame.data if six.PY3: data = data.decode("utf-8", "replace") if len(data) > 1: channel = ord(data[0]) data = data[1:] if data: if channel in [STDOUT_CHANNEL, STDERR_CHANNEL]: # keeping all messages in the order they received # for non-blocking call. self._all.write(data) self._ordered_all.append({"channel": channel, "data": data}) if channel not in self._channels: self._channels[channel] = data else: self._channels[channel] += data def run_forever(self, timeout=None): """Wait till connection is closed or timeout reached. Buffer any input received during this time.""" if timeout: start = time.time() while self.is_open() and time.time() - start < timeout: self.update(timeout=(timeout - time.time() + start)) else: while self.is_open(): self.update(timeout=None) @property def returncode(self): """ The return code, A None value indicates that the process hasn't terminated yet. """ if self.is_open(): return None else: err = self.read_channel(ERROR_CHANNEL) err = yaml.safe_load(err) if err['status'] == "Success": return 0 return int(err['details']['causes'][0]['message']) def close(self, **kwargs): """ close websocket connection. """ self._connected = False if self.sock: self.sock.close(**kwargs)
class Server(threading.Thread): def __init__(self, controlSock, clientAddr, ifPrimitive, root, ip_management): super(Server, self).__init__() self.daemon = True self.bufSize = 2000000000 self.ifPrimitive = ifPrimitive if ifPrimitive: self.controlSock = controlSock else: self.controlSock = WebSocket(controlSock, self.bufSize) self.clientAddr = clientAddr self.dataListenSock = None self.dataAddr = '127.0.0.1' self.dataPort = None self.username = '' self.authenticated = False self.if_administrator = False self.cwd = root self.root_wd = root self.typeMode = 'Binary' self.dataMode = 'PORT' self.nlst_data_socket = None self.retr_data_socket = None self.stor_data_socket = None self.ip_data_socket = None self.data_socket_for = 'NLST' self.ip_management = ip_management def run(self): self.controlSock.send('220 Service ready for new user.\r\n') while True: cmd = self.controlSock.recv(self.bufSize) if cmd == '': self.controlSock.send('221 Serviceclosingcontrolconnection.\r\n') self.controlSock.close() break try: cmdHead = cmd.split()[0].upper() except Exception as e: logging.error(e) self.controlSock.send('221 Service closing control connection.\r\n') self.controlSock.close() break print 'receive head', cmdHead if cmdHead == 'QUIT': self.controlSock.send('221 Service closing control connection.\r\n') self.controlSock.close() break elif cmdHead == 'HELP': self.controlSock.send('214 QUIT HELP USER PASS PWD CWD TYPE PASV NLST RETR STOR\r\n') elif cmdHead == 'USER': if len(cmd.split()) < 2: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') else: self.username = cmd.split()[1] self.controlSock.send('331 User name okay, need password.\r\n') elif cmdHead == 'PASS': if self.username == '': self.controlSock.send('503 Bad sequence of commands.\r\n') else: if len(cmd.split()) < 2: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') else: if self.username == 'administrator' and cmd.split()[1] == 'administrator': self.if_administrator = True self.controlSock.send('230 User logged in, proceed.\r\n') self.authenticated = True elif cmdHead == 'PWD': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') else: self.controlSock.send('257 "%s" is the current directory.\r\n' % self.cwd) elif cmdHead == 'CDUP': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') else: try: os.chdir("..") except OSError as e: print e self.controlSock.send('550 Requested action not taken. File unavailable (e.g., file busy).\r\n') else: self.cwd = os.getcwd() self.controlSock.send('250 "%s" is the current directory.\r\n' % self.cwd) os.chdir(self.root_wd) elif cmdHead == 'RMD': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') elif len(cmd.split()) < 2: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') else: dir_name = cmd[cmd.index(' ')+1: cmd.index('\r\n')] os.chdir(self.cwd) try: shutil.rmtree(dir_name) except Exception as e: logging.error(e) self.controlSock.send('550 Requested action not taken.') else: self.controlSock.send('250 Requested file action okay, completed.') os.chdir(self.root_wd) elif cmdHead == 'MKD': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') elif len(cmd.split()) < 2: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') else: dir_name = cmd[cmd.index(' ')+1: cmd.index('\r\n')] os.chdir(self.cwd) try: os.mkdir(dir_name) except Exception as e: logging.error(e) self.controlSock.send('550 Requested action not taken.') else: self.controlSock.send('250 Requested file action okay, completed.') os.chdir(self.root_wd) elif cmdHead == 'DELETE': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') elif len(cmd.split()) < 2: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') else: os.chdir(self.cwd) file_name = cmd[cmd.index(' ')+1: cmd.index('\r\n')] try: os.remove(file_name) except Exception as e: logging.error(e) self.controlSock.send('550 Requested action not taken.') else: self.controlSock.send('250 Requested file action okay, completed.') os.chdir(self.root_wd) elif cmdHead == 'CWD': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') elif len(cmd.split()) < 2: self.controlSock.send('250 "%s" is the current directory.\r\n' % self.cwd) else: print "change to dir:", cmd.split()[1] os.chdir(self.cwd) next_dir = cmd.split()[1] try: os.chdir(next_dir) except OSError as e: logging.error(e) self.controlSock.send('550 Requested action not taken. File unavailable (e.g., file busy).\r\n') else: self.cwd = os.getcwd() self.controlSock.send('250 "%s" is the current directory.\r\n' % self.cwd) os.chdir(self.root_wd) elif cmd == 'TYPE': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') else: self.controlSock.send("502 Command not implemented\r\n") elif cmdHead == 'PASV': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') elif len(cmd.split()) < 2: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') elif cmd.split()[1] != 'NLST' and cmd.split()[1] != 'RETR' and cmd.split()[1] != 'STOR' and cmd.split()[1] != 'IP': self.controlSock.send(b'501 Syntax error in parameters or arguments.\r\n') else: if self.dataListenSock is None: self.dataListenSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.dataListenSock.bind((self.dataAddr, 0)) self.dataPort = self.dataListenSock.getsockname()[1] print self.dataAddr, self.dataPort self.dataListenSock.listen(5) self.dataMode = 'PASV' DataSocket(self).start() # 为什么 self.data_socket_for = cmd.split()[1] self.controlSock.send('227 Entering passive mode (%s,%s)\r\n' % (self.dataAddr, self.dataPort)) elif cmdHead == 'PORT': if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') else: self.controlSock.send("502 Command not implemented\r\n") elif cmdHead == 'NLST': time.sleep(0.5) if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') elif self.dataMode == 'PASV' and self.nlst_data_socket is not None: self.controlSock.send(b'125 Data connection already open. Transfer starting.\r\n') os.chdir(self.cwd) dir_list = os.listdir(self.cwd) dir_with_type = {'dir': [], 'file': []} for ob in dir_list: if ob[0] == '.': continue if os.path.isdir(ob): dir_with_type['dir'].append(ob) else: dir_with_type['file'].append(ob) directory = json.dumps(dir_with_type) self.nlst_data_socket.send(directory) self.nlst_data_socket.close() self.nlst_data_socket = None self.controlSock.send('225 Closing data connection. Requested file action successful (for example, file transfer or file abort).\r\n') os.chdir(self.root_wd) else: self.controlSock.send("425 Can't open data connection.\r\n") elif cmdHead == 'RETR': time.sleep(0.5) if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') elif len(cmd.split()) < 2: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') elif self.dataMode == 'PASV' and self.retr_data_socket is not None: self.controlSock.send('125 Data connection already open; transfer starting.\r\n') file_name = cmd.split()[1] try: os.chdir(self.cwd) self.retr_data_socket.send(open(file_name, 'rb').read(), opcode=2) except Exception as e: logging.error(e) # 没有文件的话在此处理 self.controlSock.send('550 Requested action not taken. File unavailable (e.g., file busy).\r\n') else: self.controlSock.send('225 Closing data connection. Requested file action successful (for example, file transfer or file abort).\r\n') os.chdir(self.root_wd) self.retr_data_socket.close() self.retr_data_socket = None else: self.controlSock.send(b"425 Can't open data connection.\r\n") elif cmdHead == 'STOR': time.sleep(0.5) if not self.authenticated: self.controlSock.send('530 Not logged in.\r\n') elif len(cmd.split()) < 2: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') elif self.dataMode == 'PASV' and self.stor_data_socket is not None: self.controlSock.send('125 Data connection already open; transfer starting.\r\n') os.chdir(self.cwd) file_name = cmd[cmd.index(' ')+1: cmd.index('\r\n')] f = open(file_name, 'ab+') # 在非阻塞模式下, 如果recv()调用没有发现任何数据或者send()调用无法立即发送数据, 那么将引发socket.error异常。在阻塞模式下, 这些调用在处理之前都将被阻塞。 self.stor_data_socket.setblocking(False) while True: try: data = self.stor_data_socket.recv(self.bufSize) if data == b'': break if data is None: continue f.write(data) except socket.error as e: logging.error(e) break f.close() print "success" self.stor_data_socket.close() self.stor_data_socket = None self.controlSock.send('225 Closing data connection. Requested file action successful (for example, file transfer or file abort).\r\n') os.chdir(self.root_wd) else: self.controlSock.send("425 Can't open data connection.\r\n") elif cmdHead == 'IP': if self.if_administrator: if len(cmd.split()) < 2 and self.ip_data_socket is not None and self.dataMode == 'PASV': try: self.ip_data_socket.send(json.dumps(self.ip_management.ip_data['ip_list'])) except Exception as e: logging.error(e) self.controlSock.send('550 Requested action not taken.') else: self.controlSock.send('225 Closing data connection. Requested action successful.\r\n') self.ip_data_socket.close() self.ip_data_socket = None elif cmd.split()[1] == 'ADD': address = cmd.split()[2] if self.ip_management.add_ip(address): self.controlSock.send('250 Requested action okay, completed') else: self.controlSock.send('550 Requested action not taken.') elif cmd.split()[1] == 'DELETE': ip_id = cmd.split()[2] if self.ip_management.delete_ip(ip_id): self.controlSock.send('250 Requested action okay, completed') else: self.controlSock.send('550 Requested action not taken.') elif cmd.split()[1] == 'UPDATE': ip_id = cmd.split()[2] address = cmd.split()[3] if self.ip_management.modify_ip(ip_id, address): self.controlSock.send('250 Requested action okay, completed') else: self.controlSock.send('550 Requested action not taken.') else: self.controlSock.send('501 Syntax error in parameters or arguments.\r\n') else: # 非管理员 self.controlSock.send('534 Unable to take action\r\n')