Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: third_party/grpc/examples/node/route_guide/route_guide_server.js

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 *
3 * Copyright 2015-2016, Google Inc.
4 * 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
34 var PROTO_PATH = __dirname + '/../../protos/route_guide.proto';
35
36 var fs = require('fs');
37 var parseArgs = require('minimist');
38 var path = require('path');
39 var _ = require('lodash');
40 var grpc = require('grpc');
41 var routeguide = grpc.load(PROTO_PATH).routeguide;
42
43 var COORD_FACTOR = 1e7;
44
45 /**
46 * For simplicity, a point is a record type that looks like
47 * {latitude: number, longitude: number}, and a feature is a record type that
48 * looks like {name: string, location: point}. feature objects with name===''
49 * are points with no feature.
50 */
51
52 /**
53 * List of feature objects at points that have been requested so far.
54 */
55 var feature_list = [];
56
57 /**
58 * Get a feature object at the given point, or creates one if it does not exist.
59 * @param {point} point The point to check
60 * @return {feature} The feature object at the point. Note that an empty name
61 * indicates no feature
62 */
63 function checkFeature(point) {
64 var feature;
65 // Check if there is already a feature object for the given point
66 for (var i = 0; i < feature_list.length; i++) {
67 feature = feature_list[i];
68 if (feature.location.latitude === point.latitude &&
69 feature.location.longitude === point.longitude) {
70 return feature;
71 }
72 }
73 var name = '';
74 feature = {
75 name: name,
76 location: point
77 };
78 return feature;
79 }
80
81 /**
82 * getFeature request handler. Gets a request with a point, and responds with a
83 * feature object indicating whether there is a feature at that point.
84 * @param {EventEmitter} call Call object for the handler to process
85 * @param {function(Error, feature)} callback Response callback
86 */
87 function getFeature(call, callback) {
88 callback(null, checkFeature(call.request));
89 }
90
91 /**
92 * listFeatures request handler. Gets a request with two points, and responds
93 * with a stream of all features in the bounding box defined by those points.
94 * @param {Writable} call Writable stream for responses with an additional
95 * request property for the request value.
96 */
97 function listFeatures(call) {
98 var lo = call.request.lo;
99 var hi = call.request.hi;
100 var left = _.min([lo.longitude, hi.longitude]);
101 var right = _.max([lo.longitude, hi.longitude]);
102 var top = _.max([lo.latitude, hi.latitude]);
103 var bottom = _.min([lo.latitude, hi.latitude]);
104 // For each feature, check if it is in the given bounding box
105 _.each(feature_list, function(feature) {
106 if (feature.name === '') {
107 return;
108 }
109 if (feature.location.longitude >= left &&
110 feature.location.longitude <= right &&
111 feature.location.latitude >= bottom &&
112 feature.location.latitude <= top) {
113 call.write(feature);
114 }
115 });
116 call.end();
117 }
118
119 /**
120 * Calculate the distance between two points using the "haversine" formula.
121 * This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
122 * @param start The starting point
123 * @param end The end point
124 * @return The distance between the points in meters
125 */
126 function getDistance(start, end) {
127 function toRadians(num) {
128 return num * Math.PI / 180;
129 }
130 var lat1 = start.latitude / COORD_FACTOR;
131 var lat2 = end.latitude / COORD_FACTOR;
132 var lon1 = start.longitude / COORD_FACTOR;
133 var lon2 = end.longitude / COORD_FACTOR;
134 var R = 6371000; // metres
135 var φ1 = toRadians(lat1);
136 var φ2 = toRadians(lat2);
137 var Δφ = toRadians(lat2-lat1);
138 var Δλ = toRadians(lon2-lon1);
139
140 var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
141 Math.cos(φ1) * Math.cos(φ2) *
142 Math.sin(Δλ/2) * Math.sin(Δλ/2);
143 var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
144
145 return R * c;
146 }
147
148 /**
149 * recordRoute handler. Gets a stream of points, and responds with statistics
150 * about the "trip": number of points, number of known features visited, total
151 * distance traveled, and total time spent.
152 * @param {Readable} call The request point stream.
153 * @param {function(Error, routeSummary)} callback The callback to pass the
154 * response to
155 */
156 function recordRoute(call, callback) {
157 var point_count = 0;
158 var feature_count = 0;
159 var distance = 0;
160 var previous = null;
161 // Start a timer
162 var start_time = process.hrtime();
163 call.on('data', function(point) {
164 point_count += 1;
165 if (checkFeature(point).name !== '') {
166 feature_count += 1;
167 }
168 /* For each point after the first, add the incremental distance from the
169 * previous point to the total distance value */
170 if (previous != null) {
171 distance += getDistance(previous, point);
172 }
173 previous = point;
174 });
175 call.on('end', function() {
176 callback(null, {
177 point_count: point_count,
178 feature_count: feature_count,
179 // Cast the distance to an integer
180 distance: distance|0,
181 // End the timer
182 elapsed_time: process.hrtime(start_time)[0]
183 });
184 });
185 }
186
187 var route_notes = {};
188
189 /**
190 * Turn the point into a dictionary key.
191 * @param {point} point The point to use
192 * @return {string} The key for an object
193 */
194 function pointKey(point) {
195 return point.latitude + ' ' + point.longitude;
196 }
197
198 /**
199 * routeChat handler. Receives a stream of message/location pairs, and responds
200 * with a stream of all previous messages at each of those locations.
201 * @param {Duplex} call The stream for incoming and outgoing messages
202 */
203 function routeChat(call) {
204 call.on('data', function(note) {
205 var key = pointKey(note.location);
206 /* For each note sent, respond with all previous notes that correspond to
207 * the same point */
208 if (route_notes.hasOwnProperty(key)) {
209 _.each(route_notes[key], function(note) {
210 call.write(note);
211 });
212 } else {
213 route_notes[key] = [];
214 }
215 // Then add the new note to the list
216 route_notes[key].push(JSON.parse(JSON.stringify(note)));
217 });
218 call.on('end', function() {
219 call.end();
220 });
221 }
222
223 /**
224 * Get a new server with the handler functions in this file bound to the methods
225 * it serves.
226 * @return {Server} The new server object
227 */
228 function getServer() {
229 var server = new grpc.Server();
230 server.addProtoService(routeguide.RouteGuide.service, {
231 getFeature: getFeature,
232 listFeatures: listFeatures,
233 recordRoute: recordRoute,
234 routeChat: routeChat
235 });
236 return server;
237 }
238
239 if (require.main === module) {
240 // If this is run as a script, start a server on an unused port
241 var routeServer = getServer();
242 routeServer.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
243 var argv = parseArgs(process.argv, {
244 string: 'db_path'
245 });
246 fs.readFile(path.resolve(argv.db_path), function(err, data) {
247 if (err) throw err;
248 feature_list = JSON.parse(data);
249 routeServer.start();
250 });
251 }
252
253 exports.getServer = getServer;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698