refact: remove func alias, comsoliation define to types

Kim committed Mar 5, 2026 at 10:39 UTC 1a0bc802ec8b00d37ce540e4d798482c3d20b634
20 files changed +104 -192
cmd/portal-tunnel/main.go
+4 -5
@@ -17,7 +17,6 @@ import (
17 "github.com/rs/zerolog"
18 "github.com/rs/zerolog/log"
19
20 - "gosuda.org/portal/portal/netutil"
20 "gosuda.org/portal/sdk"
21 "gosuda.org/portal/types"
22 )
@@ -64,7 +63,7 @@ func runTunnel() error {
63 ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
64 defer stop()
65
67 - relayURLs := netutil.ParseURLs(flagRelayURLs)
66 + relayURLs := types.ParseURLs(flagRelayURLs)
67 if len(relayURLs) == 0 {
68 return errors.New("no relay URLs provided")
69 }
@@ -87,7 +86,7 @@ func runTunnel() error {
86 listener, err := sdkClient.Listen(
87 flagName,
88 types.WithDescription(flagDesc),
90 - types.WithTags(netutil.ParseURLs(flagTags)),
89 + types.WithTags(types.ParseURLs(flagTags)),
90 types.WithOwner(flagOwner),
91 types.WithThumbnail(flagThumbnail),
92 types.WithHide(flagHide),
@@ -169,7 +168,7 @@ loop:
168 func normalizeRelayURLsForReverseConnect(relayURLs []string) ([]string, error) {
169 normalized := make([]string, 0, len(relayURLs))
170 for _, relayURL := range relayURLs {
172 - normalizedURL, err := netutil.NormalizeRelayAPIURL(relayURL)
171 + normalizedURL, err := types.NormalizeRelayAPIURL(relayURL)
172 if err != nil {
173 return nil, fmt.Errorf("invalid relay URL %q: %w", relayURL, err)
174 }
@@ -188,7 +187,7 @@ var bufferPool = sync.Pool{
187 func proxyConnection(ctx context.Context, localAddr string, relayConn net.Conn) error {
188 defer relayConn.Close()
189
191 - targetAddr, err := netutil.NormalizeTargetAddr(localAddr)
190 + targetAddr, err := types.NormalizeTargetAddr(localAddr)
191 if err != nil {
192 return fmt.Errorf("invalid --host value %q: %w", localAddr, err)
193 }
cmd/relay-server/main.go
+7 -11
@@ -15,9 +15,9 @@ import (
15 "github.com/rs/zerolog/log"
16
17 "gosuda.org/portal/portal"
18 - "gosuda.org/portal/portal/netutil"
18 "gosuda.org/portal/portal/policy"
19 "gosuda.org/portal/portal/sni"
20 + "gosuda.org/portal/types"
21 )
22
23 const (
@@ -51,9 +51,9 @@ func main() {
51 }
52 bootstrapsCSV := trimmedEnv("BOOTSTRAP_URIS")
53 if bootstrapsCSV == "" {
54 - bootstrapsCSV = netutil.DefaultBootstrapFrom(portalURL)
54 + bootstrapsCSV = types.DefaultBootstrapFrom(portalURL)
55 }
56 - sniPort := netutil.ParsePortNumber(os.Getenv("SNI_PORT"), defaultSNIPort)
56 + sniPort := types.ParsePortNumber(os.Getenv("SNI_PORT"), defaultSNIPort)
57 keylessDir := trimmedEnv("KEYLESS_DIR")
58 if keylessDir == "" {
59 keylessDir = defaultKeylessDir
@@ -75,8 +75,8 @@ func main() {
75 flag.StringVar(&cfg.CloudflareToken, "cloudflare-token", cloudflareToken, "Cloudflare DNS API token (Zone:Read + DNS:Edit) (env: CLOUDFLARE_TOKEN)")
76 flag.Parse()
77
78 - cfg.Bootstraps = netutil.ParseURLs(bootstrapsCSV)
79 - parsedTrustedProxyCIDRs, err := parseTrustedProxyCIDRs(cfg.TrustedProxyCIDRs)
78 + cfg.Bootstraps = types.ParseURLs(bootstrapsCSV)
79 + parsedTrustedProxyCIDRs, err := policy.ParseTrustedProxyCIDRs(cfg.TrustedProxyCIDRs)
80 if err != nil {
81 log.Fatal().Err(err).Msg("parse trusted proxy CIDRs")
82 }
@@ -98,8 +98,8 @@ func runServer(cfg relayServerConfig) error {
98 Strs("bootstrap_uris", cfg.Bootstraps).
99 Msg("[server] frontend configuration")
100
101 - rootHost := netutil.PortalRootHost(cfg.PortalURL)
102 - apiUpstreamAddr := netutil.LoopbackForwardAddr(fmt.Sprintf(":%d", cfg.AdminPort))
101 + rootHost := types.PortalRootHost(cfg.PortalURL)
102 + apiUpstreamAddr := types.LoopbackForwardAddr(fmt.Sprintf(":%d", cfg.AdminPort))
103 serv, err := portal.NewRelayServer(ctx, cfg.Bootstraps, sniListenAddr, rootHost, cfg.KeylessDir, cfg.CloudflareToken)
104 if err != nil {
105 return fmt.Errorf("create relay server: %w", err)
@@ -226,7 +226,3 @@ func parseBoolEnv(name string) bool {
226 raw := trimmedEnv(name)
227 return strings.EqualFold(raw, "true") || raw == "1"
228 }
229 -
230 -func parseTrustedProxyCIDRs(raw string) ([]*net.IPNet, error) {
231 - return policy.ParseTrustedProxyCIDRs(raw)
232 -}
cmd/relay-server/registry.go
+1 -1
@@ -65,7 +65,7 @@ func (r *SDKRegistry) handleConnect(w http.ResponseWriter, req *http.Request, re
65 req,
66 registryService,
67 req.URL.Query().Get("lease_id"),
68 - req.Header.Get(portal.ReverseConnectTokenHeader),
68 + req.Header.Get(types.ReverseConnectTokenHeader),
69 true,
70 )
71 if !ok {
cmd/relay-server/serve.go
+3 -4
@@ -17,7 +17,6 @@ import (
17
18 "gosuda.org/portal/portal"
19 "gosuda.org/portal/portal/keyless"
20 - "gosuda.org/portal/portal/netutil"
20 "gosuda.org/portal/portal/policy"
21 "gosuda.org/portal/types"
22 )
@@ -99,10 +98,10 @@ func serveAPI(addr string, serv *portal.RelayServer, admin *Admin, frontend *Fro
98 })
99
100 // Create the main handler
102 - appDomain := netutil.DefaultAppPattern(cfg.PortalURL)
101 + appDomain := types.DefaultAppPattern(cfg.PortalURL)
102 handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
103 // Handle subdomain requests
105 - if netutil.IsSubdomain(appDomain, r.Host) {
104 + if types.IsSubdomain(appDomain, r.Host) {
105 log.Debug().
106 Str("host", r.Host).
107 Str("url", r.URL.String()).
@@ -129,7 +128,7 @@ func serveAPI(addr string, serv *portal.RelayServer, admin *Admin, frontend *Fro
128 TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
129 }
130 acmeManager := serv.GetACMEManager()
132 - rootHost := netutil.PortalRootHost(cfg.PortalURL)
131 + rootHost := types.PortalRootHost(cfg.PortalURL)
132 srv.TLSConfig = &tls.Config{
133 ClientAuth: tls.RequestClientCert,
134 GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
cmd/relay-server/utils.go
+4 -5
@@ -12,7 +12,6 @@ import (
12
13 "gosuda.org/portal/portal"
14 "gosuda.org/portal/portal/keyless"
15 - "gosuda.org/portal/portal/netutil"
15 "gosuda.org/portal/portal/policy"
16 "gosuda.org/portal/types"
17 )
@@ -195,15 +194,15 @@ func (r *leaseRow) fromLeaseEntry(entry *types.LeaseEntry, admin *Admin, portalU
194 r.FirstSeenISO = entry.FirstSeen.UTC().Format(time.RFC3339)
195 r.TTL = r.formatDuration(time.Until(entry.Expires))
196 linkLabel := identityID
198 - if normalized, ok := netutil.NormalizeServiceName(lease.Name); ok {
197 + if normalized, ok := types.NormalizeServiceName(lease.Name); ok {
198 linkLabel = normalized
200 - } else if normalized, ok := netutil.NormalizeServiceName(identityID); ok {
199 + } else if normalized, ok := types.NormalizeServiceName(identityID); ok {
200 linkLabel = normalized
201 }
202
204 - publicHost := netutil.PortalRootHost(portalURL)
203 + publicHost := types.PortalRootHost(portalURL)
204 if publicHost == "" {
206 - publicHost = netutil.PortalHostPort(portalURL)
205 + publicHost = types.PortalHostPort(portalURL)
206 }
207 if linkLabel != "" && publicHost != "" {
208 r.Link = fmt.Sprintf("//%s.%s/", linkLabel, publicHost)
portal/controlplane/registry/service.go
+1 -1
@@ -128,7 +128,7 @@ func (s *Service) Admit(input AdmissionInput) (AdmissionResult, *types.APIError)
128 // Register creates a new lease and associated SNI route.
129 func (s *Service) Register(input RegisterInput) (types.RegisterResponse, *types.APIError) {
130 name := strings.TrimSpace(input.Name)
131 - if !types.IsValidLeaseName(name) {
131 + if !types.IsValidServiceName(name) {
132 return types.RegisterResponse{}, apiError(httpStatusBadRequest, "invalid_name", "name must be a DNS label (letters, digits, hyphen; no dots or underscores)")
133 }
134 if !input.TLS {
portal/keyless/client.go
+2 -2
@@ -16,7 +16,7 @@ import (
16
17 keylesstls "github.com/gosuda/keyless_tls/keyless"
18
19 - "gosuda.org/portal/portal/netutil"
19 + "gosuda.org/portal/types"
20 )
21
22 // BuildClientTLSConfig builds a keyless TLS server config for tunnel-side TLS termination.
@@ -185,7 +185,7 @@ func FetchEndpointCertificateChain(ctx context.Context, endpoint string, serverN
185 tlsConn := tls.Client(rawConn, &tls.Config{
186 MinVersion: tls.VersionTLS12,
187 ServerName: serverName,
188 - InsecureSkipVerify: netutil.IsLocalhost(host),
188 + InsecureSkipVerify: types.IsLocalhost(host),
189 })
190 defer tlsConn.Close()
191 if err := tlsConn.HandshakeContext(ctx); err != nil {
portal/keyless/signer.go
+2 -12
@@ -5,7 +5,6 @@ import (
5 "errors"
6 "fmt"
7 "os"
8 - "strings"
8 "time"
9
10 ksigner "github.com/gosuda/keyless_tls/relay/signer"
@@ -33,17 +32,8 @@ type Signer struct {
32 keyID string
33 }
34
36 -type Config struct {
37 - KeyFile string
38 -}
39 -
40 -func NewSigner(cfg Config) (*Signer, error) {
41 - keyFile := strings.TrimSpace(cfg.KeyFile)
42 - if keyFile == "" {
43 - return nil, nil
44 - }
45 -
46 - keyPEM, err := os.ReadFile(keyFile)
35 +func NewSigner(KeyFile string) (*Signer, error) {
36 + keyPEM, err := os.ReadFile(KeyFile)
37 if err != nil {
38 if errors.Is(err, os.ErrNotExist) {
39 return nil, nil
portal/netutil/netutil.go deleted
-59
@@ -1,59 +0,0 @@
1 -package netutil
2 -
3 -import "gosuda.org/portal/types"
4 -
5 -func NormalizeServiceName(name string) (string, bool) {
6 - return types.NormalizeServiceName(name)
7 -}
8 -
9 -func IsSubdomain(domain, host string) bool {
10 - return types.IsSubdomain(domain, host)
11 -}
12 -
13 -func DefaultAppPattern(base string) string {
14 - return types.DefaultAppPattern(base)
15 -}
16 -
17 -func PortalHostPort(portalURL string) string {
18 - return types.PortalHostPort(portalURL)
19 -}
20 -
21 -func PortalRootHost(portalURL string) string {
22 - return types.PortalRootHost(portalURL)
23 -}
24 -
25 -func IsLocalhost(host string) bool {
26 - return types.IsLocalhost(host)
27 -}
28 -
29 -func DefaultBootstrapFrom(base string) string {
30 - return types.DefaultBootstrapFrom(base)
31 -}
32 -
33 -func ParseURLs(raw string) []string {
34 - return types.ParseURLs(raw)
35 -}
36 -
37 -func ParsePortNumber(raw string, fallback int) int {
38 - return types.ParsePortNumber(raw, fallback)
39 -}
40 -
41 -func LoopbackForwardAddr(listenAddr string) string {
42 - return types.LoopbackForwardAddr(listenAddr)
43 -}
44 -
45 -func IsValidLeaseName(name string) bool {
46 - return types.IsValidLeaseName(name)
47 -}
48 -
49 -func NormalizeRelayAPIURLs(bootstrapServers []string) ([]string, error) {
50 - return types.NormalizeRelayAPIURLs(bootstrapServers)
51 -}
52 -
53 -func NormalizeRelayAPIURL(relayURL string) (string, error) {
54 - return types.NormalizeRelayAPIURL(relayURL)
55 -}
56 -
57 -func NormalizeTargetAddr(targetAddr string) (string, error) {
58 - return types.NormalizeTargetAddr(targetAddr)
59 -}
portal/relay.go
+1 -3
@@ -54,9 +54,7 @@ func NewRelayServer(
54 }
55 server.acmeManager = acmeManager
56
57 - signer, err := keyless.NewSigner(keyless.Config{
58 - KeyFile: keyFile,
59 - })
57 + signer, err := keyless.NewSigner(keyFile)
58 if err != nil {
59 return nil, fmt.Errorf("configure keyless signer: %w", err)
60 }
portal/reverse_hub.go
+3 -10
@@ -10,14 +10,10 @@ import (
10
11 "github.com/rs/zerolog/log"
12
13 - "gosuda.org/portal/portal/sni"
13 + "gosuda.org/portal/types"
14 )
15
16 const (
17 - // ReverseKeepaliveMarker keeps idle reverse connections alive
18 - // before they are activated for a real client request.
19 - ReverseKeepaliveMarker = byte(0x00)
20 -
17 // QueueSize is the maximum number of pending reverse connections per lease.
18 QueueSize = 64
19
@@ -36,9 +32,6 @@ const (
32 // ReverseIdleKeepaliveInterval sends an idle keepalive byte to reduce
33 // reverse connection disconnections from intermediate idle timeouts.
34 ReverseIdleKeepaliveInterval = 25 * time.Second
39 -
40 - // ReverseConnectTokenHeader carries reverse auth token on /sdk/connect requests.
41 - ReverseConnectTokenHeader = "X-Portal-Reverse-Token"
35 )
36
37 // ReverseConn wraps a net.Conn with lifecycle management for the connection pool.
@@ -265,7 +258,7 @@ func (h *ReverseHub) AcquireForTLS(leaseID string, timeout time.Duration) (*Reve
258 }
259 // Stop idle keepalive and signal tunnel worker to release this connection.
260 conn.Activate()
268 - err := conn.WriteControlByte(sni.TLSStartMarker, controlWriteTimeout)
261 + err := conn.WriteControlByte(types.TLSStartMarker, controlWriteTimeout)
262 if err == nil {
263 return conn, nil
264 }
@@ -395,7 +388,7 @@ func (h *ReverseHub) keepAliveWhileIdle(conn *ReverseConn, leaseID string) {
388 case <-conn.active:
389 return
390 case <-ticker.C:
398 - if err := conn.WriteControlByte(ReverseKeepaliveMarker, controlWriteTimeout); err != nil {
391 + if err := conn.WriteControlByte(types.ReverseKeepaliveMarker, controlWriteTimeout); err != nil {
392 log.Debug().
393 Err(err).
394 Str("lease_id", leaseID).
portal/reverse_hub_test.go
+5 -5
@@ -7,7 +7,7 @@ import (
7 "testing"
8 "time"
9
10 - "gosuda.org/portal/portal/sni"
10 + "gosuda.org/portal/types"
11 )
12
13 func TestReverseHubAuthorization(t *testing.T) {
@@ -115,7 +115,7 @@ func TestHandleConnectTrimsLeaseIDAndToken(t *testing.T) {
115 case err := <-readErr:
116 t.Fatalf("failed to read marker: %v", err)
117 case marker := <-markerRead:
118 - if marker != sni.TLSStartMarker {
118 + if marker != types.TLSStartMarker {
119 t.Fatalf("unexpected marker: %d", marker)
120 }
121 case <-time.After(500 * time.Millisecond):
@@ -170,7 +170,7 @@ func TestAcquireForTLSSendsStartMarker(t *testing.T) {
170 case err := <-readErr:
171 t.Fatalf("failed to read marker: %v", err)
172 case b := <-markerRead:
173 - if b != sni.TLSStartMarker {
173 + if b != types.TLSStartMarker {
174 t.Fatalf("unexpected marker: %d", b)
175 }
176 case <-time.After(500 * time.Millisecond):
@@ -228,7 +228,7 @@ func TestAcquireForTLSPollLoopSendsStartMarker(t *testing.T) {
228 case err := <-readErr:
229 t.Fatalf("failed to read marker: %v", err)
230 case b := <-markerRead:
231 - if b != sni.TLSStartMarker {
231 + if b != types.TLSStartMarker {
232 t.Fatalf("unexpected marker: %d", b)
233 }
234 case <-time.After(500 * time.Millisecond):
@@ -295,7 +295,7 @@ func TestHandleConnectOffersAuthorizedConn(t *testing.T) {
295 case err := <-readErr:
296 t.Fatalf("failed to read start marker: %v", err)
297 case b := <-markerRead:
298 - if b != sni.TLSStartMarker {
298 + if b != types.TLSStartMarker {
299 t.Fatalf("unexpected marker: %d", b)
300 }
301 case <-time.After(500 * time.Millisecond):
portal/sni/parser.go
+14 -13
@@ -11,10 +11,11 @@ import (
11 )
12
13 const (
14 - // TLSStartMarker activates a reverse TCP connection for TLS passthrough.
15 - TLSStartMarker = byte(0x02)
16 - // NonTLSStartMarker is reserved for non-TLS protocol marker tests.
17 - NonTLSStartMarker = byte(0x01)
14 + // TLS wire constants for ClientHello/SNI parsing.
15 + tlsRecordContentTypeHandshake = byte(0x16)
16 + tlsHandshakeTypeClientHello = byte(0x01)
17 + tlsExtensionTypeServerName = uint16(0x0000)
18 + tlsServerNameTypeHostName = byte(0x00)
19 )
20
21 var (
@@ -39,8 +40,8 @@ func ExtractSNI(r io.Reader) (string, error) {
40 return "", fmt.Errorf("reading TLS header: %w", err)
41 }
42
42 - // Check ContentType (0x16 = Handshake)
43 - if header[0] != 0x16 {
43 + // Check ContentType (handshake)
44 + if header[0] != tlsRecordContentTypeHandshake {
45 return "", ErrNotClientHello
46 }
47
@@ -73,8 +74,8 @@ func parseHandshake(data []byte) (string, error) {
74 return "", ErrInvalidTLSRecord
75 }
76
76 - // Check if it's a ClientHello (0x01)
77 - if handshakeType != 0x01 {
77 + // Check if it's a ClientHello.
78 + if handshakeType != tlsHandshakeTypeClientHello {
79 return "", ErrNotClientHello
80 }
81
@@ -168,8 +169,8 @@ func parseExtensions(data []byte) (string, error) {
169 return "", ErrInvalidTLSRecord
170 }
171
171 - // Extension Type 0x0000 = server_name (SNI)
172 - if extType == 0x0000 {
172 + // Extension Type server_name (SNI)
173 + if extType == tlsExtensionTypeServerName {
174 return parseSNIExtension(data[offset : offset+extLen])
175 }
176
@@ -211,8 +212,8 @@ func parseSNIExtension(data []byte) (string, error) {
212 return "", ErrInvalidTLSRecord
213 }
214
214 - // Name Type 0x00 = host_name
215 - if nameType == 0x00 {
215 + // Name Type host_name
216 + if nameType == tlsServerNameTypeHostName {
217 if nameLen == 0 {
218 return "", ErrNoSNI
219 }
@@ -285,7 +286,7 @@ func PeekSNI(r io.Reader, bufSize int) (string, io.Reader, error) {
286 if _, err := io.ReadFull(r, header); err != nil {
287 return "", nil, fmt.Errorf("peeking TLS header: %w", err)
288 }
288 - if header[0] != 0x16 {
289 + if header[0] != tlsRecordContentTypeHandshake {
290 reader := io.MultiReader(bytes.NewReader(header), r)
291 return "", reader, ErrNotClientHello
292 }
sdk/client.go
+4 -5
@@ -23,7 +23,6 @@ import (
23 "github.com/gosuda/keyless_tls/keyless/lifecycle"
24
25 "gosuda.org/portal/portal/keyless"
26 - "gosuda.org/portal/portal/netutil"
26 "gosuda.org/portal/types"
27 )
28
@@ -94,11 +93,11 @@ func (c *Client) Listen(name string, options ...types.MetadataOption) (net.Liste
93 if name == "" {
94 return nil, errors.New("name is required")
95 }
97 - if !netutil.IsValidLeaseName(name) {
96 + if !types.IsValidServiceName(name) {
97 return nil, ErrInvalidName
98 }
99
101 - relayAddrs, err := netutil.NormalizeRelayAPIURLs(c.config.BootstrapServers)
100 + relayAddrs, err := types.NormalizeRelayAPIURLs(c.config.BootstrapServers)
101 if err != nil {
102 return nil, ErrNoAvailableRelay
103 }
@@ -210,7 +209,7 @@ func acquireLifecycleIdentity(leaseID string) (tls.Certificate, error) {
209 return tls.Certificate{}, fmt.Errorf("acquire lifecycle identity for lease %s: %w", leaseID, err)
210 }
211
213 - cert, leaf, bundle, err := decodeLifecycleIdentityBundleWithReissue(ctx, manager, leaseID, bundle)
212 + cert, leaf, _, err := decodeLifecycleIdentityBundleWithReissue(ctx, manager, leaseID, bundle)
213 if err != nil {
214 return tls.Certificate{}, err
215 }
@@ -368,7 +367,7 @@ func (c *Client) buildTLSConfig(relayAddr, leaseName string) (*tls.Config, []fun
367 if keylessServerName == "" {
368 return nil, nil, fmt.Errorf("relay hostname is required: %s", relayAddr)
369 }
371 - baseHost := netutil.PortalRootHost(relayAddr)
370 + baseHost := types.PortalRootHost(relayAddr)
371 if baseHost == "" {
372 return nil, nil, fmt.Errorf("keyless base host is required for relay %s", relayAddr)
373 }
sdk/listener.go
+7 -10
@@ -18,9 +18,6 @@ import (
18
19 "github.com/rs/zerolog/log"
20
21 - "gosuda.org/portal/portal"
22 - "gosuda.org/portal/portal/netutil"
23 - "gosuda.org/portal/portal/sni"
21 "gosuda.org/portal/types"
22 )
23
@@ -126,16 +123,16 @@ func NewListener(relayAddr string, lease *types.Lease, tlsConfig *tls.Config, co
123 return nil, errors.New("control plane client certificate is required")
124 }
125
129 - apiURL, err := netutil.NormalizeRelayAPIURL(relayAddr)
126 + apiURL, err := types.NormalizeRelayAPIURL(relayAddr)
127 if err != nil {
128 return nil, err
129 }
133 - host := netutil.PortalRootHost(apiURL)
130 + host := types.PortalRootHost(apiURL)
131 clientTransport := http.DefaultTransport.(*http.Transport).Clone()
132 clientTransport.TLSClientConfig = &tls.Config{
133 MinVersion: tls.VersionTLS12,
134 ServerName: host,
138 - InsecureSkipVerify: netutil.IsLocalhost(host),
135 + InsecureSkipVerify: types.IsLocalhost(host),
136 Certificates: []tls.Certificate{controlPlaneCert},
137 }
138
@@ -317,7 +314,7 @@ func (l *Listener) reverseAcceptWorker(workerID int) {
314 continue
315 }
316
320 - err = l.waitForReverseStart(conn, sni.TLSStartMarker)
317 + err = l.waitForReverseStart(conn, types.TLSStartMarker)
318 if err != nil {
319 if closeErr := conn.Close(); closeErr != nil {
320 log.Debug().Err(closeErr).Msg("[SDK] failed to close reverse connection")
@@ -410,7 +407,7 @@ func (l *Listener) openReverseConnection() (net.Conn, error) {
407 tlsConn := tls.Client(rawConn, &tls.Config{
408 MinVersion: tls.VersionTLS12,
409 ServerName: serverName,
413 - InsecureSkipVerify: netutil.IsLocalhost(serverName),
410 + InsecureSkipVerify: types.IsLocalhost(serverName),
411 Certificates: []tls.Certificate{l.controlPlaneCert},
412 })
413 err = tlsConn.HandshakeContext(ctx)
@@ -490,7 +487,7 @@ func buildReverseConnectRequest(u *url.URL, reverseToken string) (*http.Request,
487 return nil, fmt.Errorf("build reverse connect request: %w", err)
488 }
489 req.Host = u.Host
493 - req.Header.Set(portal.ReverseConnectTokenHeader, token)
490 + req.Header.Set(types.ReverseConnectTokenHeader, token)
491 req.Header.Set("Connection", "keep-alive")
492 return req, nil
493 }
@@ -627,7 +624,7 @@ func (l *Listener) waitForReverseStart(conn net.Conn, expectedMarker byte) error
624 _, err := io.ReadFull(conn, marker[:])
625 if err == nil {
626 _ = conn.SetReadDeadline(time.Time{})
630 - if marker[0] == portal.ReverseKeepaliveMarker {
627 + if marker[0] == types.ReverseKeepaliveMarker {
628 continue
629 }
630 if marker[0] == expectedMarker {
sdk/listener_test.go
+13 -15
@@ -12,8 +12,6 @@ import (
12 "testing"
13 "time"
14
15 - "gosuda.org/portal/portal"
16 - "gosuda.org/portal/portal/sni"
15 "gosuda.org/portal/types"
16 )
17
@@ -161,7 +159,7 @@ func TestBuildReverseConnectRequest(t *testing.T) {
159 if req.URL.Query().Get("token") != "" {
160 t.Fatalf("token must not be present in query: %q", req.URL.RawQuery)
161 }
164 - if got := req.Header.Get(portal.ReverseConnectTokenHeader); got != "token-1" {
162 + if got := req.Header.Get(types.ReverseConnectTokenHeader); got != "token-1" {
163 t.Fatalf("unexpected reverse token header: got %q want %q", got, "token-1")
164 }
165 }
@@ -482,10 +480,10 @@ func TestWaitForReverseStart_HTTPMode(t *testing.T) {
480
481 done := make(chan error, 1)
482 go func() {
485 - done <- l.waitForReverseStart(local, sni.TLSStartMarker)
483 + done <- l.waitForReverseStart(local, types.TLSStartMarker)
484 }()
485
488 - _, err := peer.Write([]byte{sni.TLSStartMarker})
486 + _, err := peer.Write([]byte{types.TLSStartMarker})
487 if err != nil {
488 t.Fatalf("write marker: %v", err)
489 }
@@ -513,10 +511,10 @@ func TestWaitForReverseStart_TLSMode(t *testing.T) {
511
512 done := make(chan error, 1)
513 go func() {
516 - done <- l.waitForReverseStart(local, sni.TLSStartMarker)
514 + done <- l.waitForReverseStart(local, types.TLSStartMarker)
515 }()
516
519 - _, err := peer.Write([]byte{sni.TLSStartMarker})
517 + _, err := peer.Write([]byte{types.TLSStartMarker})
518 if err != nil {
519 t.Fatalf("write marker: %v", err)
520 }
@@ -541,14 +539,14 @@ func TestWaitForReverseStart_IgnoresKeepaliveMarker(t *testing.T) {
539
540 done := make(chan error, 1)
541 go func() {
544 - done <- l.waitForReverseStart(local, sni.TLSStartMarker)
542 + done <- l.waitForReverseStart(local, types.TLSStartMarker)
543 }()
544
547 - _, err := peer.Write([]byte{portal.ReverseKeepaliveMarker})
545 + _, err := peer.Write([]byte{types.ReverseKeepaliveMarker})
546 if err != nil {
547 t.Fatalf("write keepalive marker: %v", err)
548 }
551 - _, err = peer.Write([]byte{sni.TLSStartMarker})
549 + _, err = peer.Write([]byte{types.TLSStartMarker})
550 if err != nil {
551 t.Fatalf("write start marker: %v", err)
552 }
@@ -576,10 +574,10 @@ func TestWaitForReverseStart_TLSRejectsHTTPMarker(t *testing.T) {
574
575 done := make(chan error, 1)
576 go func() {
579 - done <- l.waitForReverseStart(local, sni.TLSStartMarker)
577 + done <- l.waitForReverseStart(local, types.TLSStartMarker)
578 }()
579
582 - _, err := peer.Write([]byte{sni.NonTLSStartMarker})
580 + _, err := peer.Write([]byte{types.NonTLSStartMarker})
581 if err != nil {
582 t.Fatalf("write marker: %v", err)
583 }
@@ -604,10 +602,10 @@ func TestWaitForReverseStart_HTTPRejectsTLSMarker(t *testing.T) {
602
603 done := make(chan error, 1)
604 go func() {
607 - done <- l.waitForReverseStart(local, sni.NonTLSStartMarker)
605 + done <- l.waitForReverseStart(local, types.NonTLSStartMarker)
606 }()
607
610 - _, err := peer.Write([]byte{sni.TLSStartMarker})
608 + _, err := peer.Write([]byte{types.TLSStartMarker})
609 if err != nil {
610 t.Fatalf("write marker: %v", err)
611 }
@@ -631,7 +629,7 @@ func TestWaitForReverseStart_StopCancelsWait(t *testing.T) {
629
630 done := make(chan error, 1)
631 go func() {
634 - done <- l.waitForReverseStart(local, sni.TLSStartMarker)
632 + done <- l.waitForReverseStart(local, types.TLSStartMarker)
633 }()
634
635 close(l.stopCh)
types/lease.go deleted
-21
@@ -1,21 +0,0 @@
1 -package types
2 -
3 -import "time"
4 -
5 -// Lease represents a registered service.
6 -type Lease struct {
7 - Expires time.Time `json:"expires"`
8 - ID string `json:"id"`
9 - Name string `json:"name"`
10 - ReverseToken string `json:"-"`
11 - Metadata Metadata `json:"metadata"`
12 - TLS bool `json:"tls"`
13 -}
14 -
15 -// LeaseEntry represents a registered lease with expiration tracking.
16 -type LeaseEntry struct {
17 - Lease *Lease
18 - Expires time.Time
19 - LastSeen time.Time
20 - FirstSeen time.Time
21 -}
types/netutil.go
-5
@@ -290,11 +290,6 @@ func BuildSNIName(leaseName, baseHost string) string {
290 return normalizedLeaseName + "." + normalizedBaseHost
291 }
292
293 -// IsValidLeaseName reports whether a lease/service name is DNS-label-safe.
294 -func IsValidLeaseName(name string) bool {
295 - return IsValidServiceName(name)
296 -}
297 -
293 // ParseURLs splits a comma-separated string into a list of trimmed, non-empty URLs.
294 func ParseURLs(raw string) []string {
295 raw = strings.TrimSpace(raw)
types/netutil_test.go
+5 -5
@@ -203,14 +203,14 @@ func TestNonApexPortalRoundTrip(t *testing.T) {
203 }
204 }
205
206 -func TestIsValidLeaseNameUsesServiceValidation(t *testing.T) {
206 +func TestIsValidServiceName(t *testing.T) {
207 t.Parallel()
208
209 - if !IsValidLeaseName("my-app") {
210 - t.Fatalf("expected valid lease name")
209 + if !IsValidServiceName("my-app") {
210 + t.Fatalf("expected valid service name")
211 }
212 - if IsValidLeaseName("my_app") {
213 - t.Fatalf("expected underscore to be invalid for DNS-safe lease names")
212 + if IsValidServiceName("my_app") {
213 + t.Fatalf("expected underscore to be invalid for DNS-safe service names")
214 }
215 }
216
types/types.go renamed
+28
@@ -1,5 +1,33 @@
1 package types
2
3 +import "time"
4 +
5 +const (
6 + // Reverse-connect protocol markers and headers.
7 + ReverseKeepaliveMarker = byte(0x00)
8 + NonTLSStartMarker = byte(0x01)
9 + TLSStartMarker = byte(0x02)
10 + ReverseConnectTokenHeader = "X-Portal-Reverse-Token"
11 +)
12 +
13 +// Lease represents a registered service.
14 +type Lease struct {
15 + Expires time.Time `json:"expires"`
16 + ID string `json:"id"`
17 + Name string `json:"name"`
18 + ReverseToken string `json:"-"`
19 + Metadata Metadata `json:"metadata"`
20 + TLS bool `json:"tls"`
21 +}
22 +
23 +// LeaseEntry represents a registered lease with expiration tracking.
24 +type LeaseEntry struct {
25 + Lease *Lease
26 + Expires time.Time
27 + LastSeen time.Time
28 + FirstSeen time.Time
29 +}
30 +
31 // Metadata holds service metadata for a lease.
32 type Metadata struct {
33 Description string `json:"description,omitempty"`