1/*
2 *
3 * Copyright 2018 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// Binary server is an example server.
20package main
21
22import (
23	"context"
24	"flag"
25	"fmt"
26	"io"
27	"log"
28	"math/rand"
29	"net"
30	"time"
31
32	"google.golang.org/grpc"
33	"google.golang.org/grpc/codes"
34	"google.golang.org/grpc/metadata"
35	"google.golang.org/grpc/status"
36
37	pb "google.golang.org/grpc/examples/features/proto/echo"
38)
39
40var port = flag.Int("port", 50051, "the port to serve on")
41
42const (
43	timestampFormat = time.StampNano
44	streamingCount  = 10
45)
46
47type server struct {
48	pb.UnimplementedEchoServer
49}
50
51func (s *server) UnaryEcho(ctx context.Context, in *pb.EchoRequest) (*pb.EchoResponse, error) {
52	fmt.Printf("--- UnaryEcho ---\n")
53	// Create trailer in defer to record function return time.
54	defer func() {
55		trailer := metadata.Pairs("timestamp", time.Now().Format(timestampFormat))
56		grpc.SetTrailer(ctx, trailer)
57	}()
58
59	// Read metadata from client.
60	md, ok := metadata.FromIncomingContext(ctx)
61	if !ok {
62		return nil, status.Errorf(codes.DataLoss, "UnaryEcho: failed to get metadata")
63	}
64	if t, ok := md["timestamp"]; ok {
65		fmt.Printf("timestamp from metadata:\n")
66		for i, e := range t {
67			fmt.Printf(" %d. %s\n", i, e)
68		}
69	}
70
71	// Create and send header.
72	header := metadata.New(map[string]string{"location": "MTV", "timestamp": time.Now().Format(timestampFormat)})
73	grpc.SendHeader(ctx, header)
74
75	fmt.Printf("request received: %v, sending echo\n", in)
76
77	return &pb.EchoResponse{Message: in.Message}, nil
78}
79
80func (s *server) ServerStreamingEcho(in *pb.EchoRequest, stream pb.Echo_ServerStreamingEchoServer) error {
81	fmt.Printf("--- ServerStreamingEcho ---\n")
82	// Create trailer in defer to record function return time.
83	defer func() {
84		trailer := metadata.Pairs("timestamp", time.Now().Format(timestampFormat))
85		stream.SetTrailer(trailer)
86	}()
87
88	// Read metadata from client.
89	md, ok := metadata.FromIncomingContext(stream.Context())
90	if !ok {
91		return status.Errorf(codes.DataLoss, "ServerStreamingEcho: failed to get metadata")
92	}
93	if t, ok := md["timestamp"]; ok {
94		fmt.Printf("timestamp from metadata:\n")
95		for i, e := range t {
96			fmt.Printf(" %d. %s\n", i, e)
97		}
98	}
99
100	// Create and send header.
101	header := metadata.New(map[string]string{"location": "MTV", "timestamp": time.Now().Format(timestampFormat)})
102	stream.SendHeader(header)
103
104	fmt.Printf("request received: %v\n", in)
105
106	// Read requests and send responses.
107	for i := 0; i < streamingCount; i++ {
108		fmt.Printf("echo message %v\n", in.Message)
109		err := stream.Send(&pb.EchoResponse{Message: in.Message})
110		if err != nil {
111			return err
112		}
113	}
114	return nil
115}
116
117func (s *server) ClientStreamingEcho(stream pb.Echo_ClientStreamingEchoServer) error {
118	fmt.Printf("--- ClientStreamingEcho ---\n")
119	// Create trailer in defer to record function return time.
120	defer func() {
121		trailer := metadata.Pairs("timestamp", time.Now().Format(timestampFormat))
122		stream.SetTrailer(trailer)
123	}()
124
125	// Read metadata from client.
126	md, ok := metadata.FromIncomingContext(stream.Context())
127	if !ok {
128		return status.Errorf(codes.DataLoss, "ClientStreamingEcho: failed to get metadata")
129	}
130	if t, ok := md["timestamp"]; ok {
131		fmt.Printf("timestamp from metadata:\n")
132		for i, e := range t {
133			fmt.Printf(" %d. %s\n", i, e)
134		}
135	}
136
137	// Create and send header.
138	header := metadata.New(map[string]string{"location": "MTV", "timestamp": time.Now().Format(timestampFormat)})
139	stream.SendHeader(header)
140
141	// Read requests and send responses.
142	var message string
143	for {
144		in, err := stream.Recv()
145		if err == io.EOF {
146			fmt.Printf("echo last received message\n")
147			return stream.SendAndClose(&pb.EchoResponse{Message: message})
148		}
149		message = in.Message
150		fmt.Printf("request received: %v, building echo\n", in)
151		if err != nil {
152			return err
153		}
154	}
155}
156
157func (s *server) BidirectionalStreamingEcho(stream pb.Echo_BidirectionalStreamingEchoServer) error {
158	fmt.Printf("--- BidirectionalStreamingEcho ---\n")
159	// Create trailer in defer to record function return time.
160	defer func() {
161		trailer := metadata.Pairs("timestamp", time.Now().Format(timestampFormat))
162		stream.SetTrailer(trailer)
163	}()
164
165	// Read metadata from client.
166	md, ok := metadata.FromIncomingContext(stream.Context())
167	if !ok {
168		return status.Errorf(codes.DataLoss, "BidirectionalStreamingEcho: failed to get metadata")
169	}
170
171	if t, ok := md["timestamp"]; ok {
172		fmt.Printf("timestamp from metadata:\n")
173		for i, e := range t {
174			fmt.Printf(" %d. %s\n", i, e)
175		}
176	}
177
178	// Create and send header.
179	header := metadata.New(map[string]string{"location": "MTV", "timestamp": time.Now().Format(timestampFormat)})
180	stream.SendHeader(header)
181
182	// Read requests and send responses.
183	for {
184		in, err := stream.Recv()
185		if err == io.EOF {
186			return nil
187		}
188		if err != nil {
189			return err
190		}
191		fmt.Printf("request received %v, sending echo\n", in)
192		if err := stream.Send(&pb.EchoResponse{Message: in.Message}); err != nil {
193			return err
194		}
195	}
196}
197
198func main() {
199	flag.Parse()
200	rand.Seed(time.Now().UnixNano())
201	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
202	if err != nil {
203		log.Fatalf("failed to listen: %v", err)
204	}
205	fmt.Printf("server listening at %v\n", lis.Addr())
206
207	s := grpc.NewServer()
208	pb.RegisterEchoServer(s, &server{})
209	s.Serve(lis)
210}
211