/*
 *
 * Copyright 2020 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.
 *
 */

package test

import (
	"context"
	"fmt"
	"net"
	"strings"
	"testing"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/local"
	"google.golang.org/grpc/internal/stubserver"
	"google.golang.org/grpc/peer"
	"google.golang.org/grpc/status"

	testpb "google.golang.org/grpc/test/grpc_testing"
)

func testLocalCredsE2ESucceed(network, address string) error {
	ss := &stubserver.StubServer{
		EmptyCallF: func(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
			pr, ok := peer.FromContext(ctx)
			if !ok {
				return nil, status.Error(codes.DataLoss, "Failed to get peer from ctx")
			}
			type internalInfo interface {
				GetCommonAuthInfo() credentials.CommonAuthInfo
			}
			var secLevel credentials.SecurityLevel
			if info, ok := (pr.AuthInfo).(internalInfo); ok {
				secLevel = info.GetCommonAuthInfo().SecurityLevel
			} else {
				return nil, status.Errorf(codes.Unauthenticated, "peer.AuthInfo does not implement GetCommonAuthInfo()")
			}
			// Check security level
			switch network {
			case "unix":
				if secLevel != credentials.PrivacyAndIntegrity {
					return nil, status.Errorf(codes.Unauthenticated, "Wrong security level: got %q, want %q", secLevel, credentials.PrivacyAndIntegrity)
				}
			case "tcp":
				if secLevel != credentials.NoSecurity {
					return nil, status.Errorf(codes.Unauthenticated, "Wrong security level: got %q, want %q", secLevel, credentials.NoSecurity)
				}
			}
			return &testpb.Empty{}, nil
		},
	}

	sopts := []grpc.ServerOption{grpc.Creds(local.NewCredentials())}
	s := grpc.NewServer(sopts...)
	defer s.Stop()

	testpb.RegisterTestServiceServer(s, ss)

	lis, err := net.Listen(network, address)
	if err != nil {
		return fmt.Errorf("Failed to create listener: %v", err)
	}

	go s.Serve(lis)

	var cc *grpc.ClientConn
	lisAddr := lis.Addr().String()

	switch network {
	case "unix":
		cc, err = grpc.Dial(lisAddr, grpc.WithTransportCredentials(local.NewCredentials()), grpc.WithContextDialer(
			func(ctx context.Context, addr string) (net.Conn, error) {
				return net.Dial("unix", addr)
			}))
	case "tcp":
		cc, err = grpc.Dial(lisAddr, grpc.WithTransportCredentials(local.NewCredentials()))
	default:
		return fmt.Errorf("unsupported network %q", network)
	}
	if err != nil {
		return fmt.Errorf("Failed to dial server: %v, %v", err, lisAddr)
	}
	defer cc.Close()

	c := testpb.NewTestServiceClient(cc)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	if _, err = c.EmptyCall(ctx, &testpb.Empty{}); err != nil {
		return fmt.Errorf("EmptyCall(_, _) = _, %v; want _, <nil>", err)
	}
	return nil
}

func (s) TestLocalCredsLocalhost(t *testing.T) {
	if err := testLocalCredsE2ESucceed("tcp", "localhost:0"); err != nil {
		t.Fatalf("Failed e2e test for localhost: %v", err)
	}
}

func (s) TestLocalCredsUDS(t *testing.T) {
	addr := fmt.Sprintf("/tmp/grpc_fullstck_test%d", time.Now().UnixNano())
	if err := testLocalCredsE2ESucceed("unix", addr); err != nil {
		t.Fatalf("Failed e2e test for UDS: %v", err)
	}
}

type connWrapper struct {
	net.Conn
	remote net.Addr
}

func (c connWrapper) RemoteAddr() net.Addr {
	return c.remote
}

type lisWrapper struct {
	net.Listener
	remote net.Addr
}

func spoofListener(l net.Listener, remote net.Addr) net.Listener {
	return &lisWrapper{l, remote}
}

func (l *lisWrapper) Accept() (net.Conn, error) {
	c, err := l.Listener.Accept()
	if err != nil {
		return nil, err
	}
	return connWrapper{c, l.remote}, nil
}

func spoofDialer(addr net.Addr) func(target string, t time.Duration) (net.Conn, error) {
	return func(t string, d time.Duration) (net.Conn, error) {
		c, err := net.DialTimeout("tcp", t, d)
		if err != nil {
			return nil, err
		}
		return connWrapper{c, addr}, nil
	}
}

func testLocalCredsE2EFail(dopts []grpc.DialOption) error {
	ss := &stubserver.StubServer{
		EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) {
			return &testpb.Empty{}, nil
		},
	}

	sopts := []grpc.ServerOption{grpc.Creds(local.NewCredentials())}
	s := grpc.NewServer(sopts...)
	defer s.Stop()

	testpb.RegisterTestServiceServer(s, ss)

	lis, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return fmt.Errorf("Failed to create listener: %v", err)
	}

	var fakeClientAddr, fakeServerAddr net.Addr
	fakeClientAddr = &net.IPAddr{
		IP:   net.ParseIP("10.8.9.10"),
		Zone: "",
	}
	fakeServerAddr = &net.IPAddr{
		IP:   net.ParseIP("10.8.9.11"),
		Zone: "",
	}

	go s.Serve(spoofListener(lis, fakeClientAddr))

	cc, err := grpc.Dial(lis.Addr().String(), append(dopts, grpc.WithDialer(spoofDialer(fakeServerAddr)))...)
	if err != nil {
		return fmt.Errorf("Failed to dial server: %v, %v", err, lis.Addr().String())
	}
	defer cc.Close()

	c := testpb.NewTestServiceClient(cc)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	_, err = c.EmptyCall(ctx, &testpb.Empty{})
	return err
}

func isExpected(got, want error) bool {
	return status.Code(got) == status.Code(want) && strings.Contains(status.Convert(got).Message(), status.Convert(want).Message())
}

func (s) TestLocalCredsClientFail(t *testing.T) {
	// Use local creds at client-side which should lead to client-side failure.
	opts := []grpc.DialOption{grpc.WithTransportCredentials(local.NewCredentials())}
	want := status.Error(codes.Unavailable, "transport: authentication handshake failed: local credentials rejected connection to non-local address")
	if err := testLocalCredsE2EFail(opts); !isExpected(err, want) {
		t.Fatalf("testLocalCredsE2EFail() = %v; want %v", err, want)
	}
}

func (s) TestLocalCredsServerFail(t *testing.T) {
	// Use insecure at client-side which should lead to server-side failure.
	opts := []grpc.DialOption{grpc.WithInsecure()}
	if err := testLocalCredsE2EFail(opts); status.Code(err) != codes.Unavailable {
		t.Fatalf("testLocalCredsE2EFail() = %v; want %v", err, codes.Unavailable)
	}
}
