session.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. package sessdata
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "net"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. "sync/atomic"
  10. "time"
  11. "github.com/bjdgyc/anylink/base"
  12. "github.com/bjdgyc/anylink/dbdata"
  13. mapset "github.com/deckarep/golang-set"
  14. atomic2 "go.uber.org/atomic"
  15. )
  16. var (
  17. // session_token -> SessUser
  18. sessions = make(map[string]*Session)
  19. // dtlsId -> session_token
  20. dtlsIds = make(map[string]string)
  21. sessMux sync.RWMutex
  22. )
  23. // 连接sess
  24. type ConnSession struct {
  25. Sess *Session
  26. MasterSecret string // dtls协议的 master_secret
  27. IpAddr net.IP // 分配的ip地址
  28. LocalIp net.IP
  29. MacHw net.HardwareAddr // 客户端mac地址,从Session取出
  30. Username string
  31. RemoteAddr string
  32. Mtu int
  33. IfName string
  34. Client string // 客户端 mobile pc
  35. UserAgent string // 客户端信息
  36. UserLogoutCode uint8 // 用户/客户端主动登出
  37. CstpDpd int
  38. Group *dbdata.Group
  39. Limit *LimitRater
  40. BandwidthUp atomic2.Uint32 // 使用上行带宽 Byte
  41. BandwidthDown atomic2.Uint32 // 使用下行带宽 Byte
  42. BandwidthUpPeriod atomic2.Uint32 // 前一周期的总量
  43. BandwidthDownPeriod atomic2.Uint32
  44. BandwidthUpAll atomic2.Uint64 // 使用上行带宽总量
  45. BandwidthDownAll atomic2.Uint64 // 使用下行带宽总量
  46. closeOnce sync.Once
  47. CloseChan chan struct{}
  48. PayloadIn chan *Payload
  49. PayloadOutCstp chan *Payload // Cstp的数据
  50. PayloadOutDtls chan *Payload // Dtls的数据
  51. // dSess *DtlsSession
  52. dSess *atomic.Value
  53. // compress
  54. CstpPickCmp CmpEncoding
  55. DtlsPickCmp CmpEncoding
  56. }
  57. type DtlsSession struct {
  58. isActive int32
  59. CloseChan chan struct{}
  60. closeOnce sync.Once
  61. IpAddr net.IP
  62. }
  63. type Session struct {
  64. mux sync.RWMutex
  65. Sid string // auth返回的 session-id
  66. Token string // session信息的唯一token
  67. DtlsSid string // dtls协议的 session_id
  68. MacAddr string // 客户端mac地址
  69. UniqueIdGlobal string // 客户端唯一标示
  70. MacHw net.HardwareAddr
  71. UniqueMac bool // 客户端获取到真实设备mac
  72. Username string // 用户名
  73. Group string
  74. AuthStep string
  75. AuthPass string
  76. RemoteAddr string
  77. UserAgent string
  78. DeviceType string
  79. PlatformVersion string
  80. LastLogin time.Time
  81. IsActive bool
  82. // 开启link需要设置的参数
  83. CSess *ConnSession
  84. }
  85. func init() {
  86. rand.Seed(time.Now().UnixNano())
  87. }
  88. func checkSession() {
  89. // 检测过期的session
  90. go func() {
  91. if base.Cfg.SessionTimeout == 0 {
  92. return
  93. }
  94. timeout := time.Duration(base.Cfg.SessionTimeout) * time.Second
  95. tick := time.NewTicker(time.Second * 60)
  96. for range tick.C {
  97. outToken := []string{}
  98. sessMux.RLock()
  99. t := time.Now()
  100. for k, v := range sessions {
  101. v.mux.RLock()
  102. if !v.IsActive {
  103. if t.Sub(v.LastLogin) > timeout {
  104. outToken = append(outToken, k)
  105. }
  106. }
  107. v.mux.RUnlock()
  108. }
  109. sessMux.RUnlock()
  110. // 删除过期session
  111. for _, v := range outToken {
  112. CloseSess(v, dbdata.UserLogoutTimeout)
  113. }
  114. }
  115. }()
  116. }
  117. // 状态为过期的用户踢下线
  118. func CloseUserLimittimeSession() {
  119. s := mapset.NewSetFromSlice(dbdata.CheckUserlimittime())
  120. limitTimeToken := []string{}
  121. sessMux.RLock()
  122. for _, v := range sessions {
  123. v.mux.RLock()
  124. if v.IsActive && s.Contains(v.Username) {
  125. limitTimeToken = append(limitTimeToken, v.Token)
  126. }
  127. v.mux.RUnlock()
  128. }
  129. sessMux.RUnlock()
  130. for _, v := range limitTimeToken {
  131. CloseSess(v, dbdata.UserLogoutExpire)
  132. }
  133. }
  134. func GenToken() string {
  135. // 生成32位的 token
  136. bToken := make([]byte, 32)
  137. rand.Read(bToken)
  138. return fmt.Sprintf("%x", bToken)
  139. }
  140. func NewSession(token string) *Session {
  141. if token == "" {
  142. btoken := make([]byte, 32)
  143. rand.Read(btoken)
  144. token = fmt.Sprintf("%x", btoken)
  145. }
  146. // 生成 dtlsn session_id
  147. dtlsid := make([]byte, 32)
  148. rand.Read(dtlsid)
  149. sess := &Session{
  150. Sid: fmt.Sprintf("%d", time.Now().Unix()),
  151. Token: token,
  152. DtlsSid: fmt.Sprintf("%x", dtlsid),
  153. LastLogin: time.Now(),
  154. }
  155. sessMux.Lock()
  156. sessions[token] = sess
  157. dtlsIds[sess.DtlsSid] = token
  158. sessMux.Unlock()
  159. return sess
  160. }
  161. func (s *Session) NewConn() *ConnSession {
  162. s.mux.RLock()
  163. active := s.IsActive
  164. macAddr := s.MacAddr
  165. macHw := s.MacHw
  166. username := s.Username
  167. uniqueMac := s.UniqueMac
  168. s.mux.RUnlock()
  169. if active {
  170. s.CSess.Close()
  171. }
  172. limit := LimitClient(username, false)
  173. if !limit {
  174. base.Warn("limit is full", username)
  175. return nil
  176. }
  177. ip := AcquireIp(username, macAddr, uniqueMac)
  178. if ip == nil {
  179. LimitClient(username, true)
  180. return nil
  181. }
  182. // 查询group信息
  183. group := &dbdata.Group{}
  184. err := dbdata.One("Name", s.Group, group)
  185. if err != nil {
  186. base.Error(err)
  187. return nil
  188. }
  189. cSess := &ConnSession{
  190. Sess: s,
  191. MacHw: macHw,
  192. Username: username,
  193. IpAddr: ip,
  194. closeOnce: sync.Once{},
  195. CloseChan: make(chan struct{}),
  196. PayloadIn: make(chan *Payload, 64),
  197. PayloadOutCstp: make(chan *Payload, 64),
  198. PayloadOutDtls: make(chan *Payload, 64),
  199. dSess: &atomic.Value{},
  200. }
  201. dSess := &DtlsSession{
  202. isActive: -1,
  203. }
  204. cSess.dSess.Store(dSess)
  205. cSess.Group = group
  206. if group.Bandwidth > 0 {
  207. // 限流设置
  208. cSess.Limit = NewLimitRater(group.Bandwidth, group.Bandwidth)
  209. }
  210. go cSess.ratePeriod()
  211. s.mux.Lock()
  212. s.MacAddr = macAddr
  213. s.IsActive = true
  214. s.CSess = cSess
  215. s.mux.Unlock()
  216. return cSess
  217. }
  218. func (cs *ConnSession) Close() {
  219. cs.closeOnce.Do(func() {
  220. base.Info("closeOnce:", cs.IpAddr)
  221. cs.Sess.mux.Lock()
  222. defer cs.Sess.mux.Unlock()
  223. close(cs.CloseChan)
  224. cs.Sess.IsActive = false
  225. cs.Sess.LastLogin = time.Now()
  226. cs.Sess.CSess = nil
  227. dSess := cs.GetDtlsSession()
  228. if dSess != nil {
  229. dSess.Close()
  230. }
  231. ReleaseIp(cs.IpAddr, cs.Sess.MacAddr)
  232. LimitClient(cs.Username, true)
  233. AddUserActLog(cs)
  234. })
  235. }
  236. // 创建dtls链接
  237. func (cs *ConnSession) NewDtlsConn() *DtlsSession {
  238. ds := cs.dSess.Load().(*DtlsSession)
  239. isActive := atomic.LoadInt32(&ds.isActive)
  240. if isActive > 0 {
  241. // 判断原有连接存在,不进行创建
  242. return nil
  243. }
  244. dSess := &DtlsSession{
  245. isActive: 1,
  246. CloseChan: make(chan struct{}),
  247. closeOnce: sync.Once{},
  248. IpAddr: cs.IpAddr,
  249. }
  250. cs.dSess.Store(dSess)
  251. return dSess
  252. }
  253. // 关闭dtls链接
  254. func (ds *DtlsSession) Close() {
  255. ds.closeOnce.Do(func() {
  256. base.Info("closeOnce dtls:", ds.IpAddr)
  257. atomic.StoreInt32(&ds.isActive, -1)
  258. close(ds.CloseChan)
  259. })
  260. }
  261. func (cs *ConnSession) GetDtlsSession() *DtlsSession {
  262. ds := cs.dSess.Load().(*DtlsSession)
  263. isActive := atomic.LoadInt32(&ds.isActive)
  264. if isActive > 0 {
  265. return ds
  266. }
  267. return nil
  268. }
  269. const BandwidthPeriodSec = 10 // 流量速率统计周期(秒)
  270. func (cs *ConnSession) ratePeriod() {
  271. tick := time.NewTicker(time.Second * BandwidthPeriodSec)
  272. defer tick.Stop()
  273. for range tick.C {
  274. select {
  275. case <-cs.CloseChan:
  276. return
  277. default:
  278. }
  279. // 实时流量清零
  280. rtUp := cs.BandwidthUp.Swap(0)
  281. rtDown := cs.BandwidthDown.Swap(0)
  282. // 设置上一周期每秒的流量
  283. cs.BandwidthUpPeriod.Swap(rtUp / BandwidthPeriodSec)
  284. cs.BandwidthDownPeriod.Swap(rtDown / BandwidthPeriodSec)
  285. // 累加所有流量
  286. cs.BandwidthUpAll.Add(uint64(rtUp))
  287. cs.BandwidthDownAll.Add(uint64(rtDown))
  288. }
  289. }
  290. var MaxMtu = 1460
  291. func (cs *ConnSession) SetMtu(mtu string) {
  292. if base.Cfg.Mtu > 0 {
  293. MaxMtu = base.Cfg.Mtu
  294. }
  295. cs.Mtu = MaxMtu
  296. mi, err := strconv.Atoi(mtu)
  297. if err != nil || mi < 100 {
  298. return
  299. }
  300. if mi < MaxMtu {
  301. cs.Mtu = mi
  302. }
  303. }
  304. func (cs *ConnSession) SetIfName(name string) {
  305. cs.Sess.mux.Lock()
  306. defer cs.Sess.mux.Unlock()
  307. cs.IfName = name
  308. }
  309. func (cs *ConnSession) RateLimit(byt int, isUp bool) error {
  310. if isUp {
  311. cs.BandwidthUp.Add(uint32(byt))
  312. return nil
  313. }
  314. // 只对下行速率限制
  315. cs.BandwidthDown.Add(uint32(byt))
  316. if cs.Limit == nil {
  317. return nil
  318. }
  319. return cs.Limit.Wait(byt)
  320. }
  321. func (cs *ConnSession) SetPickCmp(cate, encoding string) (string, bool) {
  322. var cmpName string
  323. if !base.Cfg.Compression {
  324. return cmpName, false
  325. }
  326. var cmp CmpEncoding
  327. switch {
  328. // case strings.Contains(encoding, "oc-lz4"):
  329. // cmpName = "oc-lz4"
  330. // cmp = Lz4Cmp{}
  331. case strings.Contains(encoding, "lzs"):
  332. cmpName = "lzs"
  333. cmp = LzsgoCmp{}
  334. default:
  335. return cmpName, false
  336. }
  337. if cate == "cstp" {
  338. cs.CstpPickCmp = cmp
  339. } else {
  340. cs.DtlsPickCmp = cmp
  341. }
  342. return cmpName, true
  343. }
  344. func SToken2Sess(stoken string) *Session {
  345. stoken = strings.TrimSpace(stoken)
  346. sarr := strings.Split(stoken, "@")
  347. token := sarr[1]
  348. return Token2Sess(token)
  349. }
  350. func Token2Sess(token string) *Session {
  351. sessMux.RLock()
  352. defer sessMux.RUnlock()
  353. return sessions[token]
  354. }
  355. func Dtls2Sess(did string) *Session {
  356. sessMux.RLock()
  357. defer sessMux.RUnlock()
  358. token := dtlsIds[did]
  359. return sessions[token]
  360. }
  361. func Dtls2CSess(did string) *ConnSession {
  362. sessMux.RLock()
  363. defer sessMux.RUnlock()
  364. token := dtlsIds[did]
  365. sess := sessions[token]
  366. if sess == nil {
  367. return nil
  368. }
  369. sess.mux.RLock()
  370. defer sess.mux.RUnlock()
  371. return sess.CSess
  372. }
  373. func Dtls2MasterSecret(did string) string {
  374. sessMux.RLock()
  375. token := dtlsIds[did]
  376. sess := sessions[token]
  377. sessMux.RUnlock()
  378. if sess == nil {
  379. return ""
  380. }
  381. sess.mux.RLock()
  382. defer sess.mux.RUnlock()
  383. if sess.CSess == nil {
  384. return ""
  385. }
  386. return sess.CSess.MasterSecret
  387. }
  388. func DelSess(token string) {
  389. // sessions.Delete(token)
  390. }
  391. func CloseSess(token string, code ...uint8) {
  392. sessMux.Lock()
  393. defer sessMux.Unlock()
  394. sess, ok := sessions[token]
  395. if !ok {
  396. return
  397. }
  398. delete(sessions, token)
  399. delete(dtlsIds, sess.DtlsSid)
  400. if sess.CSess != nil {
  401. if len(code) > 0 {
  402. sess.CSess.UserLogoutCode = code[0]
  403. }
  404. sess.CSess.Close()
  405. return
  406. }
  407. AddUserActLogBySess(sess)
  408. }
  409. func CloseCSess(token string) {
  410. sessMux.RLock()
  411. defer sessMux.RUnlock()
  412. sess, ok := sessions[token]
  413. if !ok {
  414. return
  415. }
  416. if sess.CSess != nil {
  417. sess.CSess.Close()
  418. }
  419. }
  420. func DelSessByStoken(stoken string) {
  421. stoken = strings.TrimSpace(stoken)
  422. sarr := strings.Split(stoken, "@")
  423. token := sarr[1]
  424. CloseSess(token, dbdata.UserLogoutBanner)
  425. }
  426. func AddUserActLog(cs *ConnSession) {
  427. ua := dbdata.UserActLog{
  428. Username: cs.Sess.Username,
  429. GroupName: cs.Sess.Group,
  430. IpAddr: cs.IpAddr.String(),
  431. RemoteAddr: cs.RemoteAddr,
  432. DeviceType: cs.Sess.DeviceType,
  433. PlatformVersion: cs.Sess.PlatformVersion,
  434. Status: dbdata.UserLogout,
  435. }
  436. ua.Info = dbdata.UserActLogIns.GetInfoOpsById(cs.UserLogoutCode)
  437. dbdata.UserActLogIns.Add(ua, cs.UserAgent)
  438. }
  439. func AddUserActLogBySess(sess *Session) {
  440. ua := dbdata.UserActLog{
  441. Username: sess.Username,
  442. GroupName: sess.Group,
  443. IpAddr: "",
  444. RemoteAddr: sess.RemoteAddr,
  445. DeviceType: sess.DeviceType,
  446. PlatformVersion: sess.PlatformVersion,
  447. Status: dbdata.UserLogout,
  448. }
  449. ua.Info = dbdata.UserActLogIns.GetInfoOpsById(dbdata.UserLogoutBanner)
  450. dbdata.UserActLogIns.Add(ua, sess.UserAgent)
  451. }