From bf5ee68828872f05d1356a22d3807c6ea29d017f Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Mon, 3 Jan 2011 12:34:41 -0600 Subject: [PATCH 1/5] Expose getKeysym and add keyboard test. Related to issue Non-US keyboard layout option issue: https://github.com/kanaka/noVNC/issues#issue/21 --- include/canvas.js | 10 +++---- tests/keyboard.html | 67 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 tests/keyboard.html diff --git a/include/canvas.js b/include/canvas.js index 03a1e68..93aaff7 100644 --- a/include/canvas.js +++ b/include/canvas.js @@ -216,7 +216,7 @@ function constructor() { } /* Translate DOM key down/up event to keysym value */ -function getKeysym(e) { +that.getKeysym = function(e) { var evt, keysym; evt = (e ? e : window.event); @@ -362,24 +362,24 @@ function onMouseMove(e) { } function onKeyDown(e) { - //Util.Debug("keydown: " + getKeysym(e)); + //Util.Debug("keydown: " + that.getKeysym(e)); if (! conf.focused) { return true; } if (c_keyPress) { - c_keyPress(getKeysym(e), 1); + c_keyPress(that.getKeysym(e), 1); } Util.stopEvent(e); return false; } function onKeyUp(e) { - //Util.Debug("keyup: " + getKeysym(e)); + //Util.Debug("keyup: " + that.getKeysym(e)); if (! conf.focused) { return true; } if (c_keyPress) { - c_keyPress(getKeysym(e), 0); + c_keyPress(that.getKeysym(e), 0); } Util.stopEvent(e); return false; diff --git a/tests/keyboard.html b/tests/keyboard.html new file mode 100644 index 0000000..2d6df05 --- /dev/null +++ b/tests/keyboard.html @@ -0,0 +1,67 @@ + + Input Test + +

+ + Canvas:
+ + Canvas not supported. + + +
+ Results:
+ + + + + + + + + + From e3716842ef03da96ce082dc47eda71b6ca14fb3f Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Tue, 4 Jan 2011 10:27:25 -0600 Subject: [PATCH 2/5] include/rfb.js: show Flash version in console. --- include/rfb.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/rfb.js b/include/rfb.js index 7536ddc..6adccd4 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -254,7 +254,8 @@ function constructor() { Util.Info("Using native WebSockets"); updateState('loaded', 'noVNC ready: native WebSockets, ' + rmode); } else { - Util.Warn("Using web-socket-js flash bridge"); + Util.Warn("Using web-socket-js bridge. Flash version: " + + Util.Flash.version); if ((! Util.Flash) || (Util.Flash.version < 9)) { updateState('fatal', "WebSockets or Adobe Flash is required"); From 9b940131d3e44ff0e3146b637ae126d07b1d7230 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Tue, 4 Jan 2011 10:30:26 -0600 Subject: [PATCH 3/5] include/canvas.js: show full user agent in console. --- include/canvas.js | 1 + 1 file changed, 1 insertion(+) diff --git a/include/canvas.js b/include/canvas.js index 93aaff7..e28c3b0 100644 --- a/include/canvas.js +++ b/include/canvas.js @@ -109,6 +109,7 @@ function constructor() { if (! conf.ctx) { conf.ctx = c.getContext('2d'); } ctx = conf.ctx; + Util.Debug("User Agent: " + navigator.userAgent); if (UE.gecko) { Util.Debug("Browser: gecko " + UE.gecko); } if (UE.webkit) { Util.Debug("Browser: webkit " + UE.webkit); } if (UE.trident) { Util.Debug("Browser: trident " + UE.trident); } From 58da507bb81f960909f6e9c108f61137426c6ea5 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Tue, 4 Jan 2011 12:19:54 -0600 Subject: [PATCH 4/5] README: add companies/projects using noVNC. --- README.md | 17 +++++++++++++++++ docs/links | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/README.md b/README.md index ccf51ea..4d1b1e5 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,23 @@ Running in Chrome before and after connecting: See more screenshots here. +### Projects/Companies using noVNC + +* [Sentry Data Systems](http://www.sentryds.com): uses noVNC in the + [Datanex Cloud Computing Platform](http://www.sentryds.com/products/datanex/). + +* [Ganeti Web Manager](http://code.osuosl.org/projects/ganeti-webmgr): + Feature [#1935](http://code.osuosl.org/issues/1935). + +* [Archipel](http://archipelproject.org): + [Video demo](http://antoinemercadal.fr/archipelblog/wp-content/themes/ArchipelWPTemplate/video_youtube.php?title=VNC%20Demonstration&id=te_bzW574Zo) + +* [openQRM](http://www.openqrm.com/): VNC plugin available + by request. Probably included in [version + 4.8](http://www.openqrm.com/?q=node/15). [Video + demo](http://www.openqrm-enterprise.com/news/details/article/remote-vm-console-plugin-available.html). + + ### Browser Requirements * HTML5 Canvas: Except for Internet Explorer, most diff --git a/docs/links b/docs/links index 64ea754..8cb4da1 100644 --- a/docs/links +++ b/docs/links @@ -35,6 +35,10 @@ Cursor appearance/style (for Cursor pseudo-encoding): https://developer.mozilla.org/en/Using_URL_values_for_the_cursor_property +RDP Protocol specification: + http://msdn.microsoft.com/en-us/library/cc240445(v=PROT.10).aspx + + Related projects: guacamole: http://guacamole.sourceforge.net/ From 58dc1947ded37983c0add02ac6a7859510a52a5b Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Tue, 4 Jan 2011 13:14:46 -0600 Subject: [PATCH 5/5] wsproxy: warn when no cert. C sock close cleanup. Warn early about no SSL cert and add clearer warning when a connection comes in as SSL but no cert file exists. For the C version, cleanup closing of the connection socket. Use shutdown for a cleaner cleanup with the client. --- utils/websocket.c | 31 +++++++++++++++++++++---------- utils/websocket.py | 5 +++++ utils/wsproxy.c | 10 ++++++++-- utils/wsproxy.py | 2 ++ 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/utils/websocket.c b/utils/websocket.c index 4a124f1..f73bb22 100644 --- a/utils/websocket.c +++ b/utils/websocket.c @@ -187,6 +187,7 @@ int ws_socket_free(ws_ctx_t *ctx) { ctx->ssl_ctx = NULL; } if (ctx->sockfd) { + shutdown(ctx->sockfd, SHUT_RDWR); close(ctx->sockfd); ctx->sockfd = 0; } @@ -350,26 +351,30 @@ ws_ctx_t *do_handshake(int sock) { handshake[len] = 0; if (len == 0) { handler_msg("ignoring empty handshake\n"); - close(sock); return NULL; } else if (bcmp(handshake, "", 22) == 0) { len = recv(sock, handshake, 1024, 0); handshake[len] = 0; handler_msg("sending flash policy response\n"); send(sock, policy_response, sizeof(policy_response), 0); - close(sock); return NULL; } else if ((bcmp(handshake, "\x16", 1) == 0) || (bcmp(handshake, "\x80", 1) == 0)) { // SSL - if (! settings.cert) { return NULL; } + if (!settings.cert) { + handler_msg("SSL connection but no cert specified\n"); + return NULL; + } else if (access(settings.cert, R_OK) != 0) { + handler_msg("SSL connection but '%s' not found\n", + settings.cert); + return NULL; + } ws_ctx = ws_socket_ssl(sock, settings.cert, settings.key); if (! ws_ctx) { return NULL; } scheme = "wss"; handler_msg("using SSL socket\n"); } else if (settings.ssl_only) { handler_msg("non-SSL connection disallowed\n"); - close(sock); return NULL; } else { ws_ctx = ws_socket(sock); @@ -380,14 +385,12 @@ ws_ctx_t *do_handshake(int sock) { len = ws_recv(ws_ctx, handshake, 4096); if (len == 0) { handler_emsg("Client closed during handshake\n"); - close(sock); return NULL; } handshake[len] = 0; if (!parse_handshake(handshake, &headers)) { handler_emsg("Invalid WS request\n"); - close(sock); return NULL; } @@ -524,8 +527,7 @@ void start_server() { if (pid == 0) { // handler process ws_ctx = do_handshake(csock); if (ws_ctx == NULL) { - close(csock); - handler_msg("No connection after handshake"); + handler_msg("No connection after handshake\n"); break; // Child process exits } @@ -533,13 +535,22 @@ void start_server() { if (pipe_error) { handler_emsg("Closing due to SIGPIPE\n"); } - close(csock); - handler_msg("handler exit\n"); break; // Child process exits } else { // parent process settings.handler_id += 1; } } + if (pid == 0) { + if (ws_ctx) { + ws_socket_free(ws_ctx); + } else { + shutdown(csock, SHUT_RDWR); + close(csock); + } + handler_msg("handler exit\n"); + } else { + handler_msg("wsproxy exit\n"); + } } diff --git a/utils/websocket.py b/utils/websocket.py index b4bc01e..70748c1 100755 --- a/utils/websocket.py +++ b/utils/websocket.py @@ -112,6 +112,11 @@ def do_handshake(sock): sock.close() return False elif handshake[0] in ("\x16", "\x80"): + if not os.path.exists(settings['cert']): + handler_msg("SSL connection but '%s' not found" + % settings['cert']) + sock.close() + return False retsock = ssl.wrap_socket( sock, server_side=True, diff --git a/utils/wsproxy.c b/utils/wsproxy.c index dc8b5f7..5ba2206 100644 --- a/utils/wsproxy.c +++ b/utils/wsproxy.c @@ -257,6 +257,10 @@ int main(int argc, char *argv[]) }; settings.cert = realpath("self.pem", NULL); + if (!settings.cert) { + /* Make sure it's always set to something */ + settings.cert = "self.pem"; + } settings.key = ""; while (1) { @@ -326,9 +330,11 @@ int main(int argc, char *argv[]) } if (ssl_only) { - if (!settings.cert || !access(settings.cert, R_OK)) { - usage("SSL only and cert file not found\n"); + if (!access(settings.cert, R_OK)) { + usage("SSL only and cert file '%s' not found\n", settings.cert); } + } else if (access(settings.cert, R_OK) != 0) { + fprintf(stderr, "Warning: '%s' not found\n", settings.cert); } //printf(" verbose: %d\n", settings.verbose); diff --git a/utils/wsproxy.py b/utils/wsproxy.py index c5339b7..378e474 100755 --- a/utils/wsproxy.py +++ b/utils/wsproxy.py @@ -162,6 +162,8 @@ if __name__ == '__main__': if options.ssl_only and not os.path.exists(options.cert): parser.error("SSL only and %s not found" % options.cert) + elif not os.path.exists(options.cert): + print "Warning: %s not found" % options.cert settings['verbose'] = options.verbose settings['listen_host'] = host