232 lines
5.2 KiB
Go
232 lines
5.2 KiB
Go
package main
|
|
|
|
import (
|
|
utils "anytunnel/at-common"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
//###############ServerUserConn##################
|
|
|
|
type ServerUserConn struct {
|
|
TunnelID uint64
|
|
ConnectionID uint64
|
|
Connection *tls.Conn
|
|
}
|
|
|
|
type ServerUserConnPool struct {
|
|
pool utils.ConcurrentMap
|
|
}
|
|
|
|
func NewServerUserConnPool() ServerUserConnPool {
|
|
return ServerUserConnPool{
|
|
pool: utils.NewConcurrentMap(),
|
|
}
|
|
}
|
|
func (m *ServerUserConnPool) IntToString(id uint64) string {
|
|
return strconv.FormatUint(id, 10)
|
|
}
|
|
func (t *ServerUserConnPool) Put(tunnelID, connectionID uint64, conn *tls.Conn) {
|
|
tid := t.IntToString(tunnelID)
|
|
cid := t.IntToString(connectionID)
|
|
if _, e := t.pool.Get(tid); !e {
|
|
mp := utils.NewConcurrentMap()
|
|
t.pool.Set(tid, &mp)
|
|
}
|
|
m, _ := t.pool.Get(tid)
|
|
m.(*utils.ConcurrentMap).Set(cid, ServerUserConn{
|
|
Connection: conn,
|
|
TunnelID: tunnelID,
|
|
ConnectionID: tunnelID,
|
|
})
|
|
}
|
|
func (t *ServerUserConnPool) Get(tunnelID, connectionID uint64) (conn ServerUserConn, err error) {
|
|
tid := t.IntToString(tunnelID)
|
|
cid := t.IntToString(connectionID)
|
|
_, e := t.pool.Get(tid)
|
|
if !e {
|
|
err = fmt.Errorf("tunnel %d not exists", tunnelID)
|
|
return
|
|
}
|
|
m, _ := t.pool.Get(tid)
|
|
|
|
v1, e1 := m.(*utils.ConcurrentMap).Get(cid)
|
|
if !e1 {
|
|
err = fmt.Errorf("server user connection %d not exists", connectionID)
|
|
return
|
|
}
|
|
return v1.(ServerUserConn), err
|
|
}
|
|
func (t *ServerUserConnPool) Exists(tunnelID uint64, connectionID uint64) bool {
|
|
tid := t.IntToString(tunnelID)
|
|
cid := t.IntToString(connectionID)
|
|
_, e := t.pool.Get(tid)
|
|
if e {
|
|
m, _ := t.pool.Get(tid)
|
|
_, e = m.(*utils.ConcurrentMap).Get(cid)
|
|
}
|
|
return e
|
|
}
|
|
func (t *ServerUserConnPool) DeleteAll(tunnelID uint64) {
|
|
tid := t.IntToString(tunnelID)
|
|
_, e := t.pool.Get(tid)
|
|
if !e {
|
|
return
|
|
}
|
|
m, _ := t.pool.Get(tid)
|
|
for _, v := range m.(*utils.ConcurrentMap).Keys() {
|
|
el, _ := m.(*utils.ConcurrentMap).Get(v)
|
|
(*(el.(ServerUserConn)).Connection).Close()
|
|
}
|
|
t.pool.Remove(tid)
|
|
}
|
|
func (t *ServerUserConnPool) Delete(tunnelID uint64, connectionID uint64) {
|
|
tid := t.IntToString(tunnelID)
|
|
cid := t.IntToString(connectionID)
|
|
v1, e := t.pool.Get(tid)
|
|
if !e {
|
|
return
|
|
}
|
|
c, e := v1.(*utils.ConcurrentMap).Get(cid)
|
|
if !e {
|
|
return
|
|
}
|
|
(*(c.(ServerUserConn)).Connection).Close()
|
|
v1.(*utils.ConcurrentMap).Remove(cid)
|
|
if v1.(*utils.ConcurrentMap).IsEmpty() {
|
|
t.pool.Remove(tid)
|
|
}
|
|
}
|
|
|
|
//###############ListenerMap##################
|
|
type ListenerMap struct {
|
|
data utils.ConcurrentMap
|
|
}
|
|
type ListenerTimeout struct {
|
|
Listener *net.Listener
|
|
LastTime int64
|
|
}
|
|
type UDPListenerTimeout struct {
|
|
Listener *net.UDPConn
|
|
LastTime int64
|
|
}
|
|
|
|
func NewListenerMap() ListenerMap {
|
|
cm := ListenerMap{
|
|
data: utils.NewConcurrentMap(),
|
|
}
|
|
return cm
|
|
}
|
|
func (m *ListenerMap) IntToString(id uint64) string {
|
|
return strconv.FormatUint(id, 10)
|
|
}
|
|
func (m *ListenerMap) Get(id uint64) (conn *net.Listener, exists bool) {
|
|
mid := m.IntToString(id)
|
|
_conn, exists := m.data.Get(mid)
|
|
if exists {
|
|
conn = (_conn).(ListenerTimeout).Listener
|
|
}
|
|
return
|
|
}
|
|
func (m *ListenerMap) GetUDP(id uint64) (conn *net.UDPConn, exists bool) {
|
|
mid := m.IntToString(id)
|
|
_conn, exists := m.data.Get(mid)
|
|
if exists {
|
|
conn = (_conn).(UDPListenerTimeout).Listener
|
|
}
|
|
return
|
|
}
|
|
func (m *ListenerMap) Put(id uint64, Listener interface{}) {
|
|
mid := m.IntToString(id)
|
|
if v, ok := Listener.(*net.Listener); ok {
|
|
m.data.Set(mid, ListenerTimeout{
|
|
Listener: v,
|
|
LastTime: time.Now().Unix(),
|
|
})
|
|
} else {
|
|
m.data.Set(mid, UDPListenerTimeout{
|
|
Listener: Listener.(*net.UDPConn),
|
|
LastTime: time.Now().Unix(),
|
|
})
|
|
}
|
|
|
|
return
|
|
}
|
|
func (m *ListenerMap) Delete(id uint64) {
|
|
mid := m.IntToString(id)
|
|
if _conn, exists := m.data.Get(mid); exists {
|
|
if _, ok := _conn.(ListenerTimeout); ok {
|
|
(*(_conn.(ListenerTimeout)).Listener).Close()
|
|
} else {
|
|
(*(_conn.(UDPListenerTimeout)).Listener).Close()
|
|
}
|
|
|
|
}
|
|
m.data.Remove(mid)
|
|
}
|
|
|
|
//#################ip conn counter################
|
|
type IPConnCounter struct {
|
|
data utils.ConcurrentMap
|
|
blockSeconds int
|
|
maxConnCount int
|
|
}
|
|
type IPConnCounterItem struct {
|
|
LastTime int64
|
|
Count int
|
|
}
|
|
|
|
func NewIPConnCounter(maxConnCount, blockSeconds int) (ic IPConnCounter) {
|
|
ic = IPConnCounter{
|
|
data: utils.NewConcurrentMap(),
|
|
blockSeconds: blockSeconds,
|
|
maxConnCount: maxConnCount - 1,
|
|
}
|
|
ic.gc()
|
|
return
|
|
}
|
|
func (ic *IPConnCounter) Check(ip string) bool {
|
|
_item, ok := ic.data.Get(ip)
|
|
if ok {
|
|
item := _item.(IPConnCounterItem)
|
|
if item.Count > ic.maxConnCount {
|
|
if time.Now().Unix()-item.LastTime > int64(ic.blockSeconds) {
|
|
ic.data.Remove(ip)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
ic.data.Upsert(ip, nil, func(exist bool, valueInMap interface{}, newValue interface{}) (res interface{}) {
|
|
var _valueInMap IPConnCounterItem
|
|
if exist {
|
|
_valueInMap = valueInMap.(IPConnCounterItem)
|
|
_valueInMap.Count = _valueInMap.Count + 1
|
|
_valueInMap.LastTime = time.Now().Unix()
|
|
} else {
|
|
_valueInMap = IPConnCounterItem{
|
|
Count: 1,
|
|
LastTime: time.Now().Unix(),
|
|
}
|
|
}
|
|
return _valueInMap
|
|
})
|
|
return true
|
|
}
|
|
func (ic *IPConnCounter) gc() {
|
|
go func() {
|
|
for {
|
|
for k, v := range ic.data.Items() {
|
|
item := v.(IPConnCounterItem)
|
|
if time.Now().Unix()-item.LastTime > int64(ic.blockSeconds) {
|
|
ic.data.Remove(k)
|
|
}
|
|
}
|
|
time.Sleep(time.Second * 300)
|
|
}
|
|
}()
|
|
}
|