github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/example/routeguide/cc/server.cc (about)

     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 <algorithm>
    20  #include <chrono>
    21  #include <cmath>
    22  #include <iostream>
    23  #include <memory>
    24  #include <string>
    25  
    26  #include "helper.h"
    27  
    28  #include "example/routeguide/routeguide.grpc.pb.h"
    29  #include <grpc/grpc.h>
    30  #include <grpcpp/security/server_credentials.h>
    31  #include <grpcpp/server.h>
    32  #include <grpcpp/server_builder.h>
    33  #include <grpcpp/server_context.h>
    34  
    35  using example::routeguide::Feature;
    36  using example::routeguide::Point;
    37  using example::routeguide::Rectangle;
    38  using example::routeguide::RouteGuide;
    39  using example::routeguide::RouteNote;
    40  using example::routeguide::RouteSummary;
    41  using grpc::Server;
    42  using grpc::ServerBuilder;
    43  using grpc::ServerContext;
    44  using grpc::ServerReader;
    45  using grpc::ServerReaderWriter;
    46  using grpc::ServerWriter;
    47  using grpc::Status;
    48  using std::chrono::system_clock;
    49  
    50  float ConvertToRadians(float num) { return num * 3.1415926 / 180; }
    51  
    52  // The formula is based on http://mathforum.org/library/drmath/view/51879.html
    53  float GetDistance(const Point &start, const Point &end) {
    54    const float kCoordFactor = 10000000.0;
    55    float lat_1 = start.latitude() / kCoordFactor;
    56    float lat_2 = end.latitude() / kCoordFactor;
    57    float lon_1 = start.longitude() / kCoordFactor;
    58    float lon_2 = end.longitude() / kCoordFactor;
    59    float lat_rad_1 = ConvertToRadians(lat_1);
    60    float lat_rad_2 = ConvertToRadians(lat_2);
    61    float delta_lat_rad = ConvertToRadians(lat_2 - lat_1);
    62    float delta_lon_rad = ConvertToRadians(lon_2 - lon_1);
    63  
    64    float a = pow(sin(delta_lat_rad / 2), 2) +
    65              cos(lat_rad_1) * cos(lat_rad_2) * pow(sin(delta_lon_rad / 2), 2);
    66    float c = 2 * atan2(sqrt(a), sqrt(1 - a));
    67    int R = 6371000; // metres
    68  
    69    return R * c;
    70  }
    71  
    72  std::string GetFeatureName(const Point &point,
    73                             const std::vector<Feature> &feature_list) {
    74    for (const Feature &f : feature_list) {
    75      if (f.location().latitude() == point.latitude() &&
    76          f.location().longitude() == point.longitude()) {
    77        return f.name();
    78      }
    79    }
    80    return "";
    81  }
    82  
    83  class RouteGuideImpl final : public RouteGuide::Service {
    84  public:
    85    explicit RouteGuideImpl(const std::string &db) {
    86      example::routeguide::ParseDb(db, &feature_list_);
    87    }
    88  
    89    Status GetFeature(ServerContext *context, const Point *point,
    90                      Feature *feature) override {
    91      feature->set_name(GetFeatureName(*point, feature_list_));
    92      feature->mutable_location()->CopyFrom(*point);
    93      return Status::OK;
    94    }
    95  
    96    Status ListFeatures(ServerContext *context, const Rectangle *rectangle,
    97                        ServerWriter<Feature> *writer) override {
    98      auto lo = rectangle->lo();
    99      auto hi = rectangle->hi();
   100      long left = (std::min)(lo.longitude(), hi.longitude());
   101      long right = (std::max)(lo.longitude(), hi.longitude());
   102      long top = (std::max)(lo.latitude(), hi.latitude());
   103      long bottom = (std::min)(lo.latitude(), hi.latitude());
   104      for (const Feature &f : feature_list_) {
   105        if (f.location().longitude() >= left &&
   106            f.location().longitude() <= right &&
   107            f.location().latitude() >= bottom && f.location().latitude() <= top) {
   108          writer->Write(f);
   109        }
   110      }
   111      return Status::OK;
   112    }
   113  
   114    Status RecordRoute(ServerContext *context, ServerReader<Point> *reader,
   115                       RouteSummary *summary) override {
   116      Point point;
   117      int point_count = 0;
   118      int feature_count = 0;
   119      float distance = 0.0;
   120      Point previous;
   121  
   122      system_clock::time_point start_time = system_clock::now();
   123      while (reader->Read(&point)) {
   124        point_count++;
   125        if (!GetFeatureName(point, feature_list_).empty()) {
   126          feature_count++;
   127        }
   128        if (point_count != 1) {
   129          distance += GetDistance(previous, point);
   130        }
   131        previous = point;
   132      }
   133      system_clock::time_point end_time = system_clock::now();
   134      summary->set_point_count(point_count);
   135      summary->set_feature_count(feature_count);
   136      summary->set_distance(static_cast<long>(distance));
   137      auto secs =
   138          std::chrono::duration_cast<std::chrono::seconds>(end_time - start_time);
   139      summary->set_elapsed_time(secs.count());
   140  
   141      return Status::OK;
   142    }
   143  
   144    Status RouteChat(ServerContext *context,
   145                     ServerReaderWriter<RouteNote, RouteNote> *stream) override {
   146      RouteNote note;
   147      while (stream->Read(&note)) {
   148        std::unique_lock<std::mutex> lock(mu_);
   149        for (const RouteNote &n : received_notes_) {
   150          if (n.location().latitude() == note.location().latitude() &&
   151              n.location().longitude() == note.location().longitude()) {
   152            stream->Write(n);
   153          }
   154        }
   155        received_notes_.push_back(note);
   156      }
   157  
   158      return Status::OK;
   159    }
   160  
   161  private:
   162    std::vector<Feature> feature_list_;
   163    std::mutex mu_;
   164    std::vector<RouteNote> received_notes_;
   165  };
   166  
   167  void RunServer(const std::string &db_path) {
   168    std::string server_address("0.0.0.0:50051");
   169    RouteGuideImpl service(db_path);
   170  
   171    ServerBuilder builder;
   172    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
   173    builder.RegisterService(&service);
   174    std::unique_ptr<Server> server(builder.BuildAndStart());
   175    std::cout << "Server listening on " << server_address << std::endl;
   176    server->Wait();
   177  }
   178  
   179  int main(int argc, char **argv) {
   180    // Expect only arg: --db_path=path/to/route_guide_db.json.
   181    std::string db = example::routeguide::GetDbFileContent(argc, argv);
   182    RunServer(db);
   183  
   184    return 0;
   185  }