|
@@ -48,10 +48,11 @@ func (server *Server) SetDefcon(defcon uint32) {
|
48
|
48
|
}
|
49
|
49
|
|
50
|
50
|
func (client *Client) Sessions() (sessions []*Session) {
|
51
|
|
- client.stateMutex.RLock()
|
52
|
|
- sessions = client.sessions
|
53
|
|
- client.stateMutex.RUnlock()
|
54
|
|
- return
|
|
51
|
+ ptr := atomic.LoadPointer(&client.sessions)
|
|
52
|
+ if ptr == nil {
|
|
53
|
+ return nil
|
|
54
|
+ }
|
|
55
|
+ return *((*[]*Session)(ptr))
|
55
|
56
|
}
|
56
|
57
|
|
57
|
58
|
type SessionData struct {
|
|
@@ -67,12 +68,14 @@ type SessionData struct {
|
67
|
68
|
}
|
68
|
69
|
|
69
|
70
|
func (client *Client) AllSessionData(currentSession *Session, hasPrivs bool) (data []SessionData, currentIndex int) {
|
70
|
|
- currentIndex = -1
|
71
|
71
|
client.stateMutex.RLock()
|
72
|
72
|
defer client.stateMutex.RUnlock()
|
73
|
73
|
|
74
|
|
- data = make([]SessionData, len(client.sessions))
|
75
|
|
- for i, session := range client.sessions {
|
|
74
|
+ currentIndex = -1
|
|
75
|
+ sessions := client.Sessions()
|
|
76
|
+
|
|
77
|
+ data = make([]SessionData, len(sessions))
|
|
78
|
+ for i, session := range sessions {
|
76
|
79
|
if session == currentSession {
|
77
|
80
|
currentIndex = i
|
78
|
81
|
}
|
|
@@ -107,40 +110,49 @@ func (client *Client) AddSession(session *Session) (success bool, numSessions in
|
107
|
110
|
return
|
108
|
111
|
}
|
109
|
112
|
// success, attach the new session to the client
|
|
113
|
+ sessions := client.Sessions()
|
110
|
114
|
session.client = client
|
111
|
115
|
session.sessionID = client.nextSessionID
|
112
|
116
|
client.nextSessionID++
|
113
|
|
- newSessions := make([]*Session, len(client.sessions)+1)
|
114
|
|
- copy(newSessions, client.sessions)
|
|
117
|
+ newSessions := make([]*Session, len(sessions)+1)
|
|
118
|
+ copy(newSessions, sessions)
|
115
|
119
|
newSessions[len(newSessions)-1] = session
|
116
|
120
|
if client.accountSettings.AutoreplayMissed || session.deviceID != "" {
|
117
|
121
|
lastSeen = client.lastSeen[session.deviceID]
|
118
|
122
|
client.setLastSeen(time.Now().UTC(), session.deviceID)
|
119
|
123
|
}
|
120
|
|
- client.sessions = newSessions
|
|
124
|
+ client.setSessions(newSessions)
|
121
|
125
|
// TODO(#1551) there should be a cap to opt out of this behavior on a session
|
122
|
126
|
if persistenceEnabled(config.Accounts.Multiclient.AutoAway, client.accountSettings.AutoAway) {
|
123
|
127
|
client.awayMessage = ""
|
124
|
|
- if len(client.sessions) == 1 {
|
|
128
|
+ if len(newSessions) == 1 {
|
125
|
129
|
back = true
|
126
|
130
|
}
|
127
|
131
|
}
|
128
|
|
- return true, len(client.sessions), lastSeen, back
|
|
132
|
+ return true, len(newSessions), lastSeen, back
|
|
133
|
+}
|
|
134
|
+
|
|
135
|
+func (client *Client) setSessions(sessions []*Session) {
|
|
136
|
+ // must be called while holding stateMutex.Lock()
|
|
137
|
+ sessionsPtr := new([]*Session)
|
|
138
|
+ (*sessionsPtr) = sessions
|
|
139
|
+ atomic.StorePointer(&client.sessions, unsafe.Pointer(sessionsPtr))
|
129
|
140
|
}
|
130
|
141
|
|
131
|
142
|
func (client *Client) removeSession(session *Session) (success bool, length int) {
|
132
|
|
- if len(client.sessions) == 0 {
|
|
143
|
+ oldSessions := client.Sessions()
|
|
144
|
+ if len(oldSessions) == 0 {
|
133
|
145
|
return
|
134
|
146
|
}
|
135
|
|
- sessions := make([]*Session, 0, len(client.sessions)-1)
|
136
|
|
- for _, currentSession := range client.sessions {
|
|
147
|
+ sessions := make([]*Session, 0, len(oldSessions)-1)
|
|
148
|
+ for _, currentSession := range oldSessions {
|
137
|
149
|
if session == currentSession {
|
138
|
150
|
success = true
|
139
|
151
|
} else {
|
140
|
152
|
sessions = append(sessions, currentSession)
|
141
|
153
|
}
|
142
|
154
|
}
|
143
|
|
- client.sessions = sessions
|
|
155
|
+ client.setSessions(sessions)
|
144
|
156
|
length = len(sessions)
|
145
|
157
|
return
|
146
|
158
|
}
|
|
@@ -150,7 +162,7 @@ func (client *Client) getWhoisActually() (ip net.IP, hostname string) {
|
150
|
162
|
client.stateMutex.RLock()
|
151
|
163
|
defer client.stateMutex.RUnlock()
|
152
|
164
|
|
153
|
|
- for _, session := range client.sessions {
|
|
165
|
+ for _, session := range client.Sessions() {
|
154
|
166
|
return session.IP(), session.rawHostname
|
155
|
167
|
}
|
156
|
168
|
return utils.IPv4LoopbackAddress, client.server.name
|
|
@@ -223,7 +235,7 @@ func (client *Client) setAutoAwayNoMutex(config *Config) {
|
223
|
235
|
// aggregate the away statuses of the individual sessions:
|
224
|
236
|
var globalAwayState string
|
225
|
237
|
var awaySetAt time.Time
|
226
|
|
- for _, cSession := range client.sessions {
|
|
238
|
+ for _, cSession := range client.Sessions() {
|
227
|
239
|
if cSession.awayMessage == "" {
|
228
|
240
|
// a session is active, we are not auto-away
|
229
|
241
|
client.awayMessage = ""
|