func (s *GServer) UnaryAuthInterceptor(ctx context.Context,
	req interface{},
	info *grpc.UnaryServerInfo,
	handler grpc.UnaryHandler) (interface{}, error) {
	token, uuid, err := GetClientInfoFromCtx(ctx)
	if err != nil {
		return nil, err
	}
	client := s.configStore.GetConfiguredClient(token)
	if client == nil {
		log.Printf("[!] Invalid bearer token\n")
		return nil, status.Errorf(codes.Unauthenticated, err.Error())
	}
	_, ok := s.connectedClients[uuid]
	if ok {
		log.Printf("[!] gClient with uuid: %s already connected\n", uuid)
	}
	ctx = context.WithValue(ctx, contextKey("uuid"), uuid)
	return handler(ctx, req)
}
UnaryAuthInterceptor is called for all unary gRPC functions
to validate that the caller is authorized.
package gserverlib
import (
	"context"
	"fmt"
	"log"
	"net"
	"time"
	"github.com/hotnops/gTunnel/common"
	cs "github.com/hotnops/gTunnel/grpc/client"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)
type contextKey string
func (c contextKey) String() string {
	return string(c)
}
type ConfiguredClient struct {
	Arch     string
	BinType  string
	Name     string
	Platform string
	Port     uint32
	Proxy    string
	Server   string
	Token    string
}
type ConnectedClient struct {
	configuredClient *ConfiguredClient
	hostname         string
	remoteAddr       string
	uniqueID         string
	connectDate      time.Time
	endpoint         *common.Endpoint
	endpointInput    chan *cs.EndpointControlMessage
}
type GServer struct {
	configStore      *ConfigStore
	clientServer     *ClientServiceServer
	adminServer      *AdminServiceServer
	connectedClients map[string]*ConnectedClient
}
type ServerConnectionHandler struct {
	server     *GServer
	endpointID string
	tunnelID   string
}
func NewGServer() *GServer {
	newServer := new(GServer)
	newServer.configStore = NewConfigStore()
	newServer.configStore.Initialize()
	newServer.clientServer = NewClientServiceServer(newServer)
	newServer.adminServer = NewAdminServiceServer(newServer)
	newServer.connectedClients = make(map[string]*ConnectedClient)
	return newServer
}
func NewConfiguredClient(clientData map[string]interface{}) *ConfiguredClient {
	c := new(ConfiguredClient)
	c.Arch = clientData["Arch"].(string)
	c.Name = clientData["Name"].(string)
	c.Port = clientData["Port"].(uint32)
	c.Server = clientData["Server"].(string)
	c.Token = clientData["Token"].(string)
	return c
}
func (s *GServer) AddConnectedClient(uuid string, client *ConnectedClient) bool {
	_, ok := s.connectedClients[uuid]
	if ok {
		log.Printf("[!] Attempting to add client that already exists")
		return false
	}
	s.connectedClients[uuid] = client
	return true
}
func (s *GServer) StreamAuthInterceptor(srv interface{},
	ss grpc.ServerStream,
	info *grpc.StreamServerInfo,
	handler grpc.StreamHandler) error {
	ctx := ss.Context()
	token, uuid, err := GetClientInfoFromCtx(ctx)
	if err != nil {
		return err
	}
	client := s.configStore.GetConfiguredClient(token)
	if client == nil {
		log.Printf("[!] Invalid bearer token\n")
		return status.Errorf(codes.Unauthenticated, err.Error())
	}
	_, ok := s.connectedClients[uuid]
	if !ok {
		log.Printf("[!] UUID not connected\n")
		return status.Errorf(codes.Unauthenticated, err.Error())
	}
	ctx = context.WithValue(ctx, contextKey("uuid"), uuid)
	return handler(srv, ss)
}