var net = require('net'); var tls = require('tls'); var createBufferSegment = require('../../common/bufferSegment'); const MaxSendPacketSize = 64 * 1024; function TcpConnection(log, connectionId, remoteEndPoint, onConnectionClosed) { this._socket = null; this._log = log; this._connectionId = connectionId; this._remoteEndPoint = remoteEndPoint; this._localEndPoint = null; this._onConnectionClosed = onConnectionClosed; this._receiveCallback = null; this._closed = false; this._sendQueue = []; this._receiveQueue = []; Object.defineProperty(this, 'remoteEndPoint', { enumerable: true, get: function() { return this._remoteEndPoint; } }); Object.defineProperty(this, 'localEndPoint', { enumerable: true, get: function() { return this._localEndPoint; } }); } TcpConnection.prototype._initSocket = function(socket) { this._socket = socket; this._localEndPoint = {host: socket.localAddress, port: socket.localPort}; this._remoteEndPoint.host = socket.remoteAddress; this._socket.on('error', this._processError.bind(this)); this._socket.on('drain', this._trySend.bind(this)); this._socket.on('data', this._processReceive.bind(this)); this._socket.on('close', this._processClose.bind(this)); this._trySend(); }; TcpConnection.prototype.enqueueSend = function(bufSegmentArray) { for(var i = 0; i < bufSegmentArray.length; i++) { var bufSegment = bufSegmentArray[i]; this._sendQueue.push(bufSegment.toBuffer()); } this._trySend(); }; TcpConnection.prototype._trySend = function() { if (this._sendQueue.length === 0 || this._socket === null) return; var buffers = []; var bytes = 0; var sendPiece; while((sendPiece = this._sendQueue.shift())) { buffers.push(sendPiece); bytes += sendPiece.length; if (bytes > MaxSendPacketSize) break; } var joinedBuffers = Buffer.concat(buffers, bytes); if (!this._socket.write(joinedBuffers)) return; setImmediate(this._trySend.bind(this)); }; TcpConnection.prototype._processError = function(err) { this._closeInternal(err, "Socket error"); }; TcpConnection.prototype._processClose = function(had_error) { this._closeInternal(had_error, "Socket closed"); }; TcpConnection.prototype._processReceive = function(buf) { if (buf.length === 0) { //NotifyReceiveCompleted(0); this._closeInternal(null, "Socket closed"); return; } //NotifyReceiveCompleted(buf.length) this._receiveQueue.push(buf); this._tryDequeueReceivedData(); }; TcpConnection.prototype.receive = function(cb) { this._receiveCallback = cb; this._tryDequeueReceivedData(); }; TcpConnection.prototype._tryDequeueReceivedData = function() { if (this._receiveCallback === null || this._receiveQueue.length === 0) return; var res = []; while(this._receiveQueue.length > 0) { var buf = this._receiveQueue.shift(); var bufferSegment = createBufferSegment(buf); res.push(bufferSegment); } var callback = this._receiveCallback; this._receiveCallback = null; callback(this, res); var bytes = 0; for(var i=0;i