| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016 | <!DOCTYPE html><html lang="en"><head>    <meta charset="utf-8">    <title>JSDoc: Source: src/server.js</title>    <script src="scripts/prettify/prettify.js"> </script>    <script src="scripts/prettify/lang-css.js"> </script>    <!--[if lt IE 9]>      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>    <![endif]-->    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"></head><body><div id="main">    <h1 class="page-title">Source: src/server.js</h1>            <section>        <article>            <pre class="prettyprint source linenums"><code>/** * @license * Copyright 2015 gRPC authors. * * Licensed 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. * */'use strict';var _ = require('lodash');var grpc = require('./grpc_extension');var common = require('./common');var Metadata = require('./metadata');var constants = require('./constants');var stream = require('stream');var Readable = stream.Readable;var Writable = stream.Writable;var Duplex = stream.Duplex;var util = require('util');var EventEmitter = require('events').EventEmitter;/** * Handle an error on a call by sending it as a status * @private * @param {grpc.internal~Call} call The call to send the error on * @param {(Object|Error)} error The error object */function handleError(call, error) {  var statusMetadata = new Metadata();  var status = {    code: constants.status.UNKNOWN,    details: 'Unknown Error'  };  if (error.hasOwnProperty('message')) {    status.details = error.message;  }  if (error.hasOwnProperty('code')) {    status.code = error.code;    if (error.hasOwnProperty('details')) {      status.details = error.details;    }  }  if (error.hasOwnProperty('metadata')) {    statusMetadata = error.metadata;  }  status.metadata = statusMetadata._getCoreRepresentation();  var error_batch = {};  if (!call.metadataSent) {    error_batch[grpc.opType.SEND_INITIAL_METADATA] =        (new Metadata())._getCoreRepresentation();  }  error_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status;  call.startBatch(error_batch, function(){});}/** * Send a response to a unary or client streaming call. * @private * @param {grpc.Call} call The call to respond on * @param {*} value The value to respond with * @param {grpc~serialize} serialize Serialization function for the *     response * @param {grpc.Metadata=} metadata Optional trailing metadata to send with *     status * @param {number=} [flags=0] Flags for modifying how the message is sent. */function sendUnaryResponse(call, value, serialize, metadata, flags) {  var end_batch = {};  var statusMetadata = new Metadata();  var status = {    code: constants.status.OK,    details: 'OK'  };  if (metadata) {    statusMetadata = metadata;  }  var message;  try {    message = serialize(value);  } catch (e) {    e.code = constants.status.INTERNAL;    handleError(call, e);    return;  }  status.metadata = statusMetadata._getCoreRepresentation();  if (!call.metadataSent) {    end_batch[grpc.opType.SEND_INITIAL_METADATA] =        (new Metadata())._getCoreRepresentation();    call.metadataSent = true;  }  message.grpcWriteFlags = flags;  end_batch[grpc.opType.SEND_MESSAGE] = message;  end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status;  call.startBatch(end_batch, function (){});}/** * Initialize a writable stream. This is used for both the writable and duplex * stream constructors. * @private * @param {Writable} stream The stream to set up * @param {function(*):Buffer=} Serialization function for responses */function setUpWritable(stream, serialize) {  stream.finished = false;  stream.status = {    code : constants.status.OK,    details : 'OK',    metadata : new Metadata()  };  stream.serialize = common.wrapIgnoreNull(serialize);  function sendStatus() {    var batch = {};    if (!stream.call.metadataSent) {      stream.call.metadataSent = true;      batch[grpc.opType.SEND_INITIAL_METADATA] =          (new Metadata())._getCoreRepresentation();    }    if (stream.status.metadata) {      stream.status.metadata = stream.status.metadata._getCoreRepresentation();    }    batch[grpc.opType.SEND_STATUS_FROM_SERVER] = stream.status;    stream.call.startBatch(batch, function(){});  }  stream.on('finish', sendStatus);  /**   * Set the pending status to a given error status. If the error does not have   * code or details properties, the code will be set to grpc.status.UNKNOWN   * and the details will be set to 'Unknown Error'.   * @param {Error} err The error object   */  function setStatus(err) {    var code = constants.status.UNKNOWN;    var details = 'Unknown Error';    var metadata = new Metadata();    if (err.hasOwnProperty('message')) {      details = err.message;    }    if (err.hasOwnProperty('code')) {      code = err.code;      if (err.hasOwnProperty('details')) {        details = err.details;      }    }    if (err.hasOwnProperty('metadata')) {      metadata = err.metadata;    }    stream.status = {code: code, details: details, metadata: metadata};  }  /**   * Terminate the call. This includes indicating that reads are done, draining   * all pending writes, and sending the given error as a status   * @param {Error} err The error object   * @this GrpcServerStream   */  function terminateCall(err) {    // Drain readable data    setStatus(err);    stream.end();  }  stream.on('error', terminateCall);  /**   * Override of Writable#end method that allows for sending metadata with a   * success status.   * @param {Metadata=} metadata Metadata to send with the status   */  stream.end = function(metadata) {    if (metadata) {      stream.status.metadata = metadata;    }    Writable.prototype.end.call(this);  };}/** * Initialize a readable stream. This is used for both the readable and duplex * stream constructors. * @private * @param {Readable} stream The stream to initialize * @param {grpc~deserialize} deserialize Deserialization function for *     incoming data. */function setUpReadable(stream, deserialize) {  stream.deserialize = common.wrapIgnoreNull(deserialize);  stream.finished = false;  stream.reading = false;  stream.terminate = function() {    stream.finished = true;    stream.on('data', function() {});  };  stream.on('cancelled', function() {    stream.terminate();  });}/** * Emitted when the call has been cancelled. After this has been emitted, the * call's `cancelled` property will be set to `true`. * @event grpc~ServerUnaryCall~cancelled */util.inherits(ServerUnaryCall, EventEmitter);/** * An EventEmitter. Used for unary calls. * @constructor grpc~ServerUnaryCall * @extends external:EventEmitter * @param {grpc.internal~Call} call The call object associated with the request * @param {grpc.Metadata} metadata The request metadata from the client */function ServerUnaryCall(call, metadata) {  EventEmitter.call(this);  this.call = call;  /**   * Indicates if the call has been cancelled   * @member {boolean} grpc~ServerUnaryCall#cancelled   */  this.cancelled = false;  /**   * The request metadata from the client   * @member {grpc.Metadata} grpc~ServerUnaryCall#metadata   */  this.metadata = metadata;  /**   * The request message from the client   * @member {*} grpc~ServerUnaryCall#request   */  this.request = undefined;}/** * Emitted when the call has been cancelled. After this has been emitted, the * call's `cancelled` property will be set to `true`. * @event grpc~ServerWritableStream~cancelled */util.inherits(ServerWritableStream, Writable);/** * A stream that the server can write to. Used for calls that are streaming from * the server side. * @constructor grpc~ServerWritableStream * @extends external:Writable * @borrows grpc~ServerUnaryCall#sendMetadata as *     grpc~ServerWritableStream#sendMetadata * @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerWritableStream#getPeer * @param {grpc.internal~Call} call The call object to send data with * @param {grpc.Metadata} metadata The request metadata from the client * @param {grpc~serialize} serialize Serialization function for writes */function ServerWritableStream(call, metadata, serialize) {  Writable.call(this, {objectMode: true});  this.call = call;  this.finished = false;  setUpWritable(this, serialize);  /**   * Indicates if the call has been cancelled   * @member {boolean} grpc~ServerWritableStream#cancelled   */  this.cancelled = false;  /**   * The request metadata from the client   * @member {grpc.Metadata} grpc~ServerWritableStream#metadata   */  this.metadata = metadata;  /**   * The request message from the client   * @member {*} grpc~ServerWritableStream#request   */  this.request = undefined;}/** * Start writing a chunk of data. This is an implementation of a method required * for implementing stream.Writable. * @private * @param {Buffer} chunk The chunk of data to write * @param {string} encoding Used to pass write flags * @param {function(Error=)} callback Callback to indicate that the write is *     complete */function _write(chunk, encoding, callback) {  /* jshint validthis: true */  var batch = {};  var self = this;  var message;  try {    message = this.serialize(chunk);  } catch (e) {    e.code = constants.status.INTERNAL;    callback(e);    return;  }  if (!this.call.metadataSent) {    batch[grpc.opType.SEND_INITIAL_METADATA] =        (new Metadata())._getCoreRepresentation();    this.call.metadataSent = true;  }  if (_.isFinite(encoding)) {    /* Attach the encoding if it is a finite number. This is the closest we     * can get to checking that it is valid flags */    message.grpcWriteFlags = encoding;  }  batch[grpc.opType.SEND_MESSAGE] = message;  this.call.startBatch(batch, function(err, value) {    if (err) {      self.emit('error', err);      return;    }    callback();  });}ServerWritableStream.prototype._write = _write;/** * Emitted when the call has been cancelled. After this has been emitted, the * call's `cancelled` property will be set to `true`. * @event grpc~ServerReadableStream~cancelled */util.inherits(ServerReadableStream, Readable);/** * A stream that the server can read from. Used for calls that are streaming * from the client side. * @constructor grpc~ServerReadableStream * @extends external:Readable * @borrows grpc~ServerUnaryCall#sendMetadata as *     grpc~ServerReadableStream#sendMetadata * @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerReadableStream#getPeer * @param {grpc.internal~Call} call The call object to read data with * @param {grpc.Metadata} metadata The request metadata from the client * @param {grpc~deserialize} deserialize Deserialization function for reads */function ServerReadableStream(call, metadata, deserialize) {  Readable.call(this, {objectMode: true});  this.call = call;  setUpReadable(this, deserialize);  /**   * Indicates if the call has been cancelled   * @member {boolean} grpc~ServerReadableStream#cancelled   */  this.cancelled = false;  /**   * The request metadata from the client   * @member {grpc.Metadata} grpc~ServerReadableStream#metadata   */  this.metadata = metadata;}/** * Start reading from the gRPC data source. This is an implementation of a * method required for implementing stream.Readable * @access private * @param {number} size Ignored */function _read(size) {  /* jshint validthis: true */  var self = this;  /**   * Callback to be called when a READ event is received. Pushes the data onto   * the read queue and starts reading again if applicable   * @param {grpc.Event} event READ event object   */  function readCallback(err, event) {    if (err) {      self.terminate();      return;    }    if (self.finished) {      self.push(null);      return;    }    var data = event.read;    var deserialized;    try {      deserialized = self.deserialize(data);    } catch (e) {      e.code = constants.status.INTERNAL;      self.emit('error', e);      return;    }    if (self.push(deserialized) && data !== null) {      var read_batch = {};      read_batch[grpc.opType.RECV_MESSAGE] = true;      self.call.startBatch(read_batch, readCallback);    } else {      self.reading = false;    }  }  if (self.finished) {    self.push(null);  } else {    if (!self.reading) {      self.reading = true;      var batch = {};      batch[grpc.opType.RECV_MESSAGE] = true;      self.call.startBatch(batch, readCallback);    }  }}ServerReadableStream.prototype._read = _read;/** * Emitted when the call has been cancelled. After this has been emitted, the * call's `cancelled` property will be set to `true`. * @event grpc~ServerDuplexStream~cancelled */util.inherits(ServerDuplexStream, Duplex);/** * A stream that the server can read from or write to. Used for calls with * duplex streaming. * @constructor grpc~ServerDuplexStream * @extends external:Duplex * @borrows grpc~ServerUnaryCall#sendMetadata as *     grpc~ServerDuplexStream#sendMetadata * @borrows grpc~ServerUnaryCall#getPeer as grpc~ServerDuplexStream#getPeer * @param {grpc.internal~Call} call Call object to proxy * @param {grpc.Metadata} metadata The request metadata from the client * @param {grpc~serialize} serialize Serialization function for requests * @param {grpc~deserialize} deserialize Deserialization function for *     responses */function ServerDuplexStream(call, metadata, serialize, deserialize) {  Duplex.call(this, {objectMode: true});  this.call = call;  setUpWritable(this, serialize);  setUpReadable(this, deserialize);  /**   * Indicates if the call has been cancelled   * @member {boolean} grpc~ServerReadableStream#cancelled   */  this.cancelled = false;  /**   * The request metadata from the client   * @member {grpc.Metadata} grpc~ServerReadableStream#metadata   */  this.metadata = metadata;}ServerDuplexStream.prototype._read = _read;ServerDuplexStream.prototype._write = _write;/** * Send the initial metadata for a writable stream. * @alias grpc~ServerUnaryCall#sendMetadata * @param {Metadata} responseMetadata Metadata to send */function sendMetadata(responseMetadata) {  /* jshint validthis: true */  var self = this;  if (!this.call.metadataSent) {    this.call.metadataSent = true;    var batch = {};    batch[grpc.opType.SEND_INITIAL_METADATA] =        responseMetadata._getCoreRepresentation();    this.call.startBatch(batch, function(err) {      if (err) {        self.emit('error', err);        return;      }    });  }}ServerUnaryCall.prototype.sendMetadata = sendMetadata;ServerWritableStream.prototype.sendMetadata = sendMetadata;ServerReadableStream.prototype.sendMetadata = sendMetadata;ServerDuplexStream.prototype.sendMetadata = sendMetadata;/** * Get the endpoint this call/stream is connected to. * @alias grpc~ServerUnaryCall#getPeer * @return {string} The URI of the endpoint */function getPeer() {  /* jshint validthis: true */  return this.call.getPeer();}ServerUnaryCall.prototype.getPeer = getPeer;ServerReadableStream.prototype.getPeer = getPeer;ServerWritableStream.prototype.getPeer = getPeer;ServerDuplexStream.prototype.getPeer = getPeer;/** * Wait for the client to close, then emit a cancelled event if the client * cancelled. * @private */function waitForCancel() {  /* jshint validthis: true */  var self = this;  var cancel_batch = {};  cancel_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;  self.call.startBatch(cancel_batch, function(err, result) {    if (err) {      self.emit('error', err);    }    if (result.cancelled) {      self.cancelled = true;      self.emit('cancelled');    }  });}ServerUnaryCall.prototype.waitForCancel = waitForCancel;ServerReadableStream.prototype.waitForCancel = waitForCancel;ServerWritableStream.prototype.waitForCancel = waitForCancel;ServerDuplexStream.prototype.waitForCancel = waitForCancel;/** * Callback function passed to server handlers that handle methods with unary * responses. * @callback grpc.Server~sendUnaryData * @param {grpc~ServiceError} error An error, if the call failed * @param {*} value The response value. Must be a valid argument to the *     `responseSerialize` method of the method that is being handled * @param {grpc.Metadata=} trailer Trailing metadata to send, if applicable * @param {grpc.writeFlags=} flags Flags to modify writing the response *//** * User-provided method to handle unary requests on a server * @callback grpc.Server~handleUnaryCall * @param {grpc~ServerUnaryCall} call The call object * @param {grpc.Server~sendUnaryData} callback The callback to call to respond *     to the request *//** * Fully handle a unary call * @private * @param {grpc.internal~Call} call The call to handle * @param {Object} handler Request handler object for the method that was called * @param {grpc~Server.handleUnaryCall} handler.func The handler function * @param {grpc~deserialize} handler.deserialize The deserialization function *     for request data * @param {grpc~serialize} handler.serialize The serialization function for *     response data * @param {grpc.Metadata} metadata Metadata from the client */function handleUnary(call, handler, metadata) {  var emitter = new ServerUnaryCall(call, metadata);  emitter.on('error', function(error) {    handleError(call, error);  });  emitter.waitForCancel();  var batch = {};  batch[grpc.opType.RECV_MESSAGE] = true;  call.startBatch(batch, function(err, result) {    if (err) {      handleError(call, err);      return;    }    try {      emitter.request = handler.deserialize(result.read);    } catch (e) {      e.code = constants.status.INTERNAL;      handleError(call, e);      return;    }    if (emitter.cancelled) {      return;    }    handler.func(emitter, function sendUnaryData(err, value, trailer, flags) {      if (err) {        if (trailer) {          err.metadata = trailer;        }        handleError(call, err);      } else {        sendUnaryResponse(call, value, handler.serialize, trailer, flags);      }    });  });}/** * User provided method to handle server streaming methods on the server. * @callback grpc.Server~handleServerStreamingCall * @param {grpc~ServerWritableStream} call The call object *//** * Fully handle a server streaming call * @private * @param {grpc.internal~Call} call The call to handle * @param {Object} handler Request handler object for the method that was called * @param {grpc~Server.handleServerStreamingCall} handler.func The handler *     function * @param {grpc~deserialize} handler.deserialize The deserialization function *     for request data * @param {grpc~serialize} handler.serialize The serialization function for *     response data * @param {grpc.Metadata} metadata Metadata from the client */function handleServerStreaming(call, handler, metadata) {  var stream = new ServerWritableStream(call, metadata, handler.serialize);  stream.waitForCancel();  var batch = {};  batch[grpc.opType.RECV_MESSAGE] = true;  call.startBatch(batch, function(err, result) {    if (err) {      stream.emit('error', err);      return;    }    try {      stream.request = handler.deserialize(result.read);    } catch (e) {      e.code = constants.status.INTERNAL;      stream.emit('error', e);      return;    }    handler.func(stream);  });}/** * User provided method to handle client streaming methods on the server. * @callback grpc.Server~handleClientStreamingCall * @param {grpc~ServerReadableStream} call The call object * @param {grpc.Server~sendUnaryData} callback The callback to call to respond *     to the request *//** * Fully handle a client streaming call * @access private * @param {grpc.internal~Call} call The call to handle * @param {Object} handler Request handler object for the method that was called * @param {grpc~Server.handleClientStreamingCall} handler.func The handler *     function * @param {grpc~deserialize} handler.deserialize The deserialization function *     for request data * @param {grpc~serialize} handler.serialize The serialization function for *     response data * @param {grpc.Metadata} metadata Metadata from the client */function handleClientStreaming(call, handler, metadata) {  var stream = new ServerReadableStream(call, metadata, handler.deserialize);  stream.on('error', function(error) {    handleError(call, error);  });  stream.waitForCancel();  handler.func(stream, function(err, value, trailer, flags) {    stream.terminate();    if (err) {      if (trailer) {        err.metadata = trailer;      }      handleError(call, err);    } else {      sendUnaryResponse(call, value, handler.serialize, trailer, flags);    }  });}/** * User provided method to handle bidirectional streaming calls on the server. * @callback grpc.Server~handleBidiStreamingCall * @param {grpc~ServerDuplexStream} call The call object *//** * Fully handle a bidirectional streaming call * @private * @param {grpc.internal~Call} call The call to handle * @param {Object} handler Request handler object for the method that was called * @param {grpc~Server.handleBidiStreamingCall} handler.func The handler *     function * @param {grpc~deserialize} handler.deserialize The deserialization function *     for request data * @param {grpc~serialize} handler.serialize The serialization function for *     response data * @param {Metadata} metadata Metadata from the client */function handleBidiStreaming(call, handler, metadata) {  var stream = new ServerDuplexStream(call, metadata, handler.serialize,                                      handler.deserialize);  stream.waitForCancel();  handler.func(stream);}var streamHandlers = {  unary: handleUnary,  server_stream: handleServerStreaming,  client_stream: handleClientStreaming,  bidi: handleBidiStreaming};/** * Constructs a server object that stores request handlers and delegates * incoming requests to those handlers * @memberof grpc * @constructor * @param {Object=} options Options that should be passed to the internal server *     implementation * @example * var server = new grpc.Server(); * server.addProtoService(protobuf_service_descriptor, service_implementation); * server.bind('address:port', server_credential); * server.start(); */function Server(options) {  this.handlers = {};  var server = new grpc.Server(options);  this._server = server;  this.started = false;}/** * Start the server and begin handling requests */Server.prototype.start = function() {  if (this.started) {    throw new Error('Server is already running');  }  var self = this;  this.started = true;  this._server.start();  /**   * Handles the SERVER_RPC_NEW event. If there is a handler associated with   * the requested method, use that handler to respond to the request. Then   * wait for the next request   * @param {grpc.internal~Event} event The event to handle with tag   *     SERVER_RPC_NEW   */  function handleNewCall(err, event) {    if (err) {      return;    }    var details = event.new_call;    var call = details.call;    var method = details.method;    var metadata = Metadata._fromCoreRepresentation(details.metadata);    if (method === null) {      return;    }    self._server.requestCall(handleNewCall);    var handler;    if (self.handlers.hasOwnProperty(method)) {      handler = self.handlers[method];    } else {      var batch = {};      batch[grpc.opType.SEND_INITIAL_METADATA] =          (new Metadata())._getCoreRepresentation();      batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {        code: constants.status.UNIMPLEMENTED,        details: '',        metadata: {}      };      batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;      call.startBatch(batch, function() {});      return;    }    streamHandlers[handler.type](call, handler, metadata);  }  this._server.requestCall(handleNewCall);};/** * Unified type for application handlers for all types of calls * @typedef {(grpc.Server~handleUnaryCall *            |grpc.Server~handleClientStreamingCall *            |grpc.Server~handleServerStreamingCall *            |grpc.Server~handleBidiStreamingCall)} grpc.Server~handleCall *//** * Registers a handler to handle the named method. Fails if there already is * a handler for the given method. Returns true on success * @param {string} name The name of the method that the provided function should *     handle/respond to. * @param {grpc.Server~handleCall} handler Function that takes a stream of *     request values and returns a stream of response values * @param {grpc~serialize} serialize Serialization function for responses * @param {grpc~deserialize} deserialize Deserialization function for requests * @param {string} type The streaming type of method that this handles * @return {boolean} True if the handler was set. False if a handler was already *     set for that name. */Server.prototype.register = function(name, handler, serialize, deserialize,                                     type) {  if (this.handlers.hasOwnProperty(name)) {    return false;  }  this.handlers[name] = {    func: handler,    serialize: serialize,    deserialize: deserialize,    type: type  };  return true;};/** * Gracefully shuts down the server. The server will stop receiving new calls, * and any pending calls will complete. The callback will be called when all * pending calls have completed and the server is fully shut down. This method * is idempotent with itself and forceShutdown. * @param {function()} callback The shutdown complete callback */Server.prototype.tryShutdown = function(callback) {  this._server.tryShutdown(callback);};/** * Forcibly shuts down the server. The server will stop receiving new calls * and cancel all pending calls. When it returns, the server has shut down. * This method is idempotent with itself and tryShutdown, and it will trigger * any outstanding tryShutdown callbacks. */Server.prototype.forceShutdown = function() {  this._server.forceShutdown();};var unimplementedStatusResponse = {  code: constants.status.UNIMPLEMENTED,  details: 'The server does not implement this method'};var defaultHandler = {  unary: function(call, callback) {    callback(unimplementedStatusResponse);  },  client_stream: function(call, callback) {    callback(unimplementedStatusResponse);  },  server_stream: function(call) {    call.emit('error', unimplementedStatusResponse);  },  bidi: function(call) {    call.emit('error', unimplementedStatusResponse);  }};/** * Add a service to the server, with a corresponding implementation. * @param {grpc~ServiceDefinition} service The service descriptor * @param {Object<String, grpc.Server~handleCall>} implementation Map of method *     names to method implementation for the provided service. */Server.prototype.addService = function(service, implementation) {  if (!_.isObject(service) || !_.isObject(implementation)) {    throw new Error('addService requires two objects as arguments');  }  if (_.keys(service).length === 0) {    throw new Error('Cannot add an empty service to a server');  }  if (this.started) {    throw new Error('Can\'t add a service to a started server.');  }  var self = this;  _.forOwn(service, function(attrs, name) {    var method_type;    if (attrs.requestStream) {      if (attrs.responseStream) {        method_type = 'bidi';      } else {        method_type = 'client_stream';      }    } else {      if (attrs.responseStream) {        method_type = 'server_stream';      } else {        method_type = 'unary';      }    }    var impl;    if (implementation[name] === undefined) {      /* Handle the case where the method is passed with the name exactly as         written in the proto file, instead of using JavaScript function         naming style */      if (implementation[attrs.originalName] === undefined) {        common.log(constants.logVerbosity.ERROR, 'Method handler ' + name +            ' for ' + attrs.path + ' expected but not provided');        impl = defaultHandler[method_type];      } else {        impl = _.bind(implementation[attrs.originalName], implementation);      }    } else {      impl = _.bind(implementation[name], implementation);    }    var serialize = attrs.responseSerialize;    var deserialize = attrs.requestDeserialize;    var register_success = self.register(attrs.path, impl, serialize,                                         deserialize, method_type);    if (!register_success) {      throw new Error('Method handler for ' + attrs.path +          ' already provided.');    }  });};/** * Add a proto service to the server, with a corresponding implementation * @deprecated Use {@link grpc.Server#addService} instead * @param {Protobuf.Reflect.Service} service The proto service descriptor * @param {Object<String, grpc.Server~handleCall>} implementation Map of method *     names to method implementation for the provided service. */Server.prototype.addProtoService = util.deprecate(function(service,                                                           implementation) {  var options;  var protobuf_js_5_common = require('./protobuf_js_5_common');  var protobuf_js_6_common = require('./protobuf_js_6_common');  if (protobuf_js_5_common.isProbablyProtobufJs5(service)) {    options = _.defaults(service.grpc_options, common.defaultGrpcOptions);    this.addService(        protobuf_js_5_common.getProtobufServiceAttrs(service, options),        implementation);  } else if (protobuf_js_6_common.isProbablyProtobufJs6(service)) {    options = _.defaults(service.grpc_options, common.defaultGrpcOptions);    this.addService(        protobuf_js_6_common.getProtobufServiceAttrs(service, options),        implementation);  } else {    // We assume that this is a service attributes object    this.addService(service, implementation);  }}, 'Server#addProtoService: Use Server#addService instead');/** * Binds the server to the given port, with SSL disabled if creds is an * insecure credentials object * @param {string} port The port that the server should bind on, in the format *     "address:port" * @param {grpc.ServerCredentials} creds Server credential object to be used for *     SSL. Pass an insecure credentials object for an insecure port. */Server.prototype.bind = function(port, creds) {  if (this.started) {    throw new Error('Can\'t bind an already running server to an address');  }  return this._server.addHttp2Port(port, creds);};exports.Server = Server;</code></pre>        </article>    </section></div><nav>    <h2><a href="index.html">Home</a></h2><h3>Externals</h3><ul><li><a href="external-Duplex.html">Duplex</a></li><li><a href="external-EventEmitter.html">EventEmitter</a></li><li><a href="external-GoogleCredential.html">GoogleCredential</a></li><li><a href="external-Readable.html">Readable</a></li><li><a href="external-Writable.html">Writable</a></li></ul><h3>Classes</h3><ul><li><a href="grpc.Client.html">Client</a></li><li><a href="grpc.credentials-CallCredentials.html">CallCredentials</a></li><li><a href="grpc.credentials-ChannelCredentials.html">ChannelCredentials</a></li><li><a href="grpc.Metadata.html">Metadata</a></li><li><a href="grpc.Server.html">Server</a></li><li><a href="grpc.ServerCredentials.html">ServerCredentials</a></li><li><a href="grpc-ClientDuplexStream.html">ClientDuplexStream</a></li><li><a href="grpc-ClientReadableStream.html">ClientReadableStream</a></li><li><a href="grpc-ClientUnaryCall.html">ClientUnaryCall</a></li><li><a href="grpc-ClientWritableStream.html">ClientWritableStream</a></li><li><a href="grpc-ServerDuplexStream.html">ServerDuplexStream</a></li><li><a href="grpc-ServerReadableStream.html">ServerReadableStream</a></li><li><a href="grpc-ServerUnaryCall.html">ServerUnaryCall</a></li><li><a href="grpc-ServerWritableStream.html">ServerWritableStream</a></li></ul><h3>Events</h3><ul><li><a href="grpc-ClientDuplexStream.html#event:metadata">metadata</a></li><li><a href="grpc-ClientDuplexStream.html#event:status">status</a></li><li><a href="grpc-ClientReadableStream.html#event:metadata">metadata</a></li><li><a href="grpc-ClientReadableStream.html#event:status">status</a></li><li><a href="grpc-ClientUnaryCall.html#event:metadata">metadata</a></li><li><a href="grpc-ClientUnaryCall.html#event:status">status</a></li><li><a href="grpc-ClientWritableStream.html#event:metadata">metadata</a></li><li><a href="grpc-ClientWritableStream.html#event:status">status</a></li><li><a href="grpc-ServerDuplexStream.html#~event:cancelled">cancelled</a></li><li><a href="grpc-ServerReadableStream.html#~event:cancelled">cancelled</a></li><li><a href="grpc-ServerUnaryCall.html#~event:cancelled">cancelled</a></li><li><a href="grpc-ServerWritableStream.html#~event:cancelled">cancelled</a></li></ul><h3>Namespaces</h3><ul><li><a href="grpc.html">grpc</a></li><li><a href="grpc.credentials.html">credentials</a></li></ul></nav><br class="clear"><footer>    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.3</a> on Fri Sep 08 2017 11:10:31 GMT-0700 (PDT)</footer><script> prettyPrint(); </script><script src="scripts/linenumber.js"> </script></body></html>
 |