/*
 *
 * Copyright 2018 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// This file is for testing only. Runs a fake grpclb balancer server.
// The name of the service to load balance for and the addresses
// of that service are provided by command line flags.
package main

import (
	"flag"
	"net"
	"strconv"
	"strings"
	"time"

	"google.golang.org/grpc"
	lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/alts"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/status"
	"google.golang.org/grpc/testdata"
)

var (
	port         = flag.Int("port", 10000, "Port to listen on.")
	backendAddrs = flag.String("backend_addrs", "", "Comma separated list of backend IP/port addresses.")
	useALTS      = flag.Bool("use_alts", false, "Listen on ALTS credentials.")
	useTLS       = flag.Bool("use_tls", false, "Listen on TLS credentials, using a test certificate.")
	shortStream  = flag.Bool("short_stream", false, "End the balancer stream immediately after sending the first server list.")
	serviceName  = flag.String("service_name", "UNSET", "Name of the service being load balanced for.")
)

type loadBalancerServer struct {
	serverListResponse *lbpb.LoadBalanceResponse
}

func (l *loadBalancerServer) BalanceLoad(stream lbpb.LoadBalancer_BalanceLoadServer) error {
	grpclog.Info("Begin handling new BalancerLoad request.")
	var lbReq *lbpb.LoadBalanceRequest
	var err error
	if lbReq, err = stream.Recv(); err != nil {
		grpclog.Errorf("Error receiving LoadBalanceRequest: %v", err)
		return err
	}
	grpclog.Info("LoadBalancerRequest received.")
	initialReq := lbReq.GetInitialRequest()
	if initialReq == nil {
		grpclog.Info("Expected first request to be an InitialRequest. Got: %v", lbReq)
		return status.Error(codes.Unknown, "First request not an InitialRequest")
	}
	// gRPC clients targeting foo.bar.com:443 can sometimes include the ":443" suffix in
	// their requested names; handle this case. TODO: make 443 configurable?
	var cleanedName string
	var requestedNamePortNumber string
	if cleanedName, requestedNamePortNumber, err = net.SplitHostPort(initialReq.Name); err != nil {
		cleanedName = initialReq.Name
	} else {
		if requestedNamePortNumber != "443" {
			grpclog.Info("Bad requested service name port number: %v.", requestedNamePortNumber)
			return status.Error(codes.Unknown, "Bad requested service name port number")
		}
	}
	if cleanedName != *serviceName {
		grpclog.Info("Expected requested service name: %v. Got: %v", *serviceName, initialReq.Name)
		return status.Error(codes.NotFound, "Bad requested service name")
	}
	if err := stream.Send(&lbpb.LoadBalanceResponse{
		LoadBalanceResponseType: &lbpb.LoadBalanceResponse_InitialResponse{
			InitialResponse: &lbpb.InitialLoadBalanceResponse{},
		},
	}); err != nil {
		grpclog.Errorf("Error sending initial LB response: %v", err)
		return status.Error(codes.Unknown, "Error sending initial response")
	}
	grpclog.Info("Send LoadBalanceResponse: %v", l.serverListResponse)
	if err := stream.Send(l.serverListResponse); err != nil {
		grpclog.Errorf("Error sending LB response: %v", err)
		return status.Error(codes.Unknown, "Error sending response")
	}
	if *shortStream {
		return nil
	}
	for {
		grpclog.Info("Send LoadBalanceResponse: %v", l.serverListResponse)
		if err := stream.Send(l.serverListResponse); err != nil {
			grpclog.Errorf("Error sending LB response: %v", err)
			return status.Error(codes.Unknown, "Error sending response")
		}
		time.Sleep(10 * time.Second)
	}
}

func main() {
	flag.Parse()
	var opts []grpc.ServerOption
	if *useTLS {
		certFile := testdata.Path("server1.pem")
		keyFile := testdata.Path("server1.key")
		creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)
		if err != nil {
			grpclog.Fatalf("Failed to generate credentials %v", err)
		}
		opts = append(opts, grpc.Creds(creds))
	} else if *useALTS {
		altsOpts := alts.DefaultServerOptions()
		altsTC := alts.NewServerCreds(altsOpts)
		opts = append(opts, grpc.Creds(altsTC))
	}
	var serverList []*lbpb.Server
	if len(*backendAddrs) == 0 {
		serverList = make([]*lbpb.Server, 0)
	} else {
		rawBackendAddrs := strings.Split(*backendAddrs, ",")
		serverList = make([]*lbpb.Server, len(rawBackendAddrs))
		for i := range rawBackendAddrs {
			rawIP, rawPort, err := net.SplitHostPort(rawBackendAddrs[i])
			if err != nil {
				grpclog.Fatalf("Failed to parse --backend_addrs[%d]=%v, error: %v", i, rawBackendAddrs[i], err)
			}
			ip := net.ParseIP(rawIP)
			if ip == nil {
				grpclog.Fatalf("Failed to parse ip: %v", rawIP)
			}
			numericPort, err := strconv.Atoi(rawPort)
			if err != nil {
				grpclog.Fatalf("Failed to convert port %v to int", rawPort)
			}
			grpclog.Infof("Adding backend ip: %v, port: %d", ip.String(), numericPort)
			serverList[i] = &lbpb.Server{
				IpAddress: ip,
				Port:      int32(numericPort),
			}
		}
	}
	serverListResponse := &lbpb.LoadBalanceResponse{
		LoadBalanceResponseType: &lbpb.LoadBalanceResponse_ServerList{
			ServerList: &lbpb.ServerList{
				Servers: serverList,
			},
		},
	}
	server := grpc.NewServer(opts...)
	grpclog.Infof("Begin listening on %d.", *port)
	lis, err := net.Listen("tcp", ":"+strconv.Itoa(*port))
	if err != nil {
		grpclog.Fatalf("Failed to listen on port %v: %v", *port, err)
	}
	lbpb.RegisterLoadBalancerServer(server, &loadBalancerServer{
		serverListResponse: serverListResponse,
	})
	server.Serve(lis)
}
