You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
5.8 KiB

4 years ago
  1. #!/home/alpcentaur/ProjektA/PrototypeWebApp/venv/bin/python3.5
  2. import argparse
  3. import code
  4. import sys
  5. import threading
  6. import time
  7. import ssl
  8. import six
  9. from six.moves.urllib.parse import urlparse
  10. import websocket
  11. try:
  12. import readline
  13. except ImportError:
  14. pass
  15. def get_encoding():
  16. encoding = getattr(sys.stdin, "encoding", "")
  17. if not encoding:
  18. return "utf-8"
  19. else:
  20. return encoding.lower()
  21. OPCODE_DATA = (websocket.ABNF.OPCODE_TEXT, websocket.ABNF.OPCODE_BINARY)
  22. ENCODING = get_encoding()
  23. class VAction(argparse.Action):
  24. def __call__(self, parser, args, values, option_string=None):
  25. if values is None:
  26. values = "1"
  27. try:
  28. values = int(values)
  29. except ValueError:
  30. values = values.count("v") + 1
  31. setattr(args, self.dest, values)
  32. def parse_args():
  33. parser = argparse.ArgumentParser(description="WebSocket Simple Dump Tool")
  34. parser.add_argument("url", metavar="ws_url",
  35. help="websocket url. ex. ws://echo.websocket.org/")
  36. parser.add_argument("-p", "--proxy",
  37. help="proxy url. ex. http://127.0.0.1:8080")
  38. parser.add_argument("-v", "--verbose", default=0, nargs='?', action=VAction,
  39. dest="verbose",
  40. help="set verbose mode. If set to 1, show opcode. "
  41. "If set to 2, enable to trace websocket module")
  42. parser.add_argument("-n", "--nocert", action='store_true',
  43. help="Ignore invalid SSL cert")
  44. parser.add_argument("-r", "--raw", action="store_true",
  45. help="raw output")
  46. parser.add_argument("-s", "--subprotocols", nargs='*',
  47. help="Set subprotocols")
  48. parser.add_argument("-o", "--origin",
  49. help="Set origin")
  50. parser.add_argument("--eof-wait", default=0, type=int,
  51. help="wait time(second) after 'EOF' received.")
  52. parser.add_argument("-t", "--text",
  53. help="Send initial text")
  54. parser.add_argument("--timings", action="store_true",
  55. help="Print timings in seconds")
  56. parser.add_argument("--headers",
  57. help="Set custom headers. Use ',' as separator")
  58. return parser.parse_args()
  59. class RawInput:
  60. def raw_input(self, prompt):
  61. if six.PY3:
  62. line = input(prompt)
  63. else:
  64. line = raw_input(prompt)
  65. if ENCODING and ENCODING != "utf-8" and not isinstance(line, six.text_type):
  66. line = line.decode(ENCODING).encode("utf-8")
  67. elif isinstance(line, six.text_type):
  68. line = line.encode("utf-8")
  69. return line
  70. class InteractiveConsole(RawInput, code.InteractiveConsole):
  71. def write(self, data):
  72. sys.stdout.write("\033[2K\033[E")
  73. # sys.stdout.write("\n")
  74. sys.stdout.write("\033[34m< " + data + "\033[39m")
  75. sys.stdout.write("\n> ")
  76. sys.stdout.flush()
  77. def read(self):
  78. return self.raw_input("> ")
  79. class NonInteractive(RawInput):
  80. def write(self, data):
  81. sys.stdout.write(data)
  82. sys.stdout.write("\n")
  83. sys.stdout.flush()
  84. def read(self):
  85. return self.raw_input("")
  86. def main():
  87. start_time = time.time()
  88. args = parse_args()
  89. if args.verbose > 1:
  90. websocket.enableTrace(True)
  91. options = {}
  92. if args.proxy:
  93. p = urlparse(args.proxy)
  94. options["http_proxy_host"] = p.hostname
  95. options["http_proxy_port"] = p.port
  96. if args.origin:
  97. options["origin"] = args.origin
  98. if args.subprotocols:
  99. options["subprotocols"] = args.subprotocols
  100. opts = {}
  101. if args.nocert:
  102. opts = {"cert_reqs": ssl.CERT_NONE, "check_hostname": False}
  103. if args.headers:
  104. options['header'] = map(str.strip, args.headers.split(','))
  105. ws = websocket.create_connection(args.url, sslopt=opts, **options)
  106. if args.raw:
  107. console = NonInteractive()
  108. else:
  109. console = InteractiveConsole()
  110. print("Press Ctrl+C to quit")
  111. def recv():
  112. try:
  113. frame = ws.recv_frame()
  114. except websocket.WebSocketException:
  115. return websocket.ABNF.OPCODE_CLOSE, None
  116. if not frame:
  117. raise websocket.WebSocketException("Not a valid frame %s" % frame)
  118. elif frame.opcode in OPCODE_DATA:
  119. return frame.opcode, frame.data
  120. elif frame.opcode == websocket.ABNF.OPCODE_CLOSE:
  121. ws.send_close()
  122. return frame.opcode, None
  123. elif frame.opcode == websocket.ABNF.OPCODE_PING:
  124. ws.pong(frame.data)
  125. return frame.opcode, frame.data
  126. return frame.opcode, frame.data
  127. def recv_ws():
  128. while True:
  129. opcode, data = recv()
  130. msg = None
  131. if six.PY3 and opcode == websocket.ABNF.OPCODE_TEXT and isinstance(data, bytes):
  132. data = str(data, "utf-8")
  133. if not args.verbose and opcode in OPCODE_DATA:
  134. msg = data
  135. elif args.verbose:
  136. msg = "%s: %s" % (websocket.ABNF.OPCODE_MAP.get(opcode), data)
  137. if msg is not None:
  138. if args.timings:
  139. console.write(str(time.time() - start_time) + ": " + msg)
  140. else:
  141. console.write(msg)
  142. if opcode == websocket.ABNF.OPCODE_CLOSE:
  143. break
  144. thread = threading.Thread(target=recv_ws)
  145. thread.daemon = True
  146. thread.start()
  147. if args.text:
  148. ws.send(args.text)
  149. while True:
  150. try:
  151. message = console.read()
  152. ws.send(message)
  153. except KeyboardInterrupt:
  154. return
  155. except EOFError:
  156. time.sleep(args.eof_wait)
  157. return
  158. if __name__ == "__main__":
  159. try:
  160. main()
  161. except Exception as e:
  162. print(e)