github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/app/websocket_router.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "net/http" 8 9 "github.com/mattermost/mattermost-server/v5/mlog" 10 "github.com/mattermost/mattermost-server/v5/model" 11 "github.com/mattermost/mattermost-server/v5/utils" 12 ) 13 14 type webSocketHandler interface { 15 ServeWebSocket(*WebConn, *model.WebSocketRequest) 16 } 17 18 type WebSocketRouter struct { 19 server *Server 20 app *App 21 handlers map[string]webSocketHandler 22 } 23 24 func (wr *WebSocketRouter) Handle(action string, handler webSocketHandler) { 25 wr.handlers[action] = handler 26 } 27 28 func (wr *WebSocketRouter) ServeWebSocket(conn *WebConn, r *model.WebSocketRequest) { 29 wr.app = New(ServerConnector(wr.server)) 30 wr.app.InitServer() 31 32 if r.Action == "" { 33 err := model.NewAppError("ServeWebSocket", "api.web_socket_router.no_action.app_error", nil, "", http.StatusBadRequest) 34 returnWebSocketError(wr.app, conn, r, err) 35 return 36 } 37 38 if r.Seq <= 0 { 39 err := model.NewAppError("ServeWebSocket", "api.web_socket_router.bad_seq.app_error", nil, "", http.StatusBadRequest) 40 returnWebSocketError(wr.app, conn, r, err) 41 return 42 } 43 44 if r.Action == model.WEBSOCKET_AUTHENTICATION_CHALLENGE { 45 if conn.GetSessionToken() != "" { 46 return 47 } 48 49 token, ok := r.Data["token"].(string) 50 if !ok { 51 conn.WebSocket.Close() 52 return 53 } 54 55 session, err := wr.app.GetSession(token) 56 if err != nil { 57 conn.WebSocket.Close() 58 return 59 } 60 61 conn.SetSession(session) 62 conn.SetSessionToken(session.Token) 63 conn.UserId = session.UserId 64 65 wr.app.HubRegister(conn) 66 67 wr.app.Srv().Go(func() { 68 wr.app.SetStatusOnline(session.UserId, false) 69 wr.app.UpdateLastActivityAtIfNeeded(*session) 70 }) 71 72 resp := model.NewWebSocketResponse(model.STATUS_OK, r.Seq, nil) 73 hub := wr.app.GetHubForUserId(conn.UserId) 74 if hub == nil { 75 return 76 } 77 hub.SendMessage(conn, resp) 78 79 return 80 } 81 82 if !conn.IsAuthenticated() { 83 err := model.NewAppError("ServeWebSocket", "api.web_socket_router.not_authenticated.app_error", nil, "", http.StatusUnauthorized) 84 returnWebSocketError(wr.app, conn, r, err) 85 return 86 } 87 88 handler, ok := wr.handlers[r.Action] 89 if !ok { 90 err := model.NewAppError("ServeWebSocket", "api.web_socket_router.bad_action.app_error", nil, "", http.StatusInternalServerError) 91 returnWebSocketError(wr.app, conn, r, err) 92 return 93 } 94 95 handler.ServeWebSocket(conn, r) 96 } 97 98 func returnWebSocketError(app *App, conn *WebConn, r *model.WebSocketRequest, err *model.AppError) { 99 mlog.Error( 100 "websocket routing error.", 101 mlog.Int64("seq", r.Seq), 102 mlog.String("user_id", conn.UserId), 103 mlog.String("system_message", err.SystemMessage(utils.T)), 104 mlog.Err(err), 105 ) 106 107 hub := app.GetHubForUserId(conn.UserId) 108 if hub == nil { 109 return 110 } 111 112 err.DetailedError = "" 113 errorResp := model.NewWebSocketError(r.Seq, err) 114 hub.SendMessage(conn, errorResp) 115 }