blob: 83b8a7c1ec3c36b4e133f0e66950d1bdbaa08c21 [file] [log] [blame]
murgatroid9997d61302015-01-20 18:06:43 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
murgatroid9997d61302015-01-20 18:06:43 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
murgatroid99dca966d2015-02-19 14:37:18 -080034'use strict';
35
murgatroid99b6ab1b42015-01-21 10:30:36 -080036var fs = require('fs');
37var path = require('path');
murgatroid9955739d52015-06-03 10:58:21 -070038var _ = require('lodash');
murgatroid99221ae632015-12-11 15:06:32 -080039var AsyncDelayQueue = require('./async_delay_queue');
murgatroid9997d61302015-01-20 18:06:43 -080040var grpc = require('..');
murgatroid992af89e42015-10-01 11:54:00 -070041var testProto = grpc.load({
42 root: __dirname + '/../../..',
Craig Tillercd925092016-01-07 17:10:25 -080043 file: 'src/proto/grpc/testing/test.proto'}).grpc.testing;
murgatroid9997d61302015-01-20 18:06:43 -080044
murgatroid99e634f9a2015-08-27 10:02:00 -070045var ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial';
46var ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin';
murgatroid991eb113c2015-08-27 09:26:33 -070047
murgatroid99b6ab1b42015-01-21 10:30:36 -080048/**
49 * Create a buffer filled with size zeroes
50 * @param {number} size The length of the buffer
51 * @return {Buffer} The new buffer
52 */
murgatroid9997d61302015-01-20 18:06:43 -080053function zeroBuffer(size) {
54 var zeros = new Buffer(size);
55 zeros.fill(0);
56 return zeros;
57}
58
murgatroid99b6ab1b42015-01-21 10:30:36 -080059/**
murgatroid991eb113c2015-08-27 09:26:33 -070060 * Echos a header metadata item as specified in the interop spec.
61 * @param {Call} call The call to echo metadata on
62 */
63function echoHeader(call) {
64 var echo_initial = call.metadata.get(ECHO_INITIAL_KEY);
65 if (echo_initial.length > 0) {
66 var response_metadata = new grpc.Metadata();
67 response_metadata.set(ECHO_INITIAL_KEY, echo_initial[0]);
68 call.sendMetadata(response_metadata);
69 }
70}
71
72/**
73 * Gets the trailer metadata that should be echoed when the call is done,
74 * as specified in the interop spec.
75 * @param {Call} call The call to get metadata from
76 * @return {grpc.Metadata} The metadata to send as a trailer
77 */
78function getEchoTrailer(call) {
79 var echo_trailer = call.metadata.get(ECHO_TRAILING_KEY);
80 var response_trailer = new grpc.Metadata();
81 if (echo_trailer.length > 0) {
82 response_trailer.set(ECHO_TRAILING_KEY, echo_trailer[0]);
83 }
84 return response_trailer;
85}
86
murgatroid99a6a9a6d2015-10-07 16:40:04 -070087function getPayload(payload_type, size) {
David Garcia Quintase89aad02016-06-21 16:43:31 -070088 var body = zeroBuffer(size);
murgatroid99a6a9a6d2015-10-07 16:40:04 -070089 return {type: payload_type, body: body};
90}
91
murgatroid991eb113c2015-08-27 09:26:33 -070092/**
murgatroid99b6ab1b42015-01-21 10:30:36 -080093 * Respond to an empty parameter with an empty response.
94 * NOTE: this currently does not work due to issue #137
95 * @param {Call} call Call to handle
96 * @param {function(Error, Object)} callback Callback to call with result
97 * or error
98 */
murgatroid9997d61302015-01-20 18:06:43 -080099function handleEmpty(call, callback) {
murgatroid991eb113c2015-08-27 09:26:33 -0700100 echoHeader(call);
101 callback(null, {}, getEchoTrailer(call));
murgatroid9997d61302015-01-20 18:06:43 -0800102}
103
murgatroid99b6ab1b42015-01-21 10:30:36 -0800104/**
105 * Handle a unary request by sending the requested payload
106 * @param {Call} call Call to handle
107 * @param {function(Error, Object)} callback Callback to call with result or
108 * error
109 */
murgatroid9997d61302015-01-20 18:06:43 -0800110function handleUnary(call, callback) {
murgatroid991eb113c2015-08-27 09:26:33 -0700111 echoHeader(call);
murgatroid9997d61302015-01-20 18:06:43 -0800112 var req = call.request;
murgatroid99a6a9a6d2015-10-07 16:40:04 -0700113 if (req.response_status) {
114 var status = req.response_status;
115 status.metadata = getEchoTrailer(call);
116 callback(status);
117 return;
murgatroid9997d61302015-01-20 18:06:43 -0800118 }
murgatroid99a6a9a6d2015-10-07 16:40:04 -0700119 var payload = getPayload(req.response_type, req.response_size);
120 callback(null, {payload: payload},
murgatroid991eb113c2015-08-27 09:26:33 -0700121 getEchoTrailer(call));
murgatroid9997d61302015-01-20 18:06:43 -0800122}
123
murgatroid99b6ab1b42015-01-21 10:30:36 -0800124/**
125 * Respond to a streaming call with the total size of all payloads
126 * @param {Call} call Call to handle
127 * @param {function(Error, Object)} callback Callback to call with result or
128 * error
129 */
murgatroid9997d61302015-01-20 18:06:43 -0800130function handleStreamingInput(call, callback) {
murgatroid991eb113c2015-08-27 09:26:33 -0700131 echoHeader(call);
murgatroid9997d61302015-01-20 18:06:43 -0800132 var aggregate_size = 0;
133 call.on('data', function(value) {
murgatroid9920afbb92015-05-12 10:35:18 -0700134 aggregate_size += value.payload.body.length;
murgatroid9997d61302015-01-20 18:06:43 -0800135 });
136 call.on('end', function() {
murgatroid991eb113c2015-08-27 09:26:33 -0700137 callback(null, {aggregated_payload_size: aggregate_size},
138 getEchoTrailer(call));
murgatroid9997d61302015-01-20 18:06:43 -0800139 });
140}
141
murgatroid99b6ab1b42015-01-21 10:30:36 -0800142/**
143 * Respond to a payload request with a stream of the requested payloads
144 * @param {Call} call Call to handle
145 */
murgatroid9997d61302015-01-20 18:06:43 -0800146function handleStreamingOutput(call) {
murgatroid991eb113c2015-08-27 09:26:33 -0700147 echoHeader(call);
murgatroid99221ae632015-12-11 15:06:32 -0800148 var delay_queue = new AsyncDelayQueue();
murgatroid9997d61302015-01-20 18:06:43 -0800149 var req = call.request;
murgatroid99a6a9a6d2015-10-07 16:40:04 -0700150 if (req.response_status) {
151 var status = req.response_status;
152 status.metadata = getEchoTrailer(call);
153 call.emit('error', status);
154 return;
murgatroid9997d61302015-01-20 18:06:43 -0800155 }
murgatroid995dbbd912015-10-09 14:45:55 -0700156 _.each(req.response_parameters, function(resp_param) {
murgatroid99221ae632015-12-11 15:06:32 -0800157 delay_queue.add(function(next) {
158 call.write({payload: getPayload(req.response_type, resp_param.size)});
159 next();
160 }, resp_param.interval_us);
murgatroid9997d61302015-01-20 18:06:43 -0800161 });
murgatroid99221ae632015-12-11 15:06:32 -0800162 delay_queue.add(function(next) {
163 call.end(getEchoTrailer(call));
164 next();
165 });
murgatroid9997d61302015-01-20 18:06:43 -0800166}
167
murgatroid99b6ab1b42015-01-21 10:30:36 -0800168/**
169 * Respond to a stream of payload requests with a stream of payload responses as
170 * they arrive.
171 * @param {Call} call Call to handle
172 */
murgatroid9997d61302015-01-20 18:06:43 -0800173function handleFullDuplex(call) {
murgatroid991eb113c2015-08-27 09:26:33 -0700174 echoHeader(call);
murgatroid99221ae632015-12-11 15:06:32 -0800175 var delay_queue = new AsyncDelayQueue();
murgatroid9997d61302015-01-20 18:06:43 -0800176 call.on('data', function(value) {
murgatroid99a6a9a6d2015-10-07 16:40:04 -0700177 if (value.response_status) {
178 var status = value.response_status;
179 status.metadata = getEchoTrailer(call);
180 call.emit('error', status);
181 return;
murgatroid9997d61302015-01-20 18:06:43 -0800182 }
murgatroid995dbbd912015-10-09 14:45:55 -0700183 _.each(value.response_parameters, function(resp_param) {
murgatroid99221ae632015-12-11 15:06:32 -0800184 delay_queue.add(function(next) {
185 call.write({payload: getPayload(value.response_type, resp_param.size)});
186 next();
187 }, resp_param.interval_us);
murgatroid9997d61302015-01-20 18:06:43 -0800188 });
189 });
190 call.on('end', function() {
murgatroid99221ae632015-12-11 15:06:32 -0800191 delay_queue.add(function(next) {
192 call.end(getEchoTrailer(call));
193 next();
194 });
murgatroid9997d61302015-01-20 18:06:43 -0800195 });
196}
197
murgatroid99b6ab1b42015-01-21 10:30:36 -0800198/**
199 * Respond to a stream of payload requests with a stream of payload responses
200 * after all requests have arrived
201 * @param {Call} call Call to handle
202 */
murgatroid9997d61302015-01-20 18:06:43 -0800203function handleHalfDuplex(call) {
murgatroid99a6a9a6d2015-10-07 16:40:04 -0700204 call.emit('error', Error('HalfDuplexCall not yet implemented'));
murgatroid9997d61302015-01-20 18:06:43 -0800205}
206
murgatroid99b6ab1b42015-01-21 10:30:36 -0800207/**
208 * Get a server object bound to the given port
209 * @param {string} port Port to which to bind
210 * @param {boolean} tls Indicates that the bound port should use TLS
murgatroid99f034e502015-01-21 12:12:39 -0800211 * @return {{server: Server, port: number}} Server object bound to the support,
212 * and port number that the server is bound to
murgatroid99b6ab1b42015-01-21 10:30:36 -0800213 */
murgatroid9997d61302015-01-20 18:06:43 -0800214function getServer(port, tls) {
215 // TODO(mlumish): enable TLS functionality
murgatroid99b6ab1b42015-01-21 10:30:36 -0800216 var options = {};
murgatroid991a7dcac2015-07-27 16:13:28 -0700217 var server_creds;
murgatroid99b6ab1b42015-01-21 10:30:36 -0800218 if (tls) {
219 var key_path = path.join(__dirname, '../test/data/server1.key');
220 var pem_path = path.join(__dirname, '../test/data/server1.pem');
221
222 var key_data = fs.readFileSync(key_path);
223 var pem_data = fs.readFileSync(pem_path);
murgatroid99da02a672015-03-02 17:28:02 -0800224 server_creds = grpc.ServerCredentials.createSsl(null,
murgatroid996b3737d2015-08-19 15:02:15 -0700225 [{private_key: key_data,
226 cert_chain: pem_data}]);
murgatroid991a7dcac2015-07-27 16:13:28 -0700227 } else {
228 server_creds = grpc.ServerCredentials.createInsecure();
murgatroid99b6ab1b42015-01-21 10:30:36 -0800229 }
murgatroid99380b90a2015-07-16 13:16:14 -0700230 var server = new grpc.Server(options);
murgatroid99b5b5f022017-03-16 16:42:10 -0700231 server.addService(testProto.TestService.service, {
murgatroid99366e64d2015-07-15 17:01:49 -0700232 emptyCall: handleEmpty,
233 unaryCall: handleUnary,
234 streamingOutputCall: handleStreamingOutput,
235 streamingInputCall: handleStreamingInput,
236 fullDuplexCall: handleFullDuplex,
237 halfDuplexCall: handleHalfDuplex
238 });
murgatroid99da02a672015-03-02 17:28:02 -0800239 var port_num = server.bind('0.0.0.0:' + port, server_creds);
murgatroid99f034e502015-01-21 12:12:39 -0800240 return {server: server, port: port_num};
murgatroid9997d61302015-01-20 18:06:43 -0800241}
242
243if (require.main === module) {
244 var parseArgs = require('minimist');
245 var argv = parseArgs(process.argv, {
246 string: ['port', 'use_tls']
247 });
murgatroid99f034e502015-01-21 12:12:39 -0800248 var server_obj = getServer(argv.port, argv.use_tls === 'true');
murgatroid9934986de2015-01-23 13:27:20 -0800249 console.log('Server attaching to port ' + argv.port);
murgatroid99bc15a782015-08-14 11:09:04 -0700250 server_obj.server.start();
murgatroid9997d61302015-01-20 18:06:43 -0800251}
252
253/**
254 * See docs for getServer
255 */
Craig Tillerce5021b2015-02-18 09:25:21 -0800256exports.getServer = getServer;