Merge branch 'master' of https://github.com/josedpedroso/websockify
This commit is contained in:
commit
7abd7ac4a9
|
|
@ -0,0 +1,118 @@
|
||||||
|
import logging.handlers as handlers, socket, os, time
|
||||||
|
|
||||||
|
|
||||||
|
class WebsockifySysLogHandler(handlers.SysLogHandler):
|
||||||
|
"""
|
||||||
|
A handler class that sends proper Syslog-formatted messages,
|
||||||
|
as defined by RFC 5424.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_legacy_head_fmt = '<{pri}>{ident}[{pid}]: '
|
||||||
|
_rfc5424_head_fmt = '<{pri}>1 {timestamp} {hostname} {ident} {pid} - - '
|
||||||
|
_head_fmt = _rfc5424_head_fmt
|
||||||
|
_legacy = False
|
||||||
|
_timestamp_fmt = '%Y-%m-%dT%H:%M:%SZ'
|
||||||
|
_max_hostname = 255
|
||||||
|
_max_ident = 24 #safer for old daemons
|
||||||
|
_send_length = False
|
||||||
|
_tail = '\n'
|
||||||
|
|
||||||
|
|
||||||
|
ident = None
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, address=('localhost', handlers.SYSLOG_UDP_PORT),
|
||||||
|
facility=handlers.SysLogHandler.LOG_USER,
|
||||||
|
socktype=None, ident=None, legacy=False):
|
||||||
|
"""
|
||||||
|
Initialize a handler.
|
||||||
|
|
||||||
|
If address is specified as a string, a UNIX socket is used. To log to a
|
||||||
|
local syslogd, "WebsockifySysLogHandler(address="/dev/log")" can be
|
||||||
|
used. If facility is not specified, LOG_USER is used. If socktype is
|
||||||
|
specified as socket.SOCK_DGRAM or socket.SOCK_STREAM, that specific
|
||||||
|
socket type will be used. For Unix sockets, you can also specify a
|
||||||
|
socktype of None, in which case socket.SOCK_DGRAM will be used, falling
|
||||||
|
back to socket.SOCK_STREAM. If ident is specified, this string will be
|
||||||
|
used as the application name in all messages sent. Set legacy to True
|
||||||
|
to use the old version of the protocol.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.ident = ident
|
||||||
|
|
||||||
|
if legacy:
|
||||||
|
self._legacy = True
|
||||||
|
self._head_fmt = self._legacy_head_fmt
|
||||||
|
|
||||||
|
handlers.SysLogHandler.__init__(self, address, facility, socktype)
|
||||||
|
|
||||||
|
|
||||||
|
def emit(self, record):
|
||||||
|
"""
|
||||||
|
Emit a record.
|
||||||
|
|
||||||
|
The record is formatted, and then sent to the syslog server. If
|
||||||
|
exception information is present, it is NOT sent to the server.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Gather info.
|
||||||
|
text = self.format(record).replace(self._tail, ' ')
|
||||||
|
if not text: # nothing to log
|
||||||
|
return
|
||||||
|
|
||||||
|
pri = self.encodePriority(self.facility,
|
||||||
|
self.mapPriority(record.levelname))
|
||||||
|
|
||||||
|
timestamp = time.strftime(self._timestamp_fmt, time.gmtime());
|
||||||
|
|
||||||
|
hostname = socket.gethostname()[:self._max_hostname]
|
||||||
|
|
||||||
|
if self.ident:
|
||||||
|
ident = self.ident[:self._max_ident]
|
||||||
|
else:
|
||||||
|
ident = ''
|
||||||
|
|
||||||
|
pid = os.getpid() # shouldn't need truncation
|
||||||
|
|
||||||
|
# Format the header.
|
||||||
|
head = {
|
||||||
|
'pri': pri,
|
||||||
|
'timestamp': timestamp,
|
||||||
|
'hostname': hostname,
|
||||||
|
'ident': ident,
|
||||||
|
'pid': pid,
|
||||||
|
}
|
||||||
|
msg = self._head_fmt.format(**head).encode('ascii', 'ignore')
|
||||||
|
|
||||||
|
# Encode text as plain ASCII if possible, else use UTF-8 with BOM.
|
||||||
|
try:
|
||||||
|
msg += text.encode('ascii')
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
msg += text.encode('utf-8-sig')
|
||||||
|
|
||||||
|
# Add length or tail character, if necessary.
|
||||||
|
if self.socktype != socket.SOCK_DGRAM:
|
||||||
|
if self._send_length:
|
||||||
|
msg = ('%d ' % len(msg)).encode('ascii') + msg
|
||||||
|
else:
|
||||||
|
msg += self._tail.encode('ascii')
|
||||||
|
|
||||||
|
# Send the message.
|
||||||
|
if self.unixsocket:
|
||||||
|
try:
|
||||||
|
self.socket.send(msg)
|
||||||
|
except socket.error:
|
||||||
|
self._connect_unixsocket(self.address)
|
||||||
|
self.socket.send(msg)
|
||||||
|
|
||||||
|
else:
|
||||||
|
if self.socktype == socket.SOCK_DGRAM:
|
||||||
|
self.socket.sendto(msg, self.address)
|
||||||
|
else:
|
||||||
|
self.socket.sendall(msg)
|
||||||
|
|
||||||
|
except (KeyboardInterrupt, SystemExit):
|
||||||
|
raise
|
||||||
|
except:
|
||||||
|
self.handleError(record)
|
||||||
|
|
@ -146,8 +146,15 @@ Traffic Legend:
|
||||||
# in the form of token: host:port
|
# in the form of token: host:port
|
||||||
|
|
||||||
if self.host_token:
|
if self.host_token:
|
||||||
|
# Use hostname as token
|
||||||
token = self.headers.get('Host')
|
token = self.headers.get('Host')
|
||||||
|
|
||||||
|
# Remove port from hostname, as it'll always be the one where
|
||||||
|
# websockify listens (unless something between the client and
|
||||||
|
# websockify is redirecting traffic, but that's beside the point)
|
||||||
|
if token:
|
||||||
|
token = token.partition(':')[0]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Extract the token parameter from url
|
# Extract the token parameter from url
|
||||||
args = parse_qs(urlparse(self.path)[4]) # 4 is the query from url
|
args = parse_qs(urlparse(self.path)[4]) # 4 is the query from url
|
||||||
|
|
@ -530,12 +537,38 @@ def websockify_init():
|
||||||
parser.add_option("--syslog", default=None, metavar="SERVER",
|
parser.add_option("--syslog", default=None, metavar="SERVER",
|
||||||
help="Log to syslog server. SERVER can be local socket, "
|
help="Log to syslog server. SERVER can be local socket, "
|
||||||
"such as /dev/log, or a UDP host:port pair.")
|
"such as /dev/log, or a UDP host:port pair.")
|
||||||
|
parser.add_option("--legacy-syslog", action="store_true",
|
||||||
|
help="Use the old syslog protocol instead of RFC 5424. "
|
||||||
|
"Use this if the messages produced by websockify seem abnormal.")
|
||||||
|
|
||||||
(opts, args) = parser.parse_args()
|
(opts, args) = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
# Validate options.
|
||||||
|
|
||||||
|
if opts.token_source and not opts.token_plugin:
|
||||||
|
parser.error("You must use --token-plugin to use --token-source")
|
||||||
|
|
||||||
|
if opts.host_token and not opts.token_plugin:
|
||||||
|
parser.error("You must use --token-plugin to use --host-token")
|
||||||
|
|
||||||
|
if opts.auth_source and not opts.auth_plugin:
|
||||||
|
parser.error("You must use --auth-plugin to use --auth-source")
|
||||||
|
|
||||||
|
if opts.web_auth and not opts.auth_plugin:
|
||||||
|
parser.error("You must use --auth-plugin to use --web-auth")
|
||||||
|
|
||||||
|
if opts.web_auth and not opts.web:
|
||||||
|
parser.error("You must use --web to use --web-auth")
|
||||||
|
|
||||||
|
if opts.legacy_syslog and not opts.syslog:
|
||||||
|
parser.error("You must use --syslog to use --legacy-syslog")
|
||||||
|
|
||||||
|
|
||||||
opts.ssl_options = select_ssl_version(opts.ssl_version)
|
opts.ssl_options = select_ssl_version(opts.ssl_version)
|
||||||
del opts.ssl_version
|
del opts.ssl_version
|
||||||
|
|
||||||
|
|
||||||
if opts.log_file:
|
if opts.log_file:
|
||||||
# Setup logging to user-specified file.
|
# Setup logging to user-specified file.
|
||||||
opts.log_file = os.path.abspath(opts.log_file)
|
opts.log_file = os.path.abspath(opts.log_file)
|
||||||
|
|
@ -560,44 +593,30 @@ def websockify_init():
|
||||||
# User supplied a local socket file.
|
# User supplied a local socket file.
|
||||||
syslog_dest = os.path.abspath(opts.syslog)
|
syslog_dest = os.path.abspath(opts.syslog)
|
||||||
|
|
||||||
from logging.handlers import SysLogHandler
|
from websockify.sysloghandler import WebsockifySysLogHandler
|
||||||
|
|
||||||
# Determine syslog facility.
|
# Determine syslog facility.
|
||||||
if opts.daemon:
|
if opts.daemon:
|
||||||
syslog_facility = SysLogHandler.LOG_DAEMON
|
syslog_facility = WebsockifySysLogHandler.LOG_DAEMON
|
||||||
else:
|
else:
|
||||||
syslog_facility = SysLogHandler.LOG_USER
|
syslog_facility = WebsockifySysLogHandler.LOG_USER
|
||||||
|
|
||||||
# Start logging to syslog.
|
# Start logging to syslog.
|
||||||
syslog_handler = SysLogHandler(address=syslog_dest, facility=syslog_facility)
|
syslog_handler = WebsockifySysLogHandler(address=syslog_dest,
|
||||||
|
facility=syslog_facility,
|
||||||
|
ident='websockify',
|
||||||
|
legacy=opts.legacy_syslog)
|
||||||
syslog_handler.setLevel(logging.DEBUG)
|
syslog_handler.setLevel(logging.DEBUG)
|
||||||
syslog_handler.setFormatter(log_formatter)
|
syslog_handler.setFormatter(log_formatter)
|
||||||
logger.addHandler(syslog_handler)
|
logger.addHandler(syslog_handler)
|
||||||
|
|
||||||
del opts.syslog
|
del opts.syslog
|
||||||
|
del opts.legacy_syslog
|
||||||
|
|
||||||
if opts.verbose:
|
if opts.verbose:
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
# Validate options.
|
|
||||||
|
|
||||||
if opts.token_source and not opts.token_plugin:
|
|
||||||
parser.error("You must use --token-plugin to use --token-source")
|
|
||||||
|
|
||||||
if opts.host_token and not opts.token_plugin:
|
|
||||||
parser.error("You must use --token-plugin to use --host-token")
|
|
||||||
|
|
||||||
if opts.auth_source and not opts.auth_plugin:
|
|
||||||
parser.error("You must use --auth-plugin to use --auth-source")
|
|
||||||
|
|
||||||
if opts.web_auth and not opts.auth_plugin:
|
|
||||||
parser.error("You must use --auth-plugin to use --web-auth")
|
|
||||||
|
|
||||||
if opts.web_auth and not opts.web:
|
|
||||||
parser.error("You must use --web to use --web-auth")
|
|
||||||
|
|
||||||
|
|
||||||
# Transform to absolute path as daemon may chdir
|
# Transform to absolute path as daemon may chdir
|
||||||
if opts.target_cfg:
|
if opts.target_cfg:
|
||||||
opts.target_cfg = os.path.abspath(opts.target_cfg)
|
opts.target_cfg = os.path.abspath(opts.target_cfg)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue