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  }