Permalink
Browse files

Fixed UTF-8 handling (#14).

Some time ago SLIME wire protocol was changed to specify
number of bytes in the header, and here we were still counting
chars which was leading to protocol errors.
  • Loading branch information...
1 parent 4259fdd commit b31b86ea03cad2cff4843b73f241840b6478b52f @ivan4th ivan4th committed Feb 22, 2012
Showing with 45 additions and 35 deletions.
  1. +13 −3 swank-protocol-tests.js
  2. +29 −28 swank-protocol.js
  3. +3 −4 swank.js
View
16 swank-protocol-tests.js
@@ -44,7 +44,7 @@ var parser = new swp.SwankParser(
function feed (text) {
for (var i = 1; i < arguments.length; ++i)
expected.push(arguments[i]);
- parser.execute(text);
+ parser.execute(new Buffer(text));
assert.equal(0, expected.length);
}
@@ -68,9 +68,19 @@ feed(" \"COMMON-LISP-USER\" t 1");
feed(")",
list(S(":emacs-rex"), list(S("swank:connection-info")),
"COMMON-LISP-USER", S("t"), 1));
+feed('000047(:emacs-rex (:listener-eval "\\"\u0439\u0446\u0443\\"") "FIREFOX-9.0" :repl-thread 4)',
+ list(S(":emacs-rex"),
+ list(S(":listener-eval"),
+ '"\u0439\u0446\u0443"'),
+ "FIREFOX-9.0", S(":repl-thread"), 4));
assert.equal(
"000015(:return (:ok nil) 1)",
- swp.buildMessage(list(S(":return"), list(S(":ok"), nil), 1)));
+ swp.buildMessage(list(S(":return"), list(S(":ok"), nil), 1)).toString());
-// TBD: check unicode string handling (use \uxxxx notation)
+assert.equal(
+ '000047(:emacs-rex (:listener-eval "\\"\u0439\u0446\u0443\\"") "FIREFOX-9.0" :repl-thread 4)',
+ swp.buildMessage(list(S(":emacs-rex"),
+ list(S(":listener-eval"),
+ '"\u0439\u0446\u0443"'),
+ "FIREFOX-9.0", S(":repl-thread"), 4)).toString());
View
57 swank-protocol.js
@@ -33,51 +33,52 @@ const DUMMY_HEADER = "000000";
const MAX_MESSAGE_SIZE = 10 * 1024 * 1024;
function SwankParser (onMessage) {
- this.needChars = HEADER_LEN;
- this.handleData = this.handleHeader;
- this.stash = "";
this.onMessage = onMessage;
+ this.resetBuffer();
};
// FIXME: proper error handling (handle both packet parsing and reader errors)
-SwankParser.prototype.execute = function execute (text) {
+SwankParser.prototype.resetBuffer = function resetBuffer (len, handler) {
+ len = len || HEADER_LEN;
+ this.needChars = len;
+ this.handleData = handler || this.handleHeader;
+ this.stash = new Buffer(len);
+ this.pos = 0;
+};
+
+SwankParser.prototype.execute = function execute (buffer) {
var offset = 0;
- while (offset < text.length)
- offset += this.handleContent(text, offset);
+ while (offset < buffer.length)
+ offset += this.handleContent(buffer, offset);
};
-SwankParser.prototype.handleContent = function handleContent (text, offset) {
- var stashLen = this.stash.length;
- var avail = Math.min(this.needChars, text.length + stashLen - offset);
- var message = this.stash + text.substring(offset, offset + avail - stashLen);
- if (avail < this.needChars)
- this.stash = message;
- else {
- this.stash = "";
- this.handleData(message);
- }
- return message.length - stashLen;
+SwankParser.prototype.handleContent = function handleContent (buffer, offset) {
+ var newPos = Math.min(this.needChars, this.pos + buffer.length - offset);
+ var bytesToCopy = newPos - this.pos;
+ buffer.copy(this.stash, this.pos, offset, offset + bytesToCopy);
+ this.pos = newPos;
+ if (this.pos == this.needChars)
+ this.handleData();
+ return bytesToCopy; // stashLen + newPos - stashLen
};
-SwankParser.prototype.handleHeader = function handleHeader (str) {
- var count = parseInt(str, 16) || 0;
- if (count > 0 && count < MAX_MESSAGE_SIZE) {
- this.needChars = count;
- this.handleData = this.handleMessage;
- } else
- this.needChars = HEADER_LEN; // FIXME: handle errors
+SwankParser.prototype.handleHeader = function handleHeader () {
+ var count = parseInt(this.stash.toString(), 16) || 0;
+ if (count > 0 && count < MAX_MESSAGE_SIZE)
+ this.resetBuffer(count, this.handleMessage);
+ else
+ this.resetBuffer();
};
SwankParser.prototype.handleMessage = function handleMessage (str) {
- this.onMessage(readFromString(str)); // FIXME: handle errors
- this.needChars = HEADER_LEN;
- this.handleData = this.handleHeader;
+ this.onMessage(readFromString(this.stash.toString())); // FIXME: handle errors
+ this.resetBuffer();
};
function buildMessage (obj) {
var str = obj.toString();
- var lenStr = "" + str.length.toString(16);
+ var lenStr = "" + Buffer.byteLength(str).toString(16);
while (lenStr.length < HEADER_LEN)
lenStr = "0" + lenStr;
return lenStr + str;
View
7 swank.js
@@ -43,17 +43,16 @@ var executive = new swh.Executive({ config: cfg });
var swankServer = net.createServer(
function (stream) {
- stream.setEncoding("utf-8");
var handler = new swh.Handler(executive);
var parser = new swp.SwankParser(
function onMessage (message) {
handler.receive(message);
});
handler.on(
"response", function (response) {
- var responseText = swp.buildMessage(response);
- console.log("response: %s", responseText);
- stream.write(responseText);
+ var responseBuf = swp.buildMessage(response);
+ console.log("response: %s", responseBuf.toString());
+ stream.write(responseBuf);
});
stream.on(
"data", function (data) {

0 comments on commit b31b86e

Please sign in to comment.