Files
mostlymatter/api4/websocket.go
Agniva De Sarker 2743089b54 MM-34000: Use non-epoll mode for TLS connections (#17172)
* MM-34000: Use non-epoll mode for TLS connections

A *crypto/tls.Conn does not expose the underlying TCP connection
or even a File method to get the underlying file descriptor
like the way a *net/TCPConn does. Therefore the netpoll code would
fail to get the file descriptor.

Relevant issue here: https://github.com/mailru/easygo/issues/3

It is indeed possible to use reflect black magic to get the unexported
member, but I have found unexpected errors during writing to the websocket
by getting the file descriptor this way. I do not want to spend time investigating
this especially since this is already released.

Once this is out, we can decide on the right way to fix this, most probably
by proposing to expose the File method or some other way.

https://mattermost.atlassian.net/browse/MM-34000

```release-note
Fix an issue where websockets wouldn't work with TLS connections.
In that case, we just fall back to the way it works for Windows machines,
which is to use a separate goroutine for reader connection.
```

* Ignore logging errors on non-epoll

On non-epoll systems, we needed to return an error
to break from the loop. But in that case, there is no
need to log the error
2021-03-18 22:27:53 +05:30

57 строки
1.7 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package api4
import (
"net/http"
"time"
"github.com/gobwas/ws"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/shared/mlog"
)
func (api *API) InitWebSocket() {
// Optionally supports a trailing slash
api.BaseRoutes.ApiRoot.Handle("/{websocket:websocket(?:\\/)?}", api.ApiHandlerTrustRequester(connectWebSocket)).Methods("GET")
}
func connectWebSocket(c *Context, w http.ResponseWriter, r *http.Request) {
fn := c.App.OriginChecker()
if fn != nil && !fn(r) {
c.Err = model.NewAppError("origin_check", "api.web_socket.connect.check_origin.app_error", nil, "", http.StatusBadRequest)
return
}
upgrader := ws.HTTPUpgrader{
Timeout: 5 * time.Second,
}
// Uprgade the HTTP version header to 1.1, if we detect a 1.0 header.
// This is a hack to work around a flaw in our proxy configs which sends the protocol version as 1.0.
// It will be removed in a future version.
if r.ProtoMajor == 1 && r.ProtoMinor == 0 {
r.ProtoMinor = 1
mlog.Warn("The HTTP version field was detected as 1.0 during WebSocket handshake. This is most probably due to an incorrect proxy configuration. Please upgrade your proxy config to set the header version to a minimum of 1.1.")
}
conn, _, _, err := upgrader.Upgrade(r, w)
if err != nil {
c.Err = model.NewAppError("connect", "api.web_socket.connect.upgrade.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
wc := c.App.NewWebConn(conn, *c.App.Session(), c.App.T, "")
if c.App.Session().UserId != "" {
c.App.HubRegister(wc)
}
if !wc.Epoll() {
wc.BlockingPump()
} else {
go wc.Pump()
}
}