Files
2019-08-08 17:13:34 +08:00

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)
}
}()
}