From 0818b6655e8fd5ce14febd47470ac0445e3665f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Smodi=C5=A1?= Date: Mon, 5 Oct 2015 14:56:17 +0200 Subject: Bugfix: correctly handle python-nodejs transport using bytes. --- server/socket.py | 11 +++++------ web/main.js | 55 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/server/socket.py b/server/socket.py index 60f0704..121c6a4 100644 --- a/server/socket.py +++ b/server/socket.py @@ -125,21 +125,20 @@ class JsonClientSocket(SocketHandler): self.destroy() else: # packet decode loop - data = data.decode('utf-8') print("received: {}".format(data)) offset = 0 N = len(data) while (offset < N): if self.receiving_header: - i = data.find(':', offset) + i = data.find(b':', offset) if i < 0: self.buffer.append(data[offset:]) break if len(self.buffer) == 0: - self.body_length = int(data[offset:i]) + self.body_length = int(data[offset:i].decode('utf-8')) else: self.buffer.append(data[offset:i]) - self.body_length = int(''.join(self.buffer)) + self.body_length = int(b''.join(self.buffer)) self.buffer.clear() offset = i + 1 self.receiving_header = False @@ -153,12 +152,12 @@ class JsonClientSocket(SocketHandler): s = data[offset:offset+self.body_length - self.received_length] # TODO: is this correct? offset += len(s) self.buffer.append(s) - s = ''.join(self.buffer) + s = b''.join(self.buffer) self.buffer.clear() self.received_length = 0 self.receiving_header = True try: - processIncomingPacket(self, s) + processIncomingPacket(self, s.decode('utf-8')) except Exception as e: # any exception that propagates to here means a possible protocol error, we have to disconnect traceback.print_exc() diff --git a/web/main.js b/web/main.js index 8eac85c..16b318d 100644 --- a/web/main.js +++ b/web/main.js @@ -8,16 +8,17 @@ log4js.loadAppender('file'); log4js.addAppender(log4js.appenders.file('web.log'), 'log'); var logger = log4js.getLogger('log'); -Promise.onPossiblyUnhandledRejection(function (error) { - var msg = 'Unhandled promise rejection: ' + error; +var logException = function (msg, error) { if ((error instanceof Error) && (typeof error.stack === 'string')) msg += '\n' + error.stack; logger.error(msg); +}; + +Promise.onPossiblyUnhandledRejection(function (error) { + logException('Unhandled promise rejection: ' + error, error); }); process.on('uncaughtException', function (error) { - var msg = 'Uncaught exception: ' + error; - if ((error instanceof Error) && (typeof error.stack === 'string')) msg += '\n' + error.stack; - logger.error(msg); + logException('Uncaught exception: ' + error, error); }); http_server.listen(8083); @@ -136,7 +137,9 @@ server.on('connection', function (socket) { s = null; }); } - catch (e) {} // TODO: log + catch (e) { + logException('Failed to send reply to GUI about a fatal error: ' + e, e); + } socket = null; // this socket will no longer be processed session.socket = null; }, @@ -358,7 +361,7 @@ var sendPacketToPython = function sendPacketToPythonFunc(packet) { if (pythonSaturated || (pythonClient === null)) return false; logger.debug('Sending to Python: ' + packet); try { - pythonSaturated = !pythonClient.write(packet, 'utf8'); + pythonSaturated = !pythonClient.write(packet); return true; } catch (e) { @@ -390,7 +393,7 @@ var sendDataToPython = function sendDataToPythontFunc(packetObj) { } s = JSON.stringify(packetObj); - s = s.length + ':' + s; + s = new Buffer(Buffer.byteLength(s) + ':' + s); return new Promise(function (resolve, reject) { var existingResolver = pythonPromises[key]; @@ -425,7 +428,7 @@ var sendPythonQueue = function sendPythonQueueFunc() { var connectPython = function connectPythonFunc() { var receivingHeader = true, // whether we're receiving the length of the next packet, or the packet itself - receiveBuffer = [], // chunks of the next packet (header or body) + receiveBuffer = [], // chunks of the next packet (header or body), Buffer objects bodyLength = 0, // the required length of the next packet receivedLength = 0; // the size of the received body inside receiveBuffer up to now @@ -436,8 +439,6 @@ var connectPython = function connectPythonFunc() { 'port': 19732 }); - pythonClient.setEncoding('utf8'); - pythonClient.on('connect', function () { // login to the python server by sending it the list of currently handled sessions var sid, sessions = [], packet; @@ -453,6 +454,7 @@ var connectPython = function connectPythonFunc() { sendPacketToPython(packet); }); + // handler for incoming data, chunk is a Buffer object pythonClient.on('data', function (chunk) { var i, s, offset = 0, @@ -462,16 +464,21 @@ var connectPython = function connectPythonFunc() { while (offset < N) { // while there's data left to process if (receivingHeader) { // receiving the length of the packet - i = chunk.indexOf(':', offset); - if (i < 0) { + for (i = offset; i < N; i++) { + if (chunk[i] === 58) break; // found a colon? + } + if (i >= N) { // incomplete header, buffer it for the next 'data' event - receiveBuffer.push(chunk.substring(offset)); + s = chunk.slice(offset); + receiveBuffer.push(s); + receivedLength += s.length; break; } - if (receiveBuffer.length == 0) bodyLength = +chunk.substring(offset, i); + if (receiveBuffer.length == 0) bodyLength = +chunk.toString('utf8', offset, i); else { - receiveBuffer.push(chunk.substring(offset, i)); - bodyLength = +receiveBuffer.join(''); + s = chunk.slice(offset, i); + receiveBuffer.push(s); + bodyLength = +Buffer.concat(receiveBuffer, receivedLength + s.length).toString('utf8'); receiveBuffer.length = 0; receivedLength = 0; } @@ -482,26 +489,28 @@ var connectPython = function connectPythonFunc() { else if ((receivedLength + N - offset) >= bodyLength) { if (receivedLength == 0) { // an optimization in case the buffer is empty - s = chunk.substr(offset, bodyLength); + s = chunk.slice(offset, offset + bodyLength); offset += s.length; } else { - s = chunk.substr(offset, bodyLength - receivedLength); + s = chunk.slice(offset, offset + bodyLength - receivedLength); offset += s.length; receiveBuffer.push(s); - s = receiveBuffer.join(''); + s = Buffer.concat(receiveBuffer, receivedLength + s.length); receiveBuffer.length = 0; receivedLength = 0; } receivingHeader = true; // process the packet header in the next iteration try { - processPacketFromPython(s); + processPacketFromPython(s.toString('utf8')); + } + catch (e) { + logException('Failed to process a packet from Python: ' + e, e); } - catch (e) {} // TODO: log the error } else { // incomplete packet body, buffer it for the next 'data' event - s = chunk.substring(offset); + s = chunk.slice(offset); receiveBuffer.push(s); receivedLength += s.length; break; -- cgit v1.2.1