From 2fdd916b8bd30a72a496b203e98a0daaadc1d626 Mon Sep 17 00:00:00 2001 From: henrique Date: Wed, 28 Aug 2013 14:03:34 +0200 Subject: [PATCH] THRIFT-2053 NodeJS: Support for Multiplexing Services Client: nodejs Patch: Remo Hertig --- compiler/cpp/src/generate/t_js_generator.cc | 19 +- lib/nodejs/lib/thrift/connection.js | 8 + lib/nodejs/lib/thrift/index.js | 10 +- .../lib/thrift/multiplexed_processor.js | 56 ++++ lib/nodejs/lib/thrift/multiplexed_protocol.js | 63 ++++ lib/nodejs/lib/thrift/server.js | 17 +- test/ThriftTest.thrift | 6 + test/nodejs/Makefile.am | 12 + test/nodejs/multiplex_client.js | 302 ++++++++++++++++++ test/nodejs/multiplex_server.js | 242 ++++++++++++++ 10 files changed, 723 insertions(+), 12 deletions(-) create mode 100644 lib/nodejs/lib/thrift/multiplexed_processor.js create mode 100644 lib/nodejs/lib/thrift/multiplexed_protocol.js create mode 100644 test/nodejs/multiplex_client.js create mode 100644 test/nodejs/multiplex_server.js diff --git a/compiler/cpp/src/generate/t_js_generator.cc b/compiler/cpp/src/generate/t_js_generator.cc index 9f7fa041..565bb805 100644 --- a/compiler/cpp/src/generate/t_js_generator.cc +++ b/compiler/cpp/src/generate/t_js_generator.cc @@ -981,7 +981,7 @@ void t_js_generator::generate_service_client(t_service* tservice) { f_service_ << indent() << " this.output = output;" << endl << indent() << " this.pClass = pClass;" << endl << - indent() << " this.seqid = 0;" << endl << + indent() << " this._seqid = 0;" << endl << indent() << " this._reqs = {};" << endl; } else { f_service_ << @@ -1007,6 +1007,11 @@ void t_js_generator::generate_service_client(t_service* tservice) { indent(f_service_) << js_namespace(tservice->get_program())<get_program())<get_program())< functions = tservice->get_functions(); vector::const_iterator f_iter; @@ -1025,8 +1030,8 @@ void t_js_generator::generate_service_client(t_service* tservice) { if (gen_node_) { f_service_ << - indent() << "this.seqid += 1;" << endl << - indent() << "this._reqs[this.seqid] = callback;" << endl; + indent() << "this._seqid = this.new_seqid();" << endl << + indent() << "this._reqs[this.seqid()] = callback;" << endl; } else if (gen_jquery_) { f_service_ << indent() << "if (callback === undefined) {" << endl; @@ -1082,8 +1087,12 @@ void t_js_generator::generate_service_client(t_service* tservice) { std::string argsname = js_namespace(program_)+ service_name_ + "_" + (*f_iter)->get_name() + "_args"; // Serialize the request header - f_service_ << - indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name() << "', Thrift.MessageType.CALL, this.seqid);" << endl; + if (gen_node_) { + f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name() << "', Thrift.MessageType.CALL, this.seqid());" << endl; + } + else { + f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name() << "', Thrift.MessageType.CALL, this.seqid);" << endl; + } f_service_ << indent() << "var args = new " << argsname << "();" << endl; diff --git a/lib/nodejs/lib/thrift/connection.js b/lib/nodejs/lib/thrift/connection.js index 904d7bd8..4581d819 100644 --- a/lib/nodejs/lib/thrift/connection.js +++ b/lib/nodejs/lib/thrift/connection.js @@ -103,6 +103,12 @@ var Connection = exports.Connection = function(stream, options) { callback(err, success); } }; + +if(!client['recv_' + header.fname]) { +// msg was for another serivce, just drop it +delete client._reqs[dummy_seqid] +return +} client['recv_' + header.fname](message, header.mtype, dummy_seqid); } catch (e) { @@ -199,6 +205,8 @@ exports.createConnection = function(host, port, options) { return connection; } + + exports.createClient = function(cls, connection) { if (cls.Client) { cls = cls.Client; diff --git a/lib/nodejs/lib/thrift/index.js b/lib/nodejs/lib/thrift/index.js index bf340850..92014fd3 100644 --- a/lib/nodejs/lib/thrift/index.js +++ b/lib/nodejs/lib/thrift/index.js @@ -25,13 +25,19 @@ exports.createConnection = connection.createConnection; exports.createStdIOClient = connection.createStdIOClient; exports.createStdIOConnection = connection.createStdIOConnection; -server = require('./server') +var server = require('./server') exports.createServer = server.createServer; exports.createHttpServer = server.createHttpServer; -exports.httpMiddleware = server.httpMiddleware +exports.httpMiddleware = server.httpMiddleware; +exports.createMultiplexServer = server.createMultiplexServer; exports.Int64 = require('node-int64') +var mprocessor = require('./multiplexed_processor'); +var mprotocol = require('./multiplexed_protocol'); +exports.Multiplexer = mprotocol.Multiplexer +exports.MultiplexedProcessor = mprocessor.MultiplexedProcessor + /* * Export transport and protocol so they can be used outside of a * cassandra/server context diff --git a/lib/nodejs/lib/thrift/multiplexed_processor.js b/lib/nodejs/lib/thrift/multiplexed_processor.js new file mode 100644 index 00000000..cb885f47 --- /dev/null +++ b/lib/nodejs/lib/thrift/multiplexed_processor.js @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +var Thrift = require('./thrift'); + +var MultiplexedProcessor = exports.MultiplexedProcessor = function(stream, options) { + this.services = new Map(); +}; + +MultiplexedProcessor.prototype.registerProcessor = function(name, handler) { + this.services.set(name, handler); +}; + +MultiplexedProcessor.prototype.process = function(inp, out) { + + var begin = inp.readMessageBegin(); + + if (begin.mtype != Thrift.MessageType.CALL || begin.mtype == Thrift.MessageType.ONEWAY) { + throw Thrift.TException("TMultiplexedProcessor: Unexpected message type"); + } + + var p = begin.fname.split(":"); + var sname = p[0]; + var fname = p[1]; + + if (!this.services.has(sname)) { + throw Thrift.TException("TMultiplexedProcessor: Unknown service: " + sname); + } + inp.readMessageBegin = function() { + + + return { + fname: fname, + mtype: begin.mtype, + rseqid: begin.rseqid + }; + } + + this.services.get(sname).process(inp, out); + +}; diff --git a/lib/nodejs/lib/thrift/multiplexed_protocol.js b/lib/nodejs/lib/thrift/multiplexed_protocol.js new file mode 100644 index 00000000..9a955abd --- /dev/null +++ b/lib/nodejs/lib/thrift/multiplexed_protocol.js @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +var util = require('util'); +var Thrift = require('./thrift'); + +var Wrapper = exports.Wrapper = function(service_name, protocol) { + + var MultiplexProtocol = function(trans, strictRead, strictWrite) { + protocol.call(this, trans, strictRead, strictWrite); + } + util.inherits(MultiplexProtocol, protocol); + + MultiplexProtocol.prototype.writeMessageBegin = function(name, type, seqid) { + + if (type == Thrift.MessageType.CALL || type == Thrift.MessageType.ONEWAY) + MultiplexProtocol.super_.prototype.writeMessageBegin.call(this, service_name + ":" + name, type, seqid); + else + MultiplexProtocol.super_.prototype.writeMessageBegin.call(this, name, type, seqid); + } + + return MultiplexProtocol; +} + +var Multiplexer = exports.Multiplexer = function() { + this.seqid = 0; +} + +Multiplexer.prototype.createClient = function(service_name, cls, connection) { + if (cls.Client) { + cls = cls.Client; + } + var self = this; + cls.prototype.new_seqid = function() { + self.seqid += 1; + return self.seqid; + } + + var client = new cls(new connection.transport(undefined, function(buf) { + connection.write(buf); + }), new Wrapper(service_name, connection.protocol)); + + + // TODO clean this up + connection.client = client; + + return client; +} diff --git a/lib/nodejs/lib/thrift/server.js b/lib/nodejs/lib/thrift/server.js index 228bb036..e9a76233 100644 --- a/lib/nodejs/lib/thrift/server.js +++ b/lib/nodejs/lib/thrift/server.js @@ -22,11 +22,9 @@ var http = require('http'); var ttransport = require('./transport') , TBinaryProtocol = require('./protocol').TBinaryProtocol; -exports.createServer = function(cls, handler, options) { - if (cls.Processor) { - cls = cls.Processor; - } - var processor = new cls(handler); + +exports.createMultiplexServer = function(processor, options) { + var transport = (options && options.transport) ? options.transport : ttransport.TBufferedTransport; var protocol = (options && options.protocol) ? options.protocol : TBinaryProtocol; @@ -108,3 +106,12 @@ exports.httpMiddleware = httpRequestHandler; exports.createHttpServer = function(cls, handler, options) { return http.createServer(httpRequestHandler(cls, handler, options)); }; + +exports.createServer = function(cls, handler, options) { + if (cls.Processor) { + cls = cls.Processor; + } + var processor = new cls(handler); + + return exports.createMultiplexServer(processor,options); +}; diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift index 500f0eab..568ed1b6 100644 --- a/test/ThriftTest.thrift +++ b/test/ThriftTest.thrift @@ -295,6 +295,12 @@ service ThriftTest service SecondService { void blahBlah() + /** + * Prints 'testString("%s")' with thing as '%s' + * @param string thing - the string to print + * @return string - returns the string 'thing' + */ + string secondtestString(1: string thing), } struct VersioningTestV1 { diff --git a/test/nodejs/Makefile.am b/test/nodejs/Makefile.am index f796b071..ab9a554f 100755 --- a/test/nodejs/Makefile.am +++ b/test/nodejs/Makefile.am @@ -32,6 +32,12 @@ check: stubs sleep 1; $(MAKE) client; sleep 2; \ fi + @if which node &> /dev/null ; then \ + echo " Testing Multiplex Client/Server"; \ + sleep 4; timeout -s14 5 $(MAKE) mserver & \ + sleep 1; $(MAKE) mclient; sleep 2; \ + fi + clean-local: $(RM) -r gen-nodejs @@ -40,3 +46,9 @@ server: client: NODE_PATH=../../lib/nodejs/lib:../../lib/nodejs/lib/thrift:$(NODE_PATH) node client.js + +mserver: + NODE_PATH=../../lib/nodejs/lib:../../lib/nodejs/lib/thrift:$(NODE_PATH) node --harmony multiplex_server.js + +mclient: + NODE_PATH=../../lib/nodejs/lib:../../lib/nodejs/lib/thrift:$(NODE_PATH) node --harmony multiplex_client.js diff --git a/test/nodejs/multiplex_client.js b/test/nodejs/multiplex_client.js new file mode 100644 index 00000000..3b79b6c2 --- /dev/null +++ b/test/nodejs/multiplex_client.js @@ -0,0 +1,302 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +var thrift = require('thrift'); +var ttransport = require('transport'); +var assert = require('assert'); + +var ThriftTest = require('./gen-nodejs/ThriftTest'), + SecondService = require('./gen-nodejs/SecondService'), + ttypes = require('./gen-nodejs/ThriftTest_types'); + +var connection = thrift.createConnection('localhost', 9090, { + 'transport': ttransport.TFramedTransport +}); + +var mp = new thrift.Multiplexer(); + +client = mp.createClient("ThriftTest", ThriftTest, connection); +secondclient = mp.createClient("SecondService", SecondService, connection); + +connection.on('error', function(err) { + assert(false, err); +}); + +// deepEqual doesn't work with fields using node-int64 + +function checkRecursively(map1, map2) { + if (typeof map1 !== 'function' && typeof map2 !== 'function') { + if (!map1 || typeof map1 !== 'object') { + assert.equal(map1, map2); + } else { + for (var key in map1) { + checkRecursively(map1[key], map2[key]); + } + } + } +} + +client.testString("Test", function(err, response) { + assert(!err); + assert.equal("Test", response); +}); +secondclient.secondtestString("Test", function(err, response) { + assert(!err); + assert.equal("Test", response); +}); + + +client.testVoid(function(err, response) { + assert(!err); + assert.equal(undefined, response); //void +}); + + +secondclient.secondtestString("Test", function(err, response) { + assert(!err); + assert.equal("Test", response); +}); + +client.testString("", function(err, response) { + assert(!err); + assert.equal("", response); +}); + +// all Languages in UTF-8 +var stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; +client.testString(stringTest, function(err, response) { + assert(!err); + assert.equal(stringTest, response); +}); + +var specialCharacters = 'quote: \" backslash:' + + ' forwardslash-escaped: \/ ' + + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + + ' now-all-of-them-together: "\\\/\b\n\r\t' + + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; +client.testString(specialCharacters, function(err, response) { + assert(!err); + assert.equal(specialCharacters, response); +}); + + +client.testByte(1, function(err, response) { + assert(!err); + assert.equal(1, response); +}); +client.testByte(0, function(err, response) { + assert(!err); + assert.equal(0, response); +}); +client.testByte(-1, function(err, response) { + assert(!err); + assert.equal(-1, response); +}); +client.testByte(-127, function(err, response) { + assert(!err); + assert.equal(-127, response); +}); + +client.testI32(-1, function(err, response) { + assert(!err); + assert.equal(-1, response); +}); + +client.testI64(5, function(err, response) { + assert(!err); + assert.equal(5, response); +}); +client.testI64(-5, function(err, response) { + assert(!err); + assert.equal(-5, response); +}); +client.testI64(-34359738368, function(err, response) { + assert(!err); + assert.equal(-34359738368, response); +}); + +client.testDouble(-5.2098523, function(err, response) { + assert(!err); + assert.equal(-5.2098523, response); +}); +client.testDouble(7.012052175215044, function(err, response) { + assert(!err); + assert.equal(7.012052175215044, response); +}); + + +var out = new ttypes.Xtruct({ + string_thing: 'Zero', + byte_thing: 1, + i32_thing: -3, + i64_thing: 1000000 +}); +client.testStruct(out, function(err, response) { + assert(!err); + checkRecursively(out, response); +}); + + +var out2 = new ttypes.Xtruct2(); +out2.byte_thing = 1; +out2.struct_thing = out; +out2.i32_thing = 5; +client.testNest(out2, function(err, response) { + assert(!err); + checkRecursively(out2, response); +}); + + +var mapout = {}; +for (var i = 0; i < 5; ++i) { + mapout[i] = i - 10; +} +client.testMap(mapout, function(err, response) { + assert(!err); + assert.deepEqual(mapout, response); +}); + + +var mapTestInput = { + "a": "123", + "a b": "with spaces ", + "same": "same", + "0": "numeric key", + "longValue": stringTest, + stringTest: "long key" +}; +client.testStringMap(mapTestInput, function(err, response) { + assert(!err); + assert.deepEqual(mapTestInput, response); +}); + + +var setTestInput = [1, 2, 3]; +client.testSet(setTestInput, function(err, response) { + assert(!err); + assert.deepEqual(setTestInput, response); +}); +client.testList(setTestInput, function(err, response) { + assert(!err); + assert.deepEqual(setTestInput, response); +}); + +client.testEnum(ttypes.Numberz.ONE, function(err, response) { + assert(!err); + assert.equal(ttypes.Numberz.ONE, response); +}); + +client.testTypedef(69, function(err, response) { + assert(!err); + assert.equal(69, response); +}); + + +var mapMapTest = { + "4": { + "1": 1, + "2": 2, + "3": 3, + "4": 4 + }, + "-4": { + "-4": -4, + "-3": -3, + "-2": -2, + "-1": -1 + } +}; +client.testMapMap(mapMapTest, function(err, response) { + assert(!err); + assert.deepEqual(mapMapTest, response); +}); + +var crazy = new ttypes.Insanity({ + "userMap": { + "5": 5, + "8": 8 + }, + "xtructs": [new ttypes.Xtruct({ + "string_thing": "Goodbye4", + "byte_thing": 4, + "i32_thing": 4, + "i64_thing": 4 + }), new ttypes.Xtruct({ + "string_thing": "Hello2", + "byte_thing": 2, + "i32_thing": 2, + "i64_thing": 2 + })] +}); +var insanity = { + "1": { + "2": crazy, + "3": crazy + }, + "2": { + "6": { + "userMap": null, + "xtructs": null + } + } +}; +client.testInsanity(crazy, function(err, response) { + assert(!err); + checkRecursively(insanity, response); +}); + + +client.testException('TException', function(err, response) { + //assert(err); //BUG? + assert(!response); +}); +client.testException('Xception', function(err, response) { + assert(!response); + assert.equal(err.errorCode, 1001); + assert.equal('Xception', err.message); +}); +client.testException('no Exception', function(err, response) { + assert(!err); + assert.equal(undefined, response); //void +}); + + +client.testOneway(1, function(err, response) { + assert(!response); //should not answer +}); + +/** + * redo a simple test after the oneway to make sure we aren't "off by one" -- + * if the server treated oneway void like normal void, this next test will + * fail since it will get the void confirmation rather than the correct + * result. In this circumstance, the client will throw the exception: + * + * TApplicationException: Wrong method namea + */ +client.testI32(-1, function(err, response) { + assert(!err); + assert.equal(-1, response); +}); + +setTimeout(function() { + console.log("Server successfully tested!"); + connection.end(); +}, 1500); + +// to make it also run on expresso +exports.expressoTest = function() {}; diff --git a/test/nodejs/multiplex_server.js b/test/nodejs/multiplex_server.js new file mode 100644 index 00000000..6b2d7d3d --- /dev/null +++ b/test/nodejs/multiplex_server.js @@ -0,0 +1,242 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +var thrift = require('thrift'); +var Thrift = thrift.Thrift; +var ttransport = require('transport'); + +var ThriftTest = require('./gen-nodejs/ThriftTest'), + SecondService = require('./gen-nodejs/SecondService'), + ttypes = require('./gen-nodejs/ThriftTest_types'); + +var ThriftTestHandler = { + testVoid: function(result) { + console.log('testVoid()'); + result(null); + }, + + testString: function(thing, result) { + console.log('testString(\'' + thing + '\')'); + result(null, thing); + }, + + testByte: function(thing, result) { + console.log('testByte(' + thing + ')'); + result(null, thing); + }, + + testI32: function(thing, result) { + console.log('testI32(' + thing + ')'); + result(null, thing); + }, + + testI64: function(thing, result) { + console.log('testI64(' + thing + ')'); + result(null, thing); + }, + + testDouble: function(thing, result) { + console.log('testDouble(' + thing + ')'); + result(null, thing); + }, + + testStruct: function(thing, result) { + console.log('testStruct('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testNest: function(nest, result) { + console.log('testNest('); + console.log(nest); + console.log(')'); + result(null, nest); + }, + + testMap: function(thing, result) { + console.log('testMap('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testStringMap: function(thing, result) { + console.log('testStringMap('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testSet: function(thing, result) { + console.log('testSet('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testList: function(thing, result) { + console.log('testList('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + + testEnum: function(thing, result) { + console.log('testEnum(' + thing + ')'); + result(null, thing); + }, + + testTypedef: function(thing, result) { + console.log('testTypedef(' + thing + ')'); + result(null, thing); + }, + + testMapMap: function(hello, result) { + console.log('testMapMap(' + hello + ')'); + + var mapmap = []; + var pos = []; + var neg = []; + for (var i = 1; i < 5; i++) { + pos[i] = i; + neg[-i] = -i; + } + mapmap[4] = pos; + mapmap[-4] = neg; + + result(null, mapmap); + }, + + testInsanity: function(argument, result) { + console.log('testInsanity('); + console.log(argument); + console.log(')'); + + var hello = new ttypes.Xtruct(); + hello.string_thing = 'Hello2'; + hello.byte_thing = 2; + hello.i32_thing = 2; + hello.i64_thing = 2; + + var goodbye = new ttypes.Xtruct(); + goodbye.string_thing = 'Goodbye4'; + goodbye.byte_thing = 4; + goodbye.i32_thing = 4; + goodbye.i64_thing = 4; + + var crazy = new ttypes.Insanity(); + crazy.userMap = []; + crazy.userMap[ttypes.Numberz.EIGHT] = 8; + crazy.userMap[ttypes.Numberz.FIVE] = 5; + crazy.xtructs = [goodbye, hello]; + + var first_map = []; + var second_map = []; + + first_map[ttypes.Numberz.TWO] = crazy; + first_map[ttypes.Numberz.THREE] = crazy; + + var looney = new ttypes.Insanity(); + second_map[ttypes.Numberz.SIX] = looney; + + var insane = []; + insane[1] = first_map; + insane[2] = second_map; + + console.log('insane result:'); + console.log(insane); + result(null, insane); + }, + + testMulti: function(arg0, arg1, arg2, arg3, arg4, arg5, result) { + console.log('testMulti()'); + + var hello = new ttypes.Xtruct();; + hello.string_thing = 'Hello2'; + hello.byte_thing = arg0; + hello.i32_thing = arg1; + hello.i64_thing = arg2; + result(null, hello); + }, + + testException: function(arg, result) { + console.log('testException(' + arg + ')'); + if (arg === 'Xception') { + var x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = arg; + result(x); + } else if (arg === 'TException') { + result(new Thrift.TException(arg)); + } else { + result(null); + } + }, + + testMultiException: function(arg0, arg1, result) { + console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); + if (arg0 === ('Xception')) { + var x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = 'This is an Xception'; + result(x); + } else if (arg0 === ('Xception2')) { + var x = new ttypes.Xception2(); + x.errorCode = 2002; + x.struct_thing = new ttypes.Xtruct(); + x.struct_thing.string_thing = 'This is an Xception2'; + result(x); + } + + var res = new ttypes.Xtruct(); + res.string_thing = arg1; + result(null, res); + }, + + testOneway: function(sleepFor, result) { + console.log('testOneway(' + sleepFor + ') => sleeping...'); + setTimeout(function() { + console.log('Done sleeping for testOneway!'); + }, sleepFor * 1000); //seconds + } +}; + +var SecondServiceHandler = { + secondtestString: function(thing, result) { + console.log('testString(\'' + thing + '\')'); + result(null, thing); + } +}; + +var processor = new thrift.MultiplexedProcessor(); + +processor.registerProcessor( + "ThriftTest", + new ThriftTest.Processor(ThriftTestHandler)); + +processor.registerProcessor( + "SecondService", + new SecondService.Processor(SecondServiceHandler)); + + +var server = thrift.createMultiplexServer(processor, { //server options + 'transport': ttransport.TFramedTransport +}); + +server.listen(9090); -- 2.17.1