diff options
-rw-r--r-- | app/web_conn.go | 90 | ||||
-rw-r--r-- | app/websocket_router.go | 5 | ||||
-rw-r--r-- | model/session.go | 5 | ||||
-rw-r--r-- | wsapi/websocket_handler.go | 2 |
4 files changed, 71 insertions, 31 deletions
diff --git a/app/web_conn.go b/app/web_conn.go index 24b7166c0..f57d99cde 100644 --- a/app/web_conn.go +++ b/app/web_conn.go @@ -5,6 +5,7 @@ package app import ( "fmt" + "sync/atomic" "time" "github.com/mattermost/platform/einterfaces" @@ -28,11 +29,11 @@ const ( ) type WebConn struct { + sessionExpiresAt int64 // This should stay at the top for 64-bit alignment of 64-bit words accessed atomically WebSocket *websocket.Conn Send chan model.WebSocketMessage - SessionToken string - SessionExpiresAt int64 - Session *model.Session + sessionToken atomic.Value + session atomic.Value UserId string T goi18n.TranslateFunc Locale string @@ -49,15 +50,47 @@ func NewWebConn(ws *websocket.Conn, session model.Session, t goi18n.TranslateFun }() } - return &WebConn{ - Send: make(chan model.WebSocketMessage, SEND_QUEUE_SIZE), - WebSocket: ws, - UserId: session.UserId, - SessionToken: session.Token, - SessionExpiresAt: session.ExpiresAt, - T: t, - Locale: locale, + wc := &WebConn{ + Send: make(chan model.WebSocketMessage, SEND_QUEUE_SIZE), + WebSocket: ws, + UserId: session.UserId, + T: t, + Locale: locale, } + + wc.SetSession(&session) + wc.SetSessionToken(session.Token) + wc.SetSessionExpiresAt(session.ExpiresAt) + + return wc +} + +func (c *WebConn) GetSessionExpiresAt() int64 { + return atomic.LoadInt64(&c.sessionExpiresAt) +} + +func (c *WebConn) SetSessionExpiresAt(v int64) { + atomic.StoreInt64(&c.sessionExpiresAt, v) +} + +func (c *WebConn) GetSessionToken() string { + return c.sessionToken.Load().(string) +} + +func (c *WebConn) SetSessionToken(v string) { + c.sessionToken.Store(v) +} + +func (c *WebConn) GetSession() *model.Session { + return c.session.Load().(*model.Session) +} + +func (c *WebConn) SetSession(v *model.Session) { + if v != nil { + v = v.DeepCopy() + } + + c.session.Store(v) } func (c *WebConn) ReadPump() { @@ -175,7 +208,7 @@ func (c *WebConn) WritePump() { } case <-authTicker.C: - if c.SessionToken == "" { + if c.GetSessionToken() == "" { l4g.Debug(fmt.Sprintf("websocket.authTicker: did not authenticate ip=%v", c.WebSocket.RemoteAddr())) return } @@ -187,29 +220,28 @@ func (c *WebConn) WritePump() { func (webCon *WebConn) InvalidateCache() { webCon.AllChannelMembers = nil webCon.LastAllChannelMembersTime = 0 - webCon.SessionExpiresAt = 0 - webCon.Session = nil + webCon.SetSession(nil) + webCon.SetSessionExpiresAt(0) } func (webCon *WebConn) IsAuthenticated() bool { // Check the expiry to see if we need to check for a new session - if webCon.SessionExpiresAt < model.GetMillis() { - if webCon.SessionToken == "" { + if webCon.GetSessionExpiresAt() < model.GetMillis() { + if webCon.GetSessionToken() == "" { return false } - session, err := GetSession(webCon.SessionToken) + session, err := GetSession(webCon.GetSessionToken()) if err != nil { l4g.Error(utils.T("api.websocket.invalid_session.error"), err.Error()) - webCon.SessionToken = "" - webCon.SessionExpiresAt = 0 - webCon.Session = nil + webCon.SetSessionToken("") + webCon.SetSession(nil) + webCon.SetSessionExpiresAt(0) return false } - webCon.SessionToken = session.Token - webCon.SessionExpiresAt = session.ExpiresAt - webCon.Session = session + webCon.SetSession(session) + webCon.SetSessionExpiresAt(session.ExpiresAt) } return true @@ -278,18 +310,20 @@ func (webCon *WebConn) ShouldSendEvent(msg *model.WebSocketEvent) bool { func (webCon *WebConn) IsMemberOfTeam(teamId string) bool { - if webCon.Session == nil { - session, err := GetSession(webCon.SessionToken) + currentSession := webCon.GetSession() + + if currentSession == nil || len(currentSession.Token) == 0 { + session, err := GetSession(webCon.GetSessionToken()) if err != nil { l4g.Error(utils.T("api.websocket.invalid_session.error"), err.Error()) return false } else { - webCon.Session = session + webCon.SetSession(session) + currentSession = session } - } - member := webCon.Session.GetTeamByTeamId(teamId) + member := currentSession.GetTeamByTeamId(teamId) if member != nil { return true diff --git a/app/websocket_router.go b/app/websocket_router.go index e8957e6b5..a3c56454f 100644 --- a/app/websocket_router.go +++ b/app/websocket_router.go @@ -43,7 +43,7 @@ func (wr *WebSocketRouter) ServeWebSocket(conn *WebConn, r *model.WebSocketReque } if r.Action == model.WEBSOCKET_AUTHENTICATION_CHALLENGE { - if conn.SessionToken != "" { + if conn.GetSessionToken() != "" { return } @@ -63,7 +63,8 @@ func (wr *WebSocketRouter) ServeWebSocket(conn *WebConn, r *model.WebSocketReque UpdateLastActivityAtIfNeeded(*session) }() - conn.SessionToken = session.Token + conn.SetSession(session) + conn.SetSessionToken(session.Token) conn.UserId = session.UserId HubRegister(conn) diff --git a/model/session.go b/model/session.go index 960c18cbf..704af067c 100644 --- a/model/session.go +++ b/model/session.go @@ -37,6 +37,11 @@ type Session struct { TeamMembers []*TeamMember `json:"team_members" db:"-"` } +func (me *Session) DeepCopy() *Session { + copy := *me + return © +} + func (me *Session) ToJson() string { b, err := json.Marshal(me) if err != nil { diff --git a/wsapi/websocket_handler.go b/wsapi/websocket_handler.go index d137ec7fc..a847a7df4 100644 --- a/wsapi/websocket_handler.go +++ b/wsapi/websocket_handler.go @@ -23,7 +23,7 @@ type webSocketHandler struct { func (wh webSocketHandler) ServeWebSocket(conn *app.WebConn, r *model.WebSocketRequest) { l4g.Debug("/api/v3/users/websocket:%s", r.Action) - session, sessionErr := app.GetSession(conn.SessionToken) + session, sessionErr := app.GetSession(conn.GetSessionToken()) if sessionErr != nil { l4g.Error(utils.T("api.web_socket_handler.log.error"), "/api/v3/users/websocket", r.Action, r.Seq, conn.UserId, sessionErr.SystemMessage(utils.T), sessionErr.Error()) sessionErr.DetailedError = "" |