aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-09-27 16:11:55 -0700
committerAlon Zakai <alonzakai@gmail.com>2012-09-27 16:11:55 -0700
commit31f7b2a5a65d2d640343013dac4bb836c3bfba5f (patch)
treee677a00733440e57ab61fb00a696284c1d7b960b
parente546b42883bbcabb4657dfcdb523a93d0458f5b3 (diff)
initial (not-yet-working) sockets implementation
-rw-r--r--src/library.js69
-rw-r--r--src/settings.js5
-rw-r--r--system/include/net/arpa/inet.h3
-rwxr-xr-xtests/runner.py28
-rw-r--r--tests/websockets.c119
-rw-r--r--third_party/websockify/.gitignore10
-rw-r--r--third_party/websockify/CHANGES.txt18
-rw-r--r--third_party/websockify/LICENSE.txt11
-rw-r--r--third_party/websockify/MANIFEST.in1
-rw-r--r--third_party/websockify/Makefile11
-rw-r--r--third_party/websockify/README.md155
-rw-r--r--third_party/websockify/Windows/Windows Service Readme.txt39
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/Program.cs24
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/ProjectInstaller.Designer.cs61
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/ProjectInstaller.cs19
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/ProjectInstaller.resx129
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/Properties/AssemblyInfo.cs36
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/Service1.Designer.cs37
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/Service1.cs41
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/noVNC Websocket.csproj75
-rw-r--r--third_party/websockify/Windows/noVNC Websocket Service Project/noVNC Websocket.sln20
-rw-r--r--third_party/websockify/docs/LICENSE.GPL-3621
-rw-r--r--third_party/websockify/docs/LICENSE.LGPL-3165
-rw-r--r--third_party/websockify/docs/TODO9
-rw-r--r--third_party/websockify/docs/flash_policy.txt4
-rw-r--r--third_party/websockify/docs/latency_results.txt114
-rw-r--r--third_party/websockify/docs/notes17
-rw-r--r--third_party/websockify/docs/release.txt9
-rw-r--r--third_party/websockify/docs/websockify.1110
-rw-r--r--third_party/websockify/include/VT100.js919
-rw-r--r--third_party/websockify/include/base64.js147
-rw-r--r--third_party/websockify/include/keysym.js99
-rw-r--r--third_party/websockify/include/util.js303
-rw-r--r--third_party/websockify/include/web-socket-js/README.txt109
-rw-r--r--third_party/websockify/include/web-socket-js/WebSocketMain.swfbin0 -> 177114 bytes
-rw-r--r--third_party/websockify/include/web-socket-js/swfobject.js4
-rwxr-xr-xthird_party/websockify/include/web-socket-js/web_socket.js391
-rw-r--r--third_party/websockify/include/websock.js427
-rw-r--r--third_party/websockify/include/webutil.js148
-rw-r--r--third_party/websockify/include/wsirc.js235
-rw-r--r--third_party/websockify/include/wstelnet.js335
-rw-r--r--third_party/websockify/other/Makefile14
-rw-r--r--third_party/websockify/other/README.md51
-rwxr-xr-xthird_party/websockify/other/launch.sh108
-rw-r--r--third_party/websockify/other/project.clj13
-rw-r--r--third_party/websockify/other/websocket.c802
-rw-r--r--third_party/websockify/other/websocket.h84
-rw-r--r--third_party/websockify/other/websocket.rb456
-rw-r--r--third_party/websockify/other/websockify.c385
-rw-r--r--third_party/websockify/other/websockify.clj233
-rw-r--r--third_party/websockify/other/websockify.js141
-rwxr-xr-xthird_party/websockify/other/websockify.rb171
-rwxr-xr-xthird_party/websockify/other/wswrap22
-rwxr-xr-xthird_party/websockify/rebind18
-rw-r--r--third_party/websockify/rebind.c94
-rwxr-xr-xthird_party/websockify/run5
-rw-r--r--third_party/websockify/setup.py30
-rwxr-xr-xthird_party/websockify/tests/b64_vs_utf8.py29
-rw-r--r--third_party/websockify/tests/base64.html91
-rw-r--r--third_party/websockify/tests/base64.js12
-rw-r--r--third_party/websockify/tests/echo.html148
-rwxr-xr-xthird_party/websockify/tests/echo.py75
-rwxr-xr-xthird_party/websockify/tests/echo.rb62
l---------third_party/websockify/tests/include1
-rw-r--r--third_party/websockify/tests/latency.html290
l---------third_party/websockify/tests/latency.py1
-rw-r--r--third_party/websockify/tests/load.html250
-rwxr-xr-xthird_party/websockify/tests/load.py167
-rw-r--r--third_party/websockify/tests/plain_echo.html168
-rw-r--r--third_party/websockify/tests/simple.html68
-rwxr-xr-xthird_party/websockify/tests/utf8-list.py22
l---------third_party/websockify/websockify.py1
-rw-r--r--third_party/websockify/websockify/__init__.py2
-rw-r--r--third_party/websockify/websockify/websocket.py965
-rwxr-xr-xthird_party/websockify/websockify/websocketproxy.py390
-rw-r--r--third_party/websockify/wsirc.html99
-rw-r--r--third_party/websockify/wstelnet.html74
77 files changed, 10617 insertions, 2 deletions
diff --git a/src/library.js b/src/library.js
index 3531db97..06b03764 100644
--- a/src/library.js
+++ b/src/library.js
@@ -6315,6 +6315,75 @@ LibraryManager.library = {
ntohl: 'htonl',
ntohs: 'htons',
+ inet_pton__deps: ['__setErrNo', '$ERRNO_CODES'],
+ inet_pton: function(af, src, dst) {
+ // int af, const char *src, void *dst
+ if ((af ^ {{{ cDefine("AF_INET") }}}) !== 0) { ___setErrNo(ERRNO_CODES.EAFNOSUPPORT); return -1; }
+ var b = Pointer_stringify(src).split(".");
+ if (b.length !== 4) return 0;
+ var ret = Number(b[0]) | (Number(b[1]) << 8) | (Number(b[2]) << 16) | (Number(b[3]) << 24);
+ if (isNaN(ret)) return 0;
+ setValue(dst, ret, 'i32');
+ return 1;
+ },
+
+ _inet_ntop_raw: function(addr) {
+ return (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff)
+ },
+
+ inet_ntop__deps: ['_inet_ntop_raw'],
+ inet_ntop: function(af, src, dst, size) {
+ var addr = getValue(src, 'i32');
+ var str = __inet_ntop_raw(addr);
+ writeStringToMemory(str.substr(0, size), dst, true);
+ return dst;
+ },
+
+ // ==========================================================================
+ // sockets
+ // ==========================================================================
+
+ $Sockets__deps: ['__setErrNo', '$ERRNO_CODES'],
+ $Sockets: {
+ nextFd: 1,
+ fds: {},
+ sockaddr_in_layout: Runtime.generateStructInfo([
+ ['i16', 'sin_family'],
+ ['i16', 'sin_port'],
+ ['i32', 'sin_addr'],
+ ['i64', 'sin_zero'],
+ ]),
+ },
+
+ socket__deps: ['$Sockets'],
+ socket: function(family, type, protocol) {
+ var fd = Sockets.nextFd++;
+ Sockets.fds[fd] = {
+ connected: false
+ };
+ return fd;
+ },
+
+ connect__deps: ['$Sockets', '_inet_ntop_raw', 'ntohs'],
+ connect: function(fd, addr, addrlen) {
+ var info = Sockets.fds[fd];
+ info.connected = true;
+ info.addr = getValue(addr + Sockets.sockaddr_in_layout.sin_addr, 'i32');
+ info.port = _ntohs(getValue(addr + Sockets.sockaddr_in_layout.sin_port, 'i16'));
+ info.host = __inet_ntop_raw(info.addr);
+ info.socket = new WebSocket('ws://' + info.host + ':' + info.port, ['binary']);
+ info.socket.onmessage = function (event) {
+ console.log(event.data + ',' + typeof event.data);
+ }
+ return 0;
+ },
+
+ recv__deps: ['$Sockets'],
+ recv: function(fd, buf, len, flags) {
+ //___setErrNo(ERRNO_CODES.EINTR);
+ return 0; // TODO
+ },
+
// ==========================================================================
// emscripten.h
// ==========================================================================
diff --git a/src/settings.js b/src/settings.js
index f8a81711..0b9cf14b 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -1124,5 +1124,8 @@ var C_DEFINES = {'SI_MESGQ': '5',
'AT_FDCWD': '-2',
'SIGTTOU': '22',
'_CS_POSIX_V7_LP64_OFF64_LDFLAGS': '10',
- '_SC_TTY_NAME_MAX': '41'};
+ '_SC_TTY_NAME_MAX': '41',
+ 'AF_INET': '1',
+ 'AF_INET6': '6'
+};
diff --git a/system/include/net/arpa/inet.h b/system/include/net/arpa/inet.h
index 06d44183..9d078276 100644
--- a/system/include/net/arpa/inet.h
+++ b/system/include/net/arpa/inet.h
@@ -16,6 +16,9 @@ uint16_t ntohs(uint16_t netshort);
int inet_aton(const char *cp, struct in_addr *addr);
char *inet_ntoa(struct in_addr in);
+int inet_pton(int af, const char *src, void *dst);
+const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
+
typedef long in_addr_t;
in_addr_t inet_addr(const char *cp);
diff --git a/tests/runner.py b/tests/runner.py
index 475acbe3..7896b7a0 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -7802,7 +7802,7 @@ elif 'browser' in str(sys.argv):
print '(moving on..)'
def with_report_result(self, code):
- return '''
+ return r'''
#define REPORT_RESULT_INTERNAL(sync) \
char output[1000]; \
sprintf(output, \
@@ -8447,6 +8447,32 @@ elif 'browser' in str(sys.argv):
''')
self.btest('pre_run_deps.cpp', expected='10', args=['--pre-js', 'pre.js'])
+ def zzztest_websockets(self):
+ try:
+ def server_func():
+ os.system('while true; do (/bin/echo -en "test\x02") | nc -vvvl 8990; done;')
+
+ server = multiprocessing.Process(target=server_func)
+ server.start()
+ print '[Socket server on process %d]' % server.pid
+
+ def websockify_func():
+ os.system('python ' + path_from_root('third_party', 'websockify', 'run') + ' -vvv 8991 127.0.0.1:8990')
+
+ websockify = multiprocessing.Process(target=websockify_func)
+ websockify.start()
+ print '[Websockify on process %d]' % websockify.pid
+
+ self.btest('websockets.c', expected='fleefl')
+
+ finally:
+ try:
+ websockify.terminate()
+ print '[Cleaned up websockify]'
+ finally:
+ server.terminate()
+ print '[Cleaned up socket server]'
+
elif 'benchmark' in str(sys.argv):
# Benchmarks. Run them with argument |benchmark|. To run a specific test, do
# |benchmark.test_X|.
diff --git a/tests/websockets.c b/tests/websockets.c
new file mode 100644
index 00000000..5988b633
--- /dev/null
+++ b/tests/websockets.c
@@ -0,0 +1,119 @@
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if EMSCRIPTEN
+#include <emscripten.h>
+#endif
+
+#define EXPECTED_BYTES 5
+
+int SocketFD;
+
+unsigned int get_all_buf(int sock, char* output, unsigned int maxsize)
+{
+ char buffer[1024];
+
+ int n;
+ unsigned int offset = 0;
+ while((errno = 0, (n = recv(sock, buffer, sizeof(buffer), 0))>0) ||
+ errno == EINTR) {
+ if(n>0)
+ {
+ if (((unsigned int) n)+offset > maxsize) { fprintf(stderr, "too much data!"); exit(EXIT_FAILURE); }
+ memcpy(output+offset, buffer, n);
+ offset += n;
+ }
+ }
+
+ if(n < 0) {
+ fprintf(stderr, "error in get_all_buf!");
+ exit(EXIT_FAILURE);
+ }
+ return offset;
+}
+
+int done = 0;
+
+void iter(void *arg) {
+ /* perform read write operations ... */
+ static char out[1024*2];
+ static int pos = 0;
+ int n = get_all_buf(SocketFD, out+pos, 1024-pos);
+ if (n) printf("read! %d\n", n);
+ pos += n;
+ if (pos >= EXPECTED_BYTES) {
+ int i, sum = 0;
+ for (i=0; i < pos; i++) {
+ printf("%x\n", out[i]);
+ sum += out[i];
+ }
+
+ shutdown(SocketFD, SHUT_RDWR);
+
+ close(SocketFD);
+
+ done = 1;
+
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+ }
+}
+
+int main(void)
+{
+ struct sockaddr_in stSockAddr;
+ int Res;
+ SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if (-1 == SocketFD)
+ {
+ perror("cannot create socket");
+ exit(EXIT_FAILURE);
+ }
+
+ memset(&stSockAddr, 0, sizeof(stSockAddr));
+
+ stSockAddr.sin_family = AF_INET;
+ stSockAddr.sin_port = htons(
+#if EMSCRIPTEN
+ 8991
+#else
+ 8990
+#endif
+ );
+ Res = inet_pton(AF_INET, "127.0.0.1", &stSockAddr.sin_addr);
+
+ if (0 > Res) {
+ perror("error: first parameter is not a valid address family");
+ close(SocketFD);
+ exit(EXIT_FAILURE);
+ } else if (0 == Res) {
+ perror("char string (second parameter does not contain valid ipaddress)");
+ close(SocketFD);
+ exit(EXIT_FAILURE);
+ }
+
+ if (-1 == connect(SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr))) {
+ perror("connect failed");
+ close(SocketFD);
+ exit(EXIT_FAILURE);
+
+ }
+
+#if EMSCRIPTEN
+ emscripten_set_main_loop(iter, 0);
+#else
+ while (!done) iter(NULL);
+#endif
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/third_party/websockify/.gitignore b/third_party/websockify/.gitignore
new file mode 100644
index 00000000..86b78922
--- /dev/null
+++ b/third_party/websockify/.gitignore
@@ -0,0 +1,10 @@
+*.pyc
+*.o
+*.so
+other/.lein-deps-sum
+other/classes
+other/lib
+.project
+.pydevproject
+target.cfg
+target.cfg.d
diff --git a/third_party/websockify/CHANGES.txt b/third_party/websockify/CHANGES.txt
new file mode 100644
index 00000000..cbd3f73f
--- /dev/null
+++ b/third_party/websockify/CHANGES.txt
@@ -0,0 +1,18 @@
+Changes
+=======
+
+0.2.0 - Sep 17, 2012
+--------------------
+
+ * Binary data support in websock.js
+ * Target config file/dir and multiple targets with token selector
+ * IPv6 fixes
+ * SSL target support
+ * Proxy to/from unix socket
+
+
+0.1.0 - May 11, 2012
+--------------------
+
+ * Initial versioned release.
+
diff --git a/third_party/websockify/LICENSE.txt b/third_party/websockify/LICENSE.txt
new file mode 100644
index 00000000..916a77a0
--- /dev/null
+++ b/third_party/websockify/LICENSE.txt
@@ -0,0 +1,11 @@
+websockify is licensed under the LGPL version 3 (see docs/LICENSE.GPL-3 and
+docs/LICENSE.LGPL-3) with the following exceptions:
+
+ include/base64.js : Choice of MIT 1.1, GPL-2 or LGPL-2.1
+
+ include/web-socket-js/ : New BSD license. Source code at
+ https://github.com/gimite/web-socket-js
+
+ other/kumina.c : Simplified BSD license (2 clause).
+ Original source at
+ https://github.com/kumina/wsproxy
diff --git a/third_party/websockify/MANIFEST.in b/third_party/websockify/MANIFEST.in
new file mode 100644
index 00000000..2dd46d25
--- /dev/null
+++ b/third_party/websockify/MANIFEST.in
@@ -0,0 +1 @@
+include CHANGES.txt *.py README.md LICENSE.txt
diff --git a/third_party/websockify/Makefile b/third_party/websockify/Makefile
new file mode 100644
index 00000000..7dc1bc4f
--- /dev/null
+++ b/third_party/websockify/Makefile
@@ -0,0 +1,11 @@
+TARGETS=rebind.so
+CFLAGS += -fPIC
+
+all: $(TARGETS)
+
+rebind.so: rebind.o
+ $(CC) $(LDFLAGS) $^ -shared -fPIC -ldl -o $@
+
+clean:
+ rm -f rebind.o rebind.so
+
diff --git a/third_party/websockify/README.md b/third_party/websockify/README.md
new file mode 100644
index 00000000..48c790af
--- /dev/null
+++ b/third_party/websockify/README.md
@@ -0,0 +1,155 @@
+## websockify: WebSockets support for any application/server
+
+websockify was formerly named wsproxy and was part of the
+[noVNC](https://github.com/kanaka/noVNC) project.
+
+At the most basic level, websockify just translates WebSockets traffic
+to normal socket traffic. Websockify accepts the WebSockets handshake,
+parses it, and then begins forwarding traffic between the client and
+the target in both directions.
+
+### WebSockets binary data
+
+Websockify supports all versions of the WebSockets protocol (Hixie and
+HyBI). The older Hixie versions of the protocol only support UTF-8
+text payloads. In order to transport binary data over UTF-8 an
+encoding must used to encapsulate the data within UTF-8. Websockify
+uses base64 to encode all traffic to and from the client. This does
+not affect the data between websockify and the server.
+
+### Encrypted WebSocket connections (wss://)
+
+To encrypt the traffic using the WebSocket 'wss://' URI scheme you
+need to generate a certificate for websockify to load. By default websockify
+loads a certificate file name `self.pem` but the `--cert=CERT` option can
+override the file name. You can generate a self-signed certificate using
+openssl. When asked for the common name, use the hostname of the server where
+the proxy will be running:
+
+```
+openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
+```
+
+
+### Websock Javascript library
+
+
+The `include/websock.js` Javascript library library provides a Websock
+object that is similar to the standard WebSocket object but Websock
+enables communication with raw TCP sockets (i.e. the binary stream)
+via websockify. This is accomplished by base64 encoding the data
+stream between Websock and websockify.
+
+Websock has built-in receive queue buffering; the message event
+does not contain actual data but is simply a notification that
+there is new data available. Several rQ* methods are available to
+read binary data off of the receive queue.
+
+The Websock API is documented on the [websock.js API wiki page](https://github.com/kanaka/websockify/wiki/websock.js)
+
+See the "Wrap a Program" section below for an example of using Websock
+and websockify as a browser telnet client (`wstelnet.html`).
+
+
+### Additional websockify features
+
+These are not necessary for the basic operation.
+
+* Daemonizing: When the `-D` option is specified, websockify runs
+ in the background as a daemon process.
+
+* SSL (the wss:// WebSockets URI): This is detected automatically by
+ websockify by sniffing the first byte sent from the client and then
+ wrapping the socket if the data starts with '\x16' or '\x80'
+ (indicating SSL).
+
+* Flash security policy: websockify detects flash security policy
+ requests (again by sniffing the first packet) and answers with an
+ appropriate flash security policy response (and then closes the
+ port). This means no separate flash security policy server is needed
+ for supporting the flash WebSockets fallback emulator.
+
+* Session recording: This feature that allows recording of the traffic
+ sent and received from the client to a file using the `--record`
+ option.
+
+* Mini-webserver: websockify can detect and respond to normal web
+ requests on the same port as the WebSockets proxy and Flash security
+ policy. This functionality is activate with the `--web DIR` option
+ where DIR is the root of the web directory to serve.
+
+* Wrap a program: see the "Wrap a Program" section below.