daShangDao_kfzgw-info/proxy.go

511 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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"
)
// 代理类型常量
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
// 代理健康状态管理
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
}
// 代理健康状态
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
func proxyTypeManager(proxyType, username, password, machineCode string) (string, error) {
switch proxyType {
case CalfElephantProxyType:
return buildCalfElephantProxyURL(username, password)
case TailProxyType:
return buildTailProxyURL(machineCode)
default:
return "", fmt.Errorf("不支持的代理类型: %s", proxyType)
}
}
// 构建小象代理URL
func buildCalfElephantProxyURL(username, password string) (string, error) {
server := randomServer()
proxyURL := fmt.Sprintf("http://%s:%s@%s:%d",
url.QueryEscape(username),
url.QueryEscape(password),
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
}
// 尝试下一个小象代理服务器
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) {
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
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)
}
// 过滤健康代理
func filterHealthyProxies(proxies []string) []string {
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
}
// 查找可用的尾巴代理
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
// 限制并发数
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)
}
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("所有尾巴代理都不可用")
}
// 检测代理健康状态
func checkProxyHealth(proxyURL string) error {
start := time.Now()
req := gorequest.New().Proxy(proxyURL).Timeout(10 * time.Second)
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)
}
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
}
// 更新代理健康状态
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
}
}
}
// 获取代理主机名
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)
globalRand.Shuffle(len(shuffled), func(i, j int) {
shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
})
return shuffled
}
// 检查卡密是否过期
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"`
IpThread int `json:"ip_thread"`
IpCardCode string `json:"ip_card_code"`
} `json:"data"`
}
// 查询机器码
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,
}
_, 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)
}
}
// 充值卡密
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,
}
_, 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
}
// 获取代理服务器列表
func getProxies(machineCode string) ([]string, error) {
log.Printf("[INFO] 开始获取代理列表: %s", machineCode)
// 生成签名
sign := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("9999%s9999", machineCode))))
GetProxiesUrl := fmt.Sprintf("http://114.66.2.223:7842/api/proxies/get_proxy?machine_code=%s&sign=%s&agent_id=9999",
machineCode, sign)
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)
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() {
}
// 导出函数:获取代理健康状态(用于调试)
//
//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,
}
}
jsonData, err := json.Marshal(healthInfo)
if err != nil {
return C.CString(fmt.Sprintf(`{"error": "序列化健康信息失败: %v"}`, err))
}
return C.CString(string(jsonData))
}
// 导出函数:代理类型管理器
//
//export ProxyTypeManager
func ProxyTypeManager(proxyType, username, password, machineCode *C.char) *C.char {
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)
}
//// 导出函数释放C字符串内存
////
////export FreeCString
//func FreeCString(str *C.char) {
// C.free(unsafe.Pointer(str))
//}
//
//func main() {
//
//}