"use strict"; var makeChannel = require('culvert'); var wrapHandler = require('../lib/wrap-handler'); var tcp = window.chrome.sockets.tcp; var runtime = window.chrome.runtime; module.exports = connect; function connect(host, port, onError) { port = port|0; host = String(host); if (!port || !host) throw new TypeError("host and port are required"); onCreate = wrap(onCreate, onError); onConnect = wrap(onConnect, onError); onInfo = wrap(onInfo, onError); onReceive = wrap(onReceive, onError); onReceiveError = wrap(onReceiveError, onError); onData = wrapHandler(onData, onError); onWrite = wrap(onWrite, onError); var paused = false; var open = false; var socketId; var serverChannel = makeChannel(); var clientChannel = makeChannel(); var socket = { put: serverChannel.put, drain: serverChannel.drain, take: clientChannel.take }; tcp.onReceive.addListener(onReceive); tcp.onReceiveError.addListener(onReceiveError); tcp.create(onCreate); return { put: clientChannel.put, drain: clientChannel.drain, take: serverChannel.take }; function onCreate(createInfo) { socketId = createInfo.socketId; tcp.connect(socketId, host, port, onConnect); } function onConnect(result) { if (result < 0) throw new Error(runtime.lastError.message + " Connection error"); tcp.getInfo(socketId, onInfo); } function onInfo(socketInfo) { if (!socketInfo.connected) { throw new Error("Connection failed"); } open = true; socket.take(onData); } function onReceive(info) { if (info.socketId !== socketId) return; if (socket.put(new Uint8Array(info.data)) || paused) return; paused = true; tcp.setPaused(socketId, true); socket.drain(onDrain); } function onDrain() { if (!paused) return; paused = false; if (open) tcp.setPaused(socketId, false); } function onReceiveError(info) { if (info.socketId !== socketId) return; open = false; tcp.close(socketId); socket.put(); // TODO: find a way to tell close and error apart. // throw new Error("Code " + info.resultCode + " error while receiving."); } function onData(data) { tcp.send(socketId, data.buffer, onWrite); } function onWrite(info) { if (info.resultCode < 0) { throw new Error(runtime.lastError.message + " Error writing."); } socket.take(onData); } } function wrap(fn, onError) { return function () { try { return fn.apply(this, arguments); } catch (err) { onError(err); } }; }