mirror of https://github.com/grpc/grpc-go.git
Make route guide implementation more go idiomatic
This commit is contained in:
parent
a94c062d9b
commit
8fd7702f97
|
@ -2,7 +2,7 @@
|
|||
The route guide server and client demonstrates how to use grpc go libraries to
|
||||
perform unary, client streaming, server streaming and full duplex RPCs.
|
||||
|
||||
See the definition of the route guide service in route_guide.proto.
|
||||
See the definition of the route guide service in proto/route_guide.proto.
|
||||
|
||||
# Run the sample code
|
||||
To compile and run the server, assuming you are in the root of the route_guide
|
||||
|
@ -18,8 +18,8 @@ Likewise, to run the client:
|
|||
The server and client both take optional command line flags. For example, the
|
||||
client and server run without TLS by default. To enable TSL:
|
||||
|
||||
`go run server/server.go -use_tls=true`
|
||||
`go run server/server.go -tls=true`
|
||||
|
||||
and
|
||||
|
||||
`go run client/client.go -use_tls=true`
|
||||
`go run client/client.go -tls=true`
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// Package main implements a simple grpc client that demonstrates how to use grpc go libraries
|
||||
// to perform unary, client streaming, server streaming and full duplex RPCs.
|
||||
//
|
||||
// It interacts with the route guide service whose definition can be found in proto/route_guide.proto.
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -38,64 +42,59 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
pb "google.golang.org/grpc/examples/route_guide"
|
||||
pb "google.golang.org/grpc/examples/route_guide/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
useTLS = flag.Bool("use_tls", false, "Connection uses TLS if true, else plain TCP")
|
||||
tls = flag.Bool("use_tls", false, "Connection uses TLS if true, else plain TCP")
|
||||
caFile = flag.String("tls_ca_file", "testdata/ca.pem", "The file containning the CA root cert file")
|
||||
serverHost = flag.String("server_host", "127.0.0.1", "The server host name")
|
||||
serverPort = flag.Int("server_port", 10000, "The server port number")
|
||||
serverAddr = flag.String("server_addr", "127.0.0.1:10000", "The server address in the format of host:port")
|
||||
tlsServerName = flag.String("tls_server_name", "x.test.youtube.com", "The server name use to verify the hostname returned by TLS handshake")
|
||||
)
|
||||
|
||||
// doGetFeature gets the feature for the given point.
|
||||
func doGetFeature(client pb.RouteGuideClient, point *pb.Point) {
|
||||
// printFeature gets the feature for the given point.
|
||||
func printFeature(client pb.RouteGuideClient, point *pb.Point) {
|
||||
log.Printf("Getting feature for point (%d, %d)", point.Latitude, point.Longitude)
|
||||
reply, err := client.GetFeature(context.Background(), point)
|
||||
feature, err := client.GetFeature(context.Background(), point)
|
||||
if err != nil {
|
||||
log.Fatalf("%v.GetFeatures(_) = _, %v: ", client, err)
|
||||
return
|
||||
}
|
||||
log.Println(reply)
|
||||
log.Println(feature)
|
||||
}
|
||||
|
||||
// doListFeatures lists all the features within the given bounding Rectangle.
|
||||
func doListFeatures(client pb.RouteGuideClient, rect *pb.Rectangle) {
|
||||
// printFeatures lists all the features within the given bounding Rectangle.
|
||||
func printFeatures(client pb.RouteGuideClient, rect *pb.Rectangle) {
|
||||
log.Printf("Looking for features within %v", rect)
|
||||
stream, err := client.ListFeatures(context.Background(), rect)
|
||||
if err != nil {
|
||||
log.Fatalf("%v.ListFeatures(_) = _, %v", client, err)
|
||||
}
|
||||
var rpcStatus error
|
||||
for {
|
||||
reply, err := stream.Recv()
|
||||
if err != nil {
|
||||
rpcStatus = err
|
||||
feature, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
log.Println(reply)
|
||||
}
|
||||
if rpcStatus != io.EOF {
|
||||
log.Fatalf("%v.ListFeatures(_) = _, %v", client, err)
|
||||
if err != nil {
|
||||
log.Fatalf("%v.ListFeatures(_) = _, %v", client, err)
|
||||
}
|
||||
log.Println(feature)
|
||||
}
|
||||
}
|
||||
|
||||
// doRecordRoute sends a sequence of points to server and expects to get a RouteSummary from server.
|
||||
func doRecordRoute(client pb.RouteGuideClient) {
|
||||
// runRecordRoute sends a sequence of points to server and expects to get a RouteSummary from server.
|
||||
func runRecordRoute(client pb.RouteGuideClient) {
|
||||
// Create a random number of random points
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
pointCount := rand.Int31n(100) + 2 // Tranverse at least two points
|
||||
points := make([]*pb.Point, pointCount)
|
||||
for i, _ := range points {
|
||||
points[i] = randomPoint()
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
pointCount := int(r.Int31n(100)) + 2 // Traverse at least two points
|
||||
var points []*pb.Point
|
||||
for i := 0; i < pointCount; i++ {
|
||||
points = append(points, randomPoint(r))
|
||||
}
|
||||
log.Printf("Traversing %d points.", len(points))
|
||||
stream, err := client.RecordRoute(context.Background())
|
||||
|
@ -111,58 +110,57 @@ func doRecordRoute(client pb.RouteGuideClient) {
|
|||
if err != nil {
|
||||
log.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)
|
||||
}
|
||||
log.Printf("Route summary: %v\n", reply)
|
||||
log.Printf("Route summary: %v", reply)
|
||||
}
|
||||
|
||||
// doRouteChat receives a sequence of route notes, while sending notes for various locations.
|
||||
func doRouteChat(client pb.RouteGuideClient) {
|
||||
// runRouteChat receives a sequence of route notes, while sending notes for various locations.
|
||||
func runRouteChat(client pb.RouteGuideClient) {
|
||||
notes := []*pb.RouteNote{
|
||||
&pb.RouteNote{&pb.Point{0, 1}, "First message"},
|
||||
&pb.RouteNote{&pb.Point{0, 2}, "Second message"},
|
||||
&pb.RouteNote{&pb.Point{0, 3}, "Third message"},
|
||||
&pb.RouteNote{&pb.Point{0, 1}, "Fourth message"},
|
||||
&pb.RouteNote{&pb.Point{0, 2}, "Fifth message"},
|
||||
&pb.RouteNote{&pb.Point{0, 3}, "Sixth message"},
|
||||
{&pb.Point{0, 1}, "First message"},
|
||||
{&pb.Point{0, 2}, "Second message"},
|
||||
{&pb.Point{0, 3}, "Third message"},
|
||||
{&pb.Point{0, 1}, "Fourth message"},
|
||||
{&pb.Point{0, 2}, "Fifth message"},
|
||||
{&pb.Point{0, 3}, "Sixth message"},
|
||||
}
|
||||
stream, err := client.RouteChat(context.Background())
|
||||
if err != nil {
|
||||
log.Fatalf("%v.RouteChat(_) = _, %v", client, err)
|
||||
}
|
||||
c := make(chan int)
|
||||
waitc := make(chan int)
|
||||
go func() {
|
||||
for {
|
||||
in, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
// read done.
|
||||
c <- 1
|
||||
waitc <- 1
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to receive a note : %v\n", err)
|
||||
log.Fatalf("Failed to receive a note : %v", err)
|
||||
}
|
||||
log.Printf("Got message %s at point(%d, %d)\n", in.Message, in.Location.Latitude, in.Location.Longitude)
|
||||
log.Printf("Got message %s at point(%d, %d)", in.Message, in.Location.Latitude, in.Location.Longitude)
|
||||
}
|
||||
}()
|
||||
for _, note := range notes {
|
||||
if err := stream.Send(note); err != nil {
|
||||
log.Fatalf("Failed to send a note: %v\n", err)
|
||||
log.Fatalf("Failed to send a note: %v", err)
|
||||
}
|
||||
}
|
||||
stream.CloseSend()
|
||||
<-c
|
||||
<-waitc
|
||||
}
|
||||
|
||||
func randomPoint() *pb.Point {
|
||||
lat := (rand.Int31n(180) - 90) * 1e7
|
||||
long := (rand.Int31n(360) - 180) * 1e7
|
||||
func randomPoint(r *rand.Rand) *pb.Point {
|
||||
lat := (r.Int31n(180) - 90) * 1e7
|
||||
long := (r.Int31n(360) - 180) * 1e7
|
||||
return &pb.Point{lat, long}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
serverAddr := net.JoinHostPort(*serverHost, strconv.Itoa(*serverPort))
|
||||
var opts []grpc.DialOption
|
||||
if *useTLS {
|
||||
if *tls {
|
||||
var sn string
|
||||
if *tlsServerName != "" {
|
||||
sn = *tlsServerName
|
||||
|
@ -179,7 +177,7 @@ func main() {
|
|||
}
|
||||
opts = append(opts, grpc.WithClientTLS(creds))
|
||||
}
|
||||
conn, err := grpc.Dial(serverAddr, opts...)
|
||||
conn, err := grpc.Dial(*serverAddr, opts...)
|
||||
if err != nil {
|
||||
log.Fatalf("fail to dial: %v", err)
|
||||
}
|
||||
|
@ -187,17 +185,17 @@ func main() {
|
|||
client := pb.NewRouteGuideClient(conn)
|
||||
|
||||
// Looking for a valid feature
|
||||
doGetFeature(client, &pb.Point{409146138, -746188906})
|
||||
printFeature(client, &pb.Point{409146138, -746188906})
|
||||
|
||||
// Feature missing.
|
||||
doGetFeature(client, &pb.Point{0, 0})
|
||||
printFeature(client, &pb.Point{0, 0})
|
||||
|
||||
// Looking for features between 40, -75 and 42, -73.
|
||||
doListFeatures(client, &pb.Rectangle{&pb.Point{400000000, -750000000}, &pb.Point{420000000, -730000000}})
|
||||
printFeatures(client, &pb.Rectangle{&pb.Point{400000000, -750000000}, &pb.Point{420000000, -730000000}})
|
||||
|
||||
// RecordRoute
|
||||
doRecordRoute(client)
|
||||
runRecordRoute(client)
|
||||
|
||||
// RouteChat
|
||||
doRouteChat(client)
|
||||
runRouteChat(client)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: route_guide.proto
|
||||
// source: proto/route_guide.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package route_guide is a generated protocol buffer package.
|
||||
Package proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
route_guide.proto
|
||||
proto/route_guide.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Point
|
||||
|
@ -15,9 +15,9 @@ It has these top-level messages:
|
|||
RouteNote
|
||||
RouteSummary
|
||||
*/
|
||||
package route_guide
|
||||
package proto
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import proto1 "github.com/golang/protobuf/proto"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
|
@ -29,7 +29,7 @@ var _ context.Context
|
|||
var _ grpc.ClientConn
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = proto1.Marshal
|
||||
|
||||
// Points are represented as latitude-longitude pairs in the E7 representation
|
||||
// (degrees multiplied by 10**7 and rounded to the nearest integer).
|
||||
|
@ -41,7 +41,7 @@ type Point struct {
|
|||
}
|
||||
|
||||
func (m *Point) Reset() { *m = Point{} }
|
||||
func (m *Point) String() string { return proto.CompactTextString(m) }
|
||||
func (m *Point) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Point) ProtoMessage() {}
|
||||
|
||||
// A latitude-longitude rectangle, represented as two diagonally opposite
|
||||
|
@ -54,7 +54,7 @@ type Rectangle struct {
|
|||
}
|
||||
|
||||
func (m *Rectangle) Reset() { *m = Rectangle{} }
|
||||
func (m *Rectangle) String() string { return proto.CompactTextString(m) }
|
||||
func (m *Rectangle) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Rectangle) ProtoMessage() {}
|
||||
|
||||
func (m *Rectangle) GetLo() *Point {
|
||||
|
@ -82,7 +82,7 @@ type Feature struct {
|
|||
}
|
||||
|
||||
func (m *Feature) Reset() { *m = Feature{} }
|
||||
func (m *Feature) String() string { return proto.CompactTextString(m) }
|
||||
func (m *Feature) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Feature) ProtoMessage() {}
|
||||
|
||||
func (m *Feature) GetLocation() *Point {
|
||||
|
@ -101,7 +101,7 @@ type RouteNote struct {
|
|||
}
|
||||
|
||||
func (m *RouteNote) Reset() { *m = RouteNote{} }
|
||||
func (m *RouteNote) String() string { return proto.CompactTextString(m) }
|
||||
func (m *RouteNote) String() string { return proto1.CompactTextString(m) }
|
||||
func (*RouteNote) ProtoMessage() {}
|
||||
|
||||
func (m *RouteNote) GetLocation() *Point {
|
||||
|
@ -128,7 +128,7 @@ type RouteSummary struct {
|
|||
}
|
||||
|
||||
func (m *RouteSummary) Reset() { *m = RouteSummary{} }
|
||||
func (m *RouteSummary) String() string { return proto.CompactTextString(m) }
|
||||
func (m *RouteSummary) String() string { return proto1.CompactTextString(m) }
|
||||
func (*RouteSummary) ProtoMessage() {}
|
||||
|
||||
func init() {
|
||||
|
@ -170,7 +170,7 @@ func NewRouteGuideClient(cc *grpc.ClientConn) RouteGuideClient {
|
|||
|
||||
func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) {
|
||||
out := new(Feature)
|
||||
err := grpc.Invoke(ctx, "/route_guide.RouteGuide/GetFeature", in, out, c.cc, opts...)
|
||||
err := grpc.Invoke(ctx, "/proto.RouteGuide/GetFeature", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...gr
|
|||
}
|
||||
|
||||
func (c *routeGuideClient) ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[0], c.cc, "/route_guide.RouteGuide/ListFeatures", opts...)
|
||||
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[0], c.cc, "/proto.RouteGuide/ListFeatures", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) {
|
|||
}
|
||||
|
||||
func (c *routeGuideClient) RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[1], c.cc, "/route_guide.RouteGuide/RecordRoute", opts...)
|
||||
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[1], c.cc, "/proto.RouteGuide/RecordRoute", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ func (x *routeGuideRecordRouteClient) CloseAndRecv() (*RouteSummary, error) {
|
|||
}
|
||||
|
||||
func (c *routeGuideClient) RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[2], c.cc, "/route_guide.RouteGuide/RouteChat", opts...)
|
||||
stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[2], c.cc, "/proto.RouteGuide/RouteChat", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -304,9 +304,9 @@ func RegisterRouteGuideServer(s *grpc.Server, srv RouteGuideServer) {
|
|||
s.RegisterService(&_RouteGuide_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, buf []byte) (proto.Message, error) {
|
||||
func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, buf []byte) (proto1.Message, error) {
|
||||
in := new(Point)
|
||||
if err := proto.Unmarshal(buf, in); err != nil {
|
||||
if err := proto1.Unmarshal(buf, in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := srv.(RouteGuideServer).GetFeature(ctx, in)
|
||||
|
@ -390,7 +390,7 @@ func (x *routeGuideRouteChatServer) Recv() (*RouteNote, error) {
|
|||
}
|
||||
|
||||
var _RouteGuide_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "route_guide.RouteGuide",
|
||||
ServiceName: "proto.RouteGuide",
|
||||
HandlerType: (*RouteGuideServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
|
@ -29,13 +29,16 @@
|
|||
|
||||
syntax = "proto3";
|
||||
|
||||
package route_guide;
|
||||
package proto;
|
||||
|
||||
// Interface exported by the server.
|
||||
service RouteGuide {
|
||||
// A simple RPC.
|
||||
//
|
||||
// Obtains the feature at a given position.
|
||||
//
|
||||
// If no feature is found for the given point, a feature with an empty name
|
||||
// should be returned.
|
||||
rpc GetFeature(Point) returns (Feature) {}
|
||||
|
||||
// A server-to-client streaming RPC.
|
|
@ -31,11 +31,16 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// Package main implements a simple grpc server that demonstrates how to use grpc go libraries
|
||||
// to perform unary, client streaming, server streaming and full duplex RPCs.
|
||||
//
|
||||
// It implements the route guide service whose definition can be found in proto/route_guide.proto.
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
@ -49,11 +54,13 @@ import (
|
|||
|
||||
"google.golang.org/grpc/credentials"
|
||||
|
||||
pb "google.golang.org/grpc/examples/route_guide"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
|
||||
pb "google.golang.org/grpc/examples/route_guide/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
useTLS = flag.Bool("use_tls", false, "Connection uses TLS if true, else plain TCP")
|
||||
tls = flag.Bool("use_tls", false, "Connection uses TLS if true, else plain TCP")
|
||||
certFile = flag.String("tls_cert_file", "testdata/server1.pem", "The TLS cert file")
|
||||
keyFile = flag.String("tls_key_file", "testdata/server1.key", "The TLS key file")
|
||||
jsonDBFile = flag.String("route_guide_db", "testdata/route_guide_db.json", "A json file containing a list of features")
|
||||
|
@ -61,15 +68,15 @@ var (
|
|||
)
|
||||
|
||||
type routeGuideServer struct {
|
||||
savedFeatures []pb.Feature
|
||||
routeNotes map[pb.Point][]*pb.RouteNote
|
||||
savedFeatures []*pb.Feature
|
||||
routeNotes map[string][]*pb.RouteNote
|
||||
}
|
||||
|
||||
// GetFeature returns the feature at the given point.
|
||||
func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) {
|
||||
for _, feature := range s.savedFeatures {
|
||||
if *(feature.Location) == *point {
|
||||
return &feature, nil
|
||||
if proto.Equal(feature.Location, point) {
|
||||
return feature, nil
|
||||
}
|
||||
}
|
||||
// No feature was found, return an unnamed feature
|
||||
|
@ -78,16 +85,9 @@ func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb
|
|||
|
||||
// ListFeatures lists all features comtained within the given bounding Rectangle.
|
||||
func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error {
|
||||
left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))
|
||||
right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))
|
||||
top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))
|
||||
bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))
|
||||
for _, feature := range s.savedFeatures {
|
||||
if float64(feature.Location.Longitude) >= left &&
|
||||
float64(feature.Location.Longitude) <= right &&
|
||||
float64(feature.Location.Latitude) >= bottom &&
|
||||
float64(feature.Location.Latitude) <= top {
|
||||
if err := stream.Send(&feature); err != nil {
|
||||
if inRange(feature.Location, rect) {
|
||||
if err := stream.Send(feature); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) e
|
|||
}
|
||||
pointCount++
|
||||
for _, feature := range s.savedFeatures {
|
||||
if *(feature.Location) == *point {
|
||||
if proto.Equal(feature.Location, point) {
|
||||
featureCount++
|
||||
}
|
||||
}
|
||||
|
@ -142,14 +142,14 @@ func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
point := *(in.Location)
|
||||
if _, present := s.routeNotes[point]; !present {
|
||||
s.routeNotes[point] = []*pb.RouteNote{in}
|
||||
key := serialize(in.Location)
|
||||
if _, present := s.routeNotes[key]; !present {
|
||||
s.routeNotes[key] = []*pb.RouteNote{in}
|
||||
|
||||
} else {
|
||||
s.routeNotes[point] = append(s.routeNotes[point], in)
|
||||
s.routeNotes[key] = append(s.routeNotes[key], in)
|
||||
}
|
||||
for _, note := range s.routeNotes[point] {
|
||||
for _, note := range s.routeNotes[key] {
|
||||
if err := stream.Send(note); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -161,10 +161,10 @@ func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error
|
|||
func (s *routeGuideServer) loadFeatures(filePath string) {
|
||||
file, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to load default features: %v\n", err)
|
||||
log.Fatal("Failed to load default features: %v", err)
|
||||
}
|
||||
if err := json.Unmarshal(file, &(s.savedFeatures)); err != nil {
|
||||
log.Fatal("Failed to load default features: %v\n", err)
|
||||
log.Fatal("Failed to load default features: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,17 +172,19 @@ func toRadians(num float64) float64 {
|
|||
return num * math.Pi / float64(180)
|
||||
}
|
||||
|
||||
// calcDistance calculates the distance between two points using the "haversine" formula.
|
||||
// This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
|
||||
func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 {
|
||||
const COORD_FACTOR float64 = 1e7
|
||||
const CordFactor float64 = 1e7
|
||||
const R float64 = float64(6371000) // metres
|
||||
lat1 := float64(p1.Latitude) / COORD_FACTOR
|
||||
lat2 := float64(p2.Latitude) / COORD_FACTOR
|
||||
lon1 := float64(p1.Longitude) / COORD_FACTOR
|
||||
lon2 := float64(p2.Longitude) / COORD_FACTOR
|
||||
lat1 := float64(p1.Latitude) / CordFactor
|
||||
lat2 := float64(p2.Latitude) / CordFactor
|
||||
lng1 := float64(p1.Longitude) / CordFactor
|
||||
lng2 := float64(p2.Longitude) / CordFactor
|
||||
φ1 := toRadians(lat1)
|
||||
φ2 := toRadians(lat2)
|
||||
Δφ := toRadians(lat2 - lat1)
|
||||
Δλ := toRadians(lon2 - lon1)
|
||||
Δλ := toRadians(lng2 - lng1)
|
||||
|
||||
a := math.Sin(Δφ/2)*math.Sin(Δφ/2) +
|
||||
math.Cos(φ1)*math.Cos(φ2)*
|
||||
|
@ -193,10 +195,29 @@ func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 {
|
|||
return int32(distance)
|
||||
}
|
||||
|
||||
func inRange(point *pb.Point, rect *pb.Rectangle) bool {
|
||||
left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))
|
||||
right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))
|
||||
top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))
|
||||
bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))
|
||||
|
||||
if float64(point.Longitude) >= left &&
|
||||
float64(point.Longitude) <= right &&
|
||||
float64(point.Latitude) >= bottom &&
|
||||
float64(point.Latitude) <= top {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func serialize(point *pb.Point) string {
|
||||
return fmt.Sprintf("%d %d", point.Latitude, point.Longitude)
|
||||
}
|
||||
|
||||
func newServer() *routeGuideServer {
|
||||
s := new(routeGuideServer)
|
||||
s.loadFeatures(*jsonDBFile)
|
||||
s.routeNotes = make(map[pb.Point][]*pb.RouteNote, 0)
|
||||
s.routeNotes = make(map[string][]*pb.RouteNote, 0)
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -209,7 +230,7 @@ func main() {
|
|||
}
|
||||
grpcServer := grpc.NewServer()
|
||||
pb.RegisterRouteGuideServer(grpcServer, newServer())
|
||||
if *useTLS {
|
||||
if *tls {
|
||||
creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate credentials %v", err)
|
||||
|
|
Loading…
Reference in New Issue