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