Added file logging support with -l and loglevel -L

This commit is contained in:
Tomas Edwardsson 2011-10-06 18:01:21 +00:00
parent eac2c9fadd
commit b078a6cd20
3 changed files with 53 additions and 23 deletions

View File

@ -1,5 +1,6 @@
## websockify: WebSockets support for any application/server ## websockify: WebSockets support for any application/server
websockify was formerly named wsproxy and was part of the websockify was formerly named wsproxy and was part of the
[noVNC](https://github.com/kanaka/noVNC) project. [noVNC](https://github.com/kanaka/noVNC) project.

View File

@ -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 os, sys, time, errno, signal, socket, traceback, select
import warnings, logging
import array, struct import array, struct
from cgi import parse_qsl from cgi import parse_qsl
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
@ -60,8 +61,8 @@ for mod, sup in [('numpy', 'HyBi protocol'), ('ssl', 'TLS/SSL/wss'),
globals()[mod] = __import__(mod) globals()[mod] = __import__(mod)
except ImportError: except ImportError:
globals()[mod] = None globals()[mod] = None
print("WARNING: no '%s' module, %s is slower or disabled" % ( warnings.warn("WARNING: no '%s' module, %s is slower or disabled" % (
mod, sup)) mod, sup), RuntimeWarning)
if multiprocessing and sys.platform == 'win32': if multiprocessing and sys.platform == 'win32':
# make sockets pickle-able/inheritable # make sockets pickle-able/inheritable
import multiprocessing.reduction import multiprocessing.reduction
@ -97,7 +98,7 @@ Sec-WebSocket-Accept: %s\r
def __init__(self, listen_host='', listen_port=None, source_is_ipv6=False, def __init__(self, listen_host='', listen_port=None, source_is_ipv6=False,
verbose=False, cert='', key='', ssl_only=None, verbose=False, cert='', key='', ssl_only=None,
daemon=False, record='', web='', daemon=False, record='', web='', logfile=None, loglevel='4',
run_once=False, timeout=0): run_once=False, timeout=0):
# settings # settings
@ -126,6 +127,28 @@ Sec-WebSocket-Accept: %s\r
if self.web: if self.web:
os.chdir(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 # Sanity checks
if not ssl and self.ssl_only: if not ssl and self.ssl_only:
raise Exception("No 'ssl' module and SSL-only specified") 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") raise Exception("Module 'resource' required to daemonize")
# Show configuration # Show configuration
print("WebSocket server settings:") self.log.info("WebSocket server settings:")
print(" - Listen on %s:%s" % ( self.log.info(" - Listen on %s:%s" % (
self.listen_host, self.listen_port)) self.listen_host, self.listen_port))
print(" - Flash security policy server") self.log.info(" - Flash security policy server")
if self.web: if self.web:
print(" - Web server. Web root: %s" % self.web) self.log.info(" - Web server. Web root: %s" % self.web)
if ssl: if ssl:
if os.path.exists(self.cert): if os.path.exists(self.cert):
print(" - SSL/TLS support") self.log.info(" - SSL/TLS support")
if self.ssl_only: if self.ssl_only:
print(" - Deny non-SSL/TLS connections") self.log.info(" - Deny non-SSL/TLS connections")
else: else:
print(" - No SSL/TLS support (no cert file)") self.log.info(" - No SSL/TLS support (no cert file)")
else: else:
print(" - No SSL/TLS support (no 'ssl' module)") self.log.info(" - No SSL/TLS support (no 'ssl' module)")
if self.daemon: if self.daemon:
print(" - Backgrounding (daemon)") self.log.info(" - Backgrounding (daemon)")
if self.record: if self.record:
print(" - Recording to '%s.*'" % self.record) self.log.info(" - Recording to '%s.*'" % self.record)
# #
# WebSocketServer static methods # WebSocketServer static methods
@ -344,14 +367,14 @@ Sec-WebSocket-Accept: %s\r
f['mask'] = buf[f['hlen']:f['hlen']+4] f['mask'] = buf[f['hlen']:f['hlen']+4]
f['payload'] = WebSocketServer.unmask(buf, f) f['payload'] = WebSocketServer.unmask(buf, f)
else: 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] f['payload'] = buf[(f['hlen'] + has_mask * 4):full_len]
if base64 and f['opcode'] in [1, 2]: if base64 and f['opcode'] in [1, 2]:
try: try:
f['payload'] = b64decode(f['payload']) f['payload'] = b64decode(f['payload'])
except: except:
print("Exception while b64decoding buffer: %s" % self.log.error("Exception while b64decoding buffer: %s" %
repr(buf)) repr(buf))
raise raise
@ -403,7 +426,7 @@ Sec-WebSocket-Accept: %s\r
def msg(self, msg): def msg(self, msg):
""" Output message with handler_id prefix. """ """ Output message with handler_id prefix. """
if not self.daemon: if not self.daemon:
print("% 3d: %s" % (self.handler_id, msg)) self.log.debug("% 3d: %s" % (self.handler_id, msg))
def vmsg(self, msg): def vmsg(self, msg):
""" Same as msg() but only if verbose. """ """ Same as msg() but only if verbose. """
@ -820,6 +843,7 @@ Sec-WebSocket-Accept: %s\r
ready = select.select([lsock], [], [], 1)[0] ready = select.select([lsock], [], [], 1)[0]
if lsock in ready: if lsock in ready:
startsock, address = lsock.accept() startsock, address = lsock.accept()
self.log.info("Accepted connection from %s on port %i" % (address[0], address[1]))
else: else:
continue continue
except Exception: except Exception:
@ -864,11 +888,11 @@ Sec-WebSocket-Accept: %s\r
except KeyboardInterrupt: except KeyboardInterrupt:
_, exc, _ = sys.exc_info() _, exc, _ = sys.exc_info()
print("In KeyboardInterrupt") self.log.debug("In KeyboardInterrupt")
pass pass
except SystemExit: except SystemExit:
_, exc, _ = sys.exc_info() _, exc, _ = sys.exc_info()
print("In SystemExit") self.log.debug("In SystemExit")
break break
except Exception: except Exception:
_, exc, _ = sys.exc_info() _, exc, _ = sys.exc_info()

View File

@ -74,7 +74,7 @@ Traffic Legend:
WebSocketServer.__init__(self, *args, **kwargs) WebSocketServer.__init__(self, *args, **kwargs)
def run_wrap_cmd(self): 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.append(time.time())
self.wrap_times.pop(0) self.wrap_times.pop(0)
self.cmd = subprocess.Popen( self.cmd = subprocess.Popen(
@ -88,12 +88,12 @@ Traffic Legend:
# Need to call wrapped command after daemonization so we can # Need to call wrapped command after daemonization so we can
# know when the wrapped command exits # know when the wrapped command exits
if self.wrap_cmd: 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, self.listen_host, self.listen_port,
" ".join(self.wrap_cmd), self.target_port)) " ".join(self.wrap_cmd), self.target_port))
self.run_wrap_cmd() self.run_wrap_cmd()
else: 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.listen_host, self.listen_port,
self.target_host, self.target_port)) self.target_host, self.target_port))
@ -118,7 +118,7 @@ Traffic Legend:
if (now - avg) < 10: if (now - avg) < 10:
# 3 times in the last 10 seconds # 3 times in the last 10 seconds
if self.spawn_message: if self.spawn_message:
print("Command respawning too fast") self.log.error("Command respawning too fast")
self.spawn_message = False self.spawn_message = False
else: else:
self.run_wrap_cmd() self.run_wrap_cmd()
@ -145,7 +145,7 @@ Traffic Legend:
connect=True) connect=True)
if self.verbose and not self.daemon: if self.verbose and not self.daemon:
print(self.traffic_legend) self.log.debug(self.traffic_legend)
# Start proxying # Start proxying
try: try:
@ -221,6 +221,11 @@ if __name__ == '__main__':
parser = optparse.OptionParser(usage=usage) parser = optparse.OptionParser(usage=usage)
parser.add_option("--verbose", "-v", action="store_true", parser.add_option("--verbose", "-v", action="store_true",
help="verbose messages and per frame traffic") 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", parser.add_option("--record",
help="record sessions to FILE.[session_number]", metavar="FILE") help="record sessions to FILE.[session_number]", metavar="FILE")
parser.add_option("--daemon", "-D", parser.add_option("--daemon", "-D",