示例#1
0
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))
示例#2
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
示例#4
0
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()
示例#5
0
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()
示例#6
0
    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
示例#7
0
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
示例#8
0
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()
示例#9
0
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)
示例#10
0
    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)
示例#11
0
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()
示例#12
0
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()
示例#13
0
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)
示例#14
0
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)
示例#15
0
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
示例#16
0
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()
示例#17
0
    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
示例#18
0
文件: smalld.py 项目: Bemte/smalld.py
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()
示例#20
0
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))
示例#21
0
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()
示例#22
0
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
示例#23
0
文件: __init__.py 项目: fdev31/wdb
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)
示例#24
0
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')
示例#25
0
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
示例#26
0
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)
示例#27
0
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
示例#28
0
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()
示例#29
0
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)
示例#30
0
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
示例#31
0
 def on_message(socket: websocket.WebSocket, message: str):
     config["token"] = json.loads(message)["data"]["token"]
     socket.close()
示例#32
0
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)
示例#33
0
文件: gameserver.py 项目: skotopes/tt
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)
示例#34
0
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)
示例#35
0
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')