diff options
Diffstat (limited to 'js/src/Ice/browser/WSTransceiver.js')
-rw-r--r-- | js/src/Ice/browser/WSTransceiver.js | 701 |
1 files changed, 350 insertions, 351 deletions
diff --git a/js/src/Ice/browser/WSTransceiver.js b/js/src/Ice/browser/WSTransceiver.js index 9015659d9e1..f310c16dbc3 100644 --- a/js/src/Ice/browser/WSTransceiver.js +++ b/js/src/Ice/browser/WSTransceiver.js @@ -7,425 +7,424 @@ // // ********************************************************************** -(function(global){ - require("Ice/Class"); - require("Ice/Debug"); - require("Ice/ExUtil"); - require("Ice/Network"); - require("Ice/SocketOperation"); - require("Ice/Connection"); - require("Ice/Exception"); - require("Ice/LocalException"); - - var Ice = global.Ice || {}; - - var Debug = Ice.Debug; - var ExUtil = Ice.ExUtil; - var Network = Ice.Network; - var SocketOperation = Ice.SocketOperation; - var Conn = Ice.Connection; - var LocalException = Ice.LocalException; - var SocketException = Ice.SocketException; +var Ice = require("../Ice/ModuleRegistry").Ice; +Ice.__M.require(module, "Ice", + [ + "../Ice/Class", + "../Ice/Debug", + "../Ice/ExUtil", + "../Ice/Network", + "../Ice/SocketOperation", + "../Ice/Connection", + "../Ice/Exception", + "../Ice/LocalException" + ]); - var StateNeedConnect = 0; - var StateConnectPending = 1; - var StateConnected = 2; - var StateClosePending = 3; - var StateClosed = 4; +var Debug = Ice.Debug; +var ExUtil = Ice.ExUtil; +var Network = Ice.Network; +var SocketOperation = Ice.SocketOperation; +var Conn = Ice.Connection; +var LocalException = Ice.LocalException; +var SocketException = Ice.SocketException; - var IsFirefox = navigator.userAgent.indexOf("Firefox") !== -1; - - var WSTransceiver = Ice.Class({ - __init__: function(instance) - { - var id = instance.initializationData(); - this._traceLevels = instance.traceLevels(); - this._logger = id.logger; - this._readBuffers = []; - this._readPosition = 0; - this._maxSendPacketSize = id.properties.getPropertyAsIntWithDefault("Ice.TCP.SndSize", 512 * 1204); - }, - setCallbacks: function(connectedCallback, bytesAvailableCallback, bytesWrittenCallback) - { - this._connectedCallback = connectedCallback; - this._bytesAvailableCallback = bytesAvailableCallback; +var StateNeedConnect = 0; +var StateConnectPending = 1; +var StateConnected = 2; +var StateClosePending = 3; +var StateClosed = 4; - var transceiver = this; - this._bytesWrittenCallback = function() - { - if(transceiver._fd) - { - if(transceiver._fd.bufferedAmount < 1024 || this._exception) - { - bytesWrittenCallback(); - } - else - { - setTimeout(transceiver._bytesWrittenCallback, 50); - } - } - }; - }, - // - // Returns SocketOperation.None when initialization is complete. - // - initialize: function(readBuffer, writeBuffer) +var IsFirefox = navigator.userAgent.indexOf("Firefox") !== -1; + +var WSTransceiver = Ice.Class({ + __init__: function(instance) + { + var id = instance.initializationData(); + this._traceLevels = instance.traceLevels(); + this._logger = id.logger; + this._readBuffers = []; + this._readPosition = 0; + this._maxSendPacketSize = id.properties.getPropertyAsIntWithDefault("Ice.TCP.SndSize", 512 * 1204); + }, + setCallbacks: function(connectedCallback, bytesAvailableCallback, bytesWrittenCallback) + { + this._connectedCallback = connectedCallback; + this._bytesAvailableCallback = bytesAvailableCallback; + + var transceiver = this; + this._bytesWrittenCallback = function() { - try + if(transceiver._fd) { - if(this._exception) - { - throw this._exception; - } - - if(this._state === StateNeedConnect) + if(transceiver._fd.bufferedAmount < 1024 || this._exception) { - this._state = StateConnectPending; - this._fd = new WebSocket(this._url, "ice.zeroc.com"); - this._fd.binaryType = "arraybuffer"; - var self = this; - this._fd.onopen = function(e) { self.socketConnected(e); }; - this._fd.onmessage = function(e) { self.socketBytesAvailable(e.data); }; - this._fd.onclose = function(e) { self.socketClosed(e); }; - return SocketOperation.Connect; // Waiting for connect to complete. + bytesWrittenCallback(); } - else if(this._state === StateConnectPending) + else { - // - // Socket is connected. - // - this._desc = fdToString(this._addr); - this._state = StateConnected; + setTimeout(transceiver._bytesWrittenCallback, 50); } } - catch(err) + }; + }, + // + // Returns SocketOperation.None when initialization is complete. + // + initialize: function(readBuffer, writeBuffer) + { + try + { + if(this._exception) { - if(!this._exception) - { - this._exception = translateError(this._state, err); - } - - if(this._traceLevels.network >= 2) - { - var s = []; - s.push("failed to establish " + this.type() + " connection\n"); - s.push(fdToString(this._addr)); - this._logger.trace(this._traceLevels.networkCat, s.join("")); - } throw this._exception; } - Debug.assert(this._state === StateConnected); - if(this._traceLevels.network >= 1) + if(this._state === StateNeedConnect) { - this._logger.trace(this._traceLevels.networkCat, this.type() + - " connection established\n" + this._desc); + this._state = StateConnectPending; + this._fd = new WebSocket(this._url, "ice.zeroc.com"); + this._fd.binaryType = "arraybuffer"; + var self = this; + this._fd.onopen = function(e) { self.socketConnected(e); }; + this._fd.onmessage = function(e) { self.socketBytesAvailable(e.data); }; + this._fd.onclose = function(e) { self.socketClosed(e); }; + return SocketOperation.Connect; // Waiting for connect to complete. } - return SocketOperation.None; - }, - register: function() - { - // - // Register the socket data listener. - // - this._registered = true; - if(this._hasBytesAvailable || this._exception) + else if(this._state === StateConnectPending) { - this._bytesAvailableCallback(); - this._hasBytesAvailable = false; + // + // Socket is connected. + // + this._desc = fdToString(this._addr); + this._state = StateConnected; } - }, - unregister: function() - { - // - // Unregister the socket data listener. - // - this._registered = false; - }, - close: function() + } + catch(err) { - if(this._fd === null) + if(!this._exception) { - Debug.assert(this._exception); // Websocket creation failed. - return; + this._exception = translateError(this._state, err); } - // - // WORKAROUND: With Firefox, calling close() if the websocket isn't connected - // yet doesn't close the connection. The server doesn't receive any close frame - // and the underlying socket isn't closed causing the server to hang on closing - // the connection until the browser exits. - // - // To workaround this problem, we always wait for the socket to be connected - // or closed before closing the socket. - // - if(this._fd.readyState === WebSocket.CONNECTING && IsFirefox) - { - this._state = StateClosePending; - return; - } - - if(this._state == StateConnected && this._traceLevels.network >= 1) + if(this._traceLevels.network >= 2) { - this._logger.trace(this._traceLevels.networkCat, "closing " + this.type() + " connection\n" + - this._desc); + var s = []; + s.push("failed to establish " + this.type() + " connection\n"); + s.push(fdToString(this._addr)); + this._logger.trace(this._traceLevels.networkCat, s.join("")); } + throw this._exception; + } - Debug.assert(this._fd !== null); - try - { - this._state = StateClosed; - this._fd.close(); - } - catch(ex) - { - throw translateError(this._state, ex); - } - finally - { - this._fd = null; - } - }, + Debug.assert(this._state === StateConnected); + if(this._traceLevels.network >= 1) + { + this._logger.trace(this._traceLevels.networkCat, this.type() + + " connection established\n" + this._desc); + } + return SocketOperation.None; + }, + register: function() + { // - // Returns true if all of the data was flushed to the kernel buffer. + // Register the socket data listener. // - write: function(byteBuffer) + this._registered = true; + if(this._hasBytesAvailable || this._exception) { - if(this._exception) - { - throw this._exception; - } - else if(byteBuffer.remaining === 0) - { - return true; - } - - if(this._fd.bufferedAmount > 1024) - { - setTimeout(this._bytesWrittenCallback, 50); - return false; - } + this._bytesAvailableCallback(); + this._hasBytesAvailable = false; + } + }, + unregister: function() + { + // + // Unregister the socket data listener. + // + this._registered = false; + }, + close: function() + { + if(this._fd === null) + { + Debug.assert(this._exception); // Websocket creation failed. + return; + } - var packetSize = byteBuffer.remaining; - Debug.assert(packetSize > 0); - Debug.assert(this._fd); - - if(this._maxSendPacketSize > 0 && packetSize > this._maxSendPacketSize) - { - packetSize = this._maxSendPacketSize; - } + // + // WORKAROUND: With Firefox, calling close() if the websocket isn't connected + // yet doesn't close the connection. The server doesn't receive any close frame + // and the underlying socket isn't closed causing the server to hang on closing + // the connection until the browser exits. + // + // To workaround this problem, we always wait for the socket to be connected + // or closed before closing the socket. + // + if(this._fd.readyState === WebSocket.CONNECTING && IsFirefox) + { + this._state = StateClosePending; + return; + } + + if(this._state == StateConnected && this._traceLevels.network >= 1) + { + this._logger.trace(this._traceLevels.networkCat, "closing " + this.type() + " connection\n" + + this._desc); + } - while(packetSize > 0) - { - var slice = byteBuffer.b.slice(byteBuffer.position, byteBuffer.position + packetSize); - this._fd.send(slice); + Debug.assert(this._fd !== null); + try + { + this._state = StateClosed; + this._fd.close(); + } + catch(ex) + { + throw translateError(this._state, ex); + } + finally + { + this._fd = null; + } + }, + // + // Returns true if all of the data was flushed to the kernel buffer. + // + write: function(byteBuffer) + { + if(this._exception) + { + throw this._exception; + } + else if(byteBuffer.remaining === 0) + { + return true; + } - if(this._traceLevels.network >= 3) - { - this._logger.trace(this._traceLevels.networkCat, "sent " + packetSize + " of " + - byteBuffer.remaining + " bytes via " + this.type() + "\n" + this._desc); - } - byteBuffer.position = byteBuffer.position + packetSize; + if(this._fd.bufferedAmount > 1024) + { + setTimeout(this._bytesWrittenCallback, 50); + return false; + } - if(this._maxSendPacketSize > 0 && byteBuffer.remaining > this._maxSendPacketSize) - { - packetSize = this._maxSendPacketSize; - } - else - { - packetSize = byteBuffer.remaining; - } + var packetSize = byteBuffer.remaining; + Debug.assert(packetSize > 0); + Debug.assert(this._fd); + + if(this._maxSendPacketSize > 0 && packetSize > this._maxSendPacketSize) + { + packetSize = this._maxSendPacketSize; + } - if(this._fd.bufferedAmount > 0 && packetSize > 0) - { - setTimeout(this._bytesWrittenCallback, 50); - return false; - } - } - return true; - }, - read: function(byteBuffer, moreData) + while(packetSize > 0) { - if(this._exception) + var slice = byteBuffer.b.slice(byteBuffer.position, byteBuffer.position + packetSize); + this._fd.send(slice); + + if(this._traceLevels.network >= 3) { - throw this._exception; + this._logger.trace(this._traceLevels.networkCat, "sent " + packetSize + " of " + + byteBuffer.remaining + " bytes via " + this.type() + "\n" + this._desc); } + byteBuffer.position = byteBuffer.position + packetSize; - moreData.value = false; - - if(this._readBuffers.length === 0) + if(this._maxSendPacketSize > 0 && byteBuffer.remaining > this._maxSendPacketSize) { - return false; // No data available. + packetSize = this._maxSendPacketSize; } - - var avail = this._readBuffers[0].byteLength - this._readPosition; - Debug.assert(avail > 0); - var remaining = byteBuffer.remaining; - - while(byteBuffer.remaining > 0) + else { - if(avail > byteBuffer.remaining) - { - avail = byteBuffer.remaining; - } - - new Uint8Array(byteBuffer.b).set(new Uint8Array(this._readBuffers[0], this._readPosition, avail), - byteBuffer.position); - - byteBuffer.position += avail; - this._readPosition += avail; - if(this._readPosition === this._readBuffers[0].byteLength) - { - // - // We've exhausted the current read buffer. - // - this._readPosition = 0; - this._readBuffers.shift(); - if(this._readBuffers.length === 0) - { - break; // No more data - we're done. - } - else - { - avail = this._readBuffers[0].byteLength; - } - } + packetSize = byteBuffer.remaining; } - var n = remaining - byteBuffer.remaining; - if(n > 0 && this._traceLevels.network >= 3) + if(this._fd.bufferedAmount > 0 && packetSize > 0) { - var msg = "received " + n + " of " + remaining + " bytes via " + this.type() + "\n" + this._desc; - this._logger.trace(this._traceLevels.networkCat, msg); + setTimeout(this._bytesWrittenCallback, 50); + return false; } + } + return true; + }, + read: function(byteBuffer, moreData) + { + if(this._exception) + { + throw this._exception; + } - moreData.value = this._readBuffers.byteLength > 0; + moreData.value = false; - return byteBuffer.remaining === 0; - }, - type: function() - { - return this._secure ? "wss" : "ws"; - }, - getInfo: function() - { - Debug.assert(this._fd !== null); - var info = this.createInfo(); - - // - // The WebSocket API doens't provide this info - // - info.localAddress = ""; - info.localPort = -1; - info.remoteAddress = this._addr.host; - info.remotePort = this._addr.port; - return info; - }, - createInfo: function() - { - return new Ice.WSConnectionInfo(); - }, - checkSendSize: function(stream, messageSizeMax) - { - if(stream.size > messageSizeMax) - { - ExUtil.throwMemoryLimitException(stream.size, messageSizeMax); - } - }, - toString: function() + if(this._readBuffers.length === 0) { - return this._desc; - }, - socketConnected: function(e) + return false; // No data available. + } + + var avail = this._readBuffers[0].byteLength - this._readPosition; + Debug.assert(avail > 0); + var remaining = byteBuffer.remaining; + + while(byteBuffer.remaining > 0) { - if(this._state == StateClosePending) + if(avail > byteBuffer.remaining) { - this.close(); - return; + avail = byteBuffer.remaining; } - - Debug.assert(this._connectedCallback !== null); - this._connectedCallback(); - }, - socketBytesAvailable: function(buf) - { - Debug.assert(this._bytesAvailableCallback !== null); - if(buf.byteLength > 0) + + new Uint8Array(byteBuffer.b).set(new Uint8Array(this._readBuffers[0], this._readPosition, avail), + byteBuffer.position); + + byteBuffer.position += avail; + this._readPosition += avail; + if(this._readPosition === this._readBuffers[0].byteLength) { - this._readBuffers.push(buf); - if(this._registered) + // + // We've exhausted the current read buffer. + // + this._readPosition = 0; + this._readBuffers.shift(); + if(this._readBuffers.length === 0) { - this._bytesAvailableCallback(); + break; // No more data - we're done. } - else if(!this._hasBytesAvailable) + else { - this._hasBytesAvailable = true; + avail = this._readBuffers[0].byteLength; } } - }, - socketClosed: function(err) + } + + var n = remaining - byteBuffer.remaining; + if(n > 0 && this._traceLevels.network >= 3) { - if(this._state == StateClosePending) - { - this.close(); - return; - } - - this._exception = translateError(this._state, err); - if(this._state < StateConnected) + var msg = "received " + n + " of " + remaining + " bytes via " + this.type() + "\n" + this._desc; + this._logger.trace(this._traceLevels.networkCat, msg); + } + + moreData.value = this._readBuffers.byteLength > 0; + + return byteBuffer.remaining === 0; + }, + type: function() + { + return this._secure ? "wss" : "ws"; + }, + getInfo: function() + { + Debug.assert(this._fd !== null); + var info = this.createInfo(); + + // + // The WebSocket API doens't provide this info + // + info.localAddress = ""; + info.localPort = -1; + info.remoteAddress = this._addr.host; + info.remotePort = this._addr.port; + return info; + }, + createInfo: function() + { + return new Ice.WSConnectionInfo(); + }, + checkSendSize: function(stream, messageSizeMax) + { + if(stream.size > messageSizeMax) + { + ExUtil.throwMemoryLimitException(stream.size, messageSizeMax); + } + }, + toString: function() + { + return this._desc; + }, + socketConnected: function(e) + { + if(this._state == StateClosePending) + { + this.close(); + return; + } + + Debug.assert(this._connectedCallback !== null); + this._connectedCallback(); + }, + socketBytesAvailable: function(buf) + { + Debug.assert(this._bytesAvailableCallback !== null); + if(buf.byteLength > 0) + { + this._readBuffers.push(buf); + if(this._registered) { - this._connectedCallback(); + this._bytesAvailableCallback(); } - else if(this._registered) + else if(!this._hasBytesAvailable) { - this._bytesAvailableCallback(); + this._hasBytesAvailable = true; } - }, - }); - - function fdToString(address) - { - return "local address = <not available>\nremote address = " + address.host + ":" + address.port; - } - - function translateError(state, err) + } + }, + socketClosed: function(err) { - if(state < StateConnected) + if(this._state == StateClosePending) + { + this.close(); + return; + } + + this._exception = translateError(this._state, err); + if(this._state < StateConnected) { - return new Ice.ConnectFailedException(err.code, err); + this._connectedCallback(); } - else + else if(this._registered) { - if(err.code === 1000 || err.code === 1006) // CLOSE_NORMAL | CLOSE_ABNORMAL - { - return new Ice.ConnectionLostException(); - } - return new Ice.SocketException(err.code, err); + this._bytesAvailableCallback(); } + }, +}); + +function fdToString(address) +{ + return "local address = <not available>\nremote address = " + address.host + ":" + address.port; +} + +function translateError(state, err) +{ + if(state < StateConnected) + { + return new Ice.ConnectFailedException(err.code, err); } - - WSTransceiver.createOutgoing = function(instance, secure, addr, resource) + else { - var transceiver = new WSTransceiver(instance); - - var url = secure ? "wss" : "ws"; - url += "://" + addr.host; - if(addr.port !== 80) + if(err.code === 1000 || err.code === 1006) // CLOSE_NORMAL | CLOSE_ABNORMAL { - url += ":" + addr.port; + return new Ice.ConnectionLostException(); } - url += resource ? resource : "/"; - transceiver._url = url; - transceiver._fd = null; - transceiver._addr = addr; - transceiver._desc = "remote address: " + addr.host + ":" + addr.port + " <not connected>"; - transceiver._state = StateNeedConnect; - transceiver._secure = secure; - transceiver._exception = null; - - return transceiver; - }; + return new Ice.SocketException(err.code, err); + } +} + +WSTransceiver.createOutgoing = function(instance, secure, addr, resource) +{ + var transceiver = new WSTransceiver(instance); + + var url = secure ? "wss" : "ws"; + url += "://" + addr.host; + if(addr.port !== 80) + { + url += ":" + addr.port; + } + url += resource ? resource : "/"; + transceiver._url = url; + transceiver._fd = null; + transceiver._addr = addr; + transceiver._desc = "remote address: " + addr.host + ":" + addr.port + " <not connected>"; + transceiver._state = StateNeedConnect; + transceiver._secure = secure; + transceiver._exception = null; + + return transceiver; +}; - Ice.WSTransceiver = WSTransceiver; - global.Ice = Ice; -}(typeof (global) === "undefined" ? window : global)); +Ice.WSTransceiver = WSTransceiver; |