4
0

session.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. package state
  2. import (
  3. "net/netip"
  4. "sync"
  5. "time"
  6. "github.com/mk6i/retro-aim-server/wire"
  7. )
  8. // SessSendStatus is the result of sending a message to a user.
  9. type SessSendStatus int
  10. // RateClassState tracks the rate limiting state for a specific rate class
  11. // within a user's session.
  12. //
  13. // It embeds the static wire.RateClass configuration and maintains dynamic,
  14. // per-session state used to evaluate rate limits in real time.
  15. type RateClassState struct {
  16. // static rate limit configuration for this class
  17. wire.RateClass
  18. // CurrentLevel is the current exponential moving average for this rate
  19. // class.
  20. CurrentLevel int32
  21. // LastTime represents the last time a SNAC message was sent for this rate
  22. // class.
  23. LastTime time.Time
  24. // CurrentStatus is the last recorded rate limit status for this rate class.
  25. CurrentStatus wire.RateLimitStatus
  26. // Subscribed indicates whether the user wants to receive rate limit
  27. // parameter updates for this rate class.
  28. Subscribed bool
  29. // LimitedNow indicates whether the user is currently rate limited for this
  30. // rate class; the user is blocked from sending SNACs in this rate class
  31. // until the clear threshold is met.
  32. LimitedNow bool
  33. }
  34. const (
  35. // SessSendOK indicates message was sent to recipient
  36. SessSendOK SessSendStatus = iota
  37. // SessSendClosed indicates send did not complete because session is closed
  38. SessSendClosed
  39. // SessQueueFull indicates send failed due to full queue -- client is likely
  40. // dead
  41. SessQueueFull
  42. )
  43. // Session represents a user's current session. Unless stated otherwise, all
  44. // methods may be safely accessed by multiple goroutines.
  45. type Session struct {
  46. awayMessage string
  47. buddyIcon wire.BARTID
  48. caps [][16]byte
  49. chatRoomCookie string
  50. clientID string
  51. closed bool
  52. displayScreenName DisplayScreenName
  53. foodGroupVersions [wire.MDir + 1]uint16
  54. identScreenName IdentScreenName
  55. idle bool
  56. idleTime time.Time
  57. lastObservedStates [5]RateClassState
  58. msgCh chan wire.SNACMessage
  59. multiConnFlag wire.MultiConnFlag
  60. kerberosAuth bool
  61. mutex sync.RWMutex
  62. nowFn func() time.Time
  63. rateLimitStates [5]RateClassState
  64. rateLimitStatesOriginal [5]RateClassState
  65. remoteAddr *netip.AddrPort
  66. signonComplete bool
  67. signonTime time.Time
  68. stopCh chan struct{}
  69. typingEventsEnabled bool
  70. uin uint32
  71. userInfoBitmask uint16
  72. userStatusBitmask uint32
  73. warning uint16
  74. warningCh chan uint16
  75. lastWarnUpdate time.Time
  76. profile UserProfile
  77. memberSince time.Time
  78. offlineMsgCount int
  79. }
  80. // NewSession returns a new instance of Session. By default, the user may have
  81. // up to 1000 pending messages before blocking.
  82. func NewSession() *Session {
  83. now := time.Now()
  84. return &Session{
  85. msgCh: make(chan wire.SNACMessage, 1000),
  86. nowFn: time.Now,
  87. stopCh: make(chan struct{}),
  88. signonTime: now,
  89. caps: make([][16]byte, 0),
  90. userInfoBitmask: wire.OServiceUserFlagOSCARFree,
  91. userStatusBitmask: wire.OServiceUserStatusAvailable,
  92. foodGroupVersions: func() [wire.MDir + 1]uint16 {
  93. // initialize default food groups versions to 1.0
  94. vals := [wire.MDir + 1]uint16{}
  95. vals[wire.OService] = 1
  96. vals[wire.Locate] = 1
  97. vals[wire.Buddy] = 1
  98. vals[wire.ICBM] = 1
  99. vals[wire.Advert] = 1
  100. vals[wire.Invite] = 1
  101. vals[wire.Admin] = 1
  102. vals[wire.Popup] = 1
  103. vals[wire.PermitDeny] = 1
  104. vals[wire.UserLookup] = 1
  105. vals[wire.Stats] = 1
  106. vals[wire.Translate] = 1
  107. vals[wire.ChatNav] = 1
  108. vals[wire.Chat] = 1
  109. vals[wire.ODir] = 1
  110. vals[wire.BART] = 1
  111. vals[wire.Feedbag] = 1
  112. vals[wire.ICQ] = 1
  113. vals[wire.BUCP] = 1
  114. vals[wire.Alert] = 1
  115. vals[wire.Plugin] = 1
  116. vals[wire.UnnamedFG24] = 1
  117. vals[wire.MDir] = 1
  118. return vals
  119. }(),
  120. warningCh: make(chan uint16, 1),
  121. }
  122. }
  123. func (s *Session) SetRateClasses(now time.Time, classes wire.RateLimitClasses) {
  124. s.mutex.Lock()
  125. defer s.mutex.Unlock()
  126. var newStates [5]RateClassState
  127. for i, class := range classes.All() {
  128. newStates[i] = RateClassState{
  129. CurrentLevel: class.MaxLevel,
  130. CurrentStatus: wire.RateLimitStatusClear,
  131. LastTime: now,
  132. RateClass: class,
  133. Subscribed: s.lastObservedStates[i].Subscribed,
  134. }
  135. }
  136. if s.lastObservedStates[0].ID == 0 {
  137. s.lastObservedStates = newStates
  138. } else {
  139. s.lastObservedStates = s.rateLimitStates
  140. }
  141. s.rateLimitStates = newStates
  142. s.rateLimitStatesOriginal = newStates
  143. }
  144. // SetRemoteAddr sets the user's remote IP address
  145. func (s *Session) SetRemoteAddr(remoteAddr *netip.AddrPort) {
  146. s.mutex.Lock()
  147. defer s.mutex.Unlock()
  148. s.remoteAddr = remoteAddr
  149. }
  150. // RemoteAddrs returns user's remote IP address
  151. func (s *Session) RemoteAddr() (remoteAddr *netip.AddrPort) {
  152. s.mutex.RLock()
  153. defer s.mutex.RUnlock()
  154. return s.remoteAddr
  155. }
  156. // SetUserInfoFlag sets a flag to and returns UserInfoBitmask
  157. func (s *Session) SetUserInfoFlag(flag uint16) (flags uint16) {
  158. s.mutex.Lock()
  159. defer s.mutex.Unlock()
  160. s.userInfoBitmask |= flag
  161. return s.userInfoBitmask
  162. }
  163. // ClearUserInfoFlag clear a flag from and returns UserInfoBitmask
  164. func (s *Session) ClearUserInfoFlag(flag uint16) (flags uint16) {
  165. s.mutex.Lock()
  166. defer s.mutex.Unlock()
  167. s.userInfoBitmask &^= flag
  168. return s.userInfoBitmask
  169. }
  170. // UserInfoBitmask returns UserInfoBitmask
  171. func (s *Session) UserInfoBitmask() (flags uint16) {
  172. s.mutex.RLock()
  173. defer s.mutex.RUnlock()
  174. return s.userInfoBitmask
  175. }
  176. // RateLimitStates returns the current session rate limits
  177. func (s *Session) RateLimitStates() [5]RateClassState {
  178. return s.rateLimitStates
  179. }
  180. // SetUserStatusBitmask sets the user status bitmask from the client.
  181. func (s *Session) SetUserStatusBitmask(bitmask uint32) {
  182. s.mutex.Lock()
  183. defer s.mutex.Unlock()
  184. s.userStatusBitmask = bitmask
  185. }
  186. // UserStatusBitmask returns the user status bitmask.
  187. func (s *Session) UserStatusBitmask() uint32 {
  188. s.mutex.RLock()
  189. defer s.mutex.RUnlock()
  190. return s.userStatusBitmask
  191. }
  192. // ScaleWarningAndRateLimit increments the user's warning level and scales a rate limit accordingly.
  193. // The incr parameter is the warning increment (negative to decrease), and classID specifies
  194. // which rate limit class to scale. The incr param is a percentage represented as an integer
  195. // where 30 = 3.0%, 100 = 10.0%, etc.
  196. func (s *Session) ScaleWarningAndRateLimit(incr int16, classID wire.RateLimitClassID) (bool, uint16) {
  197. s.mutex.Lock()
  198. defer s.mutex.Unlock()
  199. // Handle warning level increment
  200. newWarning := int32(s.warning) + int32(incr)
  201. if newWarning > 1000 {
  202. return false, 0
  203. }
  204. if newWarning < 0 {
  205. s.warning = 0 // clamp min at 0
  206. } else {
  207. s.warning = uint16(newWarning)
  208. }
  209. pct := float32(incr) / 1000.0
  210. // create reference variables for better readability
  211. rateClass := &s.rateLimitStates[classID-1]
  212. originalRateClass := &s.rateLimitStatesOriginal[classID-1]
  213. // clamp function to constrain values between min and max
  214. clamp := func(value, min, max int32) int32 {
  215. if value < min {
  216. return min
  217. }
  218. if value > max {
  219. return max
  220. }
  221. return value
  222. }
  223. // Apply a buffer to limit/clear/alert levels so that they never approach
  224. // too close to the maximum level. Otherwise, AIM 4.8 exhibits instability
  225. // (client crashes, IM window glitches) when the warning level reaches 90-100%.
  226. maxLevel := originalRateClass.MaxLevel - 150
  227. // scale the rate limit parameters
  228. newLimitLevel := rateClass.LimitLevel + int32(float32(maxLevel-originalRateClass.LimitLevel)*pct)
  229. rateClass.LimitLevel = clamp(newLimitLevel, originalRateClass.LimitLevel, originalRateClass.MaxLevel)
  230. newLimitLevel = rateClass.ClearLevel + int32(float32(maxLevel-originalRateClass.ClearLevel)*pct)
  231. rateClass.ClearLevel = clamp(newLimitLevel, originalRateClass.ClearLevel, originalRateClass.MaxLevel)
  232. newLimitLevel = rateClass.AlertLevel + int32(float32(maxLevel-originalRateClass.AlertLevel)*pct)
  233. rateClass.AlertLevel = clamp(newLimitLevel, originalRateClass.AlertLevel, originalRateClass.MaxLevel)
  234. s.warningCh <- s.warning
  235. return true, s.warning
  236. }
  237. // SetWarning sets the user's last warning level.
  238. func (s *Session) SetWarning(warning uint16) {
  239. s.mutex.Lock()
  240. defer s.mutex.Unlock()
  241. s.warning = warning
  242. }
  243. // Warning returns the user's current warning level as a percentage.
  244. // The warning level is stored as an integer representation of a percentage
  245. // where 30 = 3.0%, 100 = 10.0%, 1000 = 100.0%, etc.
  246. // This is how the OSCAR protocol represents warning percentages.
  247. func (s *Session) Warning() uint16 {
  248. s.mutex.RLock()
  249. defer s.mutex.RUnlock()
  250. return s.warning
  251. }
  252. // WarningCh returns the warning notification channel.
  253. // Listeners can receive from this channel to be notified when warnings occur.
  254. func (s *Session) WarningCh() chan uint16 {
  255. return s.warningCh
  256. }
  257. // Invisible returns true if the user is idle.
  258. func (s *Session) Invisible() bool {
  259. s.mutex.RLock()
  260. defer s.mutex.RUnlock()
  261. return s.userStatusBitmask&wire.OServiceUserStatusInvisible == wire.OServiceUserStatusInvisible
  262. }
  263. // SetIdentScreenName sets the user's screen name.
  264. func (s *Session) SetIdentScreenName(screenName IdentScreenName) {
  265. s.mutex.Lock()
  266. defer s.mutex.Unlock()
  267. s.identScreenName = screenName
  268. }
  269. // IdentScreenName returns the user's screen name.
  270. func (s *Session) IdentScreenName() IdentScreenName {
  271. s.mutex.RLock()
  272. defer s.mutex.RUnlock()
  273. return s.identScreenName
  274. }
  275. // SetDisplayScreenName sets the user's screen name.
  276. func (s *Session) SetDisplayScreenName(displayScreenName DisplayScreenName) {
  277. s.mutex.Lock()
  278. defer s.mutex.Unlock()
  279. s.displayScreenName = displayScreenName
  280. }
  281. // DisplayScreenName returns the user's screen name.
  282. func (s *Session) DisplayScreenName() DisplayScreenName {
  283. s.mutex.RLock()
  284. defer s.mutex.RUnlock()
  285. return s.displayScreenName
  286. }
  287. // SetSignonTime sets the user's sign-ontime.
  288. func (s *Session) SetSignonTime(t time.Time) {
  289. s.mutex.Lock()
  290. defer s.mutex.Unlock()
  291. s.signonTime = t
  292. }
  293. // SignonTime reports when the user signed on
  294. func (s *Session) SignonTime() time.Time {
  295. s.mutex.RLock()
  296. defer s.mutex.RUnlock()
  297. return s.signonTime
  298. }
  299. // Idle reports the user's idle state.
  300. func (s *Session) Idle() bool {
  301. s.mutex.RLock()
  302. defer s.mutex.RUnlock()
  303. return s.idle
  304. }
  305. // IdleTime reports when the user went idle
  306. func (s *Session) IdleTime() time.Time {
  307. s.mutex.RLock()
  308. defer s.mutex.RUnlock()
  309. return s.idleTime
  310. }
  311. // SetIdle sets the user's idle state.
  312. func (s *Session) SetIdle(dur time.Duration) {
  313. s.mutex.Lock()
  314. defer s.mutex.Unlock()
  315. s.idle = true
  316. // set the time the user became idle
  317. s.idleTime = s.nowFn().Add(-dur)
  318. }
  319. // UnsetIdle removes the user's idle state.
  320. func (s *Session) UnsetIdle() {
  321. s.mutex.Lock()
  322. defer s.mutex.Unlock()
  323. s.idle = false
  324. }
  325. // SetAwayMessage sets the user's away message.
  326. func (s *Session) SetAwayMessage(awayMessage string) {
  327. s.mutex.Lock()
  328. defer s.mutex.Unlock()
  329. s.awayMessage = awayMessage
  330. }
  331. // AwayMessage returns the user's away message.
  332. func (s *Session) AwayMessage() string {
  333. s.mutex.RLock()
  334. defer s.mutex.RUnlock()
  335. return s.awayMessage
  336. }
  337. // SetChatRoomCookie sets the chatRoomCookie for the chat room the user is currently in.
  338. func (s *Session) SetChatRoomCookie(cookie string) {
  339. s.mutex.Lock()
  340. defer s.mutex.Unlock()
  341. s.chatRoomCookie = cookie
  342. }
  343. // ChatRoomCookie gets the chatRoomCookie for the chat room the user is currently in.
  344. func (s *Session) ChatRoomCookie() string {
  345. s.mutex.RLock()
  346. defer s.mutex.RUnlock()
  347. return s.chatRoomCookie
  348. }
  349. // SignonComplete indicates whether the client has completed the sign-on sequence.
  350. func (s *Session) SignonComplete() bool {
  351. s.mutex.RLock()
  352. defer s.mutex.RUnlock()
  353. return s.signonComplete
  354. }
  355. // SetSignonComplete indicates that the client has completed the sign-on sequence.
  356. func (s *Session) SetSignonComplete() {
  357. s.mutex.Lock()
  358. defer s.mutex.Unlock()
  359. s.signonComplete = true
  360. }
  361. // UIN returns the user's ICQ number.
  362. func (s *Session) UIN() uint32 {
  363. s.mutex.RLock()
  364. defer s.mutex.RUnlock()
  365. return s.uin
  366. }
  367. // SetUIN sets the user's ICQ number.
  368. func (s *Session) SetUIN(uin uint32) {
  369. s.mutex.Lock()
  370. defer s.mutex.Unlock()
  371. s.uin = uin
  372. }
  373. // TLVUserInfo returns a TLV list containing session information required by
  374. // multiple SNAC message types that convey user information.
  375. func (s *Session) TLVUserInfo() wire.TLVUserInfo {
  376. s.mutex.RLock()
  377. defer s.mutex.RUnlock()
  378. return wire.TLVUserInfo{
  379. ScreenName: string(s.displayScreenName),
  380. WarningLevel: uint16(s.warning),
  381. TLVBlock: wire.TLVBlock{
  382. TLVList: s.userInfo(),
  383. },
  384. }
  385. }
  386. func (s *Session) userInfo() wire.TLVList {
  387. tlvs := wire.TLVList{}
  388. // sign-in timestamp
  389. tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(s.signonTime.Unix())))
  390. // user info flags
  391. uFlags := s.userInfoBitmask
  392. if s.awayMessage != "" {
  393. uFlags |= wire.OServiceUserFlagUnavailable
  394. }
  395. tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uFlags))
  396. // user status flags
  397. tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoStatus, s.userStatusBitmask))
  398. // idle status
  399. if s.idle {
  400. tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoIdleTime, uint16(s.nowFn().Sub(s.idleTime).Minutes())))
  401. }
  402. // set buddy icon metadata, if user has buddy icon
  403. if bartID, hasIcon := s.BuddyIcon(); hasIcon {
  404. tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoBARTInfo, bartID))
  405. }
  406. // ICQ direct-connect info. The TLV is required for buddy arrival events to
  407. // work in ICQ, even if the values are set to default.
  408. if s.userInfoBitmask&wire.OServiceUserFlagICQ == wire.OServiceUserFlagICQ {
  409. tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoICQDC, wire.ICQDCInfo{}))
  410. }
  411. // capabilities (buddy icon, chat, etc...)
  412. if len(s.caps) > 0 {
  413. tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoOscarCaps, s.caps))
  414. }
  415. tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)))
  416. return tlvs
  417. }
  418. // SetCaps sets capability UUIDs that represent the features the client
  419. // supports. If set, capability metadata appears in the user info TLV list.
  420. func (s *Session) SetCaps(caps [][16]byte) {
  421. s.mutex.Lock()
  422. defer s.mutex.Unlock()
  423. s.caps = caps
  424. }
  425. // Caps retrieves user capabilities.
  426. func (s *Session) Caps() [][16]byte {
  427. s.mutex.RLock()
  428. defer s.mutex.RUnlock()
  429. return s.caps
  430. }
  431. // ReceiveMessage returns a channel of messages relayed via this session. It
  432. // may only be read by one consumer. The channel never closes; call this method
  433. // in a select block along with Closed in order to detect session closure.
  434. func (s *Session) ReceiveMessage() chan wire.SNACMessage {
  435. return s.msgCh
  436. }
  437. // RelayMessage receives a SNAC message from a user and passes it on
  438. // asynchronously to the consumer of this session's messages. It returns
  439. // SessSendStatus to indicate whether the message was successfully sent or
  440. // not. This method is non-blocking.
  441. func (s *Session) RelayMessage(msg wire.SNACMessage) SessSendStatus {
  442. s.mutex.RLock()
  443. defer s.mutex.RUnlock()
  444. if s.closed {
  445. return SessSendClosed
  446. }
  447. select {
  448. case s.msgCh <- msg:
  449. return SessSendOK
  450. case <-s.stopCh:
  451. return SessSendClosed
  452. default:
  453. return SessQueueFull
  454. }
  455. }
  456. // Close shuts down the session's ability to relay messages. Once invoked,
  457. // RelayMessage returns SessQueueFull and Closed returns a closed channel.
  458. // It is not possible to re-open message relaying once closed. It is safe to
  459. // call from multiple go routines.
  460. func (s *Session) Close() {
  461. s.mutex.Lock()
  462. defer s.mutex.Unlock()
  463. s.close()
  464. }
  465. func (s *Session) close() {
  466. if s.closed {
  467. return
  468. }
  469. close(s.stopCh)
  470. s.closed = true
  471. }
  472. // Closed blocks until the session is closed.
  473. func (s *Session) Closed() <-chan struct{} {
  474. return s.stopCh
  475. }
  476. // SetClientID sets the client ID.
  477. func (s *Session) SetClientID(clientID string) {
  478. s.mutex.Lock()
  479. defer s.mutex.Unlock()
  480. s.clientID = clientID
  481. }
  482. // ClientID retrieves the client ID.
  483. func (s *Session) ClientID() string {
  484. s.mutex.RLock()
  485. defer s.mutex.RUnlock()
  486. return s.clientID
  487. }
  488. // SubscribeRateLimits subscribes the Session to updates for the specified
  489. // rate limit classes. Future calls to ObserveRateChanges will report changes
  490. // for these classes.
  491. func (s *Session) SubscribeRateLimits(classes []wire.RateLimitClassID) {
  492. s.mutex.Lock()
  493. defer s.mutex.Unlock()
  494. for _, classID := range classes {
  495. s.rateLimitStates[classID-1].Subscribed = true
  496. }
  497. }
  498. // ObserveRateChanges updates rate limit states for all known classes and returns
  499. // any classes and class states that have changed since the previous observation.
  500. func (s *Session) ObserveRateChanges(now time.Time) (classDelta []RateClassState, stateDelta []RateClassState) {
  501. s.mutex.Lock()
  502. defer s.mutex.Unlock()
  503. for i, params := range s.rateLimitStates {
  504. if !params.Subscribed {
  505. continue
  506. }
  507. state, level := wire.CheckRateLimit(params.LastTime, now, params.RateClass, params.CurrentLevel, params.LimitedNow)
  508. s.rateLimitStates[i].CurrentStatus = state
  509. // clear limited now flag if passing from limited state to clear state
  510. if s.rateLimitStates[i].LimitedNow && state == wire.RateLimitStatusClear {
  511. s.rateLimitStates[i].LimitedNow = false
  512. s.rateLimitStates[i].CurrentLevel = level
  513. }
  514. // did rate class change?
  515. if params.RateClass != s.lastObservedStates[i].RateClass {
  516. classDelta = append(classDelta, s.rateLimitStates[i])
  517. }
  518. // did rate limit status change?
  519. if s.lastObservedStates[i].CurrentStatus != s.rateLimitStates[i].CurrentStatus {
  520. stateDelta = append(stateDelta, s.rateLimitStates[i])
  521. }
  522. // save it for next time
  523. s.lastObservedStates[i] = s.rateLimitStates[i]
  524. }
  525. return classDelta, stateDelta
  526. }
  527. // EvaluateRateLimit checks and updates the session’s rate limit state
  528. // for the given rate class ID. If the rate status reaches 'disconnect',
  529. // the session is closed. Rate limits are not enforced if the user is a bot
  530. // (has wire.OServiceUserFlagBot set in their user info bitmask).
  531. func (s *Session) EvaluateRateLimit(now time.Time, rateClassID wire.RateLimitClassID) wire.RateLimitStatus {
  532. s.mutex.Lock()
  533. defer s.mutex.Unlock()
  534. if s.userInfoBitmask&wire.OServiceUserFlagBot == wire.OServiceUserFlagBot {
  535. return wire.RateLimitStatusClear // don't rate limit bots
  536. }
  537. rateClass := &s.rateLimitStates[rateClassID-1]
  538. status, newLevel := wire.CheckRateLimit(rateClass.LastTime, now, rateClass.RateClass, rateClass.CurrentLevel, rateClass.LimitedNow)
  539. rateClass.CurrentLevel = newLevel
  540. rateClass.CurrentStatus = status
  541. rateClass.LastTime = now
  542. rateClass.LimitedNow = status == wire.RateLimitStatusLimited
  543. if status == wire.RateLimitStatusDisconnect {
  544. s.close()
  545. }
  546. return status
  547. }
  548. // SetFoodGroupVersions sets the client's supported food group versions
  549. func (s *Session) SetFoodGroupVersions(versions [wire.MDir + 1]uint16) {
  550. s.mutex.Lock()
  551. defer s.mutex.Unlock()
  552. s.foodGroupVersions = versions
  553. }
  554. // FoodGroupVersions retrieves the client's supported food group versions.
  555. func (s *Session) FoodGroupVersions() [wire.MDir + 1]uint16 {
  556. s.mutex.RLock()
  557. defer s.mutex.RUnlock()
  558. return s.foodGroupVersions
  559. }
  560. // TypingEventsEnabled indicates whether the client wants to send and receive
  561. // typing events.
  562. func (s *Session) TypingEventsEnabled() bool {
  563. s.mutex.RLock()
  564. defer s.mutex.RUnlock()
  565. return s.typingEventsEnabled
  566. }
  567. // SetTypingEventsEnabled sets whether the client wants to send and receive
  568. // typing events.
  569. func (s *Session) SetTypingEventsEnabled(enabled bool) {
  570. s.mutex.Lock()
  571. defer s.mutex.Unlock()
  572. s.typingEventsEnabled = enabled
  573. }
  574. // SetMultiConnFlag sets the multi-connection flag for this session.
  575. func (s *Session) SetMultiConnFlag(flag wire.MultiConnFlag) {
  576. s.mutex.Lock()
  577. defer s.mutex.Unlock()
  578. s.multiConnFlag = flag
  579. }
  580. // MultiConnFlag retrieves the multi-connection flag for this session.
  581. func (s *Session) MultiConnFlag() wire.MultiConnFlag {
  582. s.mutex.RLock()
  583. defer s.mutex.RUnlock()
  584. return s.multiConnFlag
  585. }
  586. // SetKerberosAuth sets whether Kerberos authentication was used for this session.
  587. func (s *Session) SetKerberosAuth(enabled bool) {
  588. s.mutex.Lock()
  589. defer s.mutex.Unlock()
  590. s.kerberosAuth = enabled
  591. }
  592. // KerberosAuth indicates whether Kerberos authentication was used for this session.
  593. func (s *Session) KerberosAuth() bool {
  594. s.mutex.RLock()
  595. defer s.mutex.RUnlock()
  596. return s.kerberosAuth
  597. }
  598. // SetProfile sets the user's profile information.
  599. func (s *Session) SetProfile(profile UserProfile) {
  600. s.mutex.Lock()
  601. defer s.mutex.Unlock()
  602. s.profile = profile
  603. }
  604. // Profile returns the user's profile information.
  605. func (s *Session) Profile() UserProfile {
  606. s.mutex.RLock()
  607. defer s.mutex.RUnlock()
  608. return s.profile
  609. }
  610. // SetBuddyIcon stores the session's buddy icon metadata.
  611. func (s *Session) SetBuddyIcon(icon wire.BARTID) {
  612. s.mutex.Lock()
  613. defer s.mutex.Unlock()
  614. s.buddyIcon = icon
  615. }
  616. // BuddyIcon returns the session's buddy icon metadata and reports whether it
  617. // has been set. The icon is considered set if its type is non-zero.
  618. func (s *Session) BuddyIcon() (wire.BARTID, bool) {
  619. s.mutex.RLock()
  620. defer s.mutex.RUnlock()
  621. icon := s.buddyIcon
  622. return icon, icon.Type != 0
  623. }
  624. // SetMemberSince sets the member since timestamp.
  625. func (s *Session) SetMemberSince(t time.Time) {
  626. s.mutex.Lock()
  627. defer s.mutex.Unlock()
  628. s.memberSince = t
  629. }
  630. // MemberSince reports when the user became a member.
  631. func (s *Session) MemberSince() time.Time {
  632. s.mutex.RLock()
  633. defer s.mutex.RUnlock()
  634. return s.memberSince
  635. }
  636. // SetOfflineMsgCount sets the offline message count.
  637. func (s *Session) SetOfflineMsgCount(count int) {
  638. s.mutex.Lock()
  639. defer s.mutex.Unlock()
  640. s.offlineMsgCount = count
  641. }
  642. // OfflineMsgCount returns the offline message count.
  643. func (s *Session) OfflineMsgCount() int {
  644. s.mutex.RLock()
  645. defer s.mutex.RUnlock()
  646. return s.offlineMsgCount
  647. }