Commit 07287cfd authored by Joel Martin's avatar Joel Martin

Send seq nums and b64 encode based on query string.

Query string variable 'b64encode' determine if wsproxy b64 encodes the
results. Variable 'seq_num' determines if sequence numbers are
prepended. This way, sequence numbers are only used with the flash
WebSocket proxy.
parent 8759ea6f
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
RFB.updateState('failed', "'file://' URL is incompatible with Adobe Flash"); RFB.updateState('failed', "'file://' URL is incompatible with Adobe Flash");
} else { } else {
WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf"; WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf";
RFB.force_copy = true; RFB.use_seq = true;
RFB.updateState('disconnected', 'Disconnected'); RFB.updateState('disconnected', 'Disconnected');
} }
} }
......
...@@ -83,7 +83,7 @@ RFB = { ...@@ -83,7 +83,7 @@ RFB = {
ws : null, // Web Socket object ws : null, // Web Socket object
sendID : null, sendID : null,
force_copy : false, use_seq : false,
version : "RFB 003.003\n", version : "RFB 003.003\n",
state : 'disconnected', state : 'disconnected',
...@@ -647,6 +647,84 @@ clientCutText: function (text) { ...@@ -647,6 +647,84 @@ clientCutText: function (text) {
* Utility routines * Utility routines
*/ */
recv_message: function(e) {
//console.log(">> recv_message");
RQ = RQ.concat(Base64.decode(e.data, 0));
RFB.handle_message();
//console.log("<< recv_message");
},
recv_message_reorder: function(e) {
//console.log(">> recv_message_reorder");
var offset = e.data.indexOf(":") + 1;
var seq_num = parseInt(e.data.substr(0, offset-1));
if (RQ_seq_num == seq_num) {
RQ = RQ.concat(Base64.decode(e.data, offset));
RQ_seq_num++;
} else {
console.warn("sequence number mismatch RQ_seq_num:" + RQ_seq_num + ", seq_num:" + seq_num);
if (RQ_reorder.length > 20) {
RFB.updateState('failed', "Re-order queue too long");
} else {
RQ_reorder = RQ_reorder.concat(e.data.substr(0));
var i = 0;
while (i < RQ_reorder.length) {
var offset = RQ_reorder[i].indexOf(":") + 1;
var seq_num = parseInt(RQ_reorder[i].substr(0, offset-1));
console.log("Searching reorder list item " + i + ", seq_num " + seq_num);
if (seq_num == RQ_seq_num) {
/* Remove it from reorder queue, decode it and
* add it to the receive queue */
console.log("Found re-ordered packet seq_num " + seq_num);
RQ = RQ.concat(Base64.decode(RQ_reorder.splice(i, 1)[0], offset));
RQ_seq_num++;
i = 0; // Start search again for next one
} else {
i++;
}
}
}
}
RFB.handle_message();
//console.log("<< recv_message_reorder");
},
handle_message: function () {
switch (RFB.state) {
case 'disconnected':
console.error("Got data while disconnected");
break;
case 'reset':
/* close and reset connection */
RFB.disconnect();
RFB.init_ws();
break;
case 'failed':
console.log("Giving up!");
RFB.disconnect();
break;
case 'normal':
RFB.normal_msg();
/*
while (RQ.length > 0) {
if (RFB.normal_msg() && RFB.state == 'normal') {
console.log("More to process");
} else {
break;
}
}
*/
break;
default:
RFB.init_msg();
break;
}
},
send_string: function (str) { send_string: function (str) {
//console.log(">> send_string: " + str); //console.log(">> send_string: " + str);
RFB.send_array(str.split('').map( RFB.send_array(str.split('').map(
...@@ -828,74 +906,18 @@ updateState: function(state, statusMsg) { ...@@ -828,74 +906,18 @@ updateState: function(state, statusMsg) {
init_ws: function () { init_ws: function () {
console.log(">> init_ws"); console.log(">> init_ws");
var uri = "ws://" + RFB.host + ":" + RFB.port; var uri = "ws://" + RFB.host + ":" + RFB.port + "/?b64encode";
if (RFB.use_seq) {
uri += "&seq_num";
}
console.log("connecting to " + uri); console.log("connecting to " + uri);
RFB.ws = new WebSocket(uri); RFB.ws = new WebSocket(uri);
RFB.ws.onmessage = function(e) {
//console.log(">> WebSocket.onmessage");
var offset = e.data.indexOf(":") + 1;
var seq_num = parseInt(e.data.substr(0, offset-1));
if (RQ_seq_num == seq_num) {
RQ = RQ.concat(Base64.decode(e.data, offset));
RQ_seq_num++;
} else {
console.warn("sequence number mismatch RQ_seq_num:" + RQ_seq_num + ", seq_num:" + seq_num);
if (RQ_reorder.length > 20) {
RFB.updateState('failed', "Re-order queue too long");
} else {
RQ_reorder = RQ_reorder.concat(e.data.substr(0));
var i = 0;
while (i < RQ_reorder.length) {
var offset = RQ_reorder[i].indexOf(":") + 1;
var seq_num = parseInt(RQ_reorder[i].substr(0, offset-1));
console.log("Searching reorder list item " + i + ", seq_num " + seq_num);
if (seq_num == RQ_seq_num) {
/* Remove it from reorder queue, decode it and
* add it to the receive queue */
console.log("Found re-ordered packet seq_num " + seq_num);
RQ = RQ.concat(Base64.decode(RQ_reorder.splice(i, 1)[0], offset));
RQ_seq_num++;
i = 0; // Start search again for next one
} else {
i++;
}
}
}
}
switch (RFB.state) { if (RFB.use_seq) {
case 'disconnected': RFB.ws.onmessage = RFB.recv_message_reorder;
console.error("WebSocket.onmessage while disconnected"); } else {
break; RFB.ws.onmessage = RFB.recv_message;
case 'reset': }
/* close and reset connection */
RFB.disconnect();
RFB.init_ws();
break;
case 'failed':
console.log("Giving up!");
RFB.disconnect();
break;
case 'normal':
RFB.normal_msg();
/*
while (RQ.length > 0) {
if (RFB.normal_msg() && RFB.state == 'normal') {
console.log("More to process");
} else {
break;
}
}
*/
break;
default:
RFB.init_msg();
break;
}
//console.log("<< WebSocket.onmessage");
};
RFB.ws.onopen = function(e) { RFB.ws.onopen = function(e) {
console.log(">> WebSocket.onopen"); console.log(">> WebSocket.onopen");
RFB.updateState('ProtocolVersion', "Starting VNC handshake"); RFB.updateState('ProtocolVersion', "Starting VNC handshake");
......
#!/usr/bin/python #!/usr/bin/python
import sys, os, socket, time, traceback import sys, os, socket, time, traceback, re
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
from select import select from select import select
buffer_size = 65536 buffer_size = 65536
send_seq = 0 send_seq = 0
client_settings = {}
server_handshake = """HTTP/1.1 101 Web Socket Protocol Handshake\r server_handshake = """HTTP/1.1 101 Web Socket Protocol Handshake\r
Upgrade: WebSocket\r Upgrade: WebSocket\r
...@@ -32,21 +33,27 @@ Traffic Legend: ...@@ -32,21 +33,27 @@ Traffic Legend:
def do_handshake(client): def do_handshake(client):
global client_settings
handshake = client.recv(1024) handshake = client.recv(1024)
print "Handshake [%s]" % handshake #print "Handshake [%s]" % handshake
if handshake.startswith("<policy-file-request/>"): if handshake.startswith("<policy-file-request/>"):
print "Sending:", policy_response print "Sending flash policy response"
client.send(policy_response) client.send(policy_response)
client.close() client.close()
return False return False
#handshake = client.recv(1024)
#if len(handshake) == 0:
# raise Exception("Policy exchange failed")
#print "Handshake [%s]" % handshake
req_lines = handshake.split("\r\n") req_lines = handshake.split("\r\n")
_, path, _ = req_lines[0].split(" ") _, path, _ = req_lines[0].split(" ")
_, origin = req_lines[4].split(" ") _, origin = req_lines[4].split(" ")
_, host = req_lines[3].split(" ") _, host = req_lines[3].split(" ")
# Parse settings from the path
cvars = path.partition('?')[2].partition('#')[0].split('&')
for cvar in [c for c in cvars if c]:
name, _, value = cvar.partition('=')
client_settings[name] = value and value or True
print "client_settings:", client_settings
client.send(server_handshake % (origin, host, path)) client.send(server_handshake % (origin, host, path))
return True return True
...@@ -76,7 +83,7 @@ def proxy(client, target): ...@@ -76,7 +83,7 @@ def proxy(client, target):
if tqueue and target in outs: if tqueue and target in outs:
#print "Target send: %s" % repr(tqueue[0]) #print "Target send: %s" % repr(tqueue[0])
log.write("Target send: %s\n" % map(ord, tqueue[0])) ##log.write("Target send: %s\n" % map(ord, tqueue[0]))
dat = tqueue.pop(0) dat = tqueue.pop(0)
sent = target.send(dat) sent = target.send(dat)
if sent == len(dat): if sent == len(dat):
...@@ -90,25 +97,28 @@ def proxy(client, target): ...@@ -90,25 +97,28 @@ def proxy(client, target):
sent = client.send(dat) sent = client.send(dat)
if sent == len(dat): if sent == len(dat):
traffic("<") traffic("<")
log.write("Client send: %s\n" % repr(dat)) ##log.write("Client send: %s\n" % repr(dat))
else: else:
cqueue.insert(0, dat[sent:]) cqueue.insert(0, dat[sent:])
traffic("<.") traffic("<.")
log.write("Client send partial: %s\n" % repr(dat[0:send])) ##log.write("Client send partial: %s\n" % repr(dat[0:send]))
if target in ins: if target in ins:
buf = target.recv(buffer_size) buf = target.recv(buffer_size)
if len(buf) == 0: raise Exception("Target closed") if len(buf) == 0: raise Exception("Target closed")
#enc = b64encode(buf) ##log.write("Target recv (%d): %s\n" % (len(buf), map(ord, buf)))
#chksum = sum([ord(c) for c in enc])
#cqueue.append("\x00^" + str(chksum) + "@" + enc + "$\xff")
cqueue.append("\x00%d:%s\xff" % (send_seq, b64encode(buf))) if client_settings.get("b64encode"):
send_seq += 1 buf = b64encode(buf)
if client_settings.get("seq_num"):
cqueue.append("\x00%d:%s\xff" % (send_seq, buf))
send_seq += 1
else:
cqueue.append("\x00%s\xff" % buf)
log.write("Target recv (%d): %s\n" % (len(buf), map(ord, buf)))
traffic("{") traffic("{")
if client in ins: if client in ins:
...@@ -117,7 +127,7 @@ def proxy(client, target): ...@@ -117,7 +127,7 @@ def proxy(client, target):
if buf[-1] == "\xff": if buf[-1] == "\xff":
traffic("}") traffic("}")
log.write("Client recv (%d): %s\n" % (len(buf), repr(buf))) ##log.write("Client recv (%d): %s\n" % (len(buf), repr(buf)))
if cpartial: if cpartial:
tqueue.extend(decode(cpartial + buf)) tqueue.extend(decode(cpartial + buf))
cpartial = "" cpartial = ""
...@@ -125,7 +135,7 @@ def proxy(client, target): ...@@ -125,7 +135,7 @@ def proxy(client, target):
tqueue.extend(decode(buf)) tqueue.extend(decode(buf))
else: else:
traffic("}.") traffic("}.")
log.write("Client recv partial (%d): %s\n" % (len(buf), repr(buf))) ##log.write("Client recv partial (%d): %s\n" % (len(buf), repr(buf)))
cpartial = cpartial + buf cpartial = cpartial + buf
...@@ -157,7 +167,7 @@ def start_server(listen_port, target_host, target_port): ...@@ -157,7 +167,7 @@ def start_server(listen_port, target_host, target_port):
if tsock: tsock.close() if tsock: tsock.close()
if __name__ == '__main__': if __name__ == '__main__':
log = open("ws.log", 'w') ##log = open("ws.log", 'w')
try: try:
if len(sys.argv) != 4: raise if len(sys.argv) != 4: raise
listen_port = int(sys.argv[1]) listen_port = int(sys.argv[1])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment