All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 29s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 48s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 37s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 59s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 36s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 57s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 38s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m6s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 50s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 35s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 1m0s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 52s
162 lines
3.5 KiB
Go
162 lines
3.5 KiB
Go
package plugin
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
// =============================================================================
|
|
// 客户端 API 实现
|
|
// =============================================================================
|
|
|
|
// ClientAPI 客户端 PluginAPI 实现
|
|
type ClientAPI struct {
|
|
*baseAPI
|
|
clientID string
|
|
dialer Dialer
|
|
}
|
|
|
|
// ClientAPIOption 客户端 API 配置选项
|
|
type ClientAPIOption struct {
|
|
PluginName string
|
|
ClientID string
|
|
Config map[string]string
|
|
Dialer Dialer
|
|
}
|
|
|
|
// NewClientAPI 创建客户端 API
|
|
func NewClientAPI(opt ClientAPIOption) *ClientAPI {
|
|
return &ClientAPI{
|
|
baseAPI: newBaseAPI(opt.PluginName, opt.Config),
|
|
clientID: opt.ClientID,
|
|
dialer: opt.Dialer,
|
|
}
|
|
}
|
|
|
|
// --- 网络操作 ---
|
|
|
|
// Dial 通过隧道建立连接
|
|
func (c *ClientAPI) Dial(network, address string) (net.Conn, error) {
|
|
if c.dialer == nil {
|
|
return nil, ErrNotConnected
|
|
}
|
|
return c.dialer.Dial(network, address)
|
|
}
|
|
|
|
// DialTimeout 带超时的连接(使用 context 避免 goroutine 泄漏)
|
|
func (c *ClientAPI) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
|
|
if c.dialer == nil {
|
|
return nil, ErrNotConnected
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
|
|
type result struct {
|
|
conn net.Conn
|
|
err error
|
|
}
|
|
ch := make(chan result, 1)
|
|
|
|
go func() {
|
|
conn, err := c.dialer.Dial(network, address)
|
|
select {
|
|
case ch <- result{conn, err}:
|
|
case <-ctx.Done():
|
|
if conn != nil {
|
|
conn.Close()
|
|
}
|
|
}
|
|
}()
|
|
|
|
select {
|
|
case r := <-ch:
|
|
return r.conn, r.err
|
|
case <-ctx.Done():
|
|
return nil, fmt.Errorf("dial timeout")
|
|
}
|
|
}
|
|
|
|
// Listen 客户端不支持监听
|
|
func (c *ClientAPI) Listen(network, address string) (net.Listener, error) {
|
|
return nil, ErrNotSupported
|
|
}
|
|
|
|
// --- 端口管理(客户端不支持)---
|
|
|
|
// ReservePort 客户端不支持
|
|
func (c *ClientAPI) ReservePort(port int) error {
|
|
return ErrNotSupported
|
|
}
|
|
|
|
// ReleasePort 客户端不支持
|
|
func (c *ClientAPI) ReleasePort(port int) {}
|
|
|
|
// IsPortAvailable 检查本地端口是否可用
|
|
func (c *ClientAPI) IsPortAvailable(port int) bool {
|
|
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
ln.Close()
|
|
return true
|
|
}
|
|
|
|
// --- 规则管理(客户端不支持)---
|
|
|
|
// CreateRule 客户端不支持
|
|
func (c *ClientAPI) CreateRule(rule *RuleConfig) error {
|
|
return ErrNotSupported
|
|
}
|
|
|
|
// DeleteRule 客户端不支持
|
|
func (c *ClientAPI) DeleteRule(clientID, ruleName string) error {
|
|
return ErrNotSupported
|
|
}
|
|
|
|
// GetRules 客户端不支持
|
|
func (c *ClientAPI) GetRules(clientID string) ([]RuleConfig, error) {
|
|
return nil, ErrNotSupported
|
|
}
|
|
|
|
// UpdateRule 客户端不支持
|
|
func (c *ClientAPI) UpdateRule(clientID string, rule *RuleConfig) error {
|
|
return ErrNotSupported
|
|
}
|
|
|
|
// --- 客户端管理 ---
|
|
|
|
// GetClientID 获取当前客户端 ID
|
|
func (c *ClientAPI) GetClientID() string {
|
|
return c.clientID
|
|
}
|
|
|
|
// GetClientList 客户端不支持
|
|
func (c *ClientAPI) GetClientList() ([]ClientInfo, error) {
|
|
return nil, ErrNotSupported
|
|
}
|
|
|
|
// IsClientOnline 客户端不支持
|
|
func (c *ClientAPI) IsClientOnline(clientID string) bool {
|
|
return false
|
|
}
|
|
|
|
// --- 上下文 ---
|
|
|
|
// GetContext 获取当前上下文
|
|
func (c *ClientAPI) GetContext() *Context {
|
|
return &Context{
|
|
PluginName: c.getPluginName(),
|
|
Side: SideClient,
|
|
ClientID: c.clientID,
|
|
Config: c.getConfigMap(),
|
|
}
|
|
}
|
|
|
|
// GetServerInfo 客户端不支持
|
|
func (c *ClientAPI) GetServerInfo() *ServerInfo {
|
|
return nil
|
|
}
|