package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"net"
	"net/http"
	"os"
	"syscall"
	"time"
)

func main() {
	// Generate a self-signed certificate and private key
	certPEM, keyPEM, err := generateSelfSignedCert()
	if err != nil {
		fmt.Println("Error generating certificate:", err)
		return
	}

	// Create a TCP listener
	listener, err := net.Listen("tcp", "localhost:443")
	if err != nil {
		fmt.Println("Error creating listener:", err)
		return
	}

	// Get the underlying file descriptor
	file, err := listener.(*net.TCPListener).File()
	if err != nil {
		fmt.Println("Error getting file descriptor:", err)
		return
	}
	fd := int(file.Fd())

	// SetsockoptString to bind to a specific interface (replace "eth0" with your interface name)
	err = syscall.SetsockoptString(fd, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, "eth0")
	if err != nil {
		fmt.Println("Error setting socket option:", err)
		return
	}

	// Create an HTTP server with the custom listener and TLS config
	server := &http.Server{
		Addr:    "localhost:443",
		Handler: http.HandlerFunc(handler),
		TLSConfig: &tls.Config{
			Certificates: []tls.Certificate{{
				Certificate: [][]byte{certPEM},
				PrivateKey:  keyPEM,
			}},
		},
	}

	// Start the HTTP server
	go func() {
		fmt.Println("Starting HTTP server with TLS...")
		if err := server.ServeTLS(listener, "", ""); err != nil && err != http.ErrServerClosed {
			fmt.Println("Error starting server:", err)
			return
		}
	}()

	// Start a timer
	duration := 30 * time.Second
	fmt.Printf("Timer started. Server will be closed after %s.\n", duration)
	timer := time.NewTimer(duration)

	// Wait for the timer to expire
	<-timer.C

	// Close the HTTP server gracefully
	fmt.Println("Closing HTTP server...")
	if err := server.Close(); err != nil {
		fmt.Println("Error closing server:", err)
		return
	}

	fmt.Println("HTTP server closed.")
}

// Handler for incoming requests
func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, HTTPS!")
}

// Function to generate a self-signed certificate and private key
func generateSelfSignedCert() ([]byte, []byte, error) {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, err
	}

	notBefore := time.Now()
	notAfter := notBefore.Add(365 * 24 * time.Hour)

	serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
	if err != nil {
		return nil, nil, err
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Go Playground"},
		},
		NotBefore:             notBefore,
		NotAfter:              notAfter,
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		return nil, nil, err
	}

	certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
	keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})

	return certPEM, keyPEM, nil
}
