diff options
-rw-r--r-- | .npmignore | 2 | ||||
-rw-r--r-- | chrome/background.js | 8 | ||||
-rw-r--r-- | chrome/calculator-128.png | bin | 0 -> 16537 bytes | |||
-rw-r--r-- | chrome/calculator-16.png | bin | 0 -> 1049 bytes | |||
-rw-r--r-- | chrome/manifest.json | 29 | ||||
-rw-r--r-- | chrome/window.html | 9 | ||||
-rw-r--r-- | index.js | 27 | ||||
-rw-r--r-- | lib/string.js | 90 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | socket.js | 125 |
10 files changed, 291 insertions, 1 deletions
diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..6fc8fed --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +node_modules +bundle.js
\ No newline at end of file diff --git a/chrome/background.js b/chrome/background.js new file mode 100644 index 0000000..055203a --- /dev/null +++ b/chrome/background.js @@ -0,0 +1,8 @@ +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('window.html', { + 'bounds': { + 'width': 400, + 'height': 500 + } + }); +});
\ No newline at end of file diff --git a/chrome/calculator-128.png b/chrome/calculator-128.png Binary files differnew file mode 100644 index 0000000..85963f3 --- /dev/null +++ b/chrome/calculator-128.png diff --git a/chrome/calculator-16.png b/chrome/calculator-16.png Binary files differnew file mode 100644 index 0000000..0d9135e --- /dev/null +++ b/chrome/calculator-16.png diff --git a/chrome/manifest.json b/chrome/manifest.json new file mode 100644 index 0000000..40f6e4e --- /dev/null +++ b/chrome/manifest.json @@ -0,0 +1,29 @@ +{ + "manifest_version": 2, + + "name": "Hello World!", + "description": "My first Chrome App.", + "version": "0.1.0", + + "app": { + "background": { + "scripts": ["background.js"] + } + }, + + "permissions": [ + { + "socket": [ + "tcp-connect:*:*", + "tcp-listen::*", + "udp-send-to::*" + ] + }, + "storage", + "unlimitedStorage", + "fileSystem", + "http://*/*" + ], + + "icons": { "16": "calculator-16.png", "128": "calculator-128.png" } +}
\ No newline at end of file diff --git a/chrome/window.html b/chrome/window.html new file mode 100644 index 0000000..d9482c9 --- /dev/null +++ b/chrome/window.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> + <head> + </head> + <body> + <div>Hello, world!</div> + <script src='bundle.js'></script> + </body> +</html>
\ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..1ab7708 --- /dev/null +++ b/index.js @@ -0,0 +1,27 @@ +var isChromeApp = !!(window.chrome && chrome.app && chrome.app.runtime) + +// var socket = require('./socket') + +// var sock = new socket.UDPSocket('localhost', 54244) +// sock.connect(function (err) { +// if (err) throw err + +// sock.write('hello') +// }) + + + + +// require the core node events module +var EventEmitter = require('events').EventEmitter + +//create a new event emitter +var emitter = new EventEmitter() + +// set up a listener for the event +emitter.on('pizza', function(message){ + console.log(message); +}); + +// emit an event +emitter.emit('pizza', 'pizza is extremely yummy');
\ No newline at end of file diff --git a/lib/string.js b/lib/string.js new file mode 100644 index 0000000..80b1362 --- /dev/null +++ b/lib/string.js @@ -0,0 +1,90 @@ +/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding */ + +exports.fromUTF8Arr = UTF8ArrToStr +exports.toUTF8Arr = strToUTF8Arr + +/* UTF-8 array to DOMString and vice versa */ + +function UTF8ArrToStr (aBytes) { + + var sView = ""; + + for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) { + nPart = aBytes[nIdx]; + sView += String.fromCharCode( + nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */ + /* (nPart - 252 << 32) is not possible in ECMAScript! So...: */ + (nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 + : nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */ + (nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 + : nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */ + (nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 + : nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */ + (nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 + : nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */ + (nPart - 192 << 6) + aBytes[++nIdx] - 128 + : /* nPart < 127 ? */ /* one byte */ + nPart + ); + } + + return sView; + +} + +function strToUTF8Arr (sDOMStr) { + + var aBytes, nChr, nStrLen = sDOMStr.length, nArrLen = 0; + + /* mapping... */ + + for (var nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) { + nChr = sDOMStr.charCodeAt(nMapIdx); + nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6; + } + + aBytes = new Uint8Array(nArrLen); + + /* transcription... */ + + for (var nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) { + nChr = sDOMStr.charCodeAt(nChrIdx); + if (nChr < 128) { + /* one byte */ + aBytes[nIdx++] = nChr; + } else if (nChr < 0x800) { + /* two bytes */ + aBytes[nIdx++] = 192 + (nChr >>> 6); + aBytes[nIdx++] = 128 + (nChr & 63); + } else if (nChr < 0x10000) { + /* three bytes */ + aBytes[nIdx++] = 224 + (nChr >>> 12); + aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); + aBytes[nIdx++] = 128 + (nChr & 63); + } else if (nChr < 0x200000) { + /* four bytes */ + aBytes[nIdx++] = 240 + (nChr >>> 18); + aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); + aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); + aBytes[nIdx++] = 128 + (nChr & 63); + } else if (nChr < 0x4000000) { + /* five bytes */ + aBytes[nIdx++] = 248 + (nChr >>> 24); + aBytes[nIdx++] = 128 + (nChr >>> 18 & 63); + aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); + aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); + aBytes[nIdx++] = 128 + (nChr & 63); + } else /* if (nChr <= 0x7fffffff) */ { + /* six bytes */ + aBytes[nIdx++] = 252 + /* (nChr >>> 32) is not possible in ECMAScript! So...: */ (nChr / 1073741824); + aBytes[nIdx++] = 128 + (nChr >>> 24 & 63); + aBytes[nIdx++] = 128 + (nChr >>> 18 & 63); + aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); + aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); + aBytes[nIdx++] = 128 + (nChr & 63); + } + } + + return aBytes; + +}
\ No newline at end of file diff --git a/package.json b/package.json index 81d8c13..adc5f67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webtorrent", - "version": "0.0.1", + "version": "0.1.0", "description": "A streaming torrent client in your browser, powered by webRTC data channels (no install)", "main": "index.js", "dependencies": { diff --git a/socket.js b/socket.js new file mode 100644 index 0000000..a10b335 --- /dev/null +++ b/socket.js @@ -0,0 +1,125 @@ +exports.UDPSocket = UDPSocket +// exports.TCPSocket = TCPSocket + +var EventEmitter = require('events').EventEmitter +var string = require('./lib/string') +var util = require('util') + +util.inherits(BaseSocket, EventEmitter) + +function BaseSocket (host, port) { + var self = this + self.host = host + self.port = port + + self.paused = true + self.readPending = false + + EventEmitter.call(self) +} + +BaseSocket.prototype.connect = function (cb) { + var self = this + self._create(function (err, id) { + if (err) return cb(err) + self.id = id + chrome.socket.connect(self.id, self.host, self.port, function (res) { + if (res === 0) cb(null) + else cb(new Error('Unexpected connect result:' + res)) + }) + }) +} + +BaseSocket.prototype.end = function () { + var self = this + if (!self.id) return + chrome.socket.destroy(self.id) + self.id = null // mark socket as destroyed +} + +BaseSocket.prototype.getInfo = function (cb) { + var self = this + chrome.socket.getInfo(self.id, cb) +} + +BaseSocket.prototype.pause = function () { + var self = this + self.paused = true +} + +BaseSocket.prototype.resume = function () { + var self = this + self.paused = false + self.read() +} + +BaseSocket.prototype.read = function (readLength) { + var self = self + if (self.paused || self.readPending) return + self.readPending = true + + chrome.socket.read(self.id, readLength, function (readInfo) { + self.readPending = false + if (readInfo.resultCode < 0) return self.end() + + if (readInfo.data) { + self.emit('data', readInfo.data) + try { + // only read if not closed + if (self.id) self.read() + } catch (e) { + self.emit('error', e.stack || e.message || e) + self.end() + } + } + }) +} + + +util.inherits(UDPSocket, BaseSocket) + +function UDPSocket (host, port) { + var self = this + if (!(self instanceof UDPSocket)) return new UDPSocket(host, port) + + BaseSocket.call(self, host, port) +} + +UDPSocket.prototype._create = function (cb) { + var self = this + chrome.socket.create('udp', {}, function (createInfo) { + cb(null, createInfo.socketId) + }) +} + +UDPSocket.prototype.write = function (data) { + var self = this + if (!self.id) return + + if (typeof data === 'string') { + data = string.toUTF8Arr(data).buffer + } else if (data.buffer) { + data = data.buffer + } + + chrome.socket.write(self.id, data, function (writeInfo) { + if (writeInfo.bytesWritten < 0) { + console.warn('UDPSocket ' + self.id + ' write: ' + writeInfo.bytesWritten) + return self.end() + } + }) +} + +UDPSocket.prototype.recvLoop = function() { + var self = this + + chrome.socket.recvFrom(self.id, function (recvFromInfo) { + if (recvFromInfo.resultCode > 0) { + self.emit('data', recvFromInfo.data, recvFromInfo.address, + recvFromInfo.port) + self.recvLoop() + } else { + console.warn('UDPSocket ' + self.id + ' recvFrom: ', recvFromInfo) + } + }) +} |