844 lines
25 KiB
Go
844 lines
25 KiB
Go
package main
|
||
|
||
/*
|
||
#include <stdlib.h>
|
||
*/
|
||
import "C"
|
||
import (
|
||
"crypto/md5"
|
||
"encoding/json"
|
||
"fmt"
|
||
"github.com/parnurzeal/gorequest"
|
||
"log"
|
||
"math/rand"
|
||
"net/url"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
"unsafe"
|
||
)
|
||
|
||
// 代理类型常量
|
||
const (
|
||
CalfElephantProxyType = "CALF_ELEPHANT_PROXY" // 小象代理类型
|
||
TailProxyType = "TAIL_PROXY" // 尾巴代理类型
|
||
)
|
||
|
||
// 小象代理服务器列表
|
||
var (
|
||
servers = []string{
|
||
"http-dynamic.xiaoxiangdaili.com",
|
||
"http-dynamic-S02.xiaoxiangdaili.com",
|
||
"http-dynamic-S03.xiaoxiangdaili.com",
|
||
"http-dynamic-S04.xiaoxiangdaili.com",
|
||
}
|
||
// 互斥锁,用于保护全局随机数生成器的并发访问
|
||
randMutex sync.Mutex
|
||
globalRand *rand.Rand // 全局随机数生成器
|
||
// 代理健康状态管理
|
||
// 代理健康状态映射表,key为代理主机名,value为健康状态
|
||
proxyHealthMaps = make(map[string]*ProxyHealth)
|
||
proxyHealthMutex sync.RWMutex
|
||
)
|
||
|
||
// ProxyManager 代理管理器结构体,用于管理代理配置信息
|
||
type ProxyManager struct {
|
||
servers []string `json:"servers"` // 代理服务器列表
|
||
username string `json:"username"` // 代理账号
|
||
password string `json:"password"` // 代理密码
|
||
tailCardSecret string `json:"tail_card_secret"` // 尾巴代理卡密
|
||
proxyType string `json:"proxy_type"` // 代理类型 CALF_ELEPHANT_PROXY/TAIL_PROXY
|
||
}
|
||
|
||
// ProxyHealth 代理健康状态结构体,用于跟踪代理的健康状况
|
||
type ProxyHealth struct {
|
||
SuccessCount int // 成功次数
|
||
FailCount int // 失败次数
|
||
LastCheck time.Time // 最后检查时间
|
||
ResponseTime time.Duration // 响应时间
|
||
IsHealthy bool // 是否健康
|
||
}
|
||
|
||
// 初始化函数,在程序启动时自动执行
|
||
func init() {
|
||
// 创建全局的随机数生成器,使用当前时间作为种子
|
||
globalRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||
}
|
||
|
||
/*
|
||
* 获取代理URL,代理类型管理器,根据代理类型构建不同的代理URL
|
||
* param proxyType[string] 代理类型
|
||
* param username[string] 代理用户名
|
||
* param password[string] 代理密码
|
||
* param machineCode[string] 机器码
|
||
* return 代理服务器IP,错误信息
|
||
*/
|
||
func proxyTypeManager(proxyType, username, password, machineCode string) (string, error) {
|
||
switch proxyType {
|
||
case CalfElephantProxyType:
|
||
// 小象代理:使用用户名和密码构建代理URL
|
||
return buildCalfElephantProxyURL(username, password)
|
||
case TailProxyType:
|
||
// 尾巴代理:使用机器码构建代理URL
|
||
return buildTailProxyURL(machineCode)
|
||
default:
|
||
// 不支持的代理类型,返回错误
|
||
return "", fmt.Errorf("不支持的代理类型: %s", proxyType)
|
||
}
|
||
}
|
||
|
||
func proxyTypeManagerNew(proxyType, username, password, machineCode string) (string, error) {
|
||
// 获取代理列表
|
||
proxies, err := getProxies(machineCode)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
// 检查是否获取到有效代理
|
||
if len(proxies) == 0 {
|
||
return "", fmt.Errorf("未获取到有效代理")
|
||
}
|
||
// 获取代理
|
||
proxy := randomElement(proxies)
|
||
proxy = fmt.Sprintf("http://%s", proxy)
|
||
return proxy, nil
|
||
}
|
||
|
||
/*
|
||
* 构建小象代理URL
|
||
* param username[string] 代理用户名
|
||
* param password[string] 代理密码
|
||
* return 代理服务器IP,错误信息
|
||
*/
|
||
func buildCalfElephantProxyURL(username, password string) (string, error) {
|
||
// 随机选择一个代理服务器
|
||
server := randomServer()
|
||
// 构建代理URL格式:http://用户名:密码@服务器:端口
|
||
proxyURL := fmt.Sprintf("http://%s:%s@%s:%d",
|
||
url.QueryEscape(username), // URL编码用户名,防止特殊字符问题
|
||
url.QueryEscape(password), // URL编码密码,防止特殊字符问题
|
||
server, // 服务器地址
|
||
10030) // 固定端口号
|
||
|
||
// 检测代理可用性
|
||
if err := checkProxyHealth(proxyURL); err != nil {
|
||
// 代理检测失败,记录警告日志
|
||
log.Printf("[WARN] 代理 %s 检测失败: %v", server, err)
|
||
// 尝试下一个代理服务器
|
||
return tryNextCalfElephantProxy(username, password, server)
|
||
}
|
||
// 代理检测成功,记录信息日志
|
||
log.Printf("[INFO] 使用小象代理: %s", server)
|
||
return proxyURL, nil
|
||
}
|
||
|
||
/*
|
||
* 尝试下一个小象代理服务器
|
||
* param username[string] 代理用户名
|
||
* param password[string] 代理密码
|
||
* param failedServer[string] 代理服务器
|
||
* return 代理服务器IP,错误信息
|
||
*/
|
||
func tryNextCalfElephantProxy(username, password, failedServer string) (string, error) {
|
||
// 创建服务器副本并排除失败的服务器
|
||
availableServers := make([]string, 0)
|
||
for _, server := range servers {
|
||
if server != failedServer {
|
||
availableServers = append(availableServers, server)
|
||
}
|
||
}
|
||
// 如果没有可用的服务器,返回错误
|
||
if len(availableServers) == 0 {
|
||
return "", fmt.Errorf("所有小象代理服务器都不可用")
|
||
}
|
||
|
||
// 随机尝试可用服务器
|
||
for _, server := range shuffleServers(availableServers) {
|
||
// 构建代理URL
|
||
proxyURL := fmt.Sprintf("http://%s:%s@%s:%d",
|
||
url.QueryEscape(username),
|
||
url.QueryEscape(password),
|
||
server,
|
||
10030)
|
||
// 检测代理可用性
|
||
if err := checkProxyHealth(proxyURL); err == nil {
|
||
log.Printf("[INFO] 切换到可用代理: %s", server)
|
||
return proxyURL, nil
|
||
}
|
||
// 代理不可用,记录警告日志
|
||
log.Printf("[WARN] 代理 %s 检测失败", server)
|
||
}
|
||
// 所有服务器都检测失败,返回错误
|
||
return "", fmt.Errorf("所有可用的小象代理服务器都检测失败")
|
||
}
|
||
|
||
/*
|
||
* 构建内置代理URL
|
||
* param machineCode[string] 机器码
|
||
* return 代理服务器IP,错误信息
|
||
*/
|
||
func buildTailProxyURL(machineCode string) (string, error) {
|
||
// 获取代理列表
|
||
proxies, err := getProxies(machineCode)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
// 检查是否获取到有效代理
|
||
if len(proxies) == 0 {
|
||
return "", fmt.Errorf("未获取到有效代理")
|
||
}
|
||
|
||
// 过滤并选择健康的代理
|
||
healthyProxies := filterHealthyProxies(proxies)
|
||
if len(healthyProxies) > 0 {
|
||
// 从健康代理中随机选择一个
|
||
proxyURL := "http://" + randomElement(healthyProxies)
|
||
log.Printf("[INFO] 使用健康尾巴代理: %s", proxyURL)
|
||
return proxyURL, nil
|
||
}
|
||
|
||
// 如果没有健康代理,检测所有代理
|
||
log.Printf("[INFO] 未找到健康代理,开始检测代理可用性...")
|
||
return findWorkingTailProxy(proxies)
|
||
}
|
||
|
||
/*
|
||
* 过滤健康代理,返回当前健康的代理列表
|
||
* param proxies[[]string] 内置代理服务器数组
|
||
* return 内置代理服务器数组,错误信息
|
||
*/
|
||
func filterHealthyProxies(proxies []string) []string {
|
||
// 获取读锁,允许多个goroutine同时读取
|
||
proxyHealthMutex.RLock()
|
||
defer proxyHealthMutex.RUnlock() // 确保函数结束时释放锁
|
||
|
||
var healthy []string
|
||
for _, proxy := range proxies {
|
||
if health, exists := proxyHealthMaps[proxy]; exists && health.IsHealthy {
|
||
// 检查是否在最近检查过(5分钟内),避免使用过时的健康状态
|
||
if time.Since(health.LastCheck) < 5*time.Minute {
|
||
healthy = append(healthy, proxy)
|
||
}
|
||
}
|
||
}
|
||
return healthy
|
||
}
|
||
|
||
/*
|
||
* 查找可用的尾巴代理
|
||
* param proxies[[]string] 内置代理服务器数组
|
||
* return 可用的代理服务器IP,错误信息
|
||
*/
|
||
func findWorkingTailProxy(proxies []string) (string, error) {
|
||
// 打乱代理顺序
|
||
shuffledProxies := shuffleServers(proxies)
|
||
|
||
// 并发检测代理
|
||
type proxyResult struct {
|
||
proxy string
|
||
err error
|
||
}
|
||
// 创建带缓冲的通道,用于收集检测结果
|
||
ch := make(chan proxyResult, len(shuffledProxies))
|
||
var wg sync.WaitGroup // 等待组,用于等待所有检测goroutine完成
|
||
|
||
// 限制并发数,避免同时检测太多代理导致网络拥塞
|
||
sem := make(chan struct{}, 5)
|
||
// 并发检测每个代理
|
||
for _, proxy := range shuffledProxies {
|
||
wg.Add(1) // 增加等待组计数
|
||
go func(p string) {
|
||
defer wg.Done() // 函数结束时减少等待组计数
|
||
sem <- struct{}{} // 获取信号量,限制并发数
|
||
defer func() { <-sem }() // 释放信号量
|
||
|
||
proxyURL := "http://" + p
|
||
err := checkProxyHealth(proxyURL)
|
||
// 将检测结果发送到通道
|
||
ch <- proxyResult{proxy: p, err: err}
|
||
}(proxy)
|
||
}
|
||
// 等待所有检测goroutine完成
|
||
wg.Wait()
|
||
close(ch) // 关闭通道,表示不会再有数据发送
|
||
|
||
// 收集结果,查找可用的代理
|
||
var workingProxies []string
|
||
for result := range ch {
|
||
if result.err == nil {
|
||
// 代理可用,添加到工作代理列表
|
||
workingProxies = append(workingProxies, result.proxy)
|
||
// 更新健康状态
|
||
updateProxyHealth(result.proxy, true, 0)
|
||
} else {
|
||
// 代理不可用,更新健康状态
|
||
updateProxyHealth(result.proxy, false, 0)
|
||
}
|
||
}
|
||
// 如果有可用的代理,随机选择一个
|
||
if len(workingProxies) > 0 {
|
||
selected := randomElement(workingProxies)
|
||
log.Printf("[INFO] 找到可用代理: %s (共 %d 个可用)", selected, len(workingProxies))
|
||
return "http://" + selected, nil
|
||
}
|
||
// 所有代理都不可用,返回错误
|
||
return "", fmt.Errorf("所有尾巴代理都不可用")
|
||
}
|
||
|
||
/*
|
||
* 检测代理健康状态,通过访问测试网站验证代理可用性
|
||
* param proxyURL[string] 代理服务器
|
||
* return 错误信息
|
||
*/
|
||
func checkProxyHealth(proxyURL string) error {
|
||
start := time.Now() // 记录开始时间,用于计算响应时间
|
||
// 创建HTTP请求,设置代理和超时
|
||
req := gorequest.New().Proxy(proxyURL).Timeout(10 * time.Second)
|
||
// 发送GET请求到测试网站
|
||
resp, _, errs := req.Get("https://shop.kongfz.com/").End()
|
||
|
||
responseTime := time.Since(start) // 计算响应时间
|
||
// 检查请求错误
|
||
if len(errs) > 0 {
|
||
updateProxyHealth(proxyURL, false, responseTime)
|
||
return fmt.Errorf("代理连接失败: %v", errs)
|
||
}
|
||
// 检查HTTP状态码
|
||
if resp.StatusCode != 200 {
|
||
updateProxyHealth(proxyURL, false, responseTime)
|
||
return fmt.Errorf("代理响应状态码错误: %d", resp.StatusCode)
|
||
}
|
||
// 代理检测成功
|
||
updateProxyHealth(proxyURL, true, responseTime)
|
||
log.Printf("[DEBUG] 代理 %s 检测成功, 响应时间: %v", getProxyHost(proxyURL), responseTime)
|
||
return nil
|
||
}
|
||
|
||
/*
|
||
* 更新代理健康状态
|
||
* param proxyURL[string] 代理服务器
|
||
* param success[bool] 是否成功
|
||
* param responseTime[time.Duration] 响应时间
|
||
*/
|
||
func updateProxyHealth(proxyURL string, success bool, responseTime time.Duration) {
|
||
// 获取写锁,确保更新操作的互斥性
|
||
proxyHealthMutex.Lock()
|
||
defer proxyHealthMutex.Unlock() // 确保函数结束时释放锁
|
||
// 获取代理主机名作为键
|
||
host := getProxyHost(proxyURL)
|
||
// 如果代理健康状态不存在,创建新的
|
||
if _, exists := proxyHealthMaps[host]; !exists {
|
||
proxyHealthMaps[host] = &ProxyHealth{}
|
||
}
|
||
|
||
health := proxyHealthMaps[host]
|
||
health.LastCheck = time.Now() // 更新最后检查时间
|
||
|
||
if success {
|
||
// 成功的情况
|
||
health.SuccessCount++ // 增加成功次数
|
||
health.FailCount = 0 // 重置失败次数
|
||
health.ResponseTime = responseTime // 记录响应时间
|
||
health.IsHealthy = true // 标记为健康
|
||
} else {
|
||
// 失败的情况
|
||
health.FailCount++ // 增加失败次数
|
||
health.SuccessCount = 0 // 重置成功次数
|
||
// 连续失败3次标记为不健康
|
||
if health.FailCount >= 3 {
|
||
health.IsHealthy = false
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 获取代理主机名
|
||
* param proxyURL[string] 代理服务器
|
||
* return 代理服务器IP
|
||
*/
|
||
func getProxyHost(proxyURL string) string {
|
||
// 去除协议前缀
|
||
if strings.HasPrefix(proxyURL, "http://") {
|
||
proxyURL = proxyURL[7:]
|
||
}
|
||
// 去除认证信息(用户名:密码@部分)
|
||
if atIndex := strings.Index(proxyURL, "@"); atIndex != -1 {
|
||
proxyURL = proxyURL[atIndex+1:]
|
||
}
|
||
// 去除端口
|
||
if colonIndex := strings.Index(proxyURL, ":"); colonIndex != -1 {
|
||
proxyURL = proxyURL[:colonIndex]
|
||
}
|
||
return proxyURL
|
||
}
|
||
|
||
// 随机代理服务器
|
||
func randomServer() string {
|
||
return randomElement(servers)
|
||
}
|
||
|
||
// 线程安全的随机元素选择
|
||
func randomElement(slice []string) string {
|
||
randMutex.Lock() // 获取互斥锁
|
||
defer randMutex.Unlock() // 确保函数结束时释放锁
|
||
return slice[globalRand.Intn(len(slice))] // 随机选择一个元素
|
||
}
|
||
|
||
// 打乱服务器顺序
|
||
func shuffleServers(servers []string) []string {
|
||
randMutex.Lock()
|
||
defer randMutex.Unlock()
|
||
// 创建服务器副本,避免修改原始切片
|
||
shuffled := make([]string, len(servers))
|
||
copy(shuffled, servers)
|
||
// 使用Fisher-Yates算法打乱顺序
|
||
globalRand.Shuffle(len(shuffled), func(i, j int) {
|
||
shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
|
||
})
|
||
return shuffled
|
||
}
|
||
|
||
/*
|
||
* 检查卡密是否过期
|
||
* param tailCardSecret[string] 卡密
|
||
* return 是否过期,错误信息
|
||
*/
|
||
func checkTailCardSecretExpired(tailCardSecret string) (bool, error) {
|
||
// 获取机器码信息
|
||
code, err := getMachineCode(tailCardSecret)
|
||
if err != nil {
|
||
return false, fmt.Errorf("请求错误: %v", err)
|
||
}
|
||
// 解析过期时间字符串
|
||
targetTime, err := time.Parse("2006-01-02 15:04:05", code.Data.IpExpTime)
|
||
if err != nil {
|
||
return false, fmt.Errorf("时间格式错误: %v", err)
|
||
}
|
||
currentTime := time.Now()
|
||
// 卡密日期在当前日期之后表示有效
|
||
if targetTime.After(currentTime) {
|
||
return true, nil
|
||
} else {
|
||
// 卡密已过期
|
||
return false, fmt.Errorf("卡密已经过期!过期时间: %v", targetTime)
|
||
}
|
||
}
|
||
|
||
// 定义响应结构体
|
||
type getMachineCodeResp struct {
|
||
Code int `json:"code"` // 状态码
|
||
Message string `json:"message"` // 消息
|
||
Data struct {
|
||
MachineCode string `json:"machine_code"` // 机器码
|
||
IpExpTime string `json:"ip_exp_time"` // IP过期时间
|
||
IpThread int `json:"ip_thread"` // IP线程数
|
||
IpCardCode string `json:"ip_card_code"` // IP卡密
|
||
} `json:"data"`
|
||
}
|
||
|
||
/*
|
||
* 查询机器码
|
||
* param tailCardSecret[string] 卡密
|
||
* return 响应结构体,错误信息
|
||
*/
|
||
func getMachineCode(tailCardSecret string) (*getMachineCodeResp, error) {
|
||
url := "http://114.66.2.223:7842/api/proxies/ip_show"
|
||
// 构建请求数据
|
||
data := map[string]interface{}{
|
||
"ip_card_code": tailCardSecret,
|
||
"agent_id": 9999,
|
||
}
|
||
// 发送POST请求
|
||
_, body, errs := gorequest.New().Post(url).Send(data).End()
|
||
if len(errs) > 0 {
|
||
return nil, fmt.Errorf("查询机器码失败: %v", errs)
|
||
}
|
||
// 解析响应
|
||
var resp getMachineCodeResp
|
||
if err := json.Unmarshal([]byte(body), &resp); err != nil {
|
||
return nil, fmt.Errorf("解析响应失败: %v", err)
|
||
}
|
||
// 处理不同的响应码
|
||
if resp.Code == 201 {
|
||
// 需要充值卡密
|
||
machineCode, err := rechargeCard(tailCardSecret, resp.Data.MachineCode)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
resp.Data.MachineCode = machineCode
|
||
return &resp, nil
|
||
} else if resp.Code == 200 {
|
||
// 成功获取机器码
|
||
return &resp, nil
|
||
} else {
|
||
// 其他错误
|
||
return nil, fmt.Errorf("查询机器码失败: %s", resp.Message)
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 充值卡密
|
||
* param tailCardSecret[string] 卡密
|
||
* param machineCode[string] 机器码
|
||
* return 机器码,错误信息
|
||
*/
|
||
func rechargeCard(tailCardSecret, machineCode string) (string, error) {
|
||
url := "http://114.66.2.223:7842/api/proxies/ip_recharge"
|
||
// 构建请求数据
|
||
data := map[string]interface{}{
|
||
"machine_code": machineCode,
|
||
"ip_card_code": tailCardSecret,
|
||
"agent_id": 9999,
|
||
}
|
||
// 发送POST请求
|
||
_, body, errs := gorequest.New().Post(url).Send(data).End()
|
||
if len(errs) > 0 {
|
||
return "", fmt.Errorf("充值卡密失败: %v", errs)
|
||
}
|
||
// 解析响应
|
||
var resp struct {
|
||
Code int `json:"code"` // 状态码
|
||
Message string `json:"message"` // 返回消息
|
||
Data struct {
|
||
IpExpTime string `json:"ip_exp_time"` // 过期时间
|
||
IpThread int `json:"ip_thread"` // 线程
|
||
MachineCode string `json:"machine_code"` // 机器码
|
||
} `json:"data"`
|
||
}
|
||
if err := json.Unmarshal([]byte(body), &resp); err != nil {
|
||
return "", fmt.Errorf("解析响应失败: %v", err)
|
||
}
|
||
|
||
// 检查响应状态
|
||
if resp.Code != 200 {
|
||
return "", fmt.Errorf("充值卡密失败: %s", resp.Message)
|
||
}
|
||
return resp.Data.MachineCode, nil
|
||
}
|
||
|
||
/*
|
||
* 获取代理服务器列表
|
||
* param machineCode[string] 机器码
|
||
* return 代理服务器组,错误信息
|
||
*/
|
||
func getProxies(machineCode string) ([]string, error) {
|
||
log.Printf("[INFO] 开始获取代理列表: %s", machineCode)
|
||
// 生成签名
|
||
sign := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("9999%s9999", machineCode))))
|
||
|
||
// 构建请求URL
|
||
GetProxiesUrl := fmt.Sprintf("http://114.66.2.223:7842/api/proxies/get_proxy?machine_code=%s&sign=%s&agent_id=9999",
|
||
machineCode, sign)
|
||
|
||
// 发送GET请求
|
||
req := gorequest.New().Get(GetProxiesUrl).Timeout(20 * time.Second)
|
||
_, body, errs := req.End()
|
||
if len(errs) > 0 {
|
||
return nil, fmt.Errorf("获取代理失败: %v", errs)
|
||
}
|
||
|
||
// 检查是否为JSON错误响应(响应以{开头,以}结尾)
|
||
if strings.HasPrefix(strings.TrimSpace(body), "{") && strings.HasSuffix(strings.TrimSpace(body), "}") {
|
||
// 尝试解析为JSON错误响应
|
||
var errorResp struct {
|
||
Code int `json:"code"`
|
||
Message string `json:"message"`
|
||
}
|
||
if err := json.Unmarshal([]byte(body), &errorResp); err == nil {
|
||
return nil, fmt.Errorf("获取代理失败: %s (错误码: %d)", errorResp.Message, errorResp.Code)
|
||
}
|
||
}
|
||
|
||
// 解析响应(每行一个代理地址)
|
||
lines := strings.Split(strings.TrimSpace(body), "\n")
|
||
var proxies []string
|
||
for _, line := range lines {
|
||
line = strings.TrimSpace(line)
|
||
// 过滤空行和JSON格式的行
|
||
if line != "" && !strings.HasPrefix(line, "{") {
|
||
proxies = append(proxies, line)
|
||
}
|
||
}
|
||
// 检查是否获取到有效代理
|
||
if len(proxies) == 0 {
|
||
return nil, fmt.Errorf("未获取到有效代理")
|
||
}
|
||
|
||
log.Printf("[INFO] 获取到 %d 个代理", len(proxies))
|
||
return proxies, nil
|
||
}
|
||
|
||
// 初始化代理信息
|
||
func initProxy() {
|
||
|
||
}
|
||
|
||
// =================== C 导出函数 =======================
|
||
|
||
// GetProxyHealth 导出函数:获取代理健康状态(用于调试)
|
||
//
|
||
//export GetProxyHealth
|
||
func GetProxyHealth() *C.char {
|
||
proxyHealthMutex.RLock()
|
||
defer proxyHealthMutex.RUnlock()
|
||
// 构建健康信息映射
|
||
healthInfo := make(map[string]interface{})
|
||
for proxy, health := range proxyHealthMaps {
|
||
healthInfo[proxy] = map[string]interface{}{
|
||
"success_count": health.SuccessCount,
|
||
"fail_count": health.FailCount,
|
||
"last_check": health.LastCheck.Format(time.RFC3339),
|
||
"response_time": health.ResponseTime.String(),
|
||
"is_healthy": health.IsHealthy,
|
||
}
|
||
}
|
||
// 序列化为JSON
|
||
jsonData, err := json.Marshal(healthInfo)
|
||
if err != nil {
|
||
return C.CString(fmt.Sprintf(`{"error": "序列化健康信息失败: %v"}`, err))
|
||
}
|
||
|
||
return C.CString(string(jsonData))
|
||
}
|
||
|
||
// ProxyTypeManager 导出函数:代理类型管理器
|
||
//
|
||
//export ProxyTypeManager
|
||
func ProxyTypeManager(proxyType, username, password, machineCode *C.char) *C.char {
|
||
// C字符串转换为Go字符串
|
||
goProxyType := C.GoString(proxyType)
|
||
goUsername := C.GoString(username)
|
||
goPassword := C.GoString(password)
|
||
goMachineCode := C.GoString(machineCode)
|
||
|
||
log.Printf("[DEBUG] 代理类型管理器调用: type=%s", goProxyType)
|
||
// 调用代理类型管理器
|
||
proxyURL, err := proxyTypeManager(goProxyType, goUsername, goPassword, goMachineCode)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: %v", err)
|
||
log.Printf("[ERROR] 代理类型管理器错误: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
log.Printf("[DEBUG] 代理类型管理器返回: %s", proxyURL)
|
||
return C.CString(proxyURL)
|
||
}
|
||
|
||
// ProxyTypeManagerNew 导出函数:代理类型管理器
|
||
//
|
||
//export ProxyTypeManagerNew
|
||
func ProxyTypeManagerNew(proxyType, username, password, machineCode *C.char) *C.char {
|
||
// C字符串转换为Go字符串
|
||
goProxyType := C.GoString(proxyType)
|
||
goUsername := C.GoString(username)
|
||
goPassword := C.GoString(password)
|
||
goMachineCode := C.GoString(machineCode)
|
||
|
||
// 调用代理类型管理器
|
||
proxyURL, err := proxyTypeManagerNew(goProxyType, goUsername, goPassword, goMachineCode)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
return C.CString(proxyURL)
|
||
}
|
||
|
||
// GetMachineCode 导出函数:查询机器码
|
||
//
|
||
//export GetMachineCode
|
||
func GetMachineCode(tailCardSecret *C.char) *C.char {
|
||
goTailCardSecret := C.GoString(tailCardSecret)
|
||
|
||
resp, err := getMachineCode(goTailCardSecret)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: %v", err)
|
||
log.Printf("[ERROR] 查询机器码错误: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
// 将响应转换为JSON
|
||
jsonData, err := json.Marshal(resp)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: 序列化响应失败: %v", err)
|
||
log.Printf("[ERROR] 序列化机器码响应失败: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
return C.CString(string(jsonData))
|
||
}
|
||
|
||
// RechargeCard 导出函数:充值卡密
|
||
//
|
||
//export RechargeCard
|
||
func RechargeCard(tailCardSecret, machineCode *C.char) *C.char {
|
||
goTailCardSecret := C.GoString(tailCardSecret)
|
||
goMachineCode := C.GoString(machineCode)
|
||
log.Printf("[DEBUG] 充值卡密调用: card=%s, machine_code=%s", goTailCardSecret, goMachineCode)
|
||
|
||
newMachineCode, err := rechargeCard(goTailCardSecret, goMachineCode)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: %v", err)
|
||
log.Printf("[ERROR] 充值卡密错误: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
// 构建成功响应
|
||
response := map[string]interface{}{
|
||
"success": true,
|
||
"machine_code": newMachineCode,
|
||
"message": "充值成功",
|
||
}
|
||
|
||
jsonData, err := json.Marshal(response)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: 序列化响应失败: %v", err)
|
||
log.Printf("[ERROR] 序列化充值响应失败: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
log.Printf("[DEBUG] 充值卡密成功: new_machine_code=%s", newMachineCode)
|
||
return C.CString(string(jsonData))
|
||
}
|
||
|
||
// GetProxies 导出函数:获取代理服务器列表
|
||
//
|
||
//export GetProxies
|
||
func GetProxies(machineCode *C.char) *C.char {
|
||
goMachineCode := C.GoString(machineCode)
|
||
log.Printf("[DEBUG] 获取代理服务器列表调用: machine_code=%s", goMachineCode)
|
||
|
||
proxies, err := getProxies(goMachineCode)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: %v", err)
|
||
log.Printf("[ERROR] 获取代理服务器列表错误: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
// 将代理列表转换为JSON
|
||
response := map[string]interface{}{
|
||
"success": true,
|
||
"count": len(proxies),
|
||
"proxies": proxies,
|
||
}
|
||
|
||
jsonData, err := json.Marshal(response)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: 序列化响应失败: %v", err)
|
||
log.Printf("[ERROR] 序列化代理列表失败: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
log.Printf("[DEBUG] 获取代理服务器列表成功: count=%d", len(proxies))
|
||
return C.CString(string(jsonData))
|
||
}
|
||
|
||
// CheckTailCardSecretExpired 导出函数:检查卡密是否过期
|
||
//
|
||
//export CheckTailCardSecretExpired
|
||
func CheckTailCardSecretExpired(tailCardSecret *C.char) *C.char {
|
||
goTailCardSecret := C.GoString(tailCardSecret)
|
||
|
||
isValid, err := checkTailCardSecretExpired(goTailCardSecret)
|
||
if err != nil {
|
||
// 如果是过期错误,返回特定格式
|
||
if strings.Contains(err.Error(), "卡密已经过期") {
|
||
response := map[string]interface{}{
|
||
"is_valid": false,
|
||
"message": err.Error(),
|
||
}
|
||
jsonData, _ := json.Marshal(response)
|
||
return C.CString(string(jsonData))
|
||
}
|
||
|
||
errorMsg := fmt.Sprintf("ERROR: %v", err)
|
||
log.Printf("[ERROR] 检查卡密过期错误: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
response := map[string]interface{}{
|
||
"is_valid": isValid,
|
||
"message": "卡密有效",
|
||
}
|
||
|
||
jsonData, err := json.Marshal(response)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: 序列化响应失败: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
return C.CString(string(jsonData))
|
||
}
|
||
|
||
// InitProxyManager 导出函数:初始化代理管理器
|
||
//
|
||
//export InitProxyManager
|
||
func InitProxyManager(serversJson, username, password, tailCardSecret, proxyType *C.char) *C.char {
|
||
goServersJson := C.GoString(serversJson)
|
||
goUsername := C.GoString(username)
|
||
goPassword := C.GoString(password)
|
||
goTailCardSecret := C.GoString(tailCardSecret)
|
||
goProxyType := C.GoString(proxyType)
|
||
|
||
log.Printf("[DEBUG] 初始化代理管理器调用: type=%s", goProxyType)
|
||
|
||
// 解析服务器列表
|
||
var serverList []string
|
||
if goServersJson != "" {
|
||
if err := json.Unmarshal([]byte(goServersJson), &serverList); err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: 解析服务器列表失败: %v", err)
|
||
log.Printf("[ERROR] 解析服务器列表失败: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
}
|
||
|
||
// 更新全局服务器列表
|
||
if len(serverList) > 0 {
|
||
randMutex.Lock()
|
||
servers = serverList
|
||
randMutex.Unlock()
|
||
log.Printf("[INFO] 更新服务器列表,共 %d 个服务器", len(servers))
|
||
}
|
||
|
||
// 创建代理管理器
|
||
manager := ProxyManager{
|
||
servers: servers,
|
||
username: goUsername,
|
||
password: goPassword,
|
||
tailCardSecret: goTailCardSecret,
|
||
proxyType: goProxyType,
|
||
}
|
||
|
||
// 序列化管理器信息
|
||
jsonData, err := json.Marshal(manager)
|
||
if err != nil {
|
||
errorMsg := fmt.Sprintf("ERROR: 序列化代理管理器失败: %v", err)
|
||
log.Printf("[ERROR] 序列化代理管理器失败: %v", err)
|
||
return C.CString(errorMsg)
|
||
}
|
||
|
||
log.Printf("[DEBUG] 代理管理器初始化成功")
|
||
return C.CString(string(jsonData))
|
||
}
|
||
|
||
// FreeCString 导出函数:释放C字符串内存
|
||
//
|
||
//export FreeCString
|
||
func FreeCString(str *C.char) {
|
||
C.free(unsafe.Pointer(str))
|
||
}
|
||
|
||
// PROXY_VERSION 版本号
|
||
const (
|
||
PROXY_VERSION = "v2"
|
||
)
|
||
|
||
// GetVersion 获取版本
|
||
//
|
||
//export GetVersion
|
||
func GetVersion() *C.char {
|
||
return C.CString(PROXY_VERSION)
|
||
}
|
||
|
||
// 空main函数,编译DLL时需要
|
||
func main() {
|
||
}
|