205 lines
6.8 KiB
Go
205 lines
6.8 KiB
Go
/*
|
|
*
|
|
* 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 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 (
|
|
"flag"
|
|
"io"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"golang.org/x/net/context"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
pb "google.golang.org/grpc/examples/route_guide/routeguide"
|
|
"google.golang.org/grpc/grpclog"
|
|
)
|
|
|
|
var (
|
|
tls = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP")
|
|
caFile = flag.String("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")
|
|
serverHostOverride = 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.
|
|
func printFeature(client pb.RouteGuideClient, point *pb.Point) {
|
|
grpclog.Printf("Getting feature for point (%d, %d)", point.Latitude, point.Longitude)
|
|
feature, err := client.GetFeature(context.Background(), point)
|
|
if err != nil {
|
|
grpclog.Fatalf("%v.GetFeatures(_) = _, %v: ", client, err)
|
|
}
|
|
grpclog.Println(feature)
|
|
}
|
|
|
|
// printFeatures lists all the features within the given bounding Rectangle.
|
|
func printFeatures(client pb.RouteGuideClient, rect *pb.Rectangle) {
|
|
grpclog.Printf("Looking for features within %v", rect)
|
|
stream, err := client.ListFeatures(context.Background(), rect)
|
|
if err != nil {
|
|
grpclog.Fatalf("%v.ListFeatures(_) = _, %v", client, err)
|
|
}
|
|
for {
|
|
feature, err := stream.Recv()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
grpclog.Fatalf("%v.ListFeatures(_) = _, %v", client, err)
|
|
}
|
|
grpclog.Println(feature)
|
|
}
|
|
}
|
|
|
|
// 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
|
|
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))
|
|
}
|
|
grpclog.Printf("Traversing %d points.", len(points))
|
|
stream, err := client.RecordRoute(context.Background())
|
|
if err != nil {
|
|
grpclog.Fatalf("%v.RecordRoute(_) = _, %v", client, err)
|
|
}
|
|
for _, point := range points {
|
|
if err := stream.Send(point); err != nil {
|
|
grpclog.Fatalf("%v.Send(%v) = %v", stream, point, err)
|
|
}
|
|
}
|
|
reply, err := stream.CloseAndRecv()
|
|
if err != nil {
|
|
grpclog.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)
|
|
}
|
|
grpclog.Printf("Route summary: %v", reply)
|
|
}
|
|
|
|
// runRouteChat receives a sequence of route notes, while sending notes for various locations.
|
|
func runRouteChat(client pb.RouteGuideClient) {
|
|
notes := []*pb.RouteNote{
|
|
{&pb.Point{Latitude: 0, Longitude: 1}, "First message"},
|
|
{&pb.Point{Latitude: 0, Longitude: 2}, "Second message"},
|
|
{&pb.Point{Latitude: 0, Longitude: 3}, "Third message"},
|
|
{&pb.Point{Latitude: 0, Longitude: 1}, "Fourth message"},
|
|
{&pb.Point{Latitude: 0, Longitude: 2}, "Fifth message"},
|
|
{&pb.Point{Latitude: 0, Longitude: 3}, "Sixth message"},
|
|
}
|
|
stream, err := client.RouteChat(context.Background())
|
|
if err != nil {
|
|
grpclog.Fatalf("%v.RouteChat(_) = _, %v", client, err)
|
|
}
|
|
waitc := make(chan struct{})
|
|
go func() {
|
|
for {
|
|
in, err := stream.Recv()
|
|
if err == io.EOF {
|
|
// read done.
|
|
close(waitc)
|
|
return
|
|
}
|
|
if err != nil {
|
|
grpclog.Fatalf("Failed to receive a note : %v", err)
|
|
}
|
|
grpclog.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 {
|
|
grpclog.Fatalf("Failed to send a note: %v", err)
|
|
}
|
|
}
|
|
stream.CloseSend()
|
|
<-waitc
|
|
}
|
|
|
|
func randomPoint(r *rand.Rand) *pb.Point {
|
|
lat := (r.Int31n(180) - 90) * 1e7
|
|
long := (r.Int31n(360) - 180) * 1e7
|
|
return &pb.Point{Latitude: lat, Longitude: long}
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
var opts []grpc.DialOption
|
|
if *tls {
|
|
var sn string
|
|
if *serverHostOverride != "" {
|
|
sn = *serverHostOverride
|
|
}
|
|
var creds credentials.TransportCredentials
|
|
if *caFile != "" {
|
|
var err error
|
|
creds, err = credentials.NewClientTLSFromFile(*caFile, sn)
|
|
if err != nil {
|
|
grpclog.Fatalf("Failed to create TLS credentials %v", err)
|
|
}
|
|
} else {
|
|
creds = credentials.NewClientTLSFromCert(nil, sn)
|
|
}
|
|
opts = append(opts, grpc.WithTransportCredentials(creds))
|
|
} else {
|
|
opts = append(opts, grpc.WithInsecure())
|
|
}
|
|
conn, err := grpc.Dial(*serverAddr, opts...)
|
|
if err != nil {
|
|
grpclog.Fatalf("fail to dial: %v", err)
|
|
}
|
|
defer conn.Close()
|
|
client := pb.NewRouteGuideClient(conn)
|
|
|
|
// Looking for a valid feature
|
|
printFeature(client, &pb.Point{Latitude: 409146138, Longitude: -746188906})
|
|
|
|
// Feature missing.
|
|
printFeature(client, &pb.Point{Latitude: 0, Longitude: 0})
|
|
|
|
// Looking for features between 40, -75 and 42, -73.
|
|
printFeatures(client, &pb.Rectangle{
|
|
Lo: &pb.Point{Latitude: 400000000, Longitude: -750000000},
|
|
Hi: &pb.Point{Latitude: 420000000, Longitude: -730000000},
|
|
})
|
|
|
|
// RecordRoute
|
|
runRecordRoute(client)
|
|
|
|
// RouteChat
|
|
runRouteChat(client)
|
|
}
|