/*
Copyright (c) 2026 a05777. All rights reserved. This software is provided "as is", without warranty of any kind. See LICENSE for details.
软件许可及免责声明
版权所有 (c) 2026 a05777。保留所有权利。

1. 权利保留与授权范围 (Rights & Scope)
本软件的所有权、知识产权及源代码权利均归原作者所有。获得源代码的人员（“用户”）仅拥有非营利性的个人学习、研究及调试代码的非排他性权利。未经原作者明确书面许可，严禁将本软件或其任何部分用于商业盈利、集成至商业产品、或通过网络对外提供付费/免费服务（如 SaaS/API）。

2. 绝对免责声明 (No Warranty)
本程序按“原样”（"AS IS"）提供，不附带任何形式的明示或暗示保证。作者不保证程序符合特定用途，亦不保证运行过程中不出现错误。

3. 责任限制 (Limitation of Liability)
在任何情况下，作者不对因使用本程序产生的任何损害（包括数据丢失、系统崩溃、法律诉讼等）承担任何责任。作者的全部赔偿责任上限在任何情况下均不超过用户实际支付的授权费用（如有）。

4. 风险告知与解释权 (Acceptance & Interpretation)
用户一旦运行、调试或以任何方式使用本程序，即视为完全理解并接受上述条款。作者保留对本协议的最终解释权，并有权随时更新授权条款。

*/



package main

import (
	"bufio"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type Config struct {
	EnableSSL bool   `json:"enable_ssl"`
	HTTPSPort string `json:"https_port"`
	HTTPPort  string `json:"http_port"`
	Domain    string `json:"domain"`
}

var indexCache []byte

// sniffingListener 核心：在 TCP 握手阶段探测协议
type sniffingListener struct {
	net.Listener
	tlsConfig *tls.Config
	domain    string
	port      string
}

func (l *sniffingListener) Accept() (net.Conn, error) {
	for {
		c, err := l.Listener.Accept()
		if err != nil {
			return nil, err
		}

		br := bufio.NewReader(c)
		peek, err := br.Peek(1)
		if err != nil {
			c.Close()
			continue
		}

		// 0x16 是 TLS Handshake 特征码
		if peek[0] == 0x16 {
			// 返回包装后的 TLS 连接
			return tls.Server(&bufferedConn{Conn: c, br: br}, l.tlsConfig), nil
		}

		// 处理普通 HTTP 请求：利用 config.json 里的 domain 进行重定向
		target := fmt.Sprintf("https://%s:%s", l.domain, l.port)
		redirectMsg := fmt.Sprintf("HTTP/1.1 301 Moved Permanently\r\n"+
			"Location: %s\r\n"+
			"Content-Length: 0\r\n"+
			"Connection: close\r\n\r\n", target)

		c.Write([]byte(redirectMsg))
		c.Close()
		continue
	}
}

// bufferedConn 确保被 Peek 过的字节能重新被 TLS 层读取
type bufferedConn struct {
	net.Conn
	br *bufio.Reader
}

func (bc *bufferedConn) Read(b []byte) (int, error) { return bc.br.Read(b) }

type tcpKeepAliveListener struct {
	*net.TCPListener
}

func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
	tc, err := ln.AcceptTCP()
	if err != nil {
		return nil, err
	}
	tc.SetKeepAlive(true)
	tc.SetKeepAlivePeriod(3 * time.Minute)
	return tc, nil
}

func main() {
	// 1. 读取并解析配置
	configData, err := os.ReadFile("config.json")
	if err != nil {
		log.Fatal("Fatal: 找不到 config.json")
	}
	var cfg Config
	if err := json.Unmarshal(configData, &cfg); err != nil {
		log.Fatal("Fatal: 配置文件格式错误")
	}

	// 2. 预加载 index.html
	indexCache, err = os.ReadFile(filepath.Join("html", "index.html"))
	if err != nil {
		log.Fatal("Fatal: html/index.html 缺失")
	}

	// 3. 统一路由处理器
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// 资源限制：限制请求体大小为 1MB
		r.Body = http.MaxBytesReader(w, r.Body, 1<<20)

		// 安全防护：静默拦截敏感文件请求
		cleanPath := strings.ToLower(r.URL.Path)
		if strings.Contains(cleanPath, "/ssl") || strings.Contains(cleanPath, "config.json") {
			http.Error(w, "ACCESS_DENIED", http.StatusForbidden)
			return
		}

		// 内存响应首页
		if r.URL.Path == "/" || r.URL.Path == "/index.html" {
			w.Header().Set("Content-Type", "text/html; charset=utf-8")
			w.Write(indexCache)
			return
		}

		// 静态资源文件服务
		if strings.HasPrefix(r.URL.Path, "/html/") {
			http.ServeFile(w, r, "."+r.URL.Path)
			return
		}
		http.NotFound(w, r)
	})

	srv := &http.Server{
		Handler:           mux,
		ReadHeaderTimeout: 5 * time.Second,
		ReadTimeout:       10 * time.Second,
		WriteTimeout:      15 * time.Second,
		IdleTimeout:       60 * time.Second,
		MaxHeaderBytes:    1 << 20, // 1MB
	}

	// 4. 运行逻辑
	if !cfg.EnableSSL {
		log.Printf("[HTTP] 监听: %s (域名: %s)", cfg.HTTPPort, cfg.Domain)
		log.Fatal(srv.ListenAndServe())
	} else {
		// 加载 SSL 证书
		cert, err := tls.LoadX509KeyPair(filepath.Join("ssl", "server.crt"), filepath.Join("ssl", "server.key"))
		if err != nil {
			log.Fatal("Fatal: 证书加载失败，请检查 ssl 目录")
		}

		tlsConfig := &tls.Config{
			Certificates: []tls.Certificate{cert},
			MinVersion:   tls.VersionTLS12,
		}

		// 开启底层 TCP 监听
		ln, err := net.Listen("tcp", ":"+cfg.HTTPSPort)
		if err != nil {
			log.Fatal(err)
		}

		// 启用 KeepAlive
		if tcpLn, ok := ln.(*net.TCPListener); ok {
			ln = tcpKeepAliveListener{tcpLn}
		}

		log.Printf("[HTTPS 混合模式] 端口: %s, 跳转目标: %s", cfg.HTTPSPort, cfg.Domain)

		// 注入嗅探逻辑
		l := &sniffingListener{
			Listener:  ln,
			tlsConfig: tlsConfig,
			domain:    cfg.Domain,
			port:      cfg.HTTPSPort,
		}

		log.Fatal(srv.Serve(l))
	}
}