istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/echo/portgen.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package echo
    16  
    17  import (
    18  	"math"
    19  
    20  	"istio.io/istio/pkg/config/protocol"
    21  )
    22  
    23  const (
    24  	httpBase  = 80
    25  	httpsBase = 443
    26  	grpcBase  = 7070
    27  	tcpBase   = 9090
    28  )
    29  
    30  // portGenerators creates a set of generators for service and instance ports.
    31  type portGenerators struct {
    32  	Service  *portGenerator
    33  	Instance *portGenerator
    34  }
    35  
    36  // newPortGenerators creates a new set of port generators.
    37  func newPortGenerators() *portGenerators {
    38  	return &portGenerators{
    39  		Service:  newPortGenerator(),
    40  		Instance: newPortGenerator(),
    41  	}
    42  }
    43  
    44  // portGenerator is a utility that generates reasonable default port values
    45  // for a given protocol.
    46  type portGenerator struct {
    47  	next map[protocol.Instance]int
    48  	used map[int]struct{}
    49  }
    50  
    51  func newPortGenerator() *portGenerator {
    52  	return &portGenerator{
    53  		next: map[protocol.Instance]int{
    54  			protocol.HTTP:    httpBase,
    55  			protocol.HTTPS:   httpsBase,
    56  			protocol.TLS:     httpsBase,
    57  			protocol.TCP:     tcpBase,
    58  			protocol.GRPCWeb: grpcBase,
    59  			protocol.GRPC:    grpcBase,
    60  			protocol.Mongo:   tcpBase,
    61  			protocol.MySQL:   tcpBase,
    62  			protocol.Redis:   tcpBase,
    63  			protocol.UDP:     tcpBase,
    64  		},
    65  		used: make(map[int]struct{}),
    66  	}
    67  }
    68  
    69  // SetUsed marks the given port as used, so that it will not be assigned by the
    70  // generator.
    71  func (g *portGenerator) SetUsed(port int) *portGenerator {
    72  	g.used[port] = struct{}{}
    73  	return g
    74  }
    75  
    76  // IsUsed indicates if the given port has already been used.
    77  func (g *portGenerator) IsUsed(port int) bool {
    78  	_, ok := g.used[port]
    79  	return ok
    80  }
    81  
    82  // Next assigns the next port for the given protocol.
    83  func (g *portGenerator) Next(protocol protocol.Instance) int {
    84  	for {
    85  		v := g.next[protocol]
    86  
    87  		if v == 0 {
    88  			panic("echo port generator: unsupported protocol " + protocol)
    89  		}
    90  
    91  		if v == math.MaxInt16 {
    92  			panic("echo port generator: ran out of ports")
    93  		}
    94  
    95  		g.next[protocol] = v + 1
    96  
    97  		if g.IsUsed(v) {
    98  			continue
    99  		}
   100  
   101  		// Mark this port as used.
   102  		g.SetUsed(v)
   103  		return v
   104  	}
   105  }