| // Copyright Istio 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 echo |
| |
| import ( |
| "math" |
| ) |
| |
| import ( |
| "github.com/apache/dubbo-go-pixiu/pkg/config/protocol" |
| ) |
| |
| const ( |
| httpBase = 80 |
| httpsBase = 443 |
| grpcBase = 7070 |
| tcpBase = 9090 |
| ) |
| |
| // portGenerators creates a set of generators for service and instance ports. |
| type portGenerators struct { |
| Service *portGenerator |
| Instance *portGenerator |
| } |
| |
| // newPortGenerators creates a new set of port generators. |
| func newPortGenerators() *portGenerators { |
| return &portGenerators{ |
| Service: newPortGenerator(), |
| Instance: newPortGenerator(), |
| } |
| } |
| |
| // portGenerator is a utility that generates reasonable default port values |
| // for a given protocol. |
| type portGenerator struct { |
| next map[protocol.Instance]int |
| used map[int]struct{} |
| } |
| |
| func newPortGenerator() *portGenerator { |
| return &portGenerator{ |
| next: map[protocol.Instance]int{ |
| protocol.HTTP: httpBase, |
| protocol.HTTPS: httpsBase, |
| protocol.TLS: httpsBase, |
| protocol.TCP: tcpBase, |
| protocol.GRPCWeb: grpcBase, |
| protocol.GRPC: grpcBase, |
| protocol.Mongo: tcpBase, |
| protocol.MySQL: tcpBase, |
| protocol.Redis: tcpBase, |
| protocol.UDP: tcpBase, |
| }, |
| used: make(map[int]struct{}), |
| } |
| } |
| |
| // SetUsed marks the given port as used, so that it will not be assigned by the |
| // generator. |
| func (g *portGenerator) SetUsed(port int) *portGenerator { |
| g.used[port] = struct{}{} |
| return g |
| } |
| |
| // IsUsed indicates if the given port has already been used. |
| func (g *portGenerator) IsUsed(port int) bool { |
| _, ok := g.used[port] |
| return ok |
| } |
| |
| // Next assigns the next port for the given protocol. |
| func (g *portGenerator) Next(protocol protocol.Instance) int { |
| for { |
| v := g.next[protocol] |
| |
| if v == 0 { |
| panic("echo port generator: unsupported protocol " + protocol) |
| } |
| |
| if v == math.MaxInt16 { |
| panic("echo port generator: ran out of ports") |
| } |
| |
| g.next[protocol] = v + 1 |
| |
| if g.IsUsed(v) { |
| continue |
| } |
| |
| // Mark this port as used. |
| g.SetUsed(v) |
| return v |
| } |
| } |