Files
v2ray_simple/machine/machine.go
2022-12-28 12:47:23 +08:00

197 lines
4.3 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 machine 定义一个 可以直接运行的有限状态机;这个机器可以直接被可执行文件或者动态库所使用.
machine把所有运行代理所需要的代码包装起来对外像一个黑盒子。
关键点是不使用任何静态变量所有变量都放在machine中。
*/
package machine
import (
"fmt"
"io"
"os"
"strings"
"sync"
"github.com/e1732a364fed/v2ray_simple"
"github.com/e1732a364fed/v2ray_simple/httpLayer"
"github.com/e1732a364fed/v2ray_simple/proxy"
"github.com/e1732a364fed/v2ray_simple/utils"
"go.uber.org/zap"
)
type M struct {
sync.RWMutex
v2ray_simple.GlobalInfo
AppConf
ApiServerConf
tomlApiServerConf ApiServerConf
CmdApiServerConf ApiServerConf
standardConf proxy.StandardConf
urlConf proxy.UrlConf
running bool
apiServerRunning bool
DefaultOutClient proxy.Client
routingEnv proxy.RoutingEnv
allServers []proxy.Server
allClients []proxy.Client
listenCloserList []io.Closer
callbacks
}
func New() *M {
m := new(M)
m.allClients = make([]proxy.Client, 0, 8)
m.allServers = make([]proxy.Server, 0, 8)
m.routingEnv.ClientsTagMap = make(map[string]proxy.Client)
directClient, _ := proxy.ClientFromURL(proxy.DirectURL)
m.DefaultOutClient = directClient
return m
}
// 具有 DefaultOutClient 且不是direct也不是reject; 一般表明该通向一个外界代理
func (m *M) DefaultClientUsable() bool {
dc := m.DefaultOutClient
if dc == nil {
return false
}
n := dc.Name()
return n != proxy.DirectName && n != proxy.RejectName
}
func (m *M) ServerCount() int {
return len(m.allServers)
}
func (m *M) ClientCount() int {
return len(m.allClients)
}
func (m *M) IsRunning() bool {
return m.running
}
func (m *M) IsApiServerRunning() bool {
return m.apiServerRunning
}
// 运行配置 以及 apiServer
func (m *M) Start() {
if (m.DefaultOutClient != nil) && (len(m.allServers) > 0) {
utils.Info("Starting...")
m.Lock()
m.running = true
m.callToggleFallback(1)
for _, inServer := range m.allServers {
lis := v2ray_simple.ListenSer(inServer, m.DefaultOutClient, &m.routingEnv, &m.GlobalInfo)
if lis != nil {
m.listenCloserList = append(m.listenCloserList, lis)
}
}
if dm := m.routingEnv.DnsMachine; dm != nil {
dm.StartListen()
}
m.Unlock()
}
if !m.apiServerRunning && m.EnableApiServer {
m.TryRunApiServer()
}
}
// 融合 CmdApiServerConf 和 TomlApiServerConf, CmdApiServerConf 的值会覆盖 TomlApiServerConf
func (m *M) SetupApiConf() {
m.ApiServerConf = NewApiServerConf()
m.ApiServerConf.SetUnDefault(&m.tomlApiServerConf)
m.ApiServerConf.SetUnDefault(&m.CmdApiServerConf)
}
// Stop不会停止ApiServer
func (m *M) Stop() {
utils.Info("Stopping...")
m.Lock()
m.running = false
m.callToggleFallback(0)
for _, ser := range m.allServers {
if ser != nil {
ser.Stop()
}
}
for _, listener := range m.listenCloserList {
if listener != nil {
listener.Close()
}
}
if dm := m.routingEnv.DnsMachine; dm != nil {
dm.Stop()
}
m.Unlock()
}
func (m *M) SetDefaultDirectClient() {
m.allClients = append(m.allClients, v2ray_simple.DirectClient)
m.DefaultOutClient = v2ray_simple.DirectClient
m.routingEnv.SetClient("direct", v2ray_simple.DirectClient)
}
// 将fallback配置中的@转化成实际对应的server的地址
func (m *M) ParseFallbacksAtSymbol(fs []*httpLayer.FallbackConf) {
for _, fbConf := range fs {
if fbConf.Dest == nil {
continue
}
if deststr, ok := fbConf.Dest.(string); ok && strings.HasPrefix(deststr, "@") {
for _, s := range m.allServers {
if s.GetTag() == deststr[1:] {
if ce := utils.CanLogDebug("got @tag fallback dest"); ce != nil {
ce.Write(zap.String("will set to ", s.AddrStr()), zap.String("tag", deststr[1:]))
}
fbConf.Dest = s.AddrStr()
}
}
}
}
}
func (m *M) HasProxyRunning() bool {
return len(m.listenCloserList) > 0
}
func (m *M) PrintAllState(w io.Writer) {
if w == nil {
w = os.Stdout
}
fmt.Fprintln(w, "activeConnectionCount", m.ActiveConnectionCount)
fmt.Fprintln(w, "allDownloadBytesSinceStart", m.AllDownloadBytesSinceStart)
fmt.Fprintln(w, "allUploadBytesSinceStart", m.AllUploadBytesSinceStart)
for i, s := range m.allServers {
fmt.Fprintln(w, "inServer", i, proxy.GetVSI_url(s, ""))
}
for i, c := range m.allClients {
fmt.Fprintln(w, "outClient", i, proxy.GetVSI_url(c, ""))
}
}