OSDN Git Service

new repo
[bytom/vapor.git] / vendor / google.golang.org / grpc / examples / route_guide / server / server.go
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 //go:generate protoc -I ../routeguide --go_out=plugins=grpc:../routeguide ../routeguide/route_guide.proto
20
21 // Package main implements a simple gRPC server that demonstrates how to use gRPC-Go libraries
22 // to perform unary, client streaming, server streaming and full duplex RPCs.
23 //
24 // It implements the route guide service whose definition can be found in routeguide/route_guide.proto.
25 package main
26
27 import (
28         "encoding/json"
29         "flag"
30         "fmt"
31         "io"
32         "io/ioutil"
33         "log"
34         "math"
35         "net"
36         "time"
37
38         "golang.org/x/net/context"
39         "google.golang.org/grpc"
40
41         "google.golang.org/grpc/credentials"
42         "google.golang.org/grpc/testdata"
43
44         "github.com/golang/protobuf/proto"
45
46         pb "google.golang.org/grpc/examples/route_guide/routeguide"
47 )
48
49 var (
50         tls        = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP")
51         certFile   = flag.String("cert_file", "", "The TLS cert file")
52         keyFile    = flag.String("key_file", "", "The TLS key file")
53         jsonDBFile = flag.String("json_db_file", "testdata/route_guide_db.json", "A json file containing a list of features")
54         port       = flag.Int("port", 10000, "The server port")
55 )
56
57 type routeGuideServer struct {
58         savedFeatures []*pb.Feature
59         routeNotes    map[string][]*pb.RouteNote
60 }
61
62 // GetFeature returns the feature at the given point.
63 func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) {
64         for _, feature := range s.savedFeatures {
65                 if proto.Equal(feature.Location, point) {
66                         return feature, nil
67                 }
68         }
69         // No feature was found, return an unnamed feature
70         return &pb.Feature{Location: point}, nil
71 }
72
73 // ListFeatures lists all features contained within the given bounding Rectangle.
74 func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error {
75         for _, feature := range s.savedFeatures {
76                 if inRange(feature.Location, rect) {
77                         if err := stream.Send(feature); err != nil {
78                                 return err
79                         }
80                 }
81         }
82         return nil
83 }
84
85 // RecordRoute records a route composited of a sequence of points.
86 //
87 // It gets a stream of points, and responds with statistics about the "trip":
88 // number of points,  number of known features visited, total distance traveled, and
89 // total time spent.
90 func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error {
91         var pointCount, featureCount, distance int32
92         var lastPoint *pb.Point
93         startTime := time.Now()
94         for {
95                 point, err := stream.Recv()
96                 if err == io.EOF {
97                         endTime := time.Now()
98                         return stream.SendAndClose(&pb.RouteSummary{
99                                 PointCount:   pointCount,
100                                 FeatureCount: featureCount,
101                                 Distance:     distance,
102                                 ElapsedTime:  int32(endTime.Sub(startTime).Seconds()),
103                         })
104                 }
105                 if err != nil {
106                         return err
107                 }
108                 pointCount++
109                 for _, feature := range s.savedFeatures {
110                         if proto.Equal(feature.Location, point) {
111                                 featureCount++
112                         }
113                 }
114                 if lastPoint != nil {
115                         distance += calcDistance(lastPoint, point)
116                 }
117                 lastPoint = point
118         }
119 }
120
121 // RouteChat receives a stream of message/location pairs, and responds with a stream of all
122 // previous messages at each of those locations.
123 func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error {
124         for {
125                 in, err := stream.Recv()
126                 if err == io.EOF {
127                         return nil
128                 }
129                 if err != nil {
130                         return err
131                 }
132                 key := serialize(in.Location)
133                 if _, present := s.routeNotes[key]; !present {
134                         s.routeNotes[key] = []*pb.RouteNote{in}
135                 } else {
136                         s.routeNotes[key] = append(s.routeNotes[key], in)
137                 }
138                 for _, note := range s.routeNotes[key] {
139                         if err := stream.Send(note); err != nil {
140                                 return err
141                         }
142                 }
143         }
144 }
145
146 // loadFeatures loads features from a JSON file.
147 func (s *routeGuideServer) loadFeatures(filePath string) {
148         file, err := ioutil.ReadFile(filePath)
149         if err != nil {
150                 log.Fatalf("Failed to load default features: %v", err)
151         }
152         if err := json.Unmarshal(file, &s.savedFeatures); err != nil {
153                 log.Fatalf("Failed to load default features: %v", err)
154         }
155 }
156
157 func toRadians(num float64) float64 {
158         return num * math.Pi / float64(180)
159 }
160
161 // calcDistance calculates the distance between two points using the "haversine" formula.
162 // This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
163 func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 {
164         const CordFactor float64 = 1e7
165         const R float64 = float64(6371000) // metres
166         lat1 := float64(p1.Latitude) / CordFactor
167         lat2 := float64(p2.Latitude) / CordFactor
168         lng1 := float64(p1.Longitude) / CordFactor
169         lng2 := float64(p2.Longitude) / CordFactor
170         φ1 := toRadians(lat1)
171         φ2 := toRadians(lat2)
172         Δφ := toRadians(lat2 - lat1)
173         Δλ := toRadians(lng2 - lng1)
174
175         a := math.Sin(Δφ/2)*math.Sin(Δφ/2) +
176                 math.Cos(φ1)*math.Cos(φ2)*
177                         math.Sin(Δλ/2)*math.Sin(Δλ/2)
178         c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
179
180         distance := R * c
181         return int32(distance)
182 }
183
184 func inRange(point *pb.Point, rect *pb.Rectangle) bool {
185         left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))
186         right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))
187         top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))
188         bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))
189
190         if float64(point.Longitude) >= left &&
191                 float64(point.Longitude) <= right &&
192                 float64(point.Latitude) >= bottom &&
193                 float64(point.Latitude) <= top {
194                 return true
195         }
196         return false
197 }
198
199 func serialize(point *pb.Point) string {
200         return fmt.Sprintf("%d %d", point.Latitude, point.Longitude)
201 }
202
203 func newServer() *routeGuideServer {
204         s := new(routeGuideServer)
205         s.loadFeatures(*jsonDBFile)
206         s.routeNotes = make(map[string][]*pb.RouteNote)
207         return s
208 }
209
210 func main() {
211         flag.Parse()
212         lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))
213         if err != nil {
214                 log.Fatalf("failed to listen: %v", err)
215         }
216         var opts []grpc.ServerOption
217         if *tls {
218                 if *certFile == "" {
219                         *certFile = testdata.Path("server1.pem")
220                 }
221                 if *keyFile == "" {
222                         *keyFile = testdata.Path("server1.key")
223                 }
224                 creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)
225                 if err != nil {
226                         log.Fatalf("Failed to generate credentials %v", err)
227                 }
228                 opts = []grpc.ServerOption{grpc.Creds(creds)}
229         }
230         grpcServer := grpc.NewServer(opts...)
231         pb.RegisterRouteGuideServer(grpcServer, newServer())
232         grpcServer.Serve(lis)
233 }