forked from xuos/xiuos
add jerryscript source code
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
# Available JerryScript debugger tools
|
||||
|
||||
- JerryScript console debugger client ( jerry_client.py )
|
||||
- IoT.js Code ( https://github.com/jerryscript-project/iotjscode )
|
||||
- JerryScript debugger Chrome webtool ( https://github.com/jerryscript-project/jerryscript-debugger-ts )
|
||||
@@ -0,0 +1,345 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright JS Foundation and other contributors, http://js.foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import print_function
|
||||
from cmd import Cmd
|
||||
from pprint import pprint
|
||||
import math
|
||||
import socket
|
||||
import sys
|
||||
import logging
|
||||
import time
|
||||
import jerry_client_main
|
||||
|
||||
from jerry_client_websocket import WebSocket
|
||||
from jerry_client_rawpacket import RawPacket
|
||||
from jerry_client_tcp import Socket
|
||||
|
||||
def write(string):
|
||||
print(string, end='')
|
||||
|
||||
class DebuggerPrompt(Cmd):
|
||||
# pylint: disable=too-many-instance-attributes,too-many-arguments
|
||||
def __init__(self, debugger):
|
||||
Cmd.__init__(self)
|
||||
self.debugger = debugger
|
||||
self.stop = False
|
||||
self.quit = False
|
||||
|
||||
def precmd(self, line):
|
||||
self.stop = False
|
||||
if self.debugger.non_interactive:
|
||||
print("%s" % line)
|
||||
return line
|
||||
|
||||
def postcmd(self, stop, line):
|
||||
return self.stop
|
||||
|
||||
def do_quit(self, _):
|
||||
""" Exit JerryScript debugger """
|
||||
self.debugger.quit()
|
||||
self.quit = True
|
||||
self.stop = True
|
||||
|
||||
def do_display(self, args):
|
||||
""" Toggle source code display after breakpoints """
|
||||
if args:
|
||||
line_num = src_check_args(args)
|
||||
if line_num >= 0:
|
||||
self.debugger.display = line_num
|
||||
else:
|
||||
print("Non-negative integer number expected, 0 turns off this function")
|
||||
|
||||
def do_break(self, args):
|
||||
""" Insert breakpoints on the given lines or functions """
|
||||
write(self.debugger.set_break(args))
|
||||
do_b = do_break
|
||||
|
||||
def do_list(self, _):
|
||||
""" Lists the available breakpoints """
|
||||
write(self.debugger.breakpoint_list())
|
||||
|
||||
def do_delete(self, args):
|
||||
""" Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints """
|
||||
write(self.debugger.delete(args))
|
||||
|
||||
def do_exception(self, args):
|
||||
""" Config the exception handler module """
|
||||
write(self.debugger.exception(args))
|
||||
|
||||
def do_next(self, args):
|
||||
""" Next breakpoint in the same code block """
|
||||
self.stop = True
|
||||
if not args:
|
||||
args = 0
|
||||
self.debugger.next()
|
||||
return
|
||||
|
||||
try:
|
||||
args = int(args)
|
||||
if args <= 0:
|
||||
raise ValueError(args)
|
||||
|
||||
while args > 0:
|
||||
self.debugger.next()
|
||||
time.sleep(0.1)
|
||||
|
||||
while True:
|
||||
result = self.debugger.process_messages()
|
||||
res_type = result.get_type()
|
||||
|
||||
if res_type == result.END:
|
||||
self.quit = True
|
||||
return
|
||||
elif res_type == result.TEXT:
|
||||
write(result.get_text())
|
||||
elif res_type == result.PROMPT:
|
||||
break
|
||||
|
||||
args -= 1
|
||||
except ValueError as val_errno:
|
||||
print("Error: expected a positive integer: %s" % val_errno)
|
||||
do_n = do_next
|
||||
|
||||
def do_step(self, _):
|
||||
""" Next breakpoint, step into functions """
|
||||
self.debugger.step()
|
||||
self.stop = True
|
||||
do_s = do_step
|
||||
|
||||
def do_continue(self, _):
|
||||
""" Continue execution """
|
||||
self.debugger.do_continue()
|
||||
self.stop = True
|
||||
if not self.debugger.non_interactive:
|
||||
print("Press enter to stop JavaScript execution.")
|
||||
do_c = do_continue
|
||||
|
||||
def do_finish(self, _):
|
||||
""" Continue running until the current function returns """
|
||||
self.debugger.finish()
|
||||
self.stop = True
|
||||
do_f = do_finish
|
||||
|
||||
def do_backtrace(self, args):
|
||||
""" Get backtrace data from debugger """
|
||||
write(self.debugger.backtrace(args))
|
||||
self.stop = True
|
||||
do_bt = do_backtrace
|
||||
|
||||
def do_src(self, args):
|
||||
""" Get current source code """
|
||||
if args:
|
||||
line_num = src_check_args(args)
|
||||
if line_num >= 0:
|
||||
write(self.debugger.print_source(line_num, 0))
|
||||
else:
|
||||
write(self.debugger.print_source(0, 0))
|
||||
do_source = do_src
|
||||
|
||||
def do_scroll(self, _):
|
||||
""" Scroll the source up or down """
|
||||
while True:
|
||||
key = sys.stdin.readline()
|
||||
if key == 'w\n':
|
||||
_scroll_direction(self.debugger, "up")
|
||||
elif key == 's\n':
|
||||
_scroll_direction(self.debugger, "down")
|
||||
elif key == 'q\n':
|
||||
break
|
||||
else:
|
||||
print("Invalid key")
|
||||
|
||||
def do_eval(self, args):
|
||||
""" Evaluate JavaScript source code """
|
||||
self.debugger.eval(args)
|
||||
self.stop = True
|
||||
do_e = do_eval
|
||||
do_print = do_eval
|
||||
do_p = do_eval
|
||||
|
||||
def do_eval_at(self, args):
|
||||
""" Evaluate JavaScript source code at a scope chain level """
|
||||
|
||||
code = ''
|
||||
index = 0
|
||||
try:
|
||||
args = args.split(" ", 1)
|
||||
|
||||
index = int(args[0])
|
||||
|
||||
if len(args) == 2:
|
||||
code = args[1]
|
||||
|
||||
if index < 0 or index > 65535:
|
||||
raise ValueError("Invalid scope chain index: %d (must be between 0 and 65535)" % index)
|
||||
|
||||
except ValueError as val_errno:
|
||||
print("Error: %s" % (val_errno))
|
||||
return
|
||||
|
||||
self.debugger.eval_at(code, index)
|
||||
self.stop = True
|
||||
|
||||
def do_throw(self, args):
|
||||
""" Throw an exception """
|
||||
self.debugger.throw(args)
|
||||
self.stop = True
|
||||
|
||||
def do_abort(self, args):
|
||||
""" Throw an exception which cannot be caught """
|
||||
self.debugger.abort(args)
|
||||
self.stop = True
|
||||
|
||||
def do_restart(self, _):
|
||||
""" Restart the engine's debug session """
|
||||
self.debugger.restart()
|
||||
self.stop = True
|
||||
do_res = do_restart
|
||||
|
||||
def do_scope(self, _):
|
||||
""" Get lexical environment chain """
|
||||
self.debugger.scope_chain()
|
||||
self.stop = True
|
||||
|
||||
def do_variables(self, args):
|
||||
""" Get scope variables from debugger """
|
||||
write(self.debugger.scope_variables(args))
|
||||
self.stop = True
|
||||
|
||||
def do_memstats(self, _):
|
||||
""" Memory statistics """
|
||||
self.debugger.memstats()
|
||||
self.stop = True
|
||||
do_ms = do_memstats
|
||||
|
||||
def do_dump(self, args):
|
||||
""" Dump all of the debugger data """
|
||||
if args:
|
||||
print("Error: No argument expected")
|
||||
else:
|
||||
pprint(self.debugger.function_list)
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
def do_EOF(self, _):
|
||||
""" Exit JerryScript debugger """
|
||||
print("Unexpected end of input. Connection closed.")
|
||||
self.debugger.quit()
|
||||
self.quit = True
|
||||
self.stop = True
|
||||
|
||||
def _scroll_direction(debugger, direction):
|
||||
""" Helper function for do_scroll """
|
||||
debugger.src_offset_diff = int(max(math.floor(debugger.display / 3), 1))
|
||||
if direction == "up":
|
||||
debugger.src_offset -= debugger.src_offset_diff
|
||||
else:
|
||||
debugger.src_offset += debugger.src_offset_diff
|
||||
print(debugger.print_source(debugger.display, debugger.src_offset)['value'])
|
||||
|
||||
def src_check_args(args):
|
||||
try:
|
||||
line_num = int(args)
|
||||
if line_num < 0:
|
||||
print("Error: Non-negative integer number expected")
|
||||
return -1
|
||||
|
||||
return line_num
|
||||
except ValueError as val_errno:
|
||||
print("Error: Non-negative integer number expected: %s" % (val_errno))
|
||||
return -1
|
||||
|
||||
# pylint: disable=too-many-branches,too-many-locals,too-many-statements
|
||||
def main():
|
||||
args = jerry_client_main.arguments_parse()
|
||||
|
||||
channel = None
|
||||
protocol = None
|
||||
|
||||
if args.protocol == "tcp":
|
||||
address = None
|
||||
if ":" not in args.address:
|
||||
address = (args.address, 5001) # use default port
|
||||
else:
|
||||
host, port = args.address.split(":")
|
||||
address = (host, int(port))
|
||||
|
||||
protocol = Socket(address)
|
||||
elif args.protocol == "serial":
|
||||
from jerry_client_serial import Serial
|
||||
protocol = Serial(args.serial_config)
|
||||
else:
|
||||
print("Unsupported transmission protocol")
|
||||
return -1
|
||||
|
||||
if args.channel == "websocket":
|
||||
channel = WebSocket(protocol=protocol)
|
||||
elif args.channel == "rawpacket":
|
||||
channel = RawPacket(protocol=protocol)
|
||||
else:
|
||||
print("Unsupported communication channel")
|
||||
return -1
|
||||
|
||||
debugger = jerry_client_main.JerryDebugger(channel)
|
||||
debugger.non_interactive = args.non_interactive
|
||||
|
||||
logging.debug("Connected to JerryScript")
|
||||
|
||||
prompt = DebuggerPrompt(debugger)
|
||||
prompt.prompt = "(jerry-debugger) "
|
||||
|
||||
if args.color:
|
||||
debugger.set_colors()
|
||||
|
||||
if args.display:
|
||||
debugger.display = args.display
|
||||
prompt.do_display(args.display)
|
||||
else:
|
||||
prompt.stop = False
|
||||
|
||||
if args.exception is not None:
|
||||
prompt.do_exception(str(args.exception))
|
||||
|
||||
if args.client_source:
|
||||
debugger.store_client_sources(args.client_source)
|
||||
|
||||
while True:
|
||||
if prompt.quit:
|
||||
break
|
||||
|
||||
result = debugger.process_messages()
|
||||
res_type = result.get_type()
|
||||
|
||||
if res_type == result.END:
|
||||
break
|
||||
elif res_type == result.PROMPT:
|
||||
prompt.cmdloop()
|
||||
elif res_type == result.TEXT:
|
||||
write(result.get_text())
|
||||
continue
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except socket.error as error_msg:
|
||||
ERRNO = error_msg.errno
|
||||
MSG = str(error_msg)
|
||||
if ERRNO == 111:
|
||||
sys.exit("Failed to connect to the JerryScript debugger.")
|
||||
elif ERRNO == 32 or ERRNO == 104:
|
||||
sys.exit("Connection closed.")
|
||||
else:
|
||||
sys.exit("Failed to connect to the JerryScript debugger.\nError: %s" % (MSG))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright JS Foundation and other contributors, http://js.foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import struct
|
||||
|
||||
MAX_BUFFER_SIZE = 256
|
||||
|
||||
class RawPacket(object):
|
||||
""" Simplified transmission layer. """
|
||||
def __init__(self, protocol):
|
||||
self.protocol = protocol
|
||||
self.data_buffer = b""
|
||||
|
||||
def connect(self, config_size):
|
||||
""" Create connection. """
|
||||
self.protocol.connect()
|
||||
self.data_buffer = b""
|
||||
|
||||
# It will return with the Network configurations, which has the following struct:
|
||||
# header [1] - size[1]
|
||||
# configuration [config_size]
|
||||
len_expected = config_size + 1
|
||||
|
||||
while len(self.data_buffer) < len_expected:
|
||||
self.data_buffer += self.protocol.receive_data()
|
||||
|
||||
expected = struct.pack("B", config_size)
|
||||
|
||||
if self.data_buffer[0:1] != expected:
|
||||
raise Exception("Unexpected configuration")
|
||||
|
||||
result = self.data_buffer[1:len_expected]
|
||||
self.data_buffer = self.data_buffer[len_expected:]
|
||||
|
||||
return result
|
||||
|
||||
def close(self):
|
||||
""" Close connection. """
|
||||
self.protocol.close()
|
||||
|
||||
def send_message(self, _, data):
|
||||
""" Send message. """
|
||||
msg_size = len(data)
|
||||
|
||||
while msg_size > 0:
|
||||
bytes_send = self.protocol.send_data(data)
|
||||
if bytes_send < msg_size:
|
||||
data = data[bytes_send:]
|
||||
msg_size -= bytes_send
|
||||
|
||||
def get_message(self, blocking):
|
||||
""" Receive message. """
|
||||
|
||||
# Connection was closed
|
||||
if self.data_buffer is None:
|
||||
return None
|
||||
|
||||
while True:
|
||||
if len(self.data_buffer) >= 1:
|
||||
size = ord(self.data_buffer[0])
|
||||
if size == 0:
|
||||
raise Exception("Unexpected data frame")
|
||||
|
||||
if len(self.data_buffer) >= size + 1:
|
||||
result = self.data_buffer[1:size + 1]
|
||||
self.data_buffer = self.data_buffer[size + 1:]
|
||||
return result
|
||||
|
||||
if not blocking and not self.protocol.ready():
|
||||
return b''
|
||||
|
||||
received_data = self.protocol.receive_data(MAX_BUFFER_SIZE)
|
||||
|
||||
if not received_data:
|
||||
return None
|
||||
|
||||
self.data_buffer += received_data
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright JS Foundation and other contributors, http://js.foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import select
|
||||
import serial
|
||||
|
||||
class Serial(object):
|
||||
""" Create a new socket using the given address family, socket type and protocol number. """
|
||||
def __init__(self, serial_config):
|
||||
config = serial_config.split(',')
|
||||
config_size = len(config)
|
||||
|
||||
port = config[0] if config_size > 0 else "/dev/ttyUSB0"
|
||||
baudrate = config[1] if config_size > 1 else 115200
|
||||
bytesize = int(config[2]) if config_size > 2 else 8
|
||||
parity = config[3] if config_size > 3 else 'N'
|
||||
stopbits = int(config[4]) if config_size > 4 else 1
|
||||
|
||||
self.ser = serial.Serial(port=port, baudrate=baudrate, parity=parity,
|
||||
stopbits=stopbits, bytesize=bytesize, timeout=1)
|
||||
|
||||
def connect(self):
|
||||
""" Connect to the server, write a 'c' to the serial port """
|
||||
self.send_data('c')
|
||||
|
||||
def close(self):
|
||||
"""" close the serial port. """
|
||||
self.ser.close()
|
||||
|
||||
def receive_data(self, max_size=1024):
|
||||
""" The maximum amount of data to be received at once is specified by max_size. """
|
||||
return self.ser.read(max_size)
|
||||
|
||||
def send_data(self, data):
|
||||
""" Write data to the serial port. """
|
||||
return self.ser.write(data)
|
||||
|
||||
def ready(self):
|
||||
""" Monitor the file descriptor. """
|
||||
result = select.select([self.ser.fileno()], [], [], 0)[0]
|
||||
|
||||
return self.ser.fileno() in result
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright JS Foundation and other contributors, http://js.foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import socket
|
||||
import select
|
||||
|
||||
# pylint: disable=too-many-arguments,superfluous-parens
|
||||
class Socket(object):
|
||||
""" Create a new socket using the given address family, socket type and protocol number. """
|
||||
def __init__(self, address, socket_family=socket.AF_INET, socket_type=socket.SOCK_STREAM, proto=0, fileno=None):
|
||||
self.address = address
|
||||
self.socket = socket.socket(socket_family, socket_type, proto, fileno)
|
||||
|
||||
def connect(self):
|
||||
"""
|
||||
Connect to a remote socket at address (host, port).
|
||||
The format of address depends on the address family.
|
||||
"""
|
||||
print("Connecting to: %s:%s" % (self.address[0], self.address[1]))
|
||||
self.socket.connect(self.address)
|
||||
|
||||
def close(self):
|
||||
"""" Mark the socket closed. """
|
||||
self.socket.close()
|
||||
|
||||
def receive_data(self, max_size=1024):
|
||||
""" The maximum amount of data to be received at once is specified by max_size. """
|
||||
return self.socket.recv(max_size)
|
||||
|
||||
def send_data(self, data):
|
||||
""" Send data to the socket. The socket must be connected to a remote socket. """
|
||||
return self.socket.send(data)
|
||||
|
||||
def ready(self):
|
||||
""" Monitor the file descriptor. """
|
||||
result = select.select([self.socket], [], [], 0)[0]
|
||||
|
||||
return self.socket in result
|
||||
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright JS Foundation and other contributors, http://js.foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import struct
|
||||
|
||||
MAX_BUFFER_SIZE = 128
|
||||
WEBSOCKET_BINARY_FRAME = 2
|
||||
WEBSOCKET_FIN_BIT = 0x80
|
||||
|
||||
class WebSocket(object):
|
||||
def __init__(self, protocol):
|
||||
|
||||
self.data_buffer = b""
|
||||
self.protocol = protocol
|
||||
|
||||
def __handshake(self):
|
||||
""" Client Handshake Request. """
|
||||
self.__send_data(b"GET /jerry-debugger HTTP/1.1\r\n" +
|
||||
b"Upgrade: websocket\r\n" +
|
||||
b"Connection: Upgrade\r\n" +
|
||||
b"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n")
|
||||
|
||||
# Expected answer from the handshake.
|
||||
expected = (b"HTTP/1.1 101 Switching Protocols\r\n" +
|
||||
b"Upgrade: websocket\r\n" +
|
||||
b"Connection: Upgrade\r\n" +
|
||||
b"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")
|
||||
|
||||
len_expected = len(expected)
|
||||
|
||||
while len(self.data_buffer) < len_expected:
|
||||
self.data_buffer += self.protocol.receive_data()
|
||||
|
||||
if self.data_buffer[0:len_expected] != expected:
|
||||
raise Exception("Unexpected handshake")
|
||||
|
||||
if len(self.data_buffer) > len_expected:
|
||||
self.data_buffer = self.data_buffer[len_expected:]
|
||||
else:
|
||||
self.data_buffer = b""
|
||||
|
||||
def connect(self, config_size):
|
||||
""" WebSockets connection. """
|
||||
self.protocol.connect()
|
||||
self.data_buffer = b""
|
||||
self.__handshake()
|
||||
|
||||
# It will return with the Network configurations, which has the following struct:
|
||||
# header [2] - opcode[1], size[1]
|
||||
# configuration [config_size]
|
||||
len_expected = config_size + 2
|
||||
|
||||
while len(self.data_buffer) < len_expected:
|
||||
self.data_buffer += self.protocol.receive_data()
|
||||
|
||||
expected = struct.pack("BB",
|
||||
WEBSOCKET_BINARY_FRAME | WEBSOCKET_FIN_BIT,
|
||||
config_size)
|
||||
|
||||
if self.data_buffer[0:2] != expected:
|
||||
raise Exception("Unexpected configuration")
|
||||
|
||||
result = self.data_buffer[2:len_expected]
|
||||
self.data_buffer = self.data_buffer[len_expected:]
|
||||
|
||||
return result
|
||||
|
||||
def __send_data(self, data):
|
||||
""" Private function to send data using the given protocol. """
|
||||
size = len(data)
|
||||
|
||||
while size > 0:
|
||||
bytes_send = self.protocol.send_data(data)
|
||||
if bytes_send < size:
|
||||
data = data[bytes_send:]
|
||||
size -= bytes_send
|
||||
|
||||
def send_message(self, byte_order, packed_data):
|
||||
""" Send message. """
|
||||
message = struct.pack(byte_order + "BBI",
|
||||
WEBSOCKET_BINARY_FRAME | WEBSOCKET_FIN_BIT,
|
||||
WEBSOCKET_FIN_BIT + struct.unpack(byte_order + "B", packed_data[0])[0],
|
||||
0) + packed_data[1:]
|
||||
|
||||
self.__send_data(message)
|
||||
|
||||
def close(self):
|
||||
""" Close the WebSockets connection. """
|
||||
self.protocol.close()
|
||||
|
||||
def get_message(self, blocking):
|
||||
""" Receive message. """
|
||||
|
||||
# Connection was closed
|
||||
if self.data_buffer is None:
|
||||
return None
|
||||
|
||||
while True:
|
||||
if len(self.data_buffer) >= 2:
|
||||
if ord(self.data_buffer[0]) != WEBSOCKET_BINARY_FRAME | WEBSOCKET_FIN_BIT:
|
||||
raise Exception("Unexpected data frame")
|
||||
|
||||
size = ord(self.data_buffer[1])
|
||||
if size == 0 or size >= 126:
|
||||
raise Exception("Unexpected data frame")
|
||||
|
||||
if len(self.data_buffer) >= size + 2:
|
||||
result = self.data_buffer[2:size + 2]
|
||||
self.data_buffer = self.data_buffer[size + 2:]
|
||||
return result
|
||||
|
||||
if not blocking and not self.protocol.ready():
|
||||
return b''
|
||||
|
||||
data = self.protocol.receive_data(MAX_BUFFER_SIZE)
|
||||
|
||||
if not data:
|
||||
self.data_buffer = None
|
||||
return None
|
||||
self.data_buffer += data
|
||||
Reference in New Issue
Block a user