Remove local copies of websockify
This commit removes local copies of websockify. Instead `utils/launch.sh` performs the following logic: If `utils/websockify` exists, use `utils/websockify/run` (if the latter does not exist, or is not executable, fail, since this is probably a mistake). Otherwise, check to see if websockify is installed somewhere (try `which websockify`). If it is, use that. Otherwise, clone websockify from github, and tell git to ignore that directory. Packaged versions of noVNC should simply list websockify as a requirement. The debian packaging has been updated to reflect this. Closes #433
This commit is contained in:
parent
f675e03ccc
commit
6f5148648b
|
@ -8,6 +8,6 @@ Homepage: https://github.com/kanaka/noVNC/
|
||||||
|
|
||||||
Package: novnc
|
Package: novnc
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, python (>= 2.4)
|
Depends: ${shlibs:Depends}, ${misc:Depends}, python (>= 2.4), websockify
|
||||||
Description: HTML5 VNC client
|
Description: HTML5 VNC client
|
||||||
VNC client using HTML5 (WebSockets, Canvas) with encryption (wss://) support.
|
VNC client using HTML5 (WebSockets, Canvas) with encryption (wss://) support.
|
||||||
|
|
|
@ -9,7 +9,7 @@ usage() {
|
||||||
echo
|
echo
|
||||||
echo "Starts the WebSockets proxy and a mini-webserver and "
|
echo "Starts the WebSockets proxy and a mini-webserver and "
|
||||||
echo "provides a cut-and-paste URL to go to."
|
echo "provides a cut-and-paste URL to go to."
|
||||||
echo
|
echo
|
||||||
echo " --listen PORT Port for proxy/webserver to listen on"
|
echo " --listen PORT Port for proxy/webserver to listen on"
|
||||||
echo " Default: 6080"
|
echo " Default: 6080"
|
||||||
echo " --vnc VNC_HOST:PORT VNC server host:port proxy target"
|
echo " --vnc VNC_HOST:PORT VNC server host:port proxy target"
|
||||||
|
@ -101,8 +101,40 @@ else
|
||||||
echo "Warning: could not find self.pem"
|
echo "Warning: could not find self.pem"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# try to find websockify (prefer local, try global, then download local)
|
||||||
|
if [[ -e ${HERE}/websockify ]]; then
|
||||||
|
WEBSOCKIFY=${HERE}/websockify/run
|
||||||
|
|
||||||
|
if [[ ! -x $WEBSOCKIFY ]]; then
|
||||||
|
echo "The path ${HERE}/websockify exists, but $WEBSOCKIFY either does not exist or is not executable."
|
||||||
|
echo "If you inteded to use an installed websockify package, please remove ${HERE}/websockify."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Using local websockify at $WEBSOCKIFY"
|
||||||
|
else
|
||||||
|
WEBSOCKIFY=$(which websockify 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo "No installed websockify, attempting to clone websockify..."
|
||||||
|
WEBSOCKIFY=${HERE}/websockify/run
|
||||||
|
git clone https://github.com/kanaka/websockify
|
||||||
|
git update-index --assume-unchanged websockify
|
||||||
|
|
||||||
|
if [[ ! -e $WEBSOCKIFY ]]; then
|
||||||
|
echo "Unable to locate ${HERE}/websockify/run after downloading"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Using local websockify at $WEBSOCKIFY"
|
||||||
|
else
|
||||||
|
echo "Using installed websockify at $WEBSOCKIFY"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Starting webserver and WebSockets proxy on port ${PORT}"
|
echo "Starting webserver and WebSockets proxy on port ${PORT}"
|
||||||
${HERE}/websockify --web ${WEB} ${CERT:+--cert ${CERT}} ${PORT} ${VNC_DEST} &
|
#${HERE}/websockify --web ${WEB} ${CERT:+--cert ${CERT}} ${PORT} ${VNC_DEST} &
|
||||||
|
${WEBSOCKIFY} --web ${WEB} ${CERT:+--cert ${CERT}} ${PORT} ${VNC_DEST} &
|
||||||
proxy_pid="$!"
|
proxy_pid="$!"
|
||||||
sleep 1
|
sleep 1
|
||||||
if ! ps -p ${proxy_pid} >/dev/null; then
|
if ! ps -p ${proxy_pid} >/dev/null; then
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright (c) 2012 Openstack, LLC.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
'''
|
|
||||||
Websocket proxy that is compatible with Openstack Nova.
|
|
||||||
Leverages websockify by Joel Martin
|
|
||||||
'''
|
|
||||||
|
|
||||||
import Cookie
|
|
||||||
from oslo.config import cfg
|
|
||||||
import socket
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import websockify
|
|
||||||
|
|
||||||
from nova import config
|
|
||||||
from nova import context
|
|
||||||
from nova import utils
|
|
||||||
from nova.openstack.common import rpc
|
|
||||||
|
|
||||||
|
|
||||||
opts = [
|
|
||||||
cfg.BoolOpt('record',
|
|
||||||
default=False,
|
|
||||||
help='Record sessions to FILE.[session_number]'),
|
|
||||||
cfg.BoolOpt('daemon',
|
|
||||||
default=False,
|
|
||||||
help='Become a daemon (background process)'),
|
|
||||||
cfg.BoolOpt('ssl_only',
|
|
||||||
default=False,
|
|
||||||
help='Disallow non-encrypted connections'),
|
|
||||||
cfg.BoolOpt('source_is_ipv6',
|
|
||||||
default=False,
|
|
||||||
help='Source is ipv6'),
|
|
||||||
cfg.StrOpt('cert',
|
|
||||||
default='self.pem',
|
|
||||||
help='SSL certificate file'),
|
|
||||||
cfg.StrOpt('key',
|
|
||||||
default=None,
|
|
||||||
help='SSL key file (if separate from cert)'),
|
|
||||||
cfg.StrOpt('web',
|
|
||||||
default='.',
|
|
||||||
help='Run webserver on same port. Serve files from DIR.'),
|
|
||||||
cfg.StrOpt('novncproxy_host',
|
|
||||||
default='0.0.0.0',
|
|
||||||
help='Host on which to listen for incoming requests'),
|
|
||||||
cfg.IntOpt('novncproxy_port',
|
|
||||||
default=6080,
|
|
||||||
help='Port on which to listen for incoming requests'),
|
|
||||||
]
|
|
||||||
CONF = cfg.CONF
|
|
||||||
CONF.register_cli_opts(opts)
|
|
||||||
|
|
||||||
# As of nova commit 0b11668e64450039dc071a4a123abd02206f865f we must
|
|
||||||
# manually register the rpc library
|
|
||||||
if hasattr(rpc, 'register_opts'):
|
|
||||||
rpc.register_opts(CONF)
|
|
||||||
|
|
||||||
|
|
||||||
class NovaWebSocketProxy(websockify.WebSocketProxy):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
websockify.WebSocketProxy.__init__(self, *args, **kwargs)
|
|
||||||
|
|
||||||
def new_client(self):
|
|
||||||
"""
|
|
||||||
Called after a new WebSocket connection has been established.
|
|
||||||
"""
|
|
||||||
cookie = Cookie.SimpleCookie()
|
|
||||||
cookie.load(self.headers.getheader('cookie'))
|
|
||||||
token = cookie['token'].value
|
|
||||||
ctxt = context.get_admin_context()
|
|
||||||
connect_info = rpc.call(ctxt, 'consoleauth',
|
|
||||||
{'method': 'check_token',
|
|
||||||
'args': {'token': token}})
|
|
||||||
|
|
||||||
if not connect_info:
|
|
||||||
raise Exception("Invalid Token")
|
|
||||||
|
|
||||||
host = connect_info['host']
|
|
||||||
port = int(connect_info['port'])
|
|
||||||
|
|
||||||
# Connect to the target
|
|
||||||
self.msg("connecting to: %s:%s" % (
|
|
||||||
host, port))
|
|
||||||
tsock = self.socket(host, port,
|
|
||||||
connect=True)
|
|
||||||
|
|
||||||
# Handshake as necessary
|
|
||||||
if connect_info.get('internal_access_path'):
|
|
||||||
tsock.send("CONNECT %s HTTP/1.1\r\n\r\n" %
|
|
||||||
connect_info['internal_access_path'])
|
|
||||||
while True:
|
|
||||||
data = tsock.recv(4096, socket.MSG_PEEK)
|
|
||||||
if data.find("\r\n\r\n") != -1:
|
|
||||||
if not data.split("\r\n")[0].find("200"):
|
|
||||||
raise Exception("Invalid Connection Info")
|
|
||||||
tsock.recv(len(data))
|
|
||||||
break
|
|
||||||
|
|
||||||
if self.verbose and not self.daemon:
|
|
||||||
print(self.traffic_legend)
|
|
||||||
|
|
||||||
# Start proxying
|
|
||||||
try:
|
|
||||||
self.do_proxy(tsock)
|
|
||||||
except:
|
|
||||||
if tsock:
|
|
||||||
tsock.shutdown(socket.SHUT_RDWR)
|
|
||||||
tsock.close()
|
|
||||||
self.vmsg("%s:%s: Target closed" % (host, port))
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if CONF.ssl_only and not os.path.exists(CONF.cert):
|
|
||||||
parser.error("SSL only and %s not found" % CONF.cert)
|
|
||||||
|
|
||||||
# Setup flags
|
|
||||||
config.parse_args(sys.argv)
|
|
||||||
|
|
||||||
# Create and start the NovaWebSockets proxy
|
|
||||||
server = NovaWebSocketProxy(listen_host=CONF.novncproxy_host,
|
|
||||||
listen_port=CONF.novncproxy_port,
|
|
||||||
source_is_ipv6=CONF.source_is_ipv6,
|
|
||||||
verbose=CONF.verbose,
|
|
||||||
cert=CONF.cert,
|
|
||||||
key=CONF.key,
|
|
||||||
ssl_only=CONF.ssl_only,
|
|
||||||
daemon=CONF.daemon,
|
|
||||||
record=CONF.record,
|
|
||||||
web=CONF.web,
|
|
||||||
target_host='ignore',
|
|
||||||
target_port='ignore',
|
|
||||||
wrap_mode='exit',
|
|
||||||
wrap_cmd=None)
|
|
||||||
server.start_server()
|
|
18
utils/rebind
18
utils/rebind
|
@ -1,18 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo "Usage: $(basename $0) OLD_PORT NEW_PORT COMMAND_LINE"
|
|
||||||
echo
|
|
||||||
echo "Launch COMMAND_LINE, but intercept system calls to bind"
|
|
||||||
echo "to OLD_PORT and instead bind them to localhost:NEW_PORT"
|
|
||||||
exit 2
|
|
||||||
}
|
|
||||||
|
|
||||||
# Parameter defaults
|
|
||||||
mydir=$(readlink -f $(dirname ${0}))
|
|
||||||
|
|
||||||
export REBIND_PORT_OLD="${1}"; shift
|
|
||||||
export REBIND_PORT_NEW="${1}"; shift
|
|
||||||
|
|
||||||
LD_PRELOAD=${mydir}/rebind.so "${@}"
|
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* rebind: Intercept bind calls and bind to a different port
|
|
||||||
* Copyright 2010 Joel Martin
|
|
||||||
* Licensed under MPL-2.0 (see docs/LICENSE.MPL-2.0)
|
|
||||||
*
|
|
||||||
* Overload (LD_PRELOAD) bind system call. If REBIND_PORT_OLD and
|
|
||||||
* REBIND_PORT_NEW environment variables are set then bind on the new
|
|
||||||
* port (of localhost) instead of the old port.
|
|
||||||
*
|
|
||||||
* This allows a bridge/proxy (such as websockify) to run on the old port and
|
|
||||||
* translate traffic to/from the new port.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* LD_PRELOAD=./rebind.so \
|
|
||||||
* REBIND_PORT_OLD=23 \
|
|
||||||
* REBIND_PORT_NEW=2023 \
|
|
||||||
* program
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#define DO_DEBUG 1
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define __USE_GNU 1 // Pull in RTLD_NEXT
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(DO_DEBUG)
|
|
||||||
#define DEBUG(...) \
|
|
||||||
fprintf(stderr, "wswrapper: "); \
|
|
||||||
fprintf(stderr, __VA_ARGS__);
|
|
||||||
#else
|
|
||||||
#define DEBUG(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
|
||||||
{
|
|
||||||
static void * (*func)();
|
|
||||||
int do_move = 0;
|
|
||||||
struct sockaddr_in * addr_in = (struct sockaddr_in *)addr;
|
|
||||||
struct sockaddr_in addr_tmp;
|
|
||||||
socklen_t addrlen_tmp;
|
|
||||||
char * PORT_OLD, * PORT_NEW, * end1, * end2;
|
|
||||||
int ret, oldport, newport, askport = htons(addr_in->sin_port);
|
|
||||||
uint32_t askaddr = htons(addr_in->sin_addr.s_addr);
|
|
||||||
if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "bind");
|
|
||||||
|
|
||||||
DEBUG(">> bind(%d, _, %d), askaddr %d, askport %d\n",
|
|
||||||
sockfd, addrlen, askaddr, askport);
|
|
||||||
|
|
||||||
/* Determine if we should move this socket */
|
|
||||||
if (addr_in->sin_family == AF_INET) {
|
|
||||||
// TODO: support IPv6
|
|
||||||
PORT_OLD = getenv("REBIND_OLD_PORT");
|
|
||||||
PORT_NEW = getenv("REBIND_NEW_PORT");
|
|
||||||
if (PORT_OLD && (*PORT_OLD != '\0') &&
|
|
||||||
PORT_NEW && (*PORT_NEW != '\0')) {
|
|
||||||
oldport = strtol(PORT_OLD, &end1, 10);
|
|
||||||
newport = strtol(PORT_NEW, &end2, 10);
|
|
||||||
if (oldport && (*end1 == '\0') &&
|
|
||||||
newport && (*end2 == '\0') &&
|
|
||||||
(oldport == askport)) {
|
|
||||||
do_move = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! do_move) {
|
|
||||||
/* Just pass everything right through to the real bind */
|
|
||||||
ret = (int) func(sockfd, addr, addrlen);
|
|
||||||
DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG("binding fd %d on localhost:%d instead of 0x%x:%d\n",
|
|
||||||
sockfd, newport, ntohl(addr_in->sin_addr.s_addr), oldport);
|
|
||||||
|
|
||||||
/* Use a temporary location for the new address information */
|
|
||||||
addrlen_tmp = sizeof(addr_tmp);
|
|
||||||
memcpy(&addr_tmp, addr, addrlen_tmp);
|
|
||||||
|
|
||||||
/* Bind to other port on the loopback instead */
|
|
||||||
addr_tmp.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
||||||
addr_tmp.sin_port = htons(newport);
|
|
||||||
ret = (int) func(sockfd, &addr_tmp, addrlen_tmp);
|
|
||||||
|
|
||||||
DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
1030
utils/websocket.py
1030
utils/websocket.py
File diff suppressed because it is too large
Load Diff
|
@ -1 +0,0 @@
|
||||||
websockify
|
|
|
@ -1 +0,0 @@
|
||||||
websockify
|
|
Loading…
Reference in New Issue