Added file logging support with -l and loglevel -L
This commit is contained in:
parent
eac2c9fadd
commit
b078a6cd20
|
|
@ -1,5 +1,6 @@
|
|||
## websockify: WebSockets support for any application/server
|
||||
|
||||
|
||||
websockify was formerly named wsproxy and was part of the
|
||||
[noVNC](https://github.com/kanaka/noVNC) project.
|
||||
|
||||
|
|
|
|||
60
websocket.py
60
websocket.py
|
|
@ -17,6 +17,7 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
|
|||
'''
|
||||
|
||||
import os, sys, time, errno, signal, socket, traceback, select
|
||||
import warnings, logging
|
||||
import array, struct
|
||||
from cgi import parse_qsl
|
||||
from base64 import b64encode, b64decode
|
||||
|
|
@ -60,8 +61,8 @@ for mod, sup in [('numpy', 'HyBi protocol'), ('ssl', 'TLS/SSL/wss'),
|
|||
globals()[mod] = __import__(mod)
|
||||
except ImportError:
|
||||
globals()[mod] = None
|
||||
print("WARNING: no '%s' module, %s is slower or disabled" % (
|
||||
mod, sup))
|
||||
warnings.warn("WARNING: no '%s' module, %s is slower or disabled" % (
|
||||
mod, sup), RuntimeWarning)
|
||||
if multiprocessing and sys.platform == 'win32':
|
||||
# make sockets pickle-able/inheritable
|
||||
import multiprocessing.reduction
|
||||
|
|
@ -97,7 +98,7 @@ Sec-WebSocket-Accept: %s\r
|
|||
|
||||
def __init__(self, listen_host='', listen_port=None, source_is_ipv6=False,
|
||||
verbose=False, cert='', key='', ssl_only=None,
|
||||
daemon=False, record='', web='',
|
||||
daemon=False, record='', web='', logfile=None, loglevel='4',
|
||||
run_once=False, timeout=0):
|
||||
|
||||
# settings
|
||||
|
|
@ -126,6 +127,28 @@ Sec-WebSocket-Accept: %s\r
|
|||
if self.web:
|
||||
os.chdir(self.web)
|
||||
|
||||
# Handle logging
|
||||
if loglevel.isdigit == False:
|
||||
raise Exception("Invalid loglevel specified, must be 0-5")
|
||||
|
||||
log_levels = {
|
||||
'0': None,
|
||||
'1': logging.CRITICAL,
|
||||
'2': logging.ERROR,
|
||||
'3': logging.WARNING,
|
||||
'4': logging.INFO,
|
||||
'5': logging.DEBUG,
|
||||
}
|
||||
if int(loglevel) > 5: loglevel = 5
|
||||
|
||||
logformat = '%(asctime)s %(levelname)s, %(message)s'
|
||||
if logfile == None:
|
||||
logging.basicConfig(format=logformat)
|
||||
else:
|
||||
logging.basicConfig(format=logformat, filename=logfile)
|
||||
self.log = logging.getLogger('websocket')
|
||||
self.log.setLevel(log_levels[loglevel])
|
||||
|
||||
# Sanity checks
|
||||
if not ssl and self.ssl_only:
|
||||
raise Exception("No 'ssl' module and SSL-only specified")
|
||||
|
|
@ -133,25 +156,25 @@ Sec-WebSocket-Accept: %s\r
|
|||
raise Exception("Module 'resource' required to daemonize")
|
||||
|
||||
# Show configuration
|
||||
print("WebSocket server settings:")
|
||||
print(" - Listen on %s:%s" % (
|
||||
self.log.info("WebSocket server settings:")
|
||||
self.log.info(" - Listen on %s:%s" % (
|
||||
self.listen_host, self.listen_port))
|
||||
print(" - Flash security policy server")
|
||||
self.log.info(" - Flash security policy server")
|
||||
if self.web:
|
||||
print(" - Web server. Web root: %s" % self.web)
|
||||
self.log.info(" - Web server. Web root: %s" % self.web)
|
||||
if ssl:
|
||||
if os.path.exists(self.cert):
|
||||
print(" - SSL/TLS support")
|
||||
self.log.info(" - SSL/TLS support")
|
||||
if self.ssl_only:
|
||||
print(" - Deny non-SSL/TLS connections")
|
||||
self.log.info(" - Deny non-SSL/TLS connections")
|
||||
else:
|
||||
print(" - No SSL/TLS support (no cert file)")
|
||||
self.log.info(" - No SSL/TLS support (no cert file)")
|
||||
else:
|
||||
print(" - No SSL/TLS support (no 'ssl' module)")
|
||||
self.log.info(" - No SSL/TLS support (no 'ssl' module)")
|
||||
if self.daemon:
|
||||
print(" - Backgrounding (daemon)")
|
||||
self.log.info(" - Backgrounding (daemon)")
|
||||
if self.record:
|
||||
print(" - Recording to '%s.*'" % self.record)
|
||||
self.log.info(" - Recording to '%s.*'" % self.record)
|
||||
|
||||
#
|
||||
# WebSocketServer static methods
|
||||
|
|
@ -344,14 +367,14 @@ Sec-WebSocket-Accept: %s\r
|
|||
f['mask'] = buf[f['hlen']:f['hlen']+4]
|
||||
f['payload'] = WebSocketServer.unmask(buf, f)
|
||||
else:
|
||||
print("Unmasked frame: %s" % repr(buf))
|
||||
self.log.debug("Unmasked frame: %s" % repr(buf))
|
||||
f['payload'] = buf[(f['hlen'] + has_mask * 4):full_len]
|
||||
|
||||
if base64 and f['opcode'] in [1, 2]:
|
||||
try:
|
||||
f['payload'] = b64decode(f['payload'])
|
||||
except:
|
||||
print("Exception while b64decoding buffer: %s" %
|
||||
self.log.error("Exception while b64decoding buffer: %s" %
|
||||
repr(buf))
|
||||
raise
|
||||
|
||||
|
|
@ -403,7 +426,7 @@ Sec-WebSocket-Accept: %s\r
|
|||
def msg(self, msg):
|
||||
""" Output message with handler_id prefix. """
|
||||
if not self.daemon:
|
||||
print("% 3d: %s" % (self.handler_id, msg))
|
||||
self.log.debug("% 3d: %s" % (self.handler_id, msg))
|
||||
|
||||
def vmsg(self, msg):
|
||||
""" Same as msg() but only if verbose. """
|
||||
|
|
@ -820,6 +843,7 @@ Sec-WebSocket-Accept: %s\r
|
|||
ready = select.select([lsock], [], [], 1)[0]
|
||||
if lsock in ready:
|
||||
startsock, address = lsock.accept()
|
||||
self.log.info("Accepted connection from %s on port %i" % (address[0], address[1]))
|
||||
else:
|
||||
continue
|
||||
except Exception:
|
||||
|
|
@ -864,11 +888,11 @@ Sec-WebSocket-Accept: %s\r
|
|||
|
||||
except KeyboardInterrupt:
|
||||
_, exc, _ = sys.exc_info()
|
||||
print("In KeyboardInterrupt")
|
||||
self.log.debug("In KeyboardInterrupt")
|
||||
pass
|
||||
except SystemExit:
|
||||
_, exc, _ = sys.exc_info()
|
||||
print("In SystemExit")
|
||||
self.log.debug("In SystemExit")
|
||||
break
|
||||
except Exception:
|
||||
_, exc, _ = sys.exc_info()
|
||||
|
|
|
|||
15
websockify
15
websockify
|
|
@ -74,7 +74,7 @@ Traffic Legend:
|
|||
WebSocketServer.__init__(self, *args, **kwargs)
|
||||
|
||||
def run_wrap_cmd(self):
|
||||
print("Starting '%s'" % " ".join(self.wrap_cmd))
|
||||
self.log.info("Starting '%s'" % " ".join(self.wrap_cmd))
|
||||
self.wrap_times.append(time.time())
|
||||
self.wrap_times.pop(0)
|
||||
self.cmd = subprocess.Popen(
|
||||
|
|
@ -88,12 +88,12 @@ Traffic Legend:
|
|||
# Need to call wrapped command after daemonization so we can
|
||||
# know when the wrapped command exits
|
||||
if self.wrap_cmd:
|
||||
print(" - proxying from %s:%s to '%s' (port %s)\n" % (
|
||||
self.log.info(" - proxying from %s:%s to '%s' (port %s)" % (
|
||||
self.listen_host, self.listen_port,
|
||||
" ".join(self.wrap_cmd), self.target_port))
|
||||
self.run_wrap_cmd()
|
||||
else:
|
||||
print(" - proxying from %s:%s to %s:%s\n" % (
|
||||
self.log.info(" - proxying from %s:%s to %s:%s" % (
|
||||
self.listen_host, self.listen_port,
|
||||
self.target_host, self.target_port))
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ Traffic Legend:
|
|||
if (now - avg) < 10:
|
||||
# 3 times in the last 10 seconds
|
||||
if self.spawn_message:
|
||||
print("Command respawning too fast")
|
||||
self.log.error("Command respawning too fast")
|
||||
self.spawn_message = False
|
||||
else:
|
||||
self.run_wrap_cmd()
|
||||
|
|
@ -145,7 +145,7 @@ Traffic Legend:
|
|||
connect=True)
|
||||
|
||||
if self.verbose and not self.daemon:
|
||||
print(self.traffic_legend)
|
||||
self.log.debug(self.traffic_legend)
|
||||
|
||||
# Start proxying
|
||||
try:
|
||||
|
|
@ -221,6 +221,11 @@ if __name__ == '__main__':
|
|||
parser = optparse.OptionParser(usage=usage)
|
||||
parser.add_option("--verbose", "-v", action="store_true",
|
||||
help="verbose messages and per frame traffic")
|
||||
parser.add_option("--logfile", "-l", default=None,
|
||||
help="log output to logfile", metavar="LOGFILE")
|
||||
parser.add_option("--loglevel", "-L", default='4',
|
||||
help="set loglevel 0-5 for none to debug",
|
||||
metavar="LOGLEVEL")
|
||||
parser.add_option("--record",
|
||||
help="record sessions to FILE.[session_number]", metavar="FILE")
|
||||
parser.add_option("--daemon", "-D",
|
||||
|
|
|
|||
Loading…
Reference in New Issue