|
@@ -37,29 +37,42 @@ type IdleTimer struct {
|
37
|
37
|
sync.Mutex // tier 1
|
38
|
38
|
|
39
|
39
|
// immutable after construction
|
40
|
|
- registerTimeout time.Duration
|
41
|
|
- idleTimeout time.Duration
|
42
|
|
- idleTimeoutWithResume time.Duration
|
43
|
|
- quitTimeout time.Duration
|
44
|
|
- client *Client
|
|
40
|
+ registerTimeout time.Duration
|
|
41
|
+ quitTimeout time.Duration
|
|
42
|
+ client *Client
|
45
|
43
|
|
46
|
44
|
// mutable
|
47
|
|
- state TimerState
|
48
|
|
- timer *time.Timer
|
|
45
|
+ idleTimeout time.Duration
|
|
46
|
+ state TimerState
|
|
47
|
+ timer *time.Timer
|
49
|
48
|
}
|
50
|
49
|
|
51
|
50
|
// NewIdleTimer sets up a new IdleTimer using constant timeouts.
|
52
|
51
|
func NewIdleTimer(client *Client) *IdleTimer {
|
53
|
52
|
it := IdleTimer{
|
54
|
|
- registerTimeout: RegisterTimeout,
|
55
|
|
- idleTimeout: IdleTimeout,
|
56
|
|
- idleTimeoutWithResume: IdleTimeoutWithResumeCap,
|
57
|
|
- quitTimeout: QuitTimeout,
|
58
|
|
- client: client,
|
|
53
|
+ registerTimeout: RegisterTimeout,
|
|
54
|
+ idleTimeout: IdleTimeout,
|
|
55
|
+ quitTimeout: QuitTimeout,
|
|
56
|
+ client: client,
|
59
|
57
|
}
|
60
|
58
|
return &it
|
61
|
59
|
}
|
62
|
60
|
|
|
61
|
+// updateIdleDuration updates the idle duration, given the client's caps.
|
|
62
|
+func (it *IdleTimer) updateIdleDuration() {
|
|
63
|
+ newIdleTime := IdleTimeout
|
|
64
|
+
|
|
65
|
+ // if they have the resume cap, wait longer before pinging them out
|
|
66
|
+ // to give them a chance to resume their connection
|
|
67
|
+ if it.client.capabilities.Has(caps.Resume) {
|
|
68
|
+ newIdleTime = IdleTimeoutWithResumeCap
|
|
69
|
+ }
|
|
70
|
+
|
|
71
|
+ it.Lock()
|
|
72
|
+ defer it.Unlock()
|
|
73
|
+ it.idleTimeout = newIdleTime
|
|
74
|
+}
|
|
75
|
+
|
63
|
76
|
// Start starts counting idle time; if there is no activity from the client,
|
64
|
77
|
// it will eventually be stopped.
|
65
|
78
|
func (it *IdleTimer) Start() {
|
|
@@ -75,6 +88,8 @@ func (it *IdleTimer) Touch() {
|
75
|
88
|
return
|
76
|
89
|
}
|
77
|
90
|
|
|
91
|
+ it.updateIdleDuration()
|
|
92
|
+
|
78
|
93
|
it.Lock()
|
79
|
94
|
defer it.Unlock()
|
80
|
95
|
// a touch transitions TimerUnregistered or TimerIdle into TimerActive
|
|
@@ -85,6 +100,8 @@ func (it *IdleTimer) Touch() {
|
85
|
100
|
}
|
86
|
101
|
|
87
|
102
|
func (it *IdleTimer) processTimeout() {
|
|
103
|
+ it.updateIdleDuration()
|
|
104
|
+
|
88
|
105
|
var previousState TimerState
|
89
|
106
|
func() {
|
90
|
107
|
it.Lock()
|
|
@@ -125,13 +142,7 @@ func (it *IdleTimer) resetTimeout() {
|
125
|
142
|
case TimerUnregistered:
|
126
|
143
|
nextTimeout = it.registerTimeout
|
127
|
144
|
case TimerActive:
|
128
|
|
- // if they have the resume cap, wait longer before pinging them out
|
129
|
|
- // to give them a chance to resume their connection
|
130
|
|
- if it.client.capabilities.Has(caps.Resume) {
|
131
|
|
- nextTimeout = it.idleTimeoutWithResume
|
132
|
|
- } else {
|
133
|
|
- nextTimeout = it.idleTimeout
|
134
|
|
- }
|
|
145
|
+ nextTimeout = it.idleTimeout
|
135
|
146
|
case TimerIdle:
|
136
|
147
|
nextTimeout = it.quitTimeout
|
137
|
148
|
case TimerDead:
|
|
@@ -146,6 +157,8 @@ func (it *IdleTimer) quitMessage(state TimerState) string {
|
146
|
157
|
return fmt.Sprintf("Registration timeout: %v", it.registerTimeout)
|
147
|
158
|
case TimerIdle:
|
148
|
159
|
// how many seconds before registered clients are timed out (IdleTimeout plus QuitTimeout).
|
|
160
|
+ it.Lock()
|
|
161
|
+ defer it.Unlock()
|
149
|
162
|
return fmt.Sprintf("Ping timeout: %v", (it.idleTimeout + it.quitTimeout))
|
150
|
163
|
default:
|
151
|
164
|
// shouldn't happen
|