1/* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19// Package main implements a simple gRPC server that demonstrates how to use gRPC-Go libraries 20// to perform unary, client streaming, server streaming and full duplex RPCs. 21// 22// It implements the route guide service whose definition can be found in routeguide/route_guide.proto. 23package main 24 25import ( 26 "context" 27 "encoding/json" 28 "flag" 29 "fmt" 30 "io" 31 "io/ioutil" 32 "log" 33 "math" 34 "net" 35 "sync" 36 "time" 37 38 "google.golang.org/grpc" 39 40 "google.golang.org/grpc/credentials" 41 "google.golang.org/grpc/testdata" 42 43 "github.com/golang/protobuf/proto" 44 45 pb "google.golang.org/grpc/examples/route_guide/routeguide" 46) 47 48var ( 49 tls = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP") 50 certFile = flag.String("cert_file", "", "The TLS cert file") 51 keyFile = flag.String("key_file", "", "The TLS key file") 52 jsonDBFile = flag.String("json_db_file", "", "A json file containing a list of features") 53 port = flag.Int("port", 10000, "The server port") 54) 55 56type routeGuideServer struct { 57 pb.UnimplementedRouteGuideServer 58 savedFeatures []*pb.Feature // read-only after initialized 59 60 mu sync.Mutex // protects routeNotes 61 routeNotes map[string][]*pb.RouteNote 62} 63 64// GetFeature returns the feature at the given point. 65func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) { 66 for _, feature := range s.savedFeatures { 67 if proto.Equal(feature.Location, point) { 68 return feature, nil 69 } 70 } 71 // No feature was found, return an unnamed feature 72 return &pb.Feature{Location: point}, nil 73} 74 75// ListFeatures lists all features contained within the given bounding Rectangle. 76func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error { 77 for _, feature := range s.savedFeatures { 78 if inRange(feature.Location, rect) { 79 if err := stream.Send(feature); err != nil { 80 return err 81 } 82 } 83 } 84 return nil 85} 86 87// RecordRoute records a route composited of a sequence of points. 88// 89// It gets a stream of points, and responds with statistics about the "trip": 90// number of points, number of known features visited, total distance traveled, and 91// total time spent. 92func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error { 93 var pointCount, featureCount, distance int32 94 var lastPoint *pb.Point 95 startTime := time.Now() 96 for { 97 point, err := stream.Recv() 98 if err == io.EOF { 99 endTime := time.Now() 100 return stream.SendAndClose(&pb.RouteSummary{ 101 PointCount: pointCount, 102 FeatureCount: featureCount, 103 Distance: distance, 104 ElapsedTime: int32(endTime.Sub(startTime).Seconds()), 105 }) 106 } 107 if err != nil { 108 return err 109 } 110 pointCount++ 111 for _, feature := range s.savedFeatures { 112 if proto.Equal(feature.Location, point) { 113 featureCount++ 114 } 115 } 116 if lastPoint != nil { 117 distance += calcDistance(lastPoint, point) 118 } 119 lastPoint = point 120 } 121} 122 123// RouteChat receives a stream of message/location pairs, and responds with a stream of all 124// previous messages at each of those locations. 125func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error { 126 for { 127 in, err := stream.Recv() 128 if err == io.EOF { 129 return nil 130 } 131 if err != nil { 132 return err 133 } 134 key := serialize(in.Location) 135 136 s.mu.Lock() 137 s.routeNotes[key] = append(s.routeNotes[key], in) 138 // Note: this copy prevents blocking other clients while serving this one. 139 // We don't need to do a deep copy, because elements in the slice are 140 // insert-only and never modified. 141 rn := make([]*pb.RouteNote, len(s.routeNotes[key])) 142 copy(rn, s.routeNotes[key]) 143 s.mu.Unlock() 144 145 for _, note := range rn { 146 if err := stream.Send(note); err != nil { 147 return err 148 } 149 } 150 } 151} 152 153// loadFeatures loads features from a JSON file. 154func (s *routeGuideServer) loadFeatures(filePath string) { 155 var data []byte 156 if filePath != "" { 157 var err error 158 data, err = ioutil.ReadFile(filePath) 159 if err != nil { 160 log.Fatalf("Failed to load default features: %v", err) 161 } 162 } else { 163 data = exampleData 164 } 165 if err := json.Unmarshal(data, &s.savedFeatures); err != nil { 166 log.Fatalf("Failed to load default features: %v", err) 167 } 168} 169 170func toRadians(num float64) float64 { 171 return num * math.Pi / float64(180) 172} 173 174// calcDistance calculates the distance between two points using the "haversine" formula. 175// The formula is based on http://mathforum.org/library/drmath/view/51879.html. 176func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 { 177 const CordFactor float64 = 1e7 178 const R = float64(6371000) // earth radius in metres 179 lat1 := toRadians(float64(p1.Latitude) / CordFactor) 180 lat2 := toRadians(float64(p2.Latitude) / CordFactor) 181 lng1 := toRadians(float64(p1.Longitude) / CordFactor) 182 lng2 := toRadians(float64(p2.Longitude) / CordFactor) 183 dlat := lat2 - lat1 184 dlng := lng2 - lng1 185 186 a := math.Sin(dlat/2)*math.Sin(dlat/2) + 187 math.Cos(lat1)*math.Cos(lat2)* 188 math.Sin(dlng/2)*math.Sin(dlng/2) 189 c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a)) 190 191 distance := R * c 192 return int32(distance) 193} 194 195func inRange(point *pb.Point, rect *pb.Rectangle) bool { 196 left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude)) 197 right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude)) 198 top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude)) 199 bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude)) 200 201 if float64(point.Longitude) >= left && 202 float64(point.Longitude) <= right && 203 float64(point.Latitude) >= bottom && 204 float64(point.Latitude) <= top { 205 return true 206 } 207 return false 208} 209 210func serialize(point *pb.Point) string { 211 return fmt.Sprintf("%d %d", point.Latitude, point.Longitude) 212} 213 214func newServer() *routeGuideServer { 215 s := &routeGuideServer{routeNotes: make(map[string][]*pb.RouteNote)} 216 s.loadFeatures(*jsonDBFile) 217 return s 218} 219 220func main() { 221 flag.Parse() 222 lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port)) 223 if err != nil { 224 log.Fatalf("failed to listen: %v", err) 225 } 226 var opts []grpc.ServerOption 227 if *tls { 228 if *certFile == "" { 229 *certFile = testdata.Path("server1.pem") 230 } 231 if *keyFile == "" { 232 *keyFile = testdata.Path("server1.key") 233 } 234 creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile) 235 if err != nil { 236 log.Fatalf("Failed to generate credentials %v", err) 237 } 238 opts = []grpc.ServerOption{grpc.Creds(creds)} 239 } 240 grpcServer := grpc.NewServer(opts...) 241 pb.RegisterRouteGuideServer(grpcServer, newServer()) 242 grpcServer.Serve(lis) 243} 244 245// exampleData is a copy of testdata/route_guide_db.json. It's to avoid 246// specifying file path with `go run`. 247var exampleData = []byte(`[{ 248 "location": { 249 "latitude": 407838351, 250 "longitude": -746143763 251 }, 252 "name": "Patriots Path, Mendham, NJ 07945, USA" 253}, { 254 "location": { 255 "latitude": 408122808, 256 "longitude": -743999179 257 }, 258 "name": "101 New Jersey 10, Whippany, NJ 07981, USA" 259}, { 260 "location": { 261 "latitude": 413628156, 262 "longitude": -749015468 263 }, 264 "name": "U.S. 6, Shohola, PA 18458, USA" 265}, { 266 "location": { 267 "latitude": 419999544, 268 "longitude": -740371136 269 }, 270 "name": "5 Conners Road, Kingston, NY 12401, USA" 271}, { 272 "location": { 273 "latitude": 414008389, 274 "longitude": -743951297 275 }, 276 "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" 277}, { 278 "location": { 279 "latitude": 419611318, 280 "longitude": -746524769 281 }, 282 "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" 283}, { 284 "location": { 285 "latitude": 406109563, 286 "longitude": -742186778 287 }, 288 "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" 289}, { 290 "location": { 291 "latitude": 416802456, 292 "longitude": -742370183 293 }, 294 "name": "352 South Mountain Road, Wallkill, NY 12589, USA" 295}, { 296 "location": { 297 "latitude": 412950425, 298 "longitude": -741077389 299 }, 300 "name": "Bailey Turn Road, Harriman, NY 10926, USA" 301}, { 302 "location": { 303 "latitude": 412144655, 304 "longitude": -743949739 305 }, 306 "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" 307}, { 308 "location": { 309 "latitude": 415736605, 310 "longitude": -742847522 311 }, 312 "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" 313}, { 314 "location": { 315 "latitude": 413843930, 316 "longitude": -740501726 317 }, 318 "name": "162 Merrill Road, Highland Mills, NY 10930, USA" 319}, { 320 "location": { 321 "latitude": 410873075, 322 "longitude": -744459023 323 }, 324 "name": "Clinton Road, West Milford, NJ 07480, USA" 325}, { 326 "location": { 327 "latitude": 412346009, 328 "longitude": -744026814 329 }, 330 "name": "16 Old Brook Lane, Warwick, NY 10990, USA" 331}, { 332 "location": { 333 "latitude": 402948455, 334 "longitude": -747903913 335 }, 336 "name": "3 Drake Lane, Pennington, NJ 08534, USA" 337}, { 338 "location": { 339 "latitude": 406337092, 340 "longitude": -740122226 341 }, 342 "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" 343}, { 344 "location": { 345 "latitude": 406421967, 346 "longitude": -747727624 347 }, 348 "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" 349}, { 350 "location": { 351 "latitude": 416318082, 352 "longitude": -749677716 353 }, 354 "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" 355}, { 356 "location": { 357 "latitude": 415301720, 358 "longitude": -748416257 359 }, 360 "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" 361}, { 362 "location": { 363 "latitude": 402647019, 364 "longitude": -747071791 365 }, 366 "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" 367}, { 368 "location": { 369 "latitude": 412567807, 370 "longitude": -741058078 371 }, 372 "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" 373}, { 374 "location": { 375 "latitude": 416855156, 376 "longitude": -744420597 377 }, 378 "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" 379}, { 380 "location": { 381 "latitude": 404663628, 382 "longitude": -744820157 383 }, 384 "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" 385}, { 386 "location": { 387 "latitude": 407113723, 388 "longitude": -749746483 389 }, 390 "name": "" 391}, { 392 "location": { 393 "latitude": 402133926, 394 "longitude": -743613249 395 }, 396 "name": "" 397}, { 398 "location": { 399 "latitude": 400273442, 400 "longitude": -741220915 401 }, 402 "name": "" 403}, { 404 "location": { 405 "latitude": 411236786, 406 "longitude": -744070769 407 }, 408 "name": "" 409}, { 410 "location": { 411 "latitude": 411633782, 412 "longitude": -746784970 413 }, 414 "name": "211-225 Plains Road, Augusta, NJ 07822, USA" 415}, { 416 "location": { 417 "latitude": 415830701, 418 "longitude": -742952812 419 }, 420 "name": "" 421}, { 422 "location": { 423 "latitude": 413447164, 424 "longitude": -748712898 425 }, 426 "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" 427}, { 428 "location": { 429 "latitude": 405047245, 430 "longitude": -749800722 431 }, 432 "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" 433}, { 434 "location": { 435 "latitude": 418858923, 436 "longitude": -746156790 437 }, 438 "name": "" 439}, { 440 "location": { 441 "latitude": 417951888, 442 "longitude": -748484944 443 }, 444 "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" 445}, { 446 "location": { 447 "latitude": 407033786, 448 "longitude": -743977337 449 }, 450 "name": "26 East 3rd Street, New Providence, NJ 07974, USA" 451}, { 452 "location": { 453 "latitude": 417548014, 454 "longitude": -740075041 455 }, 456 "name": "" 457}, { 458 "location": { 459 "latitude": 410395868, 460 "longitude": -744972325 461 }, 462 "name": "" 463}, { 464 "location": { 465 "latitude": 404615353, 466 "longitude": -745129803 467 }, 468 "name": "" 469}, { 470 "location": { 471 "latitude": 406589790, 472 "longitude": -743560121 473 }, 474 "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" 475}, { 476 "location": { 477 "latitude": 414653148, 478 "longitude": -740477477 479 }, 480 "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" 481}, { 482 "location": { 483 "latitude": 405957808, 484 "longitude": -743255336 485 }, 486 "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" 487}, { 488 "location": { 489 "latitude": 411733589, 490 "longitude": -741648093 491 }, 492 "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" 493}, { 494 "location": { 495 "latitude": 412676291, 496 "longitude": -742606606 497 }, 498 "name": "1270 Lakes Road, Monroe, NY 10950, USA" 499}, { 500 "location": { 501 "latitude": 409224445, 502 "longitude": -748286738 503 }, 504 "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" 505}, { 506 "location": { 507 "latitude": 406523420, 508 "longitude": -742135517 509 }, 510 "name": "652 Garden Street, Elizabeth, NJ 07202, USA" 511}, { 512 "location": { 513 "latitude": 401827388, 514 "longitude": -740294537 515 }, 516 "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" 517}, { 518 "location": { 519 "latitude": 410564152, 520 "longitude": -743685054 521 }, 522 "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" 523}, { 524 "location": { 525 "latitude": 408472324, 526 "longitude": -740726046 527 }, 528 "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" 529}, { 530 "location": { 531 "latitude": 412452168, 532 "longitude": -740214052 533 }, 534 "name": "5 White Oak Lane, Stony Point, NY 10980, USA" 535}, { 536 "location": { 537 "latitude": 409146138, 538 "longitude": -746188906 539 }, 540 "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" 541}, { 542 "location": { 543 "latitude": 404701380, 544 "longitude": -744781745 545 }, 546 "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" 547}, { 548 "location": { 549 "latitude": 409642566, 550 "longitude": -746017679 551 }, 552 "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" 553}, { 554 "location": { 555 "latitude": 408031728, 556 "longitude": -748645385 557 }, 558 "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" 559}, { 560 "location": { 561 "latitude": 413700272, 562 "longitude": -742135189 563 }, 564 "name": "367 Prospect Road, Chester, NY 10918, USA" 565}, { 566 "location": { 567 "latitude": 404310607, 568 "longitude": -740282632 569 }, 570 "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" 571}, { 572 "location": { 573 "latitude": 409319800, 574 "longitude": -746201391 575 }, 576 "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" 577}, { 578 "location": { 579 "latitude": 406685311, 580 "longitude": -742108603 581 }, 582 "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" 583}, { 584 "location": { 585 "latitude": 419018117, 586 "longitude": -749142781 587 }, 588 "name": "43 Dreher Road, Roscoe, NY 12776, USA" 589}, { 590 "location": { 591 "latitude": 412856162, 592 "longitude": -745148837 593 }, 594 "name": "Swan Street, Pine Island, NY 10969, USA" 595}, { 596 "location": { 597 "latitude": 416560744, 598 "longitude": -746721964 599 }, 600 "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" 601}, { 602 "location": { 603 "latitude": 405314270, 604 "longitude": -749836354 605 }, 606 "name": "" 607}, { 608 "location": { 609 "latitude": 414219548, 610 "longitude": -743327440 611 }, 612 "name": "" 613}, { 614 "location": { 615 "latitude": 415534177, 616 "longitude": -742900616 617 }, 618 "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" 619}, { 620 "location": { 621 "latitude": 406898530, 622 "longitude": -749127080 623 }, 624 "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" 625}, { 626 "location": { 627 "latitude": 407586880, 628 "longitude": -741670168 629 }, 630 "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" 631}, { 632 "location": { 633 "latitude": 400106455, 634 "longitude": -742870190 635 }, 636 "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" 637}, { 638 "location": { 639 "latitude": 400066188, 640 "longitude": -746793294 641 }, 642 "name": "" 643}, { 644 "location": { 645 "latitude": 418803880, 646 "longitude": -744102673 647 }, 648 "name": "40 Mountain Road, Napanoch, NY 12458, USA" 649}, { 650 "location": { 651 "latitude": 414204288, 652 "longitude": -747895140 653 }, 654 "name": "" 655}, { 656 "location": { 657 "latitude": 414777405, 658 "longitude": -740615601 659 }, 660 "name": "" 661}, { 662 "location": { 663 "latitude": 415464475, 664 "longitude": -747175374 665 }, 666 "name": "48 North Road, Forestburgh, NY 12777, USA" 667}, { 668 "location": { 669 "latitude": 404062378, 670 "longitude": -746376177 671 }, 672 "name": "" 673}, { 674 "location": { 675 "latitude": 405688272, 676 "longitude": -749285130 677 }, 678 "name": "" 679}, { 680 "location": { 681 "latitude": 400342070, 682 "longitude": -748788996 683 }, 684 "name": "" 685}, { 686 "location": { 687 "latitude": 401809022, 688 "longitude": -744157964 689 }, 690 "name": "" 691}, { 692 "location": { 693 "latitude": 404226644, 694 "longitude": -740517141 695 }, 696 "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" 697}, { 698 "location": { 699 "latitude": 410322033, 700 "longitude": -747871659 701 }, 702 "name": "" 703}, { 704 "location": { 705 "latitude": 407100674, 706 "longitude": -747742727 707 }, 708 "name": "" 709}, { 710 "location": { 711 "latitude": 418811433, 712 "longitude": -741718005 713 }, 714 "name": "213 Bush Road, Stone Ridge, NY 12484, USA" 715}, { 716 "location": { 717 "latitude": 415034302, 718 "longitude": -743850945 719 }, 720 "name": "" 721}, { 722 "location": { 723 "latitude": 411349992, 724 "longitude": -743694161 725 }, 726 "name": "" 727}, { 728 "location": { 729 "latitude": 404839914, 730 "longitude": -744759616 731 }, 732 "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" 733}, { 734 "location": { 735 "latitude": 414638017, 736 "longitude": -745957854 737 }, 738 "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" 739}, { 740 "location": { 741 "latitude": 412127800, 742 "longitude": -740173578 743 }, 744 "name": "" 745}, { 746 "location": { 747 "latitude": 401263460, 748 "longitude": -747964303 749 }, 750 "name": "" 751}, { 752 "location": { 753 "latitude": 412843391, 754 "longitude": -749086026 755 }, 756 "name": "" 757}, { 758 "location": { 759 "latitude": 418512773, 760 "longitude": -743067823 761 }, 762 "name": "" 763}, { 764 "location": { 765 "latitude": 404318328, 766 "longitude": -740835638 767 }, 768 "name": "42-102 Main Street, Belford, NJ 07718, USA" 769}, { 770 "location": { 771 "latitude": 419020746, 772 "longitude": -741172328 773 }, 774 "name": "" 775}, { 776 "location": { 777 "latitude": 404080723, 778 "longitude": -746119569 779 }, 780 "name": "" 781}, { 782 "location": { 783 "latitude": 401012643, 784 "longitude": -744035134 785 }, 786 "name": "" 787}, { 788 "location": { 789 "latitude": 404306372, 790 "longitude": -741079661 791 }, 792 "name": "" 793}, { 794 "location": { 795 "latitude": 403966326, 796 "longitude": -748519297 797 }, 798 "name": "" 799}, { 800 "location": { 801 "latitude": 405002031, 802 "longitude": -748407866 803 }, 804 "name": "" 805}, { 806 "location": { 807 "latitude": 409532885, 808 "longitude": -742200683 809 }, 810 "name": "" 811}, { 812 "location": { 813 "latitude": 416851321, 814 "longitude": -742674555 815 }, 816 "name": "" 817}, { 818 "location": { 819 "latitude": 406411633, 820 "longitude": -741722051 821 }, 822 "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" 823}, { 824 "location": { 825 "latitude": 413069058, 826 "longitude": -744597778 827 }, 828 "name": "261 Van Sickle Road, Goshen, NY 10924, USA" 829}, { 830 "location": { 831 "latitude": 418465462, 832 "longitude": -746859398 833 }, 834 "name": "" 835}, { 836 "location": { 837 "latitude": 411733222, 838 "longitude": -744228360 839 }, 840 "name": "" 841}, { 842 "location": { 843 "latitude": 410248224, 844 "longitude": -747127767 845 }, 846 "name": "3 Hasta Way, Newton, NJ 07860, USA" 847}]`) 848