202 lines
3.3 KiB
Go
202 lines
3.3 KiB
Go
|
package forward
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"git.makemake.in/kzkzzzz/mycommon/mylog"
|
||
|
"proxyport/app/db"
|
||
|
"proxyport/app/model"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
type Protocol int
|
||
|
|
||
|
func (p Protocol) String() string {
|
||
|
switch p {
|
||
|
case 0:
|
||
|
return "TCP"
|
||
|
case 1:
|
||
|
return "UDP"
|
||
|
}
|
||
|
|
||
|
return "unknown"
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
ProtocolTCP Protocol = 0
|
||
|
ProtocolUDP Protocol = 1
|
||
|
)
|
||
|
|
||
|
type IForward interface {
|
||
|
Forward() error
|
||
|
Stop()
|
||
|
}
|
||
|
|
||
|
var ListenerManager = &Manager{
|
||
|
lock: &sync.Mutex{},
|
||
|
}
|
||
|
|
||
|
type Info struct {
|
||
|
Id int
|
||
|
Name string
|
||
|
TargetAddr []string
|
||
|
LocalAddr string
|
||
|
LocalIp string
|
||
|
LocalPort int
|
||
|
Protocol Protocol
|
||
|
Status int
|
||
|
}
|
||
|
|
||
|
type activeForward struct {
|
||
|
forward IForward
|
||
|
info *Info
|
||
|
}
|
||
|
|
||
|
type forwardKey struct {
|
||
|
localAddr string
|
||
|
protocol Protocol
|
||
|
}
|
||
|
|
||
|
type Manager struct {
|
||
|
activeForwardMap map[forwardKey]*activeForward
|
||
|
lock *sync.Mutex
|
||
|
}
|
||
|
|
||
|
func (m *Manager) initForwardList() []*Info {
|
||
|
data := make([]*model.Forward, 0)
|
||
|
err := db.DB().Table("forward").Select("*").Find(&data).Error
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
list := make([]*Info, 0)
|
||
|
|
||
|
for _, v := range data {
|
||
|
if v.Status == 0 {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
list = append(list, m.convertModel(v))
|
||
|
}
|
||
|
|
||
|
return list
|
||
|
}
|
||
|
|
||
|
func (m *Manager) convertModel(v *model.Forward) *Info {
|
||
|
info := &Info{
|
||
|
Id: v.Id,
|
||
|
Name: v.Name,
|
||
|
TargetAddr: v.TargetAddr,
|
||
|
LocalIp: v.LocalIp,
|
||
|
LocalPort: v.LocalPort,
|
||
|
Protocol: Protocol(v.Protocol),
|
||
|
Status: v.Status,
|
||
|
}
|
||
|
|
||
|
if v.LocalIp == "" {
|
||
|
info.LocalAddr = fmt.Sprintf("0.0.0.0:%d", v.LocalPort)
|
||
|
} else {
|
||
|
info.LocalAddr = fmt.Sprintf("%s:%d", v.LocalIp, v.LocalPort)
|
||
|
}
|
||
|
|
||
|
return info
|
||
|
}
|
||
|
|
||
|
func (m *Manager) Add(v *model.Forward) error {
|
||
|
m.lock.Lock()
|
||
|
defer m.lock.Unlock()
|
||
|
|
||
|
forwardInfo := m.convertModel(v)
|
||
|
|
||
|
key := forwardKey{
|
||
|
localAddr: forwardInfo.LocalAddr,
|
||
|
protocol: forwardInfo.Protocol,
|
||
|
}
|
||
|
|
||
|
_, ok := m.activeForwardMap[key]
|
||
|
if ok {
|
||
|
return fmt.Errorf("[%s] [%s] is exist", forwardInfo.Protocol, forwardInfo.LocalAddr)
|
||
|
}
|
||
|
|
||
|
tmp := &activeForward{
|
||
|
info: forwardInfo,
|
||
|
}
|
||
|
if Protocol(v.Protocol) == ProtocolUDP {
|
||
|
tmp.forward = NewUDP(forwardInfo)
|
||
|
} else {
|
||
|
tmp.forward = NewTCP(forwardInfo)
|
||
|
}
|
||
|
m.activeForwardMap[key] = tmp
|
||
|
|
||
|
err := tmp.forward.Forward()
|
||
|
if err != nil {
|
||
|
delete(m.activeForwardMap, key)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (m *Manager) Remove(v *model.Forward) {
|
||
|
m.lock.Lock()
|
||
|
defer m.lock.Unlock()
|
||
|
|
||
|
forwardInfo := m.convertModel(v)
|
||
|
|
||
|
key := forwardKey{
|
||
|
localAddr: forwardInfo.LocalAddr,
|
||
|
protocol: forwardInfo.Protocol,
|
||
|
}
|
||
|
fr, ok := m.activeForwardMap[key]
|
||
|
if !ok {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
fr.forward.Stop()
|
||
|
delete(m.activeForwardMap, key)
|
||
|
}
|
||
|
|
||
|
func (m *Manager) Start(ctx context.Context) {
|
||
|
m.activeForwardMap = make(map[forwardKey]*activeForward)
|
||
|
|
||
|
list := m.initForwardList()
|
||
|
for _, v := range list {
|
||
|
key := forwardKey{
|
||
|
localAddr: v.LocalAddr,
|
||
|
protocol: v.Protocol,
|
||
|
}
|
||
|
|
||
|
switch v.Protocol {
|
||
|
case ProtocolTCP:
|
||
|
m.activeForwardMap[key] = &activeForward{
|
||
|
forward: NewTCP(v),
|
||
|
info: v,
|
||
|
}
|
||
|
|
||
|
case ProtocolUDP:
|
||
|
m.activeForwardMap[key] = &activeForward{
|
||
|
forward: NewUDP(v),
|
||
|
info: v,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for _, v := range m.activeForwardMap {
|
||
|
err := v.forward.Forward()
|
||
|
if err != nil {
|
||
|
mylog.Error(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
select {
|
||
|
case <-ctx.Done():
|
||
|
m.Stop()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (m *Manager) Stop() {
|
||
|
for _, v := range m.activeForwardMap {
|
||
|
v.forward.Stop()
|
||
|
}
|
||
|
}
|