Files
godoxy/internal/net
yusing 1705f77060 refactor(entrypoint): propagate errors from route registration and stream serving
Changed AddRoute and ListenAndServe methods to return errors instead of logging them internally and continuing. This allows callers to properly handle and propagate errors, improving error visibility and enabling better error management across the codebase. Updated all callers in fileserver, reverse_proxy, stream routes to handle these errors appropriately.
2026-02-07 21:06:22 +08:00
..
2025-04-24 15:02:31 +08:00

Network Utilities

The net package provides network utility functions for GoDoxy, including TCP connection testing and network-related helpers.

Overview

The net package implements network utility functions that are used throughout GoDoxy for connectivity testing, TCP operations, and network-related utilities.

Key Features

  • TCP connection testing (ping)
  • Connection utilities

Core Functions

TCP Ping

// PingTCP pings a TCP endpoint by attempting a connection.
func PingTCP(ctx context.Context, ip net.IP, port int) error

Usage

Basic Usage

import "github.com/yusing/godoxy/internal/net"

func checkService(ctx context.Context, ip string, port int) error {
    addr := net.ParseIP(ip)
    if addr == nil {
        return fmt.Errorf("invalid IP: %s", ip)
    }

    err := net.PingTCP(ctx, addr, port)
    if err != nil {
        return fmt.Errorf("service %s:%d unreachable: %w", ip, port, err)
    }

    fmt.Printf("Service %s:%d is reachable\n", ip, port)
    return nil
}

Timeout Usage

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

ip := net.ParseIP("192.168.1.100")
err := net.PingTCP(ctx, ip, 8080)

if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        log.Println("Connection timed out")
    } else {
        log.Printf("Connection failed: %v", err)
    }
}

Implementation

func PingTCP(ctx context.Context, ip net.IP, port int) error {
    var dialer net.Dialer
    conn, err := dialer.DialContext(ctx, "tcp", fmt.Sprintf("%s:%d", ip, port))
    if err != nil {
        return err
    }
    conn.Close()
    return nil
}

Data Flow

sequenceDiagram
    participant Caller
    participant Dialer
    participant TCPEndpoint
    participant Connection

    Caller->>Dialer: DialContext("tcp", "ip:port")
    Dialer->>TCPEndpoint: SYN
    TCPEndpoint-->>Dialer: SYN-ACK
    Dialer->>Connection: Create connection
    Connection-->>Dialer: Connection
    Dialer-->>Caller: nil error

    Note over Caller,Connection: Connection immediately closed
    Connection->>TCPEndpoint: FIN
    TCPEndpoint-->>Connection: FIN-ACK

Use Cases

Service Health Check

func checkServices(ctx context.Context, services []Service) error {
    for _, svc := range services {
        ip := net.ParseIP(svc.IP)
        if ip == nil {
            return fmt.Errorf("invalid IP for %s: %s", svc.Name, svc.IP)
        }

        if err := net.PingTCP(ctx, ip, svc.Port); err != nil {
            return fmt.Errorf("service %s (%s:%d) unreachable: %w",
                svc.Name, svc.IP, svc.Port, err)
        }
    }
    return nil
}

Proxmox Container Reachability

// Check if a Proxmox container is reachable on its proxy port
func checkContainerReachability(ctx context.Context, node *proxmox.Node, vmid int, port int) error {
    ips, err := node.LXCGetIPs(ctx, vmid)
    if err != nil {
        return err
    }

    for _, ip := range ips {
        if err := net.PingTCP(ctx, ip, port); err == nil {
            return nil // Found reachable IP
        }
    }

    return fmt.Errorf("no reachable IP found for container %d", vmid)
}
  • Route: Uses TCP ping for load balancing health checks
  • Proxmox: Uses TCP ping to verify container reachability
  • Idlewatcher: Uses TCP ping to check idle status