From 3041c94cd099fb50dce8e27c5717feff1315bb2c Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Tue, 24 Feb 2015 12:30:01 -0800 Subject: [PATCH 1/9] Add an implementation of route guide server and client --- examples/route_guide/README.md | 22 + examples/route_guide/client/client.go | 203 ++++++ examples/route_guide/route_guide.pb.go | 419 ++++++++++++ examples/route_guide/route_guide.proto | 118 ++++ examples/route_guide/server/server.go | 221 +++++++ examples/route_guide/testdata/ca.pem | 14 + .../route_guide/testdata/route_guide_db.json | 601 ++++++++++++++++++ examples/route_guide/testdata/server1.key | 15 + examples/route_guide/testdata/server1.pem | 16 + 9 files changed, 1629 insertions(+) create mode 100644 examples/route_guide/README.md create mode 100644 examples/route_guide/client/client.go create mode 100644 examples/route_guide/route_guide.pb.go create mode 100644 examples/route_guide/route_guide.proto create mode 100644 examples/route_guide/server/server.go create mode 100644 examples/route_guide/testdata/ca.pem create mode 100644 examples/route_guide/testdata/route_guide_db.json create mode 100644 examples/route_guide/testdata/server1.key create mode 100644 examples/route_guide/testdata/server1.pem diff --git a/examples/route_guide/README.md b/examples/route_guide/README.md new file mode 100644 index 00000000..0ca747f3 --- /dev/null +++ b/examples/route_guide/README.md @@ -0,0 +1,22 @@ +# Description +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. + +# Run the sample code +To compile and run the server, assuming you are in the root of the route_guide +folder, i.e., .../examples/route_guide/, simply: + +`go run server/server.go` + +Likewise, to run the client: + +`go run client/client.go` + +# Optional command line flags +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 client/client.go -use_tls=true` diff --git a/examples/route_guide/client/client.go b/examples/route_guide/client/client.go new file mode 100644 index 00000000..f0b09d22 --- /dev/null +++ b/examples/route_guide/client/client.go @@ -0,0 +1,203 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "flag" + "io" + "log" + "math/rand" + "net" + "strconv" + "time" + + pb "github.com/wonderfly/grpc-go/examples/route_guide" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +var ( + useTLS = 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") + 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) { + log.Printf("Getting feature for point (%d, %d)", point.Latitude, point.Longitude) + reply, err := client.GetFeature(context.Background(), point) + if err != nil { + log.Fatalf("%v.GetFeatures(_) = _, %v: ", client, err) + return + } + log.Println(reply) +} + +// doListFeatures lists all the features within the given bounding Rectangle. +func doListFeatures(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 + break + } + log.Println(reply) + } + if rpcStatus != io.EOF { + log.Fatalf("%v.ListFeatures(_) = _, %v", client, err) + } +} + +// doRecordRoute sends a sequence of points to server and expects to get a RouteSummary from server. +func doRecordRoute(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() + } + log.Printf("Traversing %d points.", len(points)) + stream, err := client.RecordRoute(context.Background()) + if err != nil { + log.Fatalf("%v.RecordRoute(_) = _, %v", client, err) + } + for _, point := range points { + if err := stream.Send(point); err != nil { + log.Fatalf("%v.Send(%v) = %v", stream, point, err) + } + } + reply, err := stream.CloseAndRecv() + if err != nil { + log.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil) + } + log.Printf("Route summary: %v\n", reply) +} + +// doRouteChat receives a sequence of route notes, while sending notes for various locations. +func doRouteChat(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"}, + } + stream, err := client.RouteChat(context.Background()) + if err != nil { + log.Fatalf("%v.RouteChat(_) = _, %v", client, err) + } + c := make(chan int) + go func() { + for { + in, err := stream.Recv() + if err == io.EOF { + // read done. + c <- 1 + return + } + if err != nil { + log.Fatalf("Failed to receive a note : %v\n", err) + } + log.Printf("Got message %s at point(%d, %d)\n", 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) + } + } + stream.CloseSend() + <-c +} + +func randomPoint() *pb.Point { + lat := (rand.Int31n(180) - 90) * 1e7 + long := (rand.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 { + var sn string + if *tlsServerName != "" { + sn = *tlsServerName + } + var creds credentials.TransportAuthenticator + if *caFile != "" { + var err error + creds, err = credentials.NewClientTLSFromFile(*caFile, sn) + if err != nil { + log.Fatalf("Failed to create TLS credentials %v", err) + } + } else { + creds = credentials.NewClientTLSFromCert(nil, sn) + } + opts = append(opts, grpc.WithClientTLS(creds)) + } + conn, err := grpc.Dial(serverAddr, opts...) + if err != nil { + log.Fatalf("fail to dial: %v", err) + } + defer conn.Close() + client := pb.NewRouteGuideClient(conn) + + // Looking for a valid feature + doGetFeature(client, &pb.Point{409146138, -746188906}) + + // Feature missing. + doGetFeature(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}}) + + // RecordRoute + doRecordRoute(client) + + // RouteChat + doRouteChat(client) +} diff --git a/examples/route_guide/route_guide.pb.go b/examples/route_guide/route_guide.pb.go new file mode 100644 index 00000000..765cf204 --- /dev/null +++ b/examples/route_guide/route_guide.pb.go @@ -0,0 +1,419 @@ +// Code generated by protoc-gen-go. +// source: route_guide.proto +// DO NOT EDIT! + +/* +Package route_guide is a generated protocol buffer package. + +It is generated from these files: + route_guide.proto + +It has these top-level messages: + Point + Rectangle + Feature + RouteNote + RouteSummary +*/ +package route_guide + +import proto "github.com/golang/protobuf/proto" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal + +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +type Point struct { + Latitude int32 `protobuf:"varint,1,opt,name=latitude" json:"latitude,omitempty"` + Longitude int32 `protobuf:"varint,2,opt,name=longitude" json:"longitude,omitempty"` +} + +func (m *Point) Reset() { *m = Point{} } +func (m *Point) String() string { return proto.CompactTextString(m) } +func (*Point) ProtoMessage() {} + +// A latitude-longitude rectangle, represented as two diagonally opposite +// points "lo" and "hi". +type Rectangle struct { + // One corner of the rectangle. + Lo *Point `protobuf:"bytes,1,opt,name=lo" json:"lo,omitempty"` + // The other corner of the rectangle. + Hi *Point `protobuf:"bytes,2,opt,name=hi" json:"hi,omitempty"` +} + +func (m *Rectangle) Reset() { *m = Rectangle{} } +func (m *Rectangle) String() string { return proto.CompactTextString(m) } +func (*Rectangle) ProtoMessage() {} + +func (m *Rectangle) GetLo() *Point { + if m != nil { + return m.Lo + } + return nil +} + +func (m *Rectangle) GetHi() *Point { + if m != nil { + return m.Hi + } + return nil +} + +// A feature names something at a given point. +// +// If a feature could not be named, the name is empty. +type Feature struct { + // The name of the feature. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The point where the feature is detected. + Location *Point `protobuf:"bytes,2,opt,name=location" json:"location,omitempty"` +} + +func (m *Feature) Reset() { *m = Feature{} } +func (m *Feature) String() string { return proto.CompactTextString(m) } +func (*Feature) ProtoMessage() {} + +func (m *Feature) GetLocation() *Point { + if m != nil { + return m.Location + } + return nil +} + +// A RouteNote is a message sent while at a given point. +type RouteNote struct { + // The location from which the message is sent. + Location *Point `protobuf:"bytes,1,opt,name=location" json:"location,omitempty"` + // The message to be sent. + Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` +} + +func (m *RouteNote) Reset() { *m = RouteNote{} } +func (m *RouteNote) String() string { return proto.CompactTextString(m) } +func (*RouteNote) ProtoMessage() {} + +func (m *RouteNote) GetLocation() *Point { + if m != nil { + return m.Location + } + return nil +} + +// A RouteSummary is received in response to a RecordRoute rpc. +// +// It contains the number of individual points received, the number of +// detected features, and the total distance covered as the cumulative sum of +// the distance between each point. +type RouteSummary struct { + // The number of points received. + PointCount int32 `protobuf:"varint,1,opt,name=point_count" json:"point_count,omitempty"` + // The number of known features passed while traversing the route. + FeatureCount int32 `protobuf:"varint,2,opt,name=feature_count" json:"feature_count,omitempty"` + // The distance covered in metres. + Distance int32 `protobuf:"varint,3,opt,name=distance" json:"distance,omitempty"` + // The duration of the traversal in seconds. + ElapsedTime int32 `protobuf:"varint,4,opt,name=elapsed_time" json:"elapsed_time,omitempty"` +} + +func (m *RouteSummary) Reset() { *m = RouteSummary{} } +func (m *RouteSummary) String() string { return proto.CompactTextString(m) } +func (*RouteSummary) ProtoMessage() {} + +func init() { +} + +// Client API for RouteGuide service + +type RouteGuideClient interface { + // A simple RPC. + // + // Obtains the feature at a given position. + GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) +} + +type routeGuideClient struct { + cc *grpc.ClientConn +} + +func NewRouteGuideClient(cc *grpc.ClientConn) RouteGuideClient { + return &routeGuideClient{cc} +} + +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...) + if err != nil { + return nil, err + } + return out, nil +} + +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...) + if err != nil { + return nil, err + } + x := &routeGuideListFeaturesClient{stream} + if err := x.ClientStream.SendProto(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type RouteGuide_ListFeaturesClient interface { + Recv() (*Feature, error) + grpc.ClientStream +} + +type routeGuideListFeaturesClient struct { + grpc.ClientStream +} + +func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) { + m := new(Feature) + if err := x.ClientStream.RecvProto(m); err != nil { + return nil, err + } + return m, nil +} + +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...) + if err != nil { + return nil, err + } + x := &routeGuideRecordRouteClient{stream} + return x, nil +} + +type RouteGuide_RecordRouteClient interface { + Send(*Point) error + CloseAndRecv() (*RouteSummary, error) + grpc.ClientStream +} + +type routeGuideRecordRouteClient struct { + grpc.ClientStream +} + +func (x *routeGuideRecordRouteClient) Send(m *Point) error { + return x.ClientStream.SendProto(m) +} + +func (x *routeGuideRecordRouteClient) CloseAndRecv() (*RouteSummary, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(RouteSummary) + if err := x.ClientStream.RecvProto(m); err != nil { + return nil, err + } + return m, nil +} + +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...) + if err != nil { + return nil, err + } + x := &routeGuideRouteChatClient{stream} + return x, nil +} + +type RouteGuide_RouteChatClient interface { + Send(*RouteNote) error + Recv() (*RouteNote, error) + grpc.ClientStream +} + +type routeGuideRouteChatClient struct { + grpc.ClientStream +} + +func (x *routeGuideRouteChatClient) Send(m *RouteNote) error { + return x.ClientStream.SendProto(m) +} + +func (x *routeGuideRouteChatClient) Recv() (*RouteNote, error) { + m := new(RouteNote) + if err := x.ClientStream.RecvProto(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for RouteGuide service + +type RouteGuideServer interface { + // A simple RPC. + // + // Obtains the feature at a given position. + GetFeature(context.Context, *Point) (*Feature, error) + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + RecordRoute(RouteGuide_RecordRouteServer) error + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + RouteChat(RouteGuide_RouteChatServer) error +} + +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) { + in := new(Point) + if err := proto.Unmarshal(buf, in); err != nil { + return nil, err + } + out, err := srv.(RouteGuideServer).GetFeature(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + +func _RouteGuide_ListFeatures_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(Rectangle) + if err := stream.RecvProto(m); err != nil { + return err + } + return srv.(RouteGuideServer).ListFeatures(m, &routeGuideListFeaturesServer{stream}) +} + +type RouteGuide_ListFeaturesServer interface { + Send(*Feature) error + grpc.ServerStream +} + +type routeGuideListFeaturesServer struct { + grpc.ServerStream +} + +func (x *routeGuideListFeaturesServer) Send(m *Feature) error { + return x.ServerStream.SendProto(m) +} + +func _RouteGuide_RecordRoute_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(RouteGuideServer).RecordRoute(&routeGuideRecordRouteServer{stream}) +} + +type RouteGuide_RecordRouteServer interface { + SendAndClose(*RouteSummary) error + Recv() (*Point, error) + grpc.ServerStream +} + +type routeGuideRecordRouteServer struct { + grpc.ServerStream +} + +func (x *routeGuideRecordRouteServer) SendAndClose(m *RouteSummary) error { + return x.ServerStream.SendProto(m) +} + +func (x *routeGuideRecordRouteServer) Recv() (*Point, error) { + m := new(Point) + if err := x.ServerStream.RecvProto(m); err != nil { + return nil, err + } + return m, nil +} + +func _RouteGuide_RouteChat_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(RouteGuideServer).RouteChat(&routeGuideRouteChatServer{stream}) +} + +type RouteGuide_RouteChatServer interface { + Send(*RouteNote) error + Recv() (*RouteNote, error) + grpc.ServerStream +} + +type routeGuideRouteChatServer struct { + grpc.ServerStream +} + +func (x *routeGuideRouteChatServer) Send(m *RouteNote) error { + return x.ServerStream.SendProto(m) +} + +func (x *routeGuideRouteChatServer) Recv() (*RouteNote, error) { + m := new(RouteNote) + if err := x.ServerStream.RecvProto(m); err != nil { + return nil, err + } + return m, nil +} + +var _RouteGuide_serviceDesc = grpc.ServiceDesc{ + ServiceName: "route_guide.RouteGuide", + HandlerType: (*RouteGuideServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetFeature", + Handler: _RouteGuide_GetFeature_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "ListFeatures", + Handler: _RouteGuide_ListFeatures_Handler, + ServerStreams: true, + }, + { + StreamName: "RecordRoute", + Handler: _RouteGuide_RecordRoute_Handler, + ClientStreams: true, + }, + { + StreamName: "RouteChat", + Handler: _RouteGuide_RouteChat_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, +} diff --git a/examples/route_guide/route_guide.proto b/examples/route_guide/route_guide.proto new file mode 100644 index 00000000..ba09c5eb --- /dev/null +++ b/examples/route_guide/route_guide.proto @@ -0,0 +1,118 @@ +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package route_guide; + +// Interface exported by the server. +service RouteGuide { + // A simple RPC. + // + // Obtains the feature at a given position. + rpc GetFeature(Point) returns (Feature) {} + + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature) {} + + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary) {} + + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} +} + +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + int32 latitude = 1; + int32 longitude = 2; +} + +// A latitude-longitude rectangle, represented as two diagonally opposite +// points "lo" and "hi". +message Rectangle { + // One corner of the rectangle. + Point lo = 1; + + // The other corner of the rectangle. + Point hi = 2; +} + +// A feature names something at a given point. +// +// If a feature could not be named, the name is empty. +message Feature { + // The name of the feature. + string name = 1; + + // The point where the feature is detected. + Point location = 2; +} + +// A RouteNote is a message sent while at a given point. +message RouteNote { + // The location from which the message is sent. + Point location = 1; + + // The message to be sent. + string message = 2; +} + +// A RouteSummary is received in response to a RecordRoute rpc. +// +// It contains the number of individual points received, the number of +// detected features, and the total distance covered as the cumulative sum of +// the distance between each point. +message RouteSummary { + // The number of points received. + int32 point_count = 1; + + // The number of known features passed while traversing the route. + int32 feature_count = 2; + + // The distance covered in metres. + int32 distance = 3; + + // The duration of the traversal in seconds. + int32 elapsed_time = 4; +} diff --git a/examples/route_guide/server/server.go b/examples/route_guide/server/server.go new file mode 100644 index 00000000..4adc1232 --- /dev/null +++ b/examples/route_guide/server/server.go @@ -0,0 +1,221 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package main + +import ( + "encoding/json" + "flag" + "io" + "io/ioutil" + "log" + "math" + "net" + "strconv" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + + "google.golang.org/grpc/credentials" + + pb "github.com/wonderfly/grpc-go/examples/route_guide" +) + +var ( + useTLS = 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") + port = flag.Int("port", 10000, "The server port") +) + +type routeGuideServer struct { + savedFeatures []pb.Feature + routeNotes map[pb.Point][]*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 + } + } + // No feature was found, return an unnamed feature + return &pb.Feature{"", point}, nil +} + +// 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 { + return err + } + } + } + return nil +} + +// RecordRoute records a route composited of a sequence of points. +// +// It gets a stream of points, and responds with statistics about the "trip": +// number of points, number of known features visited, total distance traveled, and +// total time spent. +func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error { + var pointCount, featureCount, distance int32 + var lastPoint *pb.Point + startTime := time.Now() + for { + point, err := stream.Recv() + if err == io.EOF { + endTime := time.Now() + return stream.SendAndClose(&pb.RouteSummary{ + PointCount: pointCount, + FeatureCount: featureCount, + Distance: distance, + ElapsedTime: int32(endTime.Sub(startTime).Seconds()), + }) + } + if err != nil { + return err + } + pointCount++ + for _, feature := range s.savedFeatures { + if *(feature.Location) == *point { + featureCount++ + } + } + if lastPoint != nil { + distance += calcDistance(lastPoint, point) + } + lastPoint = point + } +} + +// RouteChat receives a stream of message/location pairs, and responds with a stream of all +// previous messages at each of those locations. +func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error { + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + point := *(in.Location) + if _, present := s.routeNotes[point]; !present { + s.routeNotes[point] = []*pb.RouteNote{in} + + } else { + s.routeNotes[point] = append(s.routeNotes[point], in) + } + for _, note := range s.routeNotes[point] { + if err := stream.Send(note); err != nil { + return err + } + } + } +} + +// loadFeatures loads features from a JSON file. +func (s *routeGuideServer) loadFeatures(filePath string) { + file, err := ioutil.ReadFile(filePath) + if err != nil { + log.Fatal("Failed to load default features: %v\n", err) + } + if err := json.Unmarshal(file, &(s.savedFeatures)); err != nil { + log.Fatal("Failed to load default features: %v\n", err) + } +} + +func toRadians(num float64) float64 { + return num * math.Pi / float64(180) +} + +func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 { + const COORD_FACTOR 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 + φ1 := toRadians(lat1) + φ2 := toRadians(lat2) + Δφ := toRadians(lat2 - lat1) + Δλ := toRadians(lon2 - lon1) + + a := math.Sin(Δφ/2)*math.Sin(Δφ/2) + + math.Cos(φ1)*math.Cos(φ2)* + math.Sin(Δλ/2)*math.Sin(Δλ/2) + c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a)) + + distance := R * c + return int32(distance) +} + +func newServer() *routeGuideServer { + s := new(routeGuideServer) + s.loadFeatures(*jsonDBFile) + s.routeNotes = make(map[pb.Point][]*pb.RouteNote, 0) + return s +} + +func main() { + flag.Parse() + p := strconv.Itoa(*port) + lis, err := net.Listen("tcp", ":"+p) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + grpcServer := grpc.NewServer() + pb.RegisterRouteGuideServer(grpcServer, newServer()) + if *useTLS { + creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile) + if err != nil { + log.Fatalf("Failed to generate credentials %v", err) + } + grpcServer.Serve(creds.NewListener(lis)) + } else { + grpcServer.Serve(lis) + } +} diff --git a/examples/route_guide/testdata/ca.pem b/examples/route_guide/testdata/ca.pem new file mode 100644 index 00000000..999da897 --- /dev/null +++ b/examples/route_guide/testdata/ca.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICIzCCAYwCCQCFTbF7XNSvvjANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzE3MjMxNzUxWhcNMjQw +NzE0MjMxNzUxWjBWMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEh +MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0 +Y2EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMBA3wVeTGHZR1Rye/i+J8a2 +cu5gXwFV6TnObzGM7bLFCO5i9v4mLo4iFzPsHmWDUxKS3Y8iXbu0eYBlLoNY0lSv +xDx33O+DuwMmVN+DzSD+Eod9zfvwOWHsazYCZT2PhNxnVWIuJXViY4JAHUGodjx+ +QAi6yCAurUZGvYXGgZSBAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQoQVD8bwdtWJ +AniGBwcCfqYyH+/KpA10AcebJVVTyYbYvI9Q8d6RSVu4PZy9OALHR/QrWBdYTAyz +fNAmc2cmdkSRJzjhIaOstnQy1J+Fk0T9XyvQtq499yFbq9xogUVlEGH62xP6vH0Y +5ukK//dCPAzA11YuX2rnex0JhuTQfcI= +-----END CERTIFICATE----- diff --git a/examples/route_guide/testdata/route_guide_db.json b/examples/route_guide/testdata/route_guide_db.json new file mode 100644 index 00000000..9d6a980a --- /dev/null +++ b/examples/route_guide/testdata/route_guide_db.json @@ -0,0 +1,601 @@ +[{ + "location": { + "latitude": 407838351, + "longitude": -746143763 + }, + "name": "Patriots Path, Mendham, NJ 07945, USA" +}, { + "location": { + "latitude": 408122808, + "longitude": -743999179 + }, + "name": "101 New Jersey 10, Whippany, NJ 07981, USA" +}, { + "location": { + "latitude": 413628156, + "longitude": -749015468 + }, + "name": "U.S. 6, Shohola, PA 18458, USA" +}, { + "location": { + "latitude": 419999544, + "longitude": -740371136 + }, + "name": "5 Conners Road, Kingston, NY 12401, USA" +}, { + "location": { + "latitude": 414008389, + "longitude": -743951297 + }, + "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" +}, { + "location": { + "latitude": 419611318, + "longitude": -746524769 + }, + "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" +}, { + "location": { + "latitude": 406109563, + "longitude": -742186778 + }, + "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" +}, { + "location": { + "latitude": 416802456, + "longitude": -742370183 + }, + "name": "352 South Mountain Road, Wallkill, NY 12589, USA" +}, { + "location": { + "latitude": 412950425, + "longitude": -741077389 + }, + "name": "Bailey Turn Road, Harriman, NY 10926, USA" +}, { + "location": { + "latitude": 412144655, + "longitude": -743949739 + }, + "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" +}, { + "location": { + "latitude": 415736605, + "longitude": -742847522 + }, + "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" +}, { + "location": { + "latitude": 413843930, + "longitude": -740501726 + }, + "name": "162 Merrill Road, Highland Mills, NY 10930, USA" +}, { + "location": { + "latitude": 410873075, + "longitude": -744459023 + }, + "name": "Clinton Road, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 412346009, + "longitude": -744026814 + }, + "name": "16 Old Brook Lane, Warwick, NY 10990, USA" +}, { + "location": { + "latitude": 402948455, + "longitude": -747903913 + }, + "name": "3 Drake Lane, Pennington, NJ 08534, USA" +}, { + "location": { + "latitude": 406337092, + "longitude": -740122226 + }, + "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" +}, { + "location": { + "latitude": 406421967, + "longitude": -747727624 + }, + "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" +}, { + "location": { + "latitude": 416318082, + "longitude": -749677716 + }, + "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" +}, { + "location": { + "latitude": 415301720, + "longitude": -748416257 + }, + "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" +}, { + "location": { + "latitude": 402647019, + "longitude": -747071791 + }, + "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" +}, { + "location": { + "latitude": 412567807, + "longitude": -741058078 + }, + "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" +}, { + "location": { + "latitude": 416855156, + "longitude": -744420597 + }, + "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" +}, { + "location": { + "latitude": 404663628, + "longitude": -744820157 + }, + "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" +}, { + "location": { + "latitude": 407113723, + "longitude": -749746483 + }, + "name": "" +}, { + "location": { + "latitude": 402133926, + "longitude": -743613249 + }, + "name": "" +}, { + "location": { + "latitude": 400273442, + "longitude": -741220915 + }, + "name": "" +}, { + "location": { + "latitude": 411236786, + "longitude": -744070769 + }, + "name": "" +}, { + "location": { + "latitude": 411633782, + "longitude": -746784970 + }, + "name": "211-225 Plains Road, Augusta, NJ 07822, USA" +}, { + "location": { + "latitude": 415830701, + "longitude": -742952812 + }, + "name": "" +}, { + "location": { + "latitude": 413447164, + "longitude": -748712898 + }, + "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" +}, { + "location": { + "latitude": 405047245, + "longitude": -749800722 + }, + "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" +}, { + "location": { + "latitude": 418858923, + "longitude": -746156790 + }, + "name": "" +}, { + "location": { + "latitude": 417951888, + "longitude": -748484944 + }, + "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" +}, { + "location": { + "latitude": 407033786, + "longitude": -743977337 + }, + "name": "26 East 3rd Street, New Providence, NJ 07974, USA" +}, { + "location": { + "latitude": 417548014, + "longitude": -740075041 + }, + "name": "" +}, { + "location": { + "latitude": 410395868, + "longitude": -744972325 + }, + "name": "" +}, { + "location": { + "latitude": 404615353, + "longitude": -745129803 + }, + "name": "" +}, { + "location": { + "latitude": 406589790, + "longitude": -743560121 + }, + "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" +}, { + "location": { + "latitude": 414653148, + "longitude": -740477477 + }, + "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" +}, { + "location": { + "latitude": 405957808, + "longitude": -743255336 + }, + "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" +}, { + "location": { + "latitude": 411733589, + "longitude": -741648093 + }, + "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" +}, { + "location": { + "latitude": 412676291, + "longitude": -742606606 + }, + "name": "1270 Lakes Road, Monroe, NY 10950, USA" +}, { + "location": { + "latitude": 409224445, + "longitude": -748286738 + }, + "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" +}, { + "location": { + "latitude": 406523420, + "longitude": -742135517 + }, + "name": "652 Garden Street, Elizabeth, NJ 07202, USA" +}, { + "location": { + "latitude": 401827388, + "longitude": -740294537 + }, + "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" +}, { + "location": { + "latitude": 410564152, + "longitude": -743685054 + }, + "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 408472324, + "longitude": -740726046 + }, + "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" +}, { + "location": { + "latitude": 412452168, + "longitude": -740214052 + }, + "name": "5 White Oak Lane, Stony Point, NY 10980, USA" +}, { + "location": { + "latitude": 409146138, + "longitude": -746188906 + }, + "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" +}, { + "location": { + "latitude": 404701380, + "longitude": -744781745 + }, + "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 409642566, + "longitude": -746017679 + }, + "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" +}, { + "location": { + "latitude": 408031728, + "longitude": -748645385 + }, + "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" +}, { + "location": { + "latitude": 413700272, + "longitude": -742135189 + }, + "name": "367 Prospect Road, Chester, NY 10918, USA" +}, { + "location": { + "latitude": 404310607, + "longitude": -740282632 + }, + "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" +}, { + "location": { + "latitude": 409319800, + "longitude": -746201391 + }, + "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" +}, { + "location": { + "latitude": 406685311, + "longitude": -742108603 + }, + "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" +}, { + "location": { + "latitude": 419018117, + "longitude": -749142781 + }, + "name": "43 Dreher Road, Roscoe, NY 12776, USA" +}, { + "location": { + "latitude": 412856162, + "longitude": -745148837 + }, + "name": "Swan Street, Pine Island, NY 10969, USA" +}, { + "location": { + "latitude": 416560744, + "longitude": -746721964 + }, + "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" +}, { + "location": { + "latitude": 405314270, + "longitude": -749836354 + }, + "name": "" +}, { + "location": { + "latitude": 414219548, + "longitude": -743327440 + }, + "name": "" +}, { + "location": { + "latitude": 415534177, + "longitude": -742900616 + }, + "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" +}, { + "location": { + "latitude": 406898530, + "longitude": -749127080 + }, + "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" +}, { + "location": { + "latitude": 407586880, + "longitude": -741670168 + }, + "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" +}, { + "location": { + "latitude": 400106455, + "longitude": -742870190 + }, + "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" +}, { + "location": { + "latitude": 400066188, + "longitude": -746793294 + }, + "name": "" +}, { + "location": { + "latitude": 418803880, + "longitude": -744102673 + }, + "name": "40 Mountain Road, Napanoch, NY 12458, USA" +}, { + "location": { + "latitude": 414204288, + "longitude": -747895140 + }, + "name": "" +}, { + "location": { + "latitude": 414777405, + "longitude": -740615601 + }, + "name": "" +}, { + "location": { + "latitude": 415464475, + "longitude": -747175374 + }, + "name": "48 North Road, Forestburgh, NY 12777, USA" +}, { + "location": { + "latitude": 404062378, + "longitude": -746376177 + }, + "name": "" +}, { + "location": { + "latitude": 405688272, + "longitude": -749285130 + }, + "name": "" +}, { + "location": { + "latitude": 400342070, + "longitude": -748788996 + }, + "name": "" +}, { + "location": { + "latitude": 401809022, + "longitude": -744157964 + }, + "name": "" +}, { + "location": { + "latitude": 404226644, + "longitude": -740517141 + }, + "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" +}, { + "location": { + "latitude": 410322033, + "longitude": -747871659 + }, + "name": "" +}, { + "location": { + "latitude": 407100674, + "longitude": -747742727 + }, + "name": "" +}, { + "location": { + "latitude": 418811433, + "longitude": -741718005 + }, + "name": "213 Bush Road, Stone Ridge, NY 12484, USA" +}, { + "location": { + "latitude": 415034302, + "longitude": -743850945 + }, + "name": "" +}, { + "location": { + "latitude": 411349992, + "longitude": -743694161 + }, + "name": "" +}, { + "location": { + "latitude": 404839914, + "longitude": -744759616 + }, + "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 414638017, + "longitude": -745957854 + }, + "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" +}, { + "location": { + "latitude": 412127800, + "longitude": -740173578 + }, + "name": "" +}, { + "location": { + "latitude": 401263460, + "longitude": -747964303 + }, + "name": "" +}, { + "location": { + "latitude": 412843391, + "longitude": -749086026 + }, + "name": "" +}, { + "location": { + "latitude": 418512773, + "longitude": -743067823 + }, + "name": "" +}, { + "location": { + "latitude": 404318328, + "longitude": -740835638 + }, + "name": "42-102 Main Street, Belford, NJ 07718, USA" +}, { + "location": { + "latitude": 419020746, + "longitude": -741172328 + }, + "name": "" +}, { + "location": { + "latitude": 404080723, + "longitude": -746119569 + }, + "name": "" +}, { + "location": { + "latitude": 401012643, + "longitude": -744035134 + }, + "name": "" +}, { + "location": { + "latitude": 404306372, + "longitude": -741079661 + }, + "name": "" +}, { + "location": { + "latitude": 403966326, + "longitude": -748519297 + }, + "name": "" +}, { + "location": { + "latitude": 405002031, + "longitude": -748407866 + }, + "name": "" +}, { + "location": { + "latitude": 409532885, + "longitude": -742200683 + }, + "name": "" +}, { + "location": { + "latitude": 416851321, + "longitude": -742674555 + }, + "name": "" +}, { + "location": { + "latitude": 406411633, + "longitude": -741722051 + }, + "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" +}, { + "location": { + "latitude": 413069058, + "longitude": -744597778 + }, + "name": "261 Van Sickle Road, Goshen, NY 10924, USA" +}, { + "location": { + "latitude": 418465462, + "longitude": -746859398 + }, + "name": "" +}, { + "location": { + "latitude": 411733222, + "longitude": -744228360 + }, + "name": "" +}, { + "location": { + "latitude": 410248224, + "longitude": -747127767 + }, + "name": "3 Hasta Way, Newton, NJ 07860, USA" +}] diff --git a/examples/route_guide/testdata/server1.key b/examples/route_guide/testdata/server1.key new file mode 100644 index 00000000..ed00cd50 --- /dev/null +++ b/examples/route_guide/testdata/server1.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQDhwxUnKCwlSaWAwzOB2LSHVegJHv7DDWminTg4wzLLsf+LQ8nZ +bpjfn5vgIzxCuRh4Rp9QYM5FhfrJX9wcYawP/HTbJ7p7LVQO2QYAP+akMTHxgKuM +BzVV++3wWToKfVZUjFX8nfTfGMGwWAHJDnlEGnU4tl9UujoCV4ENJtzFoQIDAQAB +AoGAJ+6hpzNr24yTQZtFWQpDpEyFplddKJMOxDya3S9ppK3vTWrIITV2xNcucw7I +ceTbdyrGsyjsU0/HdCcIf9ym2jfmGLUwmyhltKVw0QYcFB0XLkc0nI5YvEYoeVDg +omZIXn1E3EW+sSIWSbkMu9bY2kstKXR2UZmMgWDtmBEPMaECQQD6yT4TAZM5hGBb +ciBKgMUP6PwOhPhOMPIvijO50Aiu6iuCV88l1QIy38gWVhxjNrq6P346j4IBg+kB +9alwpCODAkEA5nSnm9k6ykYeQWNS0fNWiRinCdl23A7usDGSuKKlm019iomJ/Rgd +MKDOp0q/2OostbteOWM2MRFf4jMH3wyVCwJAfAdjJ8szoNKTRSagSbh9vWygnB2v +IByc6l4TTuZQJRGzCveafz9lovuB3WohCABdQRd9ukCXL2CpsEpqzkafOQJAJUjc +USedDlq3zGZwYM1Yw8d8RuirBUFZNqJelYai+nRYClDkRVFgb5yksoYycbq5TxGo +VeqKOvgPpj4RWPHlLwJAGUMk3bqT91xBUCnLRs/vfoCpHpg6eywQTBDAV6xkyz4a +RH3I7/+yj3ZxR2JoWHgUwZ7lZk1VnhffFye7SBXyag== +-----END RSA PRIVATE KEY----- diff --git a/examples/route_guide/testdata/server1.pem b/examples/route_guide/testdata/server1.pem new file mode 100644 index 00000000..8e582e57 --- /dev/null +++ b/examples/route_guide/testdata/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5 +MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl +c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs +JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO +RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30 +3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL +BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6 +b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ +KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS +wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e +aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s= +-----END CERTIFICATE----- From 7ffe7b2473db52135abb16c6e9ef95cf3e33f887 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Tue, 24 Feb 2015 12:40:48 -0800 Subject: [PATCH 2/9] Use the golang import path --- examples/route_guide/client/client.go | 2 +- examples/route_guide/server/server.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/route_guide/client/client.go b/examples/route_guide/client/client.go index f0b09d22..be40d6a8 100644 --- a/examples/route_guide/client/client.go +++ b/examples/route_guide/client/client.go @@ -42,10 +42,10 @@ import ( "strconv" "time" - pb "github.com/wonderfly/grpc-go/examples/route_guide" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" + pb "google.golang.org/grpc/examples/route_guide" ) var ( diff --git a/examples/route_guide/server/server.go b/examples/route_guide/server/server.go index 4adc1232..876b8880 100644 --- a/examples/route_guide/server/server.go +++ b/examples/route_guide/server/server.go @@ -49,7 +49,7 @@ import ( "google.golang.org/grpc/credentials" - pb "github.com/wonderfly/grpc-go/examples/route_guide" + pb "google.golang.org/grpc/examples/route_guide" ) var ( From a94c062d9b02caf110e996bd0c4f4b9eb700529a Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Tue, 24 Feb 2015 12:41:18 -0800 Subject: [PATCH 3/9] Fix README --- examples/route_guide/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/route_guide/README.md b/examples/route_guide/README.md index 0ca747f3..748e9058 100644 --- a/examples/route_guide/README.md +++ b/examples/route_guide/README.md @@ -19,4 +19,7 @@ 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` + +and + `go run client/client.go -use_tls=true` From 8fd7702f97ea3a8e928366e46b9df4b7951e93dd Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Wed, 25 Feb 2015 12:08:12 -0800 Subject: [PATCH 4/9] Make route guide implementation more go idiomatic --- examples/route_guide/README.md | 6 +- examples/route_guide/client/client.go | 104 +++++++++--------- .../route_guide/{ => proto}/route_guide.pb.go | 36 +++--- .../route_guide/{ => proto}/route_guide.proto | 5 +- examples/route_guide/server/server.go | 83 ++++++++------ 5 files changed, 128 insertions(+), 106 deletions(-) rename examples/route_guide/{ => proto}/route_guide.pb.go (91%) rename examples/route_guide/{ => proto}/route_guide.proto (97%) diff --git a/examples/route_guide/README.md b/examples/route_guide/README.md index 748e9058..57b78c5c 100644 --- a/examples/route_guide/README.md +++ b/examples/route_guide/README.md @@ -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` diff --git a/examples/route_guide/client/client.go b/examples/route_guide/client/client.go index be40d6a8..70469677 100644 --- a/examples/route_guide/client/client.go +++ b/examples/route_guide/client/client.go @@ -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) } diff --git a/examples/route_guide/route_guide.pb.go b/examples/route_guide/proto/route_guide.pb.go similarity index 91% rename from examples/route_guide/route_guide.pb.go rename to examples/route_guide/proto/route_guide.pb.go index 765cf204..93c167ad 100644 --- a/examples/route_guide/route_guide.pb.go +++ b/examples/route_guide/proto/route_guide.pb.go @@ -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{ { diff --git a/examples/route_guide/route_guide.proto b/examples/route_guide/proto/route_guide.proto similarity index 97% rename from examples/route_guide/route_guide.proto rename to examples/route_guide/proto/route_guide.proto index ba09c5eb..5ea4fcf5 100644 --- a/examples/route_guide/route_guide.proto +++ b/examples/route_guide/proto/route_guide.proto @@ -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. diff --git a/examples/route_guide/server/server.go b/examples/route_guide/server/server.go index 876b8880..803b9c31 100644 --- a/examples/route_guide/server/server.go +++ b/examples/route_guide/server/server.go @@ -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) From a4b32d7c6c89b3015a2fad09e998595db1262b0f Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Wed, 25 Feb 2015 12:11:38 -0800 Subject: [PATCH 5/9] Use Sprintf instead of concatenation --- examples/route_guide/server/server.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/route_guide/server/server.go b/examples/route_guide/server/server.go index 803b9c31..d2691487 100644 --- a/examples/route_guide/server/server.go +++ b/examples/route_guide/server/server.go @@ -46,7 +46,6 @@ import ( "log" "math" "net" - "strconv" "time" "golang.org/x/net/context" @@ -223,8 +222,7 @@ func newServer() *routeGuideServer { func main() { flag.Parse() - p := strconv.Itoa(*port) - lis, err := net.Listen("tcp", ":"+p) + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) if err != nil { log.Fatalf("failed to listen: %v", err) } From 401343c0dc047f9229912f41d5e4494fc2e21ee5 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Wed, 25 Feb 2015 15:10:15 -0800 Subject: [PATCH 6/9] Fix typos in comments --- examples/route_guide/README.md | 2 +- examples/route_guide/client/client.go | 6 +++--- examples/route_guide/server/server.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/route_guide/README.md b/examples/route_guide/README.md index 57b78c5c..3d73948f 100644 --- a/examples/route_guide/README.md +++ b/examples/route_guide/README.md @@ -1,5 +1,5 @@ # Description -The route guide server and client demonstrates how to use grpc go libraries to +The route guide server and client demonstrate 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 proto/route_guide.proto. diff --git a/examples/route_guide/client/client.go b/examples/route_guide/client/client.go index 70469677..a96361ff 100644 --- a/examples/route_guide/client/client.go +++ b/examples/route_guide/client/client.go @@ -31,7 +31,7 @@ * */ -// Package main implements a simple grpc client that demonstrates how to use grpc go libraries +// 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. @@ -127,13 +127,13 @@ func runRouteChat(client pb.RouteGuideClient) { if err != nil { log.Fatalf("%v.RouteChat(_) = _, %v", client, err) } - waitc := make(chan int) + waitc := make(chan struct{}) go func() { for { in, err := stream.Recv() if err == io.EOF { // read done. - waitc <- 1 + close(waitc) return } if err != nil { diff --git a/examples/route_guide/server/server.go b/examples/route_guide/server/server.go index d2691487..7fa8d861 100644 --- a/examples/route_guide/server/server.go +++ b/examples/route_guide/server/server.go @@ -31,7 +31,7 @@ * */ -// Package main implements a simple grpc server that demonstrates how to use grpc go libraries +// 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. From d58af39eadb12fa9935125a4d8cfbd4cf9cd1b73 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Wed, 25 Feb 2015 15:43:26 -0800 Subject: [PATCH 7/9] Change tls_server_name to server_host_override and improve README --- examples/route_guide/README.md | 16 ++++++++++++---- examples/route_guide/client/client.go | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/examples/route_guide/README.md b/examples/route_guide/README.md index 3d73948f..63ec0bbc 100644 --- a/examples/route_guide/README.md +++ b/examples/route_guide/README.md @@ -8,18 +8,26 @@ See the definition of the route guide service in proto/route_guide.proto. To compile and run the server, assuming you are in the root of the route_guide folder, i.e., .../examples/route_guide/, simply: -`go run server/server.go` +```sh +$ go run server/server.go +``` Likewise, to run the client: -`go run client/client.go` +```sh +$ go run client/client.go +``` # Optional command line flags 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 -tls=true` +```sh +go run server/server.go -tls=true +``` and -`go run client/client.go -tls=true` +```sh +go run client/client.go -tls=true +``` diff --git a/examples/route_guide/client/client.go b/examples/route_guide/client/client.go index a96361ff..abd93f7b 100644 --- a/examples/route_guide/client/client.go +++ b/examples/route_guide/client/client.go @@ -54,7 +54,7 @@ var ( 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") 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") + tlsServerName = flag.String("server_host_override", "x.test.youtube.com", "The server name use to verify the hostname returned by TLS handshake") ) // printFeature gets the feature for the given point. From 9c8fb9517b610f0517de28ab9fea1666c812768e Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Wed, 25 Feb 2015 15:45:56 -0800 Subject: [PATCH 8/9] Fix README --- examples/route_guide/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/route_guide/README.md b/examples/route_guide/README.md index 63ec0bbc..cb299a4a 100644 --- a/examples/route_guide/README.md +++ b/examples/route_guide/README.md @@ -23,11 +23,11 @@ The server and client both take optional command line flags. For example, the client and server run without TLS by default. To enable TSL: ```sh -go run server/server.go -tls=true +$ go run server/server.go -tls=true ``` and ```sh -go run client/client.go -tls=true +$ go run client/client.go -tls=true ``` From 385ff1a296341cda61cd565781d7dd9995c798e6 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Wed, 25 Feb 2015 15:52:16 -0800 Subject: [PATCH 9/9] Remove generated code from source --- examples/route_guide/proto/route_guide.pb.go | 419 ------------------- 1 file changed, 419 deletions(-) delete mode 100644 examples/route_guide/proto/route_guide.pb.go diff --git a/examples/route_guide/proto/route_guide.pb.go b/examples/route_guide/proto/route_guide.pb.go deleted file mode 100644 index 93c167ad..00000000 --- a/examples/route_guide/proto/route_guide.pb.go +++ /dev/null @@ -1,419 +0,0 @@ -// Code generated by protoc-gen-go. -// source: proto/route_guide.proto -// DO NOT EDIT! - -/* -Package proto is a generated protocol buffer package. - -It is generated from these files: - proto/route_guide.proto - -It has these top-level messages: - Point - Rectangle - Feature - RouteNote - RouteSummary -*/ -package proto - -import proto1 "github.com/golang/protobuf/proto" - -import ( - context "golang.org/x/net/context" - grpc "google.golang.org/grpc" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// Reference imports to suppress errors if they are not otherwise used. -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). -// Latitudes should be in the range +/- 90 degrees and longitude should be in -// the range +/- 180 degrees (inclusive). -type Point struct { - Latitude int32 `protobuf:"varint,1,opt,name=latitude" json:"latitude,omitempty"` - Longitude int32 `protobuf:"varint,2,opt,name=longitude" json:"longitude,omitempty"` -} - -func (m *Point) Reset() { *m = Point{} } -func (m *Point) String() string { return proto1.CompactTextString(m) } -func (*Point) ProtoMessage() {} - -// A latitude-longitude rectangle, represented as two diagonally opposite -// points "lo" and "hi". -type Rectangle struct { - // One corner of the rectangle. - Lo *Point `protobuf:"bytes,1,opt,name=lo" json:"lo,omitempty"` - // The other corner of the rectangle. - Hi *Point `protobuf:"bytes,2,opt,name=hi" json:"hi,omitempty"` -} - -func (m *Rectangle) Reset() { *m = Rectangle{} } -func (m *Rectangle) String() string { return proto1.CompactTextString(m) } -func (*Rectangle) ProtoMessage() {} - -func (m *Rectangle) GetLo() *Point { - if m != nil { - return m.Lo - } - return nil -} - -func (m *Rectangle) GetHi() *Point { - if m != nil { - return m.Hi - } - return nil -} - -// A feature names something at a given point. -// -// If a feature could not be named, the name is empty. -type Feature struct { - // The name of the feature. - Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - // The point where the feature is detected. - Location *Point `protobuf:"bytes,2,opt,name=location" json:"location,omitempty"` -} - -func (m *Feature) Reset() { *m = Feature{} } -func (m *Feature) String() string { return proto1.CompactTextString(m) } -func (*Feature) ProtoMessage() {} - -func (m *Feature) GetLocation() *Point { - if m != nil { - return m.Location - } - return nil -} - -// A RouteNote is a message sent while at a given point. -type RouteNote struct { - // The location from which the message is sent. - Location *Point `protobuf:"bytes,1,opt,name=location" json:"location,omitempty"` - // The message to be sent. - Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` -} - -func (m *RouteNote) Reset() { *m = RouteNote{} } -func (m *RouteNote) String() string { return proto1.CompactTextString(m) } -func (*RouteNote) ProtoMessage() {} - -func (m *RouteNote) GetLocation() *Point { - if m != nil { - return m.Location - } - return nil -} - -// A RouteSummary is received in response to a RecordRoute rpc. -// -// It contains the number of individual points received, the number of -// detected features, and the total distance covered as the cumulative sum of -// the distance between each point. -type RouteSummary struct { - // The number of points received. - PointCount int32 `protobuf:"varint,1,opt,name=point_count" json:"point_count,omitempty"` - // The number of known features passed while traversing the route. - FeatureCount int32 `protobuf:"varint,2,opt,name=feature_count" json:"feature_count,omitempty"` - // The distance covered in metres. - Distance int32 `protobuf:"varint,3,opt,name=distance" json:"distance,omitempty"` - // The duration of the traversal in seconds. - ElapsedTime int32 `protobuf:"varint,4,opt,name=elapsed_time" json:"elapsed_time,omitempty"` -} - -func (m *RouteSummary) Reset() { *m = RouteSummary{} } -func (m *RouteSummary) String() string { return proto1.CompactTextString(m) } -func (*RouteSummary) ProtoMessage() {} - -func init() { -} - -// Client API for RouteGuide service - -type RouteGuideClient interface { - // A simple RPC. - // - // Obtains the feature at a given position. - GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) - // A server-to-client streaming RPC. - // - // Obtains the Features available within the given Rectangle. Results are - // streamed rather than returned at once (e.g. in a response message with a - // repeated field), as the rectangle may cover a large area and contain a - // huge number of features. - ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) - // A client-to-server streaming RPC. - // - // Accepts a stream of Points on a route being traversed, returning a - // RouteSummary when traversal is completed. - RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) - // A Bidirectional streaming RPC. - // - // Accepts a stream of RouteNotes sent while a route is being traversed, - // while receiving other RouteNotes (e.g. from other users). - RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) -} - -type routeGuideClient struct { - cc *grpc.ClientConn -} - -func NewRouteGuideClient(cc *grpc.ClientConn) RouteGuideClient { - return &routeGuideClient{cc} -} - -func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) { - out := new(Feature) - err := grpc.Invoke(ctx, "/proto.RouteGuide/GetFeature", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -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, "/proto.RouteGuide/ListFeatures", opts...) - if err != nil { - return nil, err - } - x := &routeGuideListFeaturesClient{stream} - if err := x.ClientStream.SendProto(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type RouteGuide_ListFeaturesClient interface { - Recv() (*Feature, error) - grpc.ClientStream -} - -type routeGuideListFeaturesClient struct { - grpc.ClientStream -} - -func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) { - m := new(Feature) - if err := x.ClientStream.RecvProto(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *routeGuideClient) RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) { - stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[1], c.cc, "/proto.RouteGuide/RecordRoute", opts...) - if err != nil { - return nil, err - } - x := &routeGuideRecordRouteClient{stream} - return x, nil -} - -type RouteGuide_RecordRouteClient interface { - Send(*Point) error - CloseAndRecv() (*RouteSummary, error) - grpc.ClientStream -} - -type routeGuideRecordRouteClient struct { - grpc.ClientStream -} - -func (x *routeGuideRecordRouteClient) Send(m *Point) error { - return x.ClientStream.SendProto(m) -} - -func (x *routeGuideRecordRouteClient) CloseAndRecv() (*RouteSummary, error) { - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - m := new(RouteSummary) - if err := x.ClientStream.RecvProto(m); err != nil { - return nil, err - } - return m, nil -} - -func (c *routeGuideClient) RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) { - stream, err := grpc.NewClientStream(ctx, &_RouteGuide_serviceDesc.Streams[2], c.cc, "/proto.RouteGuide/RouteChat", opts...) - if err != nil { - return nil, err - } - x := &routeGuideRouteChatClient{stream} - return x, nil -} - -type RouteGuide_RouteChatClient interface { - Send(*RouteNote) error - Recv() (*RouteNote, error) - grpc.ClientStream -} - -type routeGuideRouteChatClient struct { - grpc.ClientStream -} - -func (x *routeGuideRouteChatClient) Send(m *RouteNote) error { - return x.ClientStream.SendProto(m) -} - -func (x *routeGuideRouteChatClient) Recv() (*RouteNote, error) { - m := new(RouteNote) - if err := x.ClientStream.RecvProto(m); err != nil { - return nil, err - } - return m, nil -} - -// Server API for RouteGuide service - -type RouteGuideServer interface { - // A simple RPC. - // - // Obtains the feature at a given position. - GetFeature(context.Context, *Point) (*Feature, error) - // A server-to-client streaming RPC. - // - // Obtains the Features available within the given Rectangle. Results are - // streamed rather than returned at once (e.g. in a response message with a - // repeated field), as the rectangle may cover a large area and contain a - // huge number of features. - ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error - // A client-to-server streaming RPC. - // - // Accepts a stream of Points on a route being traversed, returning a - // RouteSummary when traversal is completed. - RecordRoute(RouteGuide_RecordRouteServer) error - // A Bidirectional streaming RPC. - // - // Accepts a stream of RouteNotes sent while a route is being traversed, - // while receiving other RouteNotes (e.g. from other users). - RouteChat(RouteGuide_RouteChatServer) error -} - -func RegisterRouteGuideServer(s *grpc.Server, srv RouteGuideServer) { - s.RegisterService(&_RouteGuide_serviceDesc, srv) -} - -func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, buf []byte) (proto1.Message, error) { - in := new(Point) - if err := proto1.Unmarshal(buf, in); err != nil { - return nil, err - } - out, err := srv.(RouteGuideServer).GetFeature(ctx, in) - if err != nil { - return nil, err - } - return out, nil -} - -func _RouteGuide_ListFeatures_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(Rectangle) - if err := stream.RecvProto(m); err != nil { - return err - } - return srv.(RouteGuideServer).ListFeatures(m, &routeGuideListFeaturesServer{stream}) -} - -type RouteGuide_ListFeaturesServer interface { - Send(*Feature) error - grpc.ServerStream -} - -type routeGuideListFeaturesServer struct { - grpc.ServerStream -} - -func (x *routeGuideListFeaturesServer) Send(m *Feature) error { - return x.ServerStream.SendProto(m) -} - -func _RouteGuide_RecordRoute_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(RouteGuideServer).RecordRoute(&routeGuideRecordRouteServer{stream}) -} - -type RouteGuide_RecordRouteServer interface { - SendAndClose(*RouteSummary) error - Recv() (*Point, error) - grpc.ServerStream -} - -type routeGuideRecordRouteServer struct { - grpc.ServerStream -} - -func (x *routeGuideRecordRouteServer) SendAndClose(m *RouteSummary) error { - return x.ServerStream.SendProto(m) -} - -func (x *routeGuideRecordRouteServer) Recv() (*Point, error) { - m := new(Point) - if err := x.ServerStream.RecvProto(m); err != nil { - return nil, err - } - return m, nil -} - -func _RouteGuide_RouteChat_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(RouteGuideServer).RouteChat(&routeGuideRouteChatServer{stream}) -} - -type RouteGuide_RouteChatServer interface { - Send(*RouteNote) error - Recv() (*RouteNote, error) - grpc.ServerStream -} - -type routeGuideRouteChatServer struct { - grpc.ServerStream -} - -func (x *routeGuideRouteChatServer) Send(m *RouteNote) error { - return x.ServerStream.SendProto(m) -} - -func (x *routeGuideRouteChatServer) Recv() (*RouteNote, error) { - m := new(RouteNote) - if err := x.ServerStream.RecvProto(m); err != nil { - return nil, err - } - return m, nil -} - -var _RouteGuide_serviceDesc = grpc.ServiceDesc{ - ServiceName: "proto.RouteGuide", - HandlerType: (*RouteGuideServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetFeature", - Handler: _RouteGuide_GetFeature_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "ListFeatures", - Handler: _RouteGuide_ListFeatures_Handler, - ServerStreams: true, - }, - { - StreamName: "RecordRoute", - Handler: _RouteGuide_RecordRoute_Handler, - ClientStreams: true, - }, - { - StreamName: "RouteChat", - Handler: _RouteGuide_RouteChat_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, -}