1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <chrono>
20 #include <iostream>
21 #include <memory>
22 #include <random>
23 #include <string>
24 #include <thread>
25
26 #include "helper.h"
27
28 #include <grpc/grpc.h>
29 #include <grpcpp/channel.h>
30 #include <grpcpp/client_context.h>
31 #include <grpcpp/create_channel.h>
32 #include <grpcpp/security/credentials.h>
33 #ifdef BAZEL_BUILD
34 #include "examples/protos/route_guide.grpc.pb.h"
35 #else
36 #include "route_guide.grpc.pb.h"
37 #endif
38
39 using grpc::Channel;
40 using grpc::ClientContext;
41 using grpc::ClientReader;
42 using grpc::ClientReaderWriter;
43 using grpc::ClientWriter;
44 using grpc::Status;
45 using routeguide::Feature;
46 using routeguide::Point;
47 using routeguide::Rectangle;
48 using routeguide::RouteGuide;
49 using routeguide::RouteNote;
50 using routeguide::RouteSummary;
51
MakePoint(long latitude,long longitude)52 Point MakePoint(long latitude, long longitude) {
53 Point p;
54 p.set_latitude(latitude);
55 p.set_longitude(longitude);
56 return p;
57 }
58
MakeFeature(const std::string & name,long latitude,long longitude)59 Feature MakeFeature(const std::string& name, long latitude, long longitude) {
60 Feature f;
61 f.set_name(name);
62 f.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
63 return f;
64 }
65
MakeRouteNote(const std::string & message,long latitude,long longitude)66 RouteNote MakeRouteNote(const std::string& message, long latitude,
67 long longitude) {
68 RouteNote n;
69 n.set_message(message);
70 n.mutable_location()->CopyFrom(MakePoint(latitude, longitude));
71 return n;
72 }
73
74 class RouteGuideClient {
75 public:
RouteGuideClient(std::shared_ptr<Channel> channel,const std::string & db)76 RouteGuideClient(std::shared_ptr<Channel> channel, const std::string& db)
77 : stub_(RouteGuide::NewStub(channel)) {
78 routeguide::ParseDb(db, &feature_list_);
79 }
80
GetFeature()81 void GetFeature() {
82 Point point;
83 Feature feature;
84 point = MakePoint(409146138, -746188906);
85 GetOneFeature(point, &feature);
86 point = MakePoint(0, 0);
87 GetOneFeature(point, &feature);
88 }
89
ListFeatures()90 void ListFeatures() {
91 routeguide::Rectangle rect;
92 Feature feature;
93 ClientContext context;
94
95 rect.mutable_lo()->set_latitude(400000000);
96 rect.mutable_lo()->set_longitude(-750000000);
97 rect.mutable_hi()->set_latitude(420000000);
98 rect.mutable_hi()->set_longitude(-730000000);
99 std::cout << "Looking for features between 40, -75 and 42, -73"
100 << std::endl;
101
102 std::unique_ptr<ClientReader<Feature> > reader(
103 stub_->ListFeatures(&context, rect));
104 while (reader->Read(&feature)) {
105 std::cout << "Found feature called " << feature.name() << " at "
106 << feature.location().latitude() / kCoordFactor_ << ", "
107 << feature.location().longitude() / kCoordFactor_ << std::endl;
108 }
109 Status status = reader->Finish();
110 if (status.ok()) {
111 std::cout << "ListFeatures rpc succeeded." << std::endl;
112 } else {
113 std::cout << "ListFeatures rpc failed." << std::endl;
114 }
115 }
116
RecordRoute()117 void RecordRoute() {
118 Point point;
119 RouteSummary stats;
120 ClientContext context;
121 const int kPoints = 10;
122 unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
123
124 std::default_random_engine generator(seed);
125 std::uniform_int_distribution<int> feature_distribution(
126 0, feature_list_.size() - 1);
127 std::uniform_int_distribution<int> delay_distribution(500, 1500);
128
129 std::unique_ptr<ClientWriter<Point> > writer(
130 stub_->RecordRoute(&context, &stats));
131 for (int i = 0; i < kPoints; i++) {
132 const Feature& f = feature_list_[feature_distribution(generator)];
133 std::cout << "Visiting point " << f.location().latitude() / kCoordFactor_
134 << ", " << f.location().longitude() / kCoordFactor_
135 << std::endl;
136 if (!writer->Write(f.location())) {
137 // Broken stream.
138 break;
139 }
140 std::this_thread::sleep_for(
141 std::chrono::milliseconds(delay_distribution(generator)));
142 }
143 writer->WritesDone();
144 Status status = writer->Finish();
145 if (status.ok()) {
146 std::cout << "Finished trip with " << stats.point_count() << " points\n"
147 << "Passed " << stats.feature_count() << " features\n"
148 << "Travelled " << stats.distance() << " meters\n"
149 << "It took " << stats.elapsed_time() << " seconds"
150 << std::endl;
151 } else {
152 std::cout << "RecordRoute rpc failed." << std::endl;
153 }
154 }
155
RouteChat()156 void RouteChat() {
157 ClientContext context;
158
159 std::shared_ptr<ClientReaderWriter<RouteNote, RouteNote> > stream(
160 stub_->RouteChat(&context));
161
162 std::thread writer([stream]() {
163 std::vector<RouteNote> notes{MakeRouteNote("First message", 0, 0),
164 MakeRouteNote("Second message", 0, 1),
165 MakeRouteNote("Third message", 1, 0),
166 MakeRouteNote("Fourth message", 0, 0)};
167 for (const RouteNote& note : notes) {
168 std::cout << "Sending message " << note.message() << " at "
169 << note.location().latitude() << ", "
170 << note.location().longitude() << std::endl;
171 stream->Write(note);
172 }
173 stream->WritesDone();
174 });
175
176 RouteNote server_note;
177 while (stream->Read(&server_note)) {
178 std::cout << "Got message " << server_note.message() << " at "
179 << server_note.location().latitude() << ", "
180 << server_note.location().longitude() << std::endl;
181 }
182 writer.join();
183 Status status = stream->Finish();
184 if (!status.ok()) {
185 std::cout << "RouteChat rpc failed." << std::endl;
186 }
187 }
188
189 private:
GetOneFeature(const Point & point,Feature * feature)190 bool GetOneFeature(const Point& point, Feature* feature) {
191 ClientContext context;
192 Status status = stub_->GetFeature(&context, point, feature);
193 if (!status.ok()) {
194 std::cout << "GetFeature rpc failed." << std::endl;
195 return false;
196 }
197 if (!feature->has_location()) {
198 std::cout << "Server returns incomplete feature." << std::endl;
199 return false;
200 }
201 if (feature->name().empty()) {
202 std::cout << "Found no feature at "
203 << feature->location().latitude() / kCoordFactor_ << ", "
204 << feature->location().longitude() / kCoordFactor_ << std::endl;
205 } else {
206 std::cout << "Found feature called " << feature->name() << " at "
207 << feature->location().latitude() / kCoordFactor_ << ", "
208 << feature->location().longitude() / kCoordFactor_ << std::endl;
209 }
210 return true;
211 }
212
213 const float kCoordFactor_ = 10000000.0;
214 std::unique_ptr<RouteGuide::Stub> stub_;
215 std::vector<Feature> feature_list_;
216 };
217
main(int argc,char ** argv)218 int main(int argc, char** argv) {
219 // Expect only arg: --db_path=path/to/route_guide_db.json.
220 std::string db = routeguide::GetDbFileContent(argc, argv);
221 RouteGuideClient guide(
222 grpc::CreateChannel("localhost:50051",
223 grpc::InsecureChannelCredentials()),
224 db);
225
226 std::cout << "-------------- GetFeature --------------" << std::endl;
227 guide.GetFeature();
228 std::cout << "-------------- ListFeatures --------------" << std::endl;
229 guide.ListFeatures();
230 std::cout << "-------------- RecordRoute --------------" << std::endl;
231 guide.RecordRoute();
232 std::cout << "-------------- RouteChat --------------" << std::endl;
233 guide.RouteChat();
234
235 return 0;
236 }
237