Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
N
noVNC
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
rasky
noVNC
Commits
fc003a13
Commit
fc003a13
authored
Aug 15, 2012
by
Joel Martin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Pull in latest websockify."
This reverts commit
4dd1bb1e
.
parent
ca6b3f4c
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
127 additions
and
301 deletions
+127
-301
websock.js
include/websock.js
+20
-83
websocket.py
utils/websocket.py
+89
-105
websockify
utils/websockify
+18
-113
No files found.
include/websock.js
View file @
fc003a13
...
@@ -61,8 +61,6 @@ function Websock() {
...
@@ -61,8 +61,6 @@ function Websock() {
var
api
=
{},
// Public API
var
api
=
{},
// Public API
websocket
=
null
,
// WebSocket object
websocket
=
null
,
// WebSocket object
protocols
,
// Protocols to request in priority order
mode
=
'base64'
,
rQ
=
[],
// Receive queue
rQ
=
[],
// Receive queue
rQi
=
0
,
// Receive queue index
rQi
=
0
,
// Receive queue index
rQmax
=
10000
,
// Max receive queue size before compacting
rQmax
=
10000
,
// Max receive queue size before compacting
...
@@ -125,46 +123,26 @@ function rQshift32() {
...
@@ -125,46 +123,26 @@ function rQshift32() {
(
rQ
[
rQi
++
]
<<
8
)
+
(
rQ
[
rQi
++
]
<<
8
)
+
(
rQ
[
rQi
++
]
);
(
rQ
[
rQi
++
]
);
}
}
function
rQslice
(
start
,
end
)
{
if
(
mode
===
'binary'
)
{
if
(
end
)
{
return
rQ
.
subarray
(
rQi
+
start
,
rQi
+
end
);
}
else
{
return
rQ
.
subarray
(
rQi
+
start
);
}
}
else
{
if
(
end
)
{
return
rQ
.
slice
(
rQi
+
start
,
rQi
+
end
);
}
else
{
return
rQ
.
slice
(
rQi
+
start
);
}
}
}
function
rQshiftStr
(
len
)
{
function
rQshiftStr
(
len
)
{
if
(
typeof
(
len
)
===
'undefined'
)
{
len
=
rQlen
();
}
if
(
typeof
(
len
)
===
'undefined'
)
{
len
=
rQlen
();
}
var
arr
=
rQ
slice
(
0
,
len
);
var
arr
=
rQ
.
slice
(
rQi
,
rQi
+
len
);
rQi
+=
len
;
rQi
+=
len
;
return
String
.
fromCharCode
.
apply
(
null
,
arr
);
return
arr
.
map
(
function
(
num
)
{
return
String
.
fromCharCode
(
num
);
}
).
join
(
''
);
}
}
function
rQshiftBytes
(
len
)
{
function
rQshiftBytes
(
len
)
{
if
(
typeof
(
len
)
===
'undefined'
)
{
len
=
rQlen
();
}
if
(
typeof
(
len
)
===
'undefined'
)
{
len
=
rQlen
();
}
var
a
=
rQslice
(
0
,
len
),
b
=
[];
if
(
mode
===
'binary'
)
{
// Convert to plain array
b
.
push
.
apply
(
b
,
a
);
}
else
{
// Already plain array, just return the original
b
=
a
}
rQi
+=
len
;
rQi
+=
len
;
return
b
;
return
rQ
.
slice
(
rQi
-
len
,
rQi
)
;
}
}
function
rQshiftArray
(
len
)
{
if
(
typeof
(
len
)
===
'undefined'
)
{
len
=
rQlen
();
}
function
rQslice
(
start
,
end
)
{
var
a
=
rQslice
(
0
,
len
);
if
(
end
)
{
rQi
+=
len
;
return
rQ
.
slice
(
rQi
+
start
,
rQi
+
end
);
return
a
;
}
else
{
return
rQ
.
slice
(
rQi
+
start
);
}
}
}
// Check to see if we must wait for 'num' bytes (default to FBU.bytes)
// Check to see if we must wait for 'num' bytes (default to FBU.bytes)
...
@@ -192,26 +170,13 @@ function rQwait(msg, num, goback) {
...
@@ -192,26 +170,13 @@ function rQwait(msg, num, goback) {
function
encode_message
()
{
function
encode_message
()
{
/* base64 encode */
/* base64 encode */
if
(
mode
===
'binary'
)
{
return
(
new
Uint8Array
(
sQ
)).
buffer
;
}
else
{
return
Base64
.
encode
(
sQ
);
return
Base64
.
encode
(
sQ
);
}
}
}
function
decode_message
(
data
)
{
function
decode_message
(
data
)
{
//Util.Debug(">> decode_message: " + data);
//Util.Debug(">> decode_message: " + data);
if
(
mode
===
'binary'
)
{
/* base64 decode */
// Create new arraybuffer and dump old and new data into it
// TODO: this could be far more efficient and re-use the array
var
new_rQ
=
new
Uint8Array
(
rQ
.
length
+
data
.
byteLength
);
new_rQ
.
set
(
rQ
);
new_rQ
.
set
(
new
Uint8Array
(
data
),
rQ
.
length
);
rQ
=
new_rQ
;
}
else
{
/* base64 decode and concat to the end */
rQ
=
rQ
.
concat
(
Base64
.
decode
(
data
,
0
));
rQ
=
rQ
.
concat
(
Base64
.
decode
(
data
,
0
));
}
//Util.Debug(">> decode_message, rQ: " + rQ);
//Util.Debug(">> decode_message, rQ: " + rQ);
}
}
...
@@ -265,7 +230,7 @@ function recv_message(e) {
...
@@ -265,7 +230,7 @@ function recv_message(e) {
// Compact the receive queue
// Compact the receive queue
if
(
rQ
.
length
>
rQmax
)
{
if
(
rQ
.
length
>
rQmax
)
{
//Util.Debug("Compacting receive queue");
//Util.Debug("Compacting receive queue");
rQ
=
rQslice
(
rQi
);
rQ
=
rQ
.
slice
(
rQi
);
rQi
=
0
;
rQi
=
0
;
}
}
}
else
{
}
else
{
...
@@ -298,32 +263,7 @@ function init() {
...
@@ -298,32 +263,7 @@ function init() {
rQ
=
[];
rQ
=
[];
rQi
=
0
;
rQi
=
0
;
sQ
=
[];
sQ
=
[];
websocket
=
null
,
websocket
=
null
;
protocols
=
"base64"
;
var
bt
=
false
,
wsbt
=
false
;
if
((
'Uint8Array'
in
window
)
&&
(
'set'
in
Uint8Array
.
prototype
))
{
bt
=
true
;
}
// TODO: this sucks, the property should exist on the prototype
// but it does not.
try
{
if
(
bt
&&
(
'binaryType'
in
(
new
WebSocket
(
"ws://localhost:17523"
))))
{
wsbt
=
true
;
}
}
catch
(
exc
)
{
// Just ignore failed test localhost connections
}
if
(
bt
&&
wsbt
)
{
Util
.
Info
(
"Detected binaryType support in WebSockets"
);
protocols
=
[
'binary'
,
'base64'
];
}
else
{
Util
.
Info
(
"No binaryType support in WebSockets, using base64 encoding"
);
protocols
=
'base64'
;
}
}
}
function
open
(
uri
)
{
function
open
(
uri
)
{
...
@@ -332,22 +272,19 @@ function open(uri) {
...
@@ -332,22 +272,19 @@ function open(uri) {
if
(
test_mode
)
{
if
(
test_mode
)
{
websocket
=
{};
websocket
=
{};
}
else
{
}
else
{
websocket
=
new
WebSocket
(
uri
,
protocols
);
websocket
=
new
WebSocket
(
uri
,
'base64'
);
// TODO: future native binary support
//websocket = new WebSocket(uri, ['binary', 'base64']);
}
}
websocket
.
onmessage
=
recv_message
;
websocket
.
onmessage
=
recv_message
;
websocket
.
onopen
=
function
()
{
websocket
.
onopen
=
function
()
{
Util
.
Debug
(
">> WebSock.onopen"
);
Util
.
Debug
(
">> WebSock.onopen"
);
if
(
websocket
.
protocol
)
{
if
(
websocket
.
protocol
)
{
mode
=
websocket
.
protocol
;
Util
.
Info
(
"Server chose sub-protocol: "
+
websocket
.
protocol
);
Util
.
Info
(
"Server chose sub-protocol: "
+
websocket
.
protocol
);
}
else
{
}
else
{
mode
=
'base64'
;
Util
.
Error
(
"Server select no sub-protocol!: "
+
websocket
.
protocol
);
Util
.
Error
(
"Server select no sub-protocol!: "
+
websocket
.
protocol
);
}
}
if
(
mode
===
'binary'
)
{
websocket
.
binaryType
=
'arraybuffer'
;
}
eventHandlers
.
open
();
eventHandlers
.
open
();
Util
.
Debug
(
"<< WebSock.onopen"
);
Util
.
Debug
(
"<< WebSock.onopen"
);
};
};
...
...
utils/websocket.py
View file @
fc003a13
...
@@ -18,6 +18,7 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
...
@@ -18,6 +18,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
array
,
struct
import
array
,
struct
from
cgi
import
parse_qsl
from
base64
import
b64encode
,
b64decode
from
base64
import
b64encode
,
b64decode
# Imports that vary by python version
# Imports that vary by python version
...
@@ -35,6 +36,8 @@ try: from io import StringIO
...
@@ -35,6 +36,8 @@ try: from io import StringIO
except
:
from
cStringIO
import
StringIO
except
:
from
cStringIO
import
StringIO
try
:
from
http.server
import
SimpleHTTPRequestHandler
try
:
from
http.server
import
SimpleHTTPRequestHandler
except
:
from
SimpleHTTPServer
import
SimpleHTTPRequestHandler
except
:
from
SimpleHTTPServer
import
SimpleHTTPRequestHandler
try
:
from
urllib.parse
import
urlsplit
except
:
from
urlparse
import
urlsplit
# python 2.6 differences
# python 2.6 differences
try
:
from
hashlib
import
md5
,
sha1
try
:
from
hashlib
import
md5
,
sha1
...
@@ -72,7 +75,6 @@ class WebSocketServer(object):
...
@@ -72,7 +75,6 @@ class WebSocketServer(object):
buffer_size
=
65536
buffer_size
=
65536
server_handshake_hixie
=
"""HTTP/1.1 101 Web Socket Protocol Handshake
\r
server_handshake_hixie
=
"""HTTP/1.1 101 Web Socket Protocol Handshake
\r
Upgrade: WebSocket
\r
Upgrade: WebSocket
\r
Connection: Upgrade
\r
Connection: Upgrade
\r
...
@@ -107,7 +109,6 @@ Sec-WebSocket-Accept: %s\r
...
@@ -107,7 +109,6 @@ Sec-WebSocket-Accept: %s\r
self
.
verbose
=
verbose
self
.
verbose
=
verbose
self
.
listen_host
=
listen_host
self
.
listen_host
=
listen_host
self
.
listen_port
=
listen_port
self
.
listen_port
=
listen_port
self
.
prefer_ipv6
=
source_is_ipv6
self
.
ssl_only
=
ssl_only
self
.
ssl_only
=
ssl_only
self
.
daemon
=
daemon
self
.
daemon
=
daemon
self
.
run_once
=
run_once
self
.
run_once
=
run_once
...
@@ -162,7 +163,7 @@ Sec-WebSocket-Accept: %s\r
...
@@ -162,7 +163,7 @@ Sec-WebSocket-Accept: %s\r
#
#
@
staticmethod
@
staticmethod
def
socket
(
host
,
port
=
None
,
connect
=
False
,
prefer_ipv6
=
False
,
unix_socket
=
None
,
use_ssl
=
False
):
def
socket
(
host
,
port
=
None
,
connect
=
False
,
prefer_ipv6
=
False
):
""" Resolve a host (and optional port) to an IPv4 or IPv6
""" Resolve a host (and optional port) to an IPv4 or IPv6
address. Create a socket. Bind to it if listen is set,
address. Create a socket. Bind to it if listen is set,
otherwise connect to it. Return the socket.
otherwise connect to it. Return the socket.
...
@@ -170,36 +171,24 @@ Sec-WebSocket-Accept: %s\r
...
@@ -170,36 +171,24 @@ Sec-WebSocket-Accept: %s\r
flags
=
0
flags
=
0
if
host
==
''
:
if
host
==
''
:
host
=
None
host
=
None
if
connect
and
not
(
port
or
unix_socket
)
:
if
connect
and
not
port
:
raise
Exception
(
"Connect mode requires a port"
)
raise
Exception
(
"Connect mode requires a port"
)
if
use_ssl
and
not
ssl
:
raise
Exception
(
"SSL socket requested but Python SSL module not loaded."
);
if
not
connect
and
use_ssl
:
raise
Exception
(
"SSL only supported in connect mode (for now)"
)
if
not
connect
:
if
not
connect
:
flags
=
flags
|
socket
.
AI_PASSIVE
flags
=
flags
|
socket
.
AI_PASSIVE
if
not
unix_socket
:
addrs
=
socket
.
getaddrinfo
(
host
,
port
,
0
,
socket
.
SOCK_STREAM
,
addrs
=
socket
.
getaddrinfo
(
host
,
port
,
0
,
socket
.
SOCK_STREAM
,
socket
.
IPPROTO_TCP
,
flags
)
socket
.
IPPROTO_TCP
,
flags
)
if
not
addrs
:
if
not
addrs
:
raise
Exception
(
"Could not
resolve host '
%
s'"
%
host
)
raise
Exception
(
"Could
resolve host '
%
s'"
%
host
)
addrs
.
sort
(
key
=
lambda
x
:
x
[
0
])
addrs
.
sort
(
key
=
lambda
x
:
x
[
0
])
if
prefer_ipv6
:
if
prefer_ipv6
:
addrs
.
reverse
()
addrs
.
reverse
()
sock
=
socket
.
socket
(
addrs
[
0
][
0
],
addrs
[
0
][
1
])
sock
=
socket
.
socket
(
addrs
[
0
][
0
],
addrs
[
0
][
1
])
if
connect
:
if
connect
:
sock
.
connect
(
addrs
[
0
][
4
])
sock
.
connect
(
addrs
[
0
][
4
])
if
use_ssl
:
sock
=
ssl
.
wrap_socket
(
sock
)
else
:
else
:
sock
.
setsockopt
(
socket
.
SOL_SOCKET
,
socket
.
SO_REUSEADDR
,
1
)
sock
.
setsockopt
(
socket
.
SOL_SOCKET
,
socket
.
SO_REUSEADDR
,
1
)
sock
.
bind
(
addrs
[
0
][
4
])
sock
.
bind
(
addrs
[
0
][
4
])
sock
.
listen
(
100
)
sock
.
listen
(
100
)
else
:
sock
=
socket
.
socket
(
socket
.
AF_UNIX
,
socket
.
SOCK_STREAM
)
sock
.
connect
(
unix_socket
)
return
sock
return
sock
@
staticmethod
@
staticmethod
...
@@ -563,72 +552,6 @@ Sec-WebSocket-Accept: %s\r
...
@@ -563,72 +552,6 @@ Sec-WebSocket-Accept: %s\r
# No orderly close for 75
# No orderly close for 75
def
do_websocket_handshake
(
self
,
headers
,
path
):
h
=
self
.
headers
=
headers
self
.
path
=
path
prot
=
'WebSocket-Protocol'
protocols
=
h
.
get
(
'Sec-'
+
prot
,
h
.
get
(
prot
,
''
))
.
split
(
','
)
ver
=
h
.
get
(
'Sec-WebSocket-Version'
)
if
ver
:
# HyBi/IETF version of the protocol
# HyBi-07 report version 7
# HyBi-08 - HyBi-12 report version 8
# HyBi-13 reports version 13
if
ver
in
[
'7'
,
'8'
,
'13'
]:
self
.
version
=
"hybi-
%02
d"
%
int
(
ver
)
else
:
raise
self
.
EClose
(
'Unsupported protocol version
%
s'
%
ver
)
key
=
h
[
'Sec-WebSocket-Key'
]
# Choose binary if client supports it
if
'binary'
in
protocols
:
self
.
base64
=
False
elif
'base64'
in
protocols
:
self
.
base64
=
True
else
:
raise
self
.
EClose
(
"Client must support 'binary' or 'base64' protocol"
)
# Generate the hash value for the accept header
accept
=
b64encode
(
sha1
(
s2b
(
key
+
self
.
GUID
))
.
digest
())
response
=
self
.
server_handshake_hybi
%
b2s
(
accept
)
if
self
.
base64
:
response
+=
"Sec-WebSocket-Protocol: base64
\r\n
"
else
:
response
+=
"Sec-WebSocket-Protocol: binary
\r\n
"
response
+=
"
\r\n
"
else
:
# Hixie version of the protocol (75 or 76)
if
h
.
get
(
'key3'
):
trailer
=
self
.
gen_md5
(
h
)
pre
=
"Sec-"
self
.
version
=
"hixie-76"
else
:
trailer
=
""
pre
=
""
self
.
version
=
"hixie-75"
# We only support base64 in Hixie era
self
.
base64
=
True
response
=
self
.
server_handshake_hixie
%
(
pre
,
h
[
'Origin'
],
pre
,
self
.
scheme
,
h
[
'Host'
],
path
)
if
'base64'
in
protocols
:
response
+=
"
%
sWebSocket-Protocol: base64
\r\n
"
%
pre
else
:
self
.
msg
(
"Warning: client does not report 'base64' protocol support"
)
response
+=
"
\r\n
"
+
trailer
return
response
def
do_handshake
(
self
,
sock
,
address
):
def
do_handshake
(
self
,
sock
,
address
):
"""
"""
do_handshake does the following:
do_handshake does the following:
...
@@ -646,10 +569,10 @@ Sec-WebSocket-Accept: %s\r
...
@@ -646,10 +569,10 @@ Sec-WebSocket-Accept: %s\r
- Send a WebSockets handshake server response.
- Send a WebSockets handshake server response.
- Return the socket for this WebSocket client.
- Return the socket for this WebSocket client.
"""
"""
stype
=
""
ready
=
select
.
select
([
sock
],
[],
[],
3
)[
0
]
stype
=
""
ready
=
select
.
select
([
sock
],
[],
[],
3
)[
0
]
if
not
ready
:
if
not
ready
:
raise
self
.
EClose
(
"ignoring socket not ready"
)
raise
self
.
EClose
(
"ignoring socket not ready"
)
# Peek, but do not read the data so that we have a opportunity
# Peek, but do not read the data so that we have a opportunity
...
@@ -690,7 +613,7 @@ Sec-WebSocket-Accept: %s\r
...
@@ -690,7 +613,7 @@ Sec-WebSocket-Accept: %s\r
else
:
else
:
raise
raise
s
elf
.
s
cheme
=
"wss"
scheme
=
"wss"
stype
=
"SSL/TLS (wss://)"
stype
=
"SSL/TLS (wss://)"
elif
self
.
ssl_only
:
elif
self
.
ssl_only
:
...
@@ -698,7 +621,7 @@ Sec-WebSocket-Accept: %s\r
...
@@ -698,7 +621,7 @@ Sec-WebSocket-Accept: %s\r
else
:
else
:
retsock
=
sock
retsock
=
sock
s
elf
.
s
cheme
=
"ws"
scheme
=
"ws"
stype
=
"Plain non-SSL (ws://)"
stype
=
"Plain non-SSL (ws://)"
wsh
=
WSRequestHandler
(
retsock
,
address
,
not
self
.
web
)
wsh
=
WSRequestHandler
(
retsock
,
address
,
not
self
.
web
)
...
@@ -714,7 +637,67 @@ Sec-WebSocket-Accept: %s\r
...
@@ -714,7 +637,67 @@ Sec-WebSocket-Accept: %s\r
else
:
else
:
raise
self
.
EClose
(
""
)
raise
self
.
EClose
(
""
)
response
=
self
.
do_websocket_handshake
(
wsh
.
headers
,
wsh
.
path
)
h
=
self
.
headers
=
wsh
.
headers
path
=
self
.
path
=
wsh
.
path
prot
=
'WebSocket-Protocol'
protocols
=
h
.
get
(
'Sec-'
+
prot
,
h
.
get
(
prot
,
''
))
.
split
(
','
)
ver
=
h
.
get
(
'Sec-WebSocket-Version'
)
if
ver
:
# HyBi/IETF version of the protocol
# HyBi-07 report version 7
# HyBi-08 - HyBi-12 report version 8
# HyBi-13 reports version 13
if
ver
in
[
'7'
,
'8'
,
'13'
]:
self
.
version
=
"hybi-
%02
d"
%
int
(
ver
)
else
:
raise
self
.
EClose
(
'Unsupported protocol version
%
s'
%
ver
)
key
=
h
[
'Sec-WebSocket-Key'
]
# Choose binary if client supports it
if
'binary'
in
protocols
:
self
.
base64
=
False
elif
'base64'
in
protocols
:
self
.
base64
=
True
else
:
raise
self
.
EClose
(
"Client must support 'binary' or 'base64' protocol"
)
# Generate the hash value for the accept header
accept
=
b64encode
(
sha1
(
s2b
(
key
+
self
.
GUID
))
.
digest
())
response
=
self
.
server_handshake_hybi
%
b2s
(
accept
)
if
self
.
base64
:
response
+=
"Sec-WebSocket-Protocol: base64
\r\n
"
else
:
response
+=
"Sec-WebSocket-Protocol: binary
\r\n
"
response
+=
"
\r\n
"
else
:
# Hixie version of the protocol (75 or 76)
if
h
.
get
(
'key3'
):
trailer
=
self
.
gen_md5
(
h
)
pre
=
"Sec-"
self
.
version
=
"hixie-76"
else
:
trailer
=
""
pre
=
""
self
.
version
=
"hixie-75"
# We only support base64 in Hixie era
self
.
base64
=
True
response
=
self
.
server_handshake_hixie
%
(
pre
,
h
[
'Origin'
],
pre
,
scheme
,
h
[
'Host'
],
path
)
if
'base64'
in
protocols
:
response
+=
"
%
sWebSocket-Protocol: base64
\r\n
"
%
pre
else
:
self
.
msg
(
"Warning: client does not report 'base64' protocol support"
)
response
+=
"
\r\n
"
+
trailer
self
.
msg
(
"
%
s:
%
s WebSocket connection"
%
(
address
[
0
],
stype
))
self
.
msg
(
"
%
s:
%
s WebSocket connection"
%
(
address
[
0
],
stype
))
self
.
msg
(
"
%
s: Version
%
s, base64: '
%
s'"
%
(
address
[
0
],
self
.
msg
(
"
%
s: Version
%
s, base64: '
%
s'"
%
(
address
[
0
],
...
@@ -818,7 +801,7 @@ Sec-WebSocket-Accept: %s\r
...
@@ -818,7 +801,7 @@ Sec-WebSocket-Accept: %s\r
is a WebSockets client then call new_client() method (which must
is a WebSockets client then call new_client() method (which must
be overridden) for each new client connection.
be overridden) for each new client connection.
"""
"""
lsock
=
self
.
socket
(
self
.
listen_host
,
self
.
listen_port
,
False
,
self
.
prefer_ipv6
)
lsock
=
self
.
socket
(
self
.
listen_host
,
self
.
listen_port
)
if
self
.
daemon
:
if
self
.
daemon
:
self
.
daemonize
(
keepfd
=
lsock
.
fileno
(),
chdir
=
self
.
web
)
self
.
daemonize
(
keepfd
=
lsock
.
fileno
(),
chdir
=
self
.
web
)
...
@@ -944,3 +927,4 @@ class WSRequestHandler(SimpleHTTPRequestHandler):
...
@@ -944,3 +927,4 @@ class WSRequestHandler(SimpleHTTPRequestHandler):
def
log_message
(
self
,
f
,
*
args
):
def
log_message
(
self
,
f
,
*
args
):
# Save instead of printing
# Save instead of printing
self
.
last_message
=
f
%
args
self
.
last_message
=
f
%
args
utils/websockify
View file @
fc003a13
...
@@ -13,11 +13,9 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
...
@@ -13,11 +13,9 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
import
socket
,
optparse
,
time
,
os
,
sys
,
subprocess
import
socket
,
optparse
,
time
,
os
,
sys
,
subprocess
from
select
import
select
from
select
import
select
import
websocket
from
websocket
import
WebSocketServer
try
:
from
urllib.parse
import
parse_qs
,
urlparse
except
:
from
urlparse
import
parse_qs
,
urlparse
class
WebSocketProxy
(
websocket
.
WebSocketServer
):
class
WebSocketProxy
(
WebSocketServer
):
"""
"""
Proxy traffic to and from a WebSockets client to a normal TCP
Proxy traffic to and from a WebSockets client to a normal TCP
socket server target. All traffic to/from the client is base64
socket server target. All traffic to/from the client is base64
...
@@ -45,9 +43,6 @@ Traffic Legend:
...
@@ -45,9 +43,6 @@ Traffic Legend:
self
.
target_port
=
kwargs
.
pop
(
'target_port'
)
self
.
target_port
=
kwargs
.
pop
(
'target_port'
)
self
.
wrap_cmd
=
kwargs
.
pop
(
'wrap_cmd'
)
self
.
wrap_cmd
=
kwargs
.
pop
(
'wrap_cmd'
)
self
.
wrap_mode
=
kwargs
.
pop
(
'wrap_mode'
)
self
.
wrap_mode
=
kwargs
.
pop
(
'wrap_mode'
)
self
.
unix_target
=
kwargs
.
pop
(
'unix_target'
)
self
.
ssl_target
=
kwargs
.
pop
(
'ssl_target'
)
self
.
target_cfg
=
kwargs
.
pop
(
'target_cfg'
)
# Last 3 timestamps command was run
# Last 3 timestamps command was run
self
.
wrap_times
=
[
0
,
0
,
0
]
self
.
wrap_times
=
[
0
,
0
,
0
]
...
@@ -63,7 +58,6 @@ Traffic Legend:
...
@@ -63,7 +58,6 @@ Traffic Legend:
if
not
self
.
rebinder
:
if
not
self
.
rebinder
:
raise
Exception
(
"rebind.so not found, perhaps you need to run make"
)
raise
Exception
(
"rebind.so not found, perhaps you need to run make"
)
self
.
rebinder
=
os
.
path
.
abspath
(
self
.
rebinder
)
self
.
target_host
=
"127.0.0.1"
# Loopback
self
.
target_host
=
"127.0.0.1"
# Loopback
# Find a free high port
# Find a free high port
...
@@ -77,10 +71,7 @@ Traffic Legend:
...
@@ -77,10 +71,7 @@ Traffic Legend:
"REBIND_OLD_PORT"
:
str
(
kwargs
[
'listen_port'
]),
"REBIND_OLD_PORT"
:
str
(
kwargs
[
'listen_port'
]),
"REBIND_NEW_PORT"
:
str
(
self
.
target_port
)})
"REBIND_NEW_PORT"
:
str
(
self
.
target_port
)})
if
self
.
target_cfg
:
WebSocketServer
.
__init__
(
self
,
*
args
,
**
kwargs
)
self
.
target_cfg
=
os
.
path
.
abspath
(
self
.
target_cfg
)
websocket
.
WebSocketServer
.
__init__
(
self
,
*
args
,
**
kwargs
)
def
run_wrap_cmd
(
self
):
def
run_wrap_cmd
(
self
):
print
(
"Starting '
%
s'"
%
" "
.
join
(
self
.
wrap_cmd
))
print
(
"Starting '
%
s'"
%
" "
.
join
(
self
.
wrap_cmd
))
...
@@ -97,26 +88,14 @@ Traffic Legend:
...
@@ -97,26 +88,14 @@ 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
:
dst_string
=
"'
%
s' (port
%
s)"
%
(
" "
.
join
(
self
.
wrap_cmd
),
self
.
target_port
)
print
(
" - proxying from
%
s:
%
s to '
%
s' (port
%
s)
\n
"
%
(
elif
self
.
unix_target
:
self
.
listen_host
,
self
.
listen_port
,
dst_string
=
self
.
unix_target
" "
.
join
(
self
.
wrap_cmd
),
self
.
target_port
))
else
:
dst_string
=
"
%
s:
%
s"
%
(
self
.
target_host
,
self
.
target_port
)
if
self
.
target_cfg
:
msg
=
" - proxying from
%
s:
%
s to targets in
%
s"
%
(
self
.
listen_host
,
self
.
listen_port
,
self
.
target_cfg
)
else
:
msg
=
" - proxying from
%
s:
%
s to
%
s"
%
(
self
.
listen_host
,
self
.
listen_port
,
dst_string
)
if
self
.
ssl_target
:
msg
+=
" (using SSL)"
print
(
msg
+
"
\n
"
)
if
self
.
wrap_cmd
:
self
.
run_wrap_cmd
()
self
.
run_wrap_cmd
()
else
:
print
(
" - proxying from
%
s:
%
s to
%
s:
%
s
\n
"
%
(
self
.
listen_host
,
self
.
listen_port
,
self
.
target_host
,
self
.
target_port
))
def
poll
(
self
):
def
poll
(
self
):
# If we are wrapping a command, check it's status
# If we are wrapping a command, check it's status
...
@@ -158,26 +137,12 @@ Traffic Legend:
...
@@ -158,26 +137,12 @@ Traffic Legend:
"""
"""
Called after a new WebSocket connection has been established.
Called after a new WebSocket connection has been established.
"""
"""
# Checks if we receive a token, and look
# for a valid target for it then
if
self
.
target_cfg
:
(
self
.
target_host
,
self
.
target_port
)
=
self
.
get_target
(
self
.
target_cfg
,
self
.
path
)
# Connect to the target
# Connect to the target
if
self
.
wrap_cmd
:
self
.
msg
(
"connecting to:
%
s:
%
s"
%
(
msg
=
"connecting to command:
%
s"
%
(
" "
.
join
(
self
.
wrap_cmd
),
self
.
target_port
)
self
.
target_host
,
self
.
target_port
))
elif
self
.
unix_target
:
msg
=
"connecting to unix socket:
%
s"
%
self
.
unix_target
else
:
msg
=
"connecting to:
%
s:
%
s"
%
(
self
.
target_host
,
self
.
target_port
)
if
self
.
ssl_target
:
msg
+=
" (using SSL)"
self
.
msg
(
msg
)
tsock
=
self
.
socket
(
self
.
target_host
,
self
.
target_port
,
tsock
=
self
.
socket
(
self
.
target_host
,
self
.
target_port
,
connect
=
True
,
use_ssl
=
self
.
ssl_target
,
unix_socket
=
self
.
unix_target
)
connect
=
True
)
if
self
.
verbose
and
not
self
.
daemon
:
if
self
.
verbose
and
not
self
.
daemon
:
print
(
self
.
traffic_legend
)
print
(
self
.
traffic_legend
)
...
@@ -189,49 +154,10 @@ Traffic Legend:
...
@@ -189,49 +154,10 @@ Traffic Legend:
if
tsock
:
if
tsock
:
tsock
.
shutdown
(
socket
.
SHUT_RDWR
)
tsock
.
shutdown
(
socket
.
SHUT_RDWR
)
tsock
.
close
()
tsock
.
close
()
self
.
vmsg
(
"
%
s:
%
s:
Closed target
"
%
(
self
.
vmsg
(
"
%
s:
%
s:
Target closed
"
%
(
self
.
target_host
,
self
.
target_port
))
self
.
target_host
,
self
.
target_port
))
raise
raise
def
get_target
(
self
,
target_cfg
,
path
):
"""
Parses the path, extracts a token, and looks for a valid
target for that token in the configuration file(s). Sets
target_host and target_port if successful
"""
# The files in targets contain the lines
# in the form of token: host:port
# Extract the token parameter from url
args
=
parse_qs
(
urlparse
(
path
)[
4
])
# 4 is the query from url
if
not
len
(
args
[
'token'
]):
raise
self
.
EClose
(
"Token not present"
)
token
=
args
[
'token'
][
0
]
.
rstrip
(
'
\n
'
)
# target_cfg can be a single config file or directory of
# config files
if
os
.
path
.
isdir
(
target_cfg
):
cfg_files
=
[
os
.
path
.
join
(
target_cfg
,
f
)
for
f
in
os
.
listdir
(
target_cfg
)]
else
:
cfg_files
=
[
target_cfg
]
targets
=
{}
for
f
in
cfg_files
:
for
line
in
[
l
.
strip
()
for
l
in
file
(
f
)
.
readlines
()]:
if
line
and
not
line
.
startswith
(
'#'
):
ttoken
,
target
=
line
.
split
(
': '
)
targets
[
ttoken
]
=
target
.
strip
()
self
.
vmsg
(
"Target config:
%
s"
%
repr
(
targets
))
if
targets
.
has_key
(
token
):
return
targets
[
token
]
.
split
(
':'
)
else
:
raise
self
.
EClose
(
"Token '
%
s' not found"
%
token
)
def
do_proxy
(
self
,
target
):
def
do_proxy
(
self
,
target
):
"""
"""
Proxy client WebSocket to normal target socket.
Proxy client WebSocket to normal target socket.
...
@@ -265,8 +191,6 @@ Traffic Legend:
...
@@ -265,8 +191,6 @@ Traffic Legend:
# Receive target data, encode it and queue for client
# Receive target data, encode it and queue for client
buf
=
target
.
recv
(
self
.
buffer_size
)
buf
=
target
.
recv
(
self
.
buffer_size
)
if
len
(
buf
)
==
0
:
if
len
(
buf
)
==
0
:
self
.
vmsg
(
"
%
s:
%
s: Target closed connection"
%
(
self
.
target_host
,
self
.
target_port
))
raise
self
.
CClose
(
1000
,
"Target closed"
)
raise
self
.
CClose
(
1000
,
"Target closed"
)
cqueue
.
append
(
buf
)
cqueue
.
append
(
buf
)
...
@@ -287,13 +211,11 @@ Traffic Legend:
...
@@ -287,13 +211,11 @@ Traffic Legend:
if
closed
:
if
closed
:
# TODO: What about blocking on client socket?
# TODO: What about blocking on client socket?
self
.
vmsg
(
"
%
s:
%
s: Client closed connection"
%
(
self
.
target_host
,
self
.
target_port
))
raise
self
.
CClose
(
closed
[
'code'
],
closed
[
'reason'
])
raise
self
.
CClose
(
closed
[
'code'
],
closed
[
'reason'
])
def
websockify_init
():
def
websockify_init
():
usage
=
"
\n
%
prog [options]"
usage
=
"
\n
%
prog [options]"
usage
+=
" [source_addr:]source_port
[target_addr:target_port]
"
usage
+=
" [source_addr:]source_port
target_addr:target_port
"
usage
+=
"
\n
%
prog [options]"
usage
+=
"
\n
%
prog [options]"
usage
+=
" [source_addr:]source_port -- WRAP_COMMAND_LINE"
usage
+=
" [source_addr:]source_port -- WRAP_COMMAND_LINE"
parser
=
optparse
.
OptionParser
(
usage
=
usage
)
parser
=
optparse
.
OptionParser
(
usage
=
usage
)
...
@@ -313,29 +235,17 @@ def websockify_init():
...
@@ -313,29 +235,17 @@ def websockify_init():
parser
.
add_option
(
"--key"
,
default
=
None
,
parser
.
add_option
(
"--key"
,
default
=
None
,
help
=
"SSL key file (if separate from cert)"
)
help
=
"SSL key file (if separate from cert)"
)
parser
.
add_option
(
"--ssl-only"
,
action
=
"store_true"
,
parser
.
add_option
(
"--ssl-only"
,
action
=
"store_true"
,
help
=
"disallow non-encrypted client connections"
)
help
=
"disallow non-encrypted connections"
)
parser
.
add_option
(
"--ssl-target"
,
action
=
"store_true"
,
help
=
"connect to SSL target as SSL client"
)
parser
.
add_option
(
"--unix-target"
,
help
=
"connect to unix socket target"
,
metavar
=
"FILE"
)
parser
.
add_option
(
"--web"
,
default
=
None
,
metavar
=
"DIR"
,
parser
.
add_option
(
"--web"
,
default
=
None
,
metavar
=
"DIR"
,
help
=
"run webserver on same port. Serve files from DIR."
)
help
=
"run webserver on same port. Serve files from DIR."
)
parser
.
add_option
(
"--wrap-mode"
,
default
=
"exit"
,
metavar
=
"MODE"
,
parser
.
add_option
(
"--wrap-mode"
,
default
=
"exit"
,
metavar
=
"MODE"
,
choices
=
[
"exit"
,
"ignore"
,
"respawn"
],
choices
=
[
"exit"
,
"ignore"
,
"respawn"
],
help
=
"action to take when the wrapped program exits "
help
=
"action to take when the wrapped program exits "
"or daemonizes: exit (default), ignore, respawn"
)
"or daemonizes: exit (default), ignore, respawn"
)
parser
.
add_option
(
"--prefer-ipv6"
,
"-6"
,
action
=
"store_true"
,
dest
=
"source_is_ipv6"
,
help
=
"prefer IPv6 when resolving source_addr"
)
parser
.
add_option
(
"--target-config"
,
metavar
=
"FILE"
,
dest
=
"target_cfg"
,
help
=
"Configuration file containing valid targets "
"in the form 'token: host:port' or, alternatively, a "
"directory containing configuration files of this form"
)
(
opts
,
args
)
=
parser
.
parse_args
()
(
opts
,
args
)
=
parser
.
parse_args
()
# Sanity checks
# Sanity checks
if
len
(
args
)
<
2
and
not
opts
.
target_cfg
:
if
len
(
args
)
<
2
:
parser
.
error
(
"Too few arguments"
)
parser
.
error
(
"Too few arguments"
)
if
sys
.
argv
.
count
(
'--'
):
if
sys
.
argv
.
count
(
'--'
):
opts
.
wrap_cmd
=
args
[
1
:]
opts
.
wrap_cmd
=
args
[
1
:]
...
@@ -344,29 +254,24 @@ def websockify_init():
...
@@ -344,29 +254,24 @@ def websockify_init():
if
len
(
args
)
>
2
:
if
len
(
args
)
>
2
:
parser
.
error
(
"Too many arguments"
)
parser
.
error
(
"Too many arguments"
)
if
not
websocket
.
ssl
and
opts
.
ssl_target
:
parser
.
error
(
"SSL target requested and Python SSL module not loaded."
);
if
opts
.
ssl_only
and
not
os
.
path
.
exists
(
opts
.
cert
):
if
opts
.
ssl_only
and
not
os
.
path
.
exists
(
opts
.
cert
):
parser
.
error
(
"SSL only and
%
s not found"
%
opts
.
cert
)
parser
.
error
(
"SSL only and
%
s not found"
%
opts
.
cert
)
# Parse host:port and convert ports to numbers
# Parse host:port and convert ports to numbers
if
args
[
0
]
.
count
(
':'
)
>
0
:
if
args
[
0
]
.
count
(
':'
)
>
0
:
opts
.
listen_host
,
opts
.
listen_port
=
args
[
0
]
.
rsplit
(
':'
,
1
)
opts
.
listen_host
,
opts
.
listen_port
=
args
[
0
]
.
rsplit
(
':'
,
1
)
opts
.
listen_host
=
opts
.
listen_host
.
strip
(
'[]'
)
else
:
else
:
opts
.
listen_host
,
opts
.
listen_port
=
''
,
args
[
0
]
opts
.
listen_host
,
opts
.
listen_port
=
''
,
args
[
0
]
try
:
opts
.
listen_port
=
int
(
opts
.
listen_port
)
try
:
opts
.
listen_port
=
int
(
opts
.
listen_port
)
except
:
parser
.
error
(
"Error parsing listen port"
)
except
:
parser
.
error
(
"Error parsing listen port"
)
if
opts
.
wrap_cmd
or
opts
.
unix_target
or
opts
.
target_cfg
:
if
opts
.
wrap_cmd
:
opts
.
target_host
=
None
opts
.
target_host
=
None
opts
.
target_port
=
None
opts
.
target_port
=
None
else
:
else
:
if
args
[
1
]
.
count
(
':'
)
>
0
:
if
args
[
1
]
.
count
(
':'
)
>
0
:
opts
.
target_host
,
opts
.
target_port
=
args
[
1
]
.
rsplit
(
':'
,
1
)
opts
.
target_host
,
opts
.
target_port
=
args
[
1
]
.
rsplit
(
':'
,
1
)
opts
.
target_host
=
opts
.
target_host
.
strip
(
'[]'
)
else
:
else
:
parser
.
error
(
"Error parsing target"
)
parser
.
error
(
"Error parsing target"
)
try
:
opts
.
target_port
=
int
(
opts
.
target_port
)
try
:
opts
.
target_port
=
int
(
opts
.
target_port
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment