diff --git a/src/net.cc b/src/net.cc index 53c914bd85..58abffa162 100644 --- a/src/net.cc +++ b/src/net.cc @@ -19,6 +19,7 @@ using namespace node; #define UTF8_SYMBOL String::NewSymbol("utf8") #define RAW_SYMBOL String::NewSymbol("raw") +#define RAWS_SYMBOL String::NewSymbol("raws") #define ASCII_SYMBOL String::NewSymbol("ascii") #define SERVER_SYMBOL String::NewSymbol("server") @@ -288,9 +289,12 @@ Connection::SetEncoding (const Arguments& args) return scope.Close(UTF8_SYMBOL); case RAW: - default: connection->encoding_ = RAW; return scope.Close(RAW_SYMBOL); + + case RAWS: + connection->encoding_ = RAWS; + return scope.Close(RAWS_SYMBOL); } } diff --git a/src/node.cc b/src/node.cc index 0cd82a1e8e..55aee83176 100644 --- a/src/node.cc +++ b/src/node.cc @@ -47,6 +47,17 @@ node::Encode (const void *buf, size_t len, enum encoding encoding) return scope.Close(array); } + if (encoding == RAWS) { + const unsigned char *cbuf = static_cast(buf); + uint16_t twobytebuf[len]; + for (size_t i = 0; i < len; i++) { + // XXX is the following line platform independent? + twobytebuf[i] = cbuf[i]; + } + Local chunk = String::New(twobytebuf, len); + return scope.Close(chunk); + } + // utf8 or ascii encoding Local chunk = String::New((const char*)buf, len); return scope.Close(chunk); @@ -109,7 +120,23 @@ node::DecodeWrite (char *buf, size_t buflen, v8::Handle val, enum enc return buflen; } - string->WriteAscii(buf, 0, buflen); + if (encoding == ASCII) { + string->WriteAscii(buf, 0, buflen); + return buflen; + } + + // THIS IS AWFUL!!! FIXME + + uint16_t twobytebuf[buflen]; + + string->Write(twobytebuf, 0, buflen); + + for (size_t i = 0; i < buflen; i++) { + unsigned char *b = reinterpret_cast(&twobytebuf[i]); + assert(b[1] == 0); + buf[i] = b[0]; + } + return buflen; } @@ -300,7 +327,7 @@ eio_want_poll (void) } enum encoding -node::ParseEncoding (Handle encoding_v) +node::ParseEncoding (Handle encoding_v, enum encoding _default) { HandleScope scope; @@ -313,8 +340,12 @@ node::ParseEncoding (Handle encoding_v) return UTF8; } else if (strcasecmp(*encoding, "ascii") == 0) { return ASCII; - } else { + } else if (strcasecmp(*encoding, "raw") == 0) { return RAW; + } else if (strcasecmp(*encoding, "raws") == 0) { + return RAWS; + } else { + return _default; } } diff --git a/src/node.h b/src/node.h index a5a153cf28..a2d5258cf9 100644 --- a/src/node.h +++ b/src/node.h @@ -32,8 +32,8 @@ do { \ __callback##_TEM); \ } while(0) -enum encoding {ASCII, UTF8, RAW}; -enum encoding ParseEncoding (v8::Handle encoding_v); +enum encoding {ASCII, UTF8, RAW, RAWS}; +enum encoding ParseEncoding (v8::Handle encoding_v, enum encoding _default = RAW); void FatalException (v8::TryCatch &try_catch); v8::Local diff --git a/src/node_stdio.cc b/src/node_stdio.cc index cff050714d..ff703c5e33 100644 --- a/src/node_stdio.cc +++ b/src/node_stdio.cc @@ -67,7 +67,13 @@ Write (const Arguments& args) { HandleScope scope; - enum encoding enc = ParseEncoding(args[1]); + if (args.Length() == 0) { + return ThrowException(Exception::Error(String::New("Bad argument"))); + } + + enum encoding enc = UTF8; + if (args.Length() > 1) enc = ParseEncoding(args[1], UTF8); + ssize_t len = DecodeBytes(args[0], enc); if (len < 0) { diff --git a/test/mjsunit/test-tcp-raws.js b/test/mjsunit/test-tcp-raws.js new file mode 100644 index 0000000000..5d86a1b3a4 --- /dev/null +++ b/test/mjsunit/test-tcp-raws.js @@ -0,0 +1,56 @@ +include("mjsunit.js"); +PORT = 23123; + +binaryString = ""; +for (var i = 0; i < 256; i++) { + var j = 255 - i; + var s = "'\\" + j.toString(8) + "'"; + S = eval(s); + puts(s + " " + JSON.stringify(S) + " " + S.charCodeAt(0)); + node.assert(S.charCodeAt(0) == j); + binaryString += S; +} + +var echoServer = node.tcp.createServer(function (connection) { + connection.setEncoding("raws"); + connection.addListener("receive", function (chunk) { + puts("recved: " + JSON.stringify(chunk)); + connection.send(chunk, "raws"); + }); + connection.addListener("eof", function () { + connection.close(); + }); +}); +echoServer.listen(PORT); + +var recv = ""; +var j = 0; + +var c = node.tcp.createConnection(PORT); + +c.setEncoding("raws"); +c.addListener("receive", function (chunk) { + if (j++ < 256) { + c.send([j]); + } else { + c.close(); + } + recv += chunk; +}); + +c.addListener("connect", function () { + c.send(binaryString, "raws"); +}); + +c.addListener("close", function () { + p(recv); + echoServer.close(); +}); + +process.addListener("exit", function () { + assertEquals(2*256, recv.length); + for (var i = 0; i < 256; i++) { + assertEquals(i, recv.charCodeAt(255+i)); + assertEquals(i, recv.charCodeAt(255-i)); + } +});