diff --git a/tcp/doc.go b/tcp/doc.go deleted file mode 100644 index be63989..0000000 --- a/tcp/doc.go +++ /dev/null @@ -1,28 +0,0 @@ -// Package tcp provides a minimal, production-hardened TCP listener implementation -// with secure cross-platform defaults suitable for internet-facing services. -// -// This package exports a single function Listen() that creates TCP listeners -// with optimized settings for production workloads including connection reuse, -// keep-alive monitoring, optimized buffer sizes, and minimal latency configuration. -// -// The implementation uses only Go standard library components to ensure -// compatibility across Windows, Linux, macOS, and BSD systems without -// requiring platform-specific code or external dependencies. -// -// Example usage: -// -// listener, err := tcp.Listen("tcp", ":8080") -// if err != nil { -// log.Fatalf("Failed to create listener: %v", err) -// } -// defer listener.Close() -// -// for { -// conn, err := listener.Accept() -// if err != nil { -// log.Printf("Accept error: %v", err) -// continue -// } -// go handleConnection(conn) -// } -package tcp diff --git a/tcp/listen.go b/tcp/listen.go deleted file mode 100644 index a81e22e..0000000 --- a/tcp/listen.go +++ /dev/null @@ -1,140 +0,0 @@ -package tcp - -import ( - "fmt" - "net" - "syscall" - "time" -) - -const ( - // Production-optimized defaults - keepAliveInterval = 30 * time.Second - bufferSize = 64 * 1024 // 64KB - connectionBacklog = 128 -) - -// Listen creates a TCP listener with production-hardened defaults suitable -// for internet-facing services. The implementation applies secure socket -// options including address reuse, keep-alive monitoring, optimized buffers, -// and minimal latency configuration. -// -// Parameters: -// - network: Must be "tcp", "tcp4", or "tcp6" -// - address: Standard Go network address format (e.g., ":8080", "127.0.0.1:8080") -// -// Returns a net.Listener configured with production defaults, or an error -// if the listener cannot be created or configured. -// -// The listener applies these optimizations: -// - SO_REUSEADDR: Prevents "address already in use" during rapid restarts -// - Keep-alive: 30-second interval for connection health monitoring -// - Buffer sizes: 64KB receive/send buffers for optimal throughput -// - TCP_NODELAY: Enabled to minimize latency -// - Backlog: 128 pending connections in accept queue -func Listen(network, address string) (net.Listener, error) { - // Validate network parameter - if !isValidNetwork(network) { - return nil, fmt.Errorf("tcp.Listen: invalid network type %q for addr %s, must be tcp, tcp4, or tcp6", network, address) - } - - // Validate address format by attempting to resolve - if _, err := net.ResolveTCPAddr(network, address); err != nil { - return nil, fmt.Errorf("tcp.Listen: invalid address %q for network %q: %w", address, network, err) - } - - // Create the base listener - listener, err := net.Listen(network, address) - if err != nil { - return nil, fmt.Errorf("tcp.Listen: failed to create listener on %s %s: %w", network, address, err) - } - - // Apply production socket configurations - tcpListener, ok := listener.(*net.TCPListener) - if !ok { - listener.Close() - return nil, fmt.Errorf("tcp.Listen: unexpected listener type for %s %s", network, address) - } - - // Configure the underlying socket with production defaults - if err := configureSocket(tcpListener); err != nil { - // Ensure proper cleanup even if socket is in inconsistent state - if closeErr := listener.Close(); closeErr != nil { - // Log the close error but return the original configuration error - // since that's the primary failure point - return nil, fmt.Errorf("tcp.Listen: failed to configure socket options for %s %s (%w), and failed to close listener (%v)", network, address, err, closeErr) - } - return nil, fmt.Errorf("tcp.Listen: failed to configure socket options for %s %s: %w", network, address, err) - } - - return tcpListener, nil -} - -// isValidNetwork validates the network parameter -func isValidNetwork(network string) bool { - switch network { - case "tcp", "tcp4", "tcp6": - return true - default: - return false - } -} - -// configureSocket applies production-ready socket options to the TCP listener -func configureSocket(listener *net.TCPListener) error { - // Use SyscallConn to access the raw socket without duplicating the file descriptor - rawConn, err := listener.SyscallConn() - if err != nil { - return fmt.Errorf("failed to get listener syscall connection: %w", err) - } - - // Apply socket options using the raw connection - var sockErr error - err = rawConn.Control(func(fd uintptr) { - // Enable SO_REUSEADDR to prevent "address already in use" errors - if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { - sockErr = fmt.Errorf("failed to set SO_REUSEADDR: %w", err) - return - } - - // Enable SO_KEEPALIVE for connection health monitoring - if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil { - sockErr = fmt.Errorf("failed to set SO_KEEPALIVE: %w", err) - return - } - - // Set keep-alive probe interval (Linux-specific, gracefully degrade on other platforms) - keepAliveSeconds := int(keepAliveInterval.Seconds()) - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, keepAliveSeconds); err != nil { - // TCP_KEEPINTVL may not be available on all platforms, continue without failing - // The SO_KEEPALIVE setting above will still provide basic keep-alive functionality - } - - // Set receive buffer size for optimal throughput - if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, bufferSize); err != nil { - sockErr = fmt.Errorf("failed to set receive buffer size: %w", err) - return - } - - // Set send buffer size for optimal throughput - if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUF, bufferSize); err != nil { - sockErr = fmt.Errorf("failed to set send buffer size: %w", err) - return - } - - // Enable TCP_NODELAY to minimize latency (disable Nagle's algorithm) - if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1); err != nil { - sockErr = fmt.Errorf("failed to set TCP_NODELAY: %w", err) - return - } - }) - - if err != nil { - return fmt.Errorf("failed to access socket for configuration: %w", err) - } - if sockErr != nil { - return sockErr - } - - return nil -} diff --git a/tcp/listen_test.go b/tcp/listen_test.go deleted file mode 100644 index bdd6f53..0000000 --- a/tcp/listen_test.go +++ /dev/null @@ -1,295 +0,0 @@ -package tcp - -import ( - "fmt" - "net" - "strings" - "sync" - "testing" - "time" -) - -func TestListen_ValidNetworks(t *testing.T) { - testCases := []struct { - network string - address string - }{ - {"tcp", ":0"}, - {"tcp4", ":0"}, - {"tcp6", ":0"}, - {"tcp", "127.0.0.1:0"}, - {"tcp4", "127.0.0.1:0"}, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("%s_%s", tc.network, tc.address), func(t *testing.T) { - listener, err := Listen(tc.network, tc.address) - if err != nil { - t.Fatalf("Listen(%s, %s) failed: %v", tc.network, tc.address, err) - } - defer listener.Close() - - // Verify we can get the actual address - addr := listener.Addr() - if addr == nil { - t.Fatal("Listener address is nil") - } - - // Verify the address has expected network type - if !strings.HasPrefix(addr.Network(), "tcp") { - t.Errorf("Expected tcp network, got %s", addr.Network()) - } - }) - } -} - -func TestListen_InvalidNetworks(t *testing.T) { - invalidNetworks := []string{"udp", "unix", "ip", "", "TCP", "tcp1"} - - for _, network := range invalidNetworks { - t.Run(network, func(t *testing.T) { - _, err := Listen(network, ":0") - if err == nil { - t.Fatalf("Listen(%s, :0) should have failed", network) - } - - expectedMsg := "invalid network type" - if !strings.Contains(err.Error(), expectedMsg) { - t.Errorf("Error should contain %q, got: %v", expectedMsg, err) - } - }) - } -} - -func TestListen_InvalidAddresses(t *testing.T) { - invalidAddresses := []string{ - ":::", - ":::8080", - "256.256.256.256:8080", - "invalid:address", - "127.0.0.1:99999", - } - - for _, addr := range invalidAddresses { - t.Run(addr, func(t *testing.T) { - _, err := Listen("tcp", addr) - if err == nil { - t.Fatalf("Listen(tcp, %s) should have failed", addr) - } - - expectedMsg := "invalid address" - if !strings.Contains(err.Error(), expectedMsg) { - t.Errorf("Error should contain %q, got: %v", expectedMsg, err) - } - }) - } -} - -func TestListen_AcceptConnections(t *testing.T) { - listener, err := Listen("tcp", ":0") - if err != nil { - t.Fatalf("Failed to create listener: %v", err) - } - defer listener.Close() - - addr := listener.Addr().String() - - // Test accepting multiple connections - const numConnections = 5 - var wg sync.WaitGroup - - // Start accepting connections - wg.Add(1) - go func() { - defer wg.Done() - for i := 0; i < numConnections; i++ { - conn, err := listener.Accept() - if err != nil { - t.Errorf("Accept failed: %v", err) - return - } - conn.Close() - } - }() - - // Create client connections - for i := 0; i < numConnections; i++ { - conn, err := net.Dial("tcp", addr) - if err != nil { - t.Fatalf("Failed to dial listener: %v", err) - } - conn.Close() - } - - wg.Wait() -} - -func TestListen_RapidRestarts(t *testing.T) { - // Test that SO_REUSEADDR prevents "address already in use" errors - address := ":0" - - // Create and close listener to get a port - initialListener, err := Listen("tcp", address) - if err != nil { - t.Fatalf("Failed to create initial listener: %v", err) - } - - // Get the actual assigned port - actualAddr := initialListener.Addr().String() - initialListener.Close() - - // Rapidly restart listeners on the same port - for i := 0; i < 3; i++ { - listener, err := Listen("tcp", actualAddr) - if err != nil { - t.Fatalf("Restart %d failed: %v", i, err) - } - listener.Close() - - // Brief pause to simulate real restart scenario - time.Sleep(10 * time.Millisecond) - } -} - -func TestListen_ConcurrentAccess(t *testing.T) { - listener, err := Listen("tcp", ":0") - if err != nil { - t.Fatalf("Failed to create listener: %v", err) - } - defer listener.Close() - - addr := listener.Addr().String() - const numGoroutines = 10 - var wg sync.WaitGroup - - // Start multiple goroutines that will connect simultaneously - wg.Add(numGoroutines) - for i := 0; i < numGoroutines; i++ { - go func(id int) { - defer wg.Done() - - conn, err := net.Dial("tcp", addr) - if err != nil { - t.Errorf("Goroutine %d: dial failed: %v", id, err) - return - } - defer conn.Close() - - // Write some data to verify connection works - testData := fmt.Sprintf("test-%d", id) - if _, err := conn.Write([]byte(testData)); err != nil { - t.Errorf("Goroutine %d: write failed: %v", id, err) - } - }(i) - } - - // Accept all connections - acceptedCount := 0 - done := make(chan bool) - - go func() { - for { - conn, err := listener.Accept() - if err != nil { - return - } - acceptedCount++ - conn.Close() - - if acceptedCount >= numGoroutines { - done <- true - return - } - } - }() - - // Wait for all connections with timeout - select { - case <-done: - // Success - case <-time.After(5 * time.Second): - t.Fatalf("Timeout waiting for connections, accepted %d/%d", acceptedCount, numGoroutines) - } - - wg.Wait() -} - -func TestListen_ErrorMessages(t *testing.T) { - testCases := []struct { - network string - address string - expectedErr string - }{ - {"udp", ":8080", "invalid network type"}, - {"tcp", ":::", "invalid address"}, - {"", ":8080", "invalid network type"}, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("%s_%s", tc.network, tc.address), func(t *testing.T) { - _, err := Listen(tc.network, tc.address) - if err == nil { - t.Fatalf("Expected error for Listen(%s, %s)", tc.network, tc.address) - } - - if !strings.Contains(err.Error(), tc.expectedErr) { - t.Errorf("Error should contain %q, got: %v", tc.expectedErr, err) - } - - // Verify error message includes the problematic values - errMsg := err.Error() - if tc.network != "" && !strings.Contains(errMsg, tc.network) { - t.Errorf("Error should include network %q: %v", tc.network, err) - } - if tc.address != "" && !strings.Contains(errMsg, tc.address) { - t.Errorf("Error should include address %q: %v", tc.address, err) - } - }) - } -} - -// Benchmark the listener creation overhead -func BenchmarkListen(b *testing.B) { - for i := 0; i < b.N; i++ { - listener, err := Listen("tcp", ":0") - if err != nil { - b.Fatalf("Listen failed: %v", err) - } - listener.Close() - } -} - -func TestConfigureSocket_NoResourceLeak(t *testing.T) { - // Create a listener - listener, err := net.Listen("tcp", ":0") - if err != nil { - t.Fatalf("Failed to create base listener: %v", err) - } - defer listener.Close() - - tcpListener := listener.(*net.TCPListener) - - // Configure the socket - this should not invalidate the listener - err = configureSocket(tcpListener) - if err != nil { - t.Fatalf("Socket configuration failed: %v", err) - } - - // Verify the listener is still usable by accepting a connection - addr := listener.Addr().String() - - // Test connection in a goroutine - go func() { - conn, err := net.Dial("tcp", addr) - if err == nil { - conn.Close() - } - }() - - // This should succeed if the listener wasn't invalidated - conn, err := listener.Accept() - if err != nil { - t.Fatalf("Listener became unusable after configuration: %v", err) - } - conn.Close() -}