github.com/gigforks/mattermost-server@v4.9.1-0.20180619094218-800d97fa55d0+incompatible/app/websocket_router.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  
    10  	"github.com/mattermost/mattermost-server/mlog"
    11  	"github.com/mattermost/mattermost-server/model"
    12  	"github.com/mattermost/mattermost-server/utils"
    13  )
    14  
    15  type webSocketHandler interface {
    16  	ServeWebSocket(*WebConn, *model.WebSocketRequest)
    17  }
    18  
    19  type WebSocketRouter struct {
    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  	if r.Action == "" {
    30  		err := model.NewAppError("ServeWebSocket", "api.web_socket_router.no_action.app_error", nil, "", http.StatusBadRequest)
    31  		ReturnWebSocketError(conn, r, err)
    32  		return
    33  	}
    34  
    35  	if r.Seq <= 0 {
    36  		err := model.NewAppError("ServeWebSocket", "api.web_socket_router.bad_seq.app_error", nil, "", http.StatusBadRequest)
    37  		ReturnWebSocketError(conn, r, err)
    38  		return
    39  	}
    40  
    41  	if r.Action == model.WEBSOCKET_AUTHENTICATION_CHALLENGE {
    42  		if conn.GetSessionToken() != "" {
    43  			return
    44  		}
    45  
    46  		token, ok := r.Data["token"].(string)
    47  		if !ok {
    48  			conn.WebSocket.Close()
    49  			return
    50  		}
    51  
    52  		session, err := wr.app.GetSession(token)
    53  
    54  		if err != nil {
    55  			conn.WebSocket.Close()
    56  		} else {
    57  			wr.app.Go(func() {
    58  				wr.app.SetStatusOnline(session.UserId, session.Id, false)
    59  				wr.app.UpdateLastActivityAtIfNeeded(*session)
    60  			})
    61  
    62  			conn.SetSession(session)
    63  			conn.SetSessionToken(session.Token)
    64  			conn.UserId = session.UserId
    65  
    66  			wr.app.HubRegister(conn)
    67  
    68  			resp := model.NewWebSocketResponse(model.STATUS_OK, r.Seq, nil)
    69  			conn.Send <- resp
    70  		}
    71  
    72  		return
    73  	}
    74  
    75  	if !conn.IsAuthenticated() {
    76  		err := model.NewAppError("ServeWebSocket", "api.web_socket_router.not_authenticated.app_error", nil, "", http.StatusUnauthorized)
    77  		ReturnWebSocketError(conn, r, err)
    78  		return
    79  	}
    80  
    81  	var handler webSocketHandler
    82  	if h, ok := wr.handlers[r.Action]; !ok {
    83  		err := model.NewAppError("ServeWebSocket", "api.web_socket_router.bad_action.app_error", nil, "", http.StatusInternalServerError)
    84  		ReturnWebSocketError(conn, r, err)
    85  		return
    86  	} else {
    87  		handler = h
    88  	}
    89  
    90  	handler.ServeWebSocket(conn, r)
    91  }
    92  
    93  func ReturnWebSocketError(conn *WebConn, r *model.WebSocketRequest, err *model.AppError) {
    94  	mlog.Error(fmt.Sprintf("websocket routing error: seq=%v uid=%v %v [details: %v]", r.Seq, conn.UserId, err.SystemMessage(utils.T), err.DetailedError))
    95  
    96  	err.DetailedError = ""
    97  	errorResp := model.NewWebSocketError(r.Seq, err)
    98  
    99  	conn.Send <- errorResp
   100  }