Files
mc-gateway/cmd/gateway/websocket.go
tursom f508ecc1b9
Some checks failed
Go / build (.exe, 386, windows, windows-386) (push) Has been cancelled
Go / build (.exe, amd64, windows, windows-amd64) (push) Has been cancelled
Go / build (.exe, arm64, windows, windows-arm64) (push) Has been cancelled
Go / build (386, freebsd, freebsd-386) (push) Has been cancelled
Go / build (386, linux, linux-386) (push) Has been cancelled
Go / build (386, netbsd, netbsd-386) (push) Has been cancelled
Go / build (386, openbsd, openbsd-386) (push) Has been cancelled
Go / build (386, plan9, plan9-386) (push) Has been cancelled
Go / build (amd64, darwin, darwin-amd64) (push) Has been cancelled
Go / build (amd64, dragonfly, dragonfly-amd64) (push) Has been cancelled
Go / build (amd64, freebsd, freebsd-amd64) (push) Has been cancelled
Go / build (amd64, illumos, illumos-amd64) (push) Has been cancelled
Go / build (amd64, linux, linux-amd64) (push) Has been cancelled
Go / build (amd64, netbsd, netbsd-amd64) (push) Has been cancelled
Go / build (amd64, openbsd, openbsd-amd64) (push) Has been cancelled
Go / build (amd64, plan9, plan9-amd64) (push) Has been cancelled
Go / build (amd64, solaris, solaris-amd64) (push) Has been cancelled
Go / build (arm, 6, linux, linux-armv6) (push) Has been cancelled
Go / build (arm, 7, linux, linux-armv7) (push) Has been cancelled
Go / build (arm, freebsd, freebsd-arm) (push) Has been cancelled
Go / build (arm, netbsd, netbsd-arm) (push) Has been cancelled
Go / build (arm, openbsd, openbsd-arm) (push) Has been cancelled
Go / build (arm, plan9, plan9-arm) (push) Has been cancelled
Go / build (arm64, darwin, darwin-arm64) (push) Has been cancelled
Go / build (arm64, freebsd, freebsd-arm64) (push) Has been cancelled
Go / build (arm64, linux, linux-arm64) (push) Has been cancelled
Go / build (arm64, netbsd, netbsd-arm64) (push) Has been cancelled
Go / build (arm64, openbsd, openbsd-arm64) (push) Has been cancelled
Go / build (loong64, linux, linux-loong64) (push) Has been cancelled
Go / build (mips, linux, linux-mips) (push) Has been cancelled
Go / build (mips64, linux, linux-mips64) (push) Has been cancelled
Go / build (mips64le, linux, linux-mips64le) (push) Has been cancelled
Go / build (mipsle, linux, linux-mipsle) (push) Has been cancelled
Go / build (ppc64, aix, aix-ppc64) (push) Has been cancelled
Go / build (ppc64, linux, linux-ppc64) (push) Has been cancelled
Go / build (ppc64, openbsd, openbsd-ppc64) (push) Has been cancelled
Go / build (ppc64le, linux, linux-ppc64le) (push) Has been cancelled
Go / build (riscv64, freebsd, freebsd-riscv64) (push) Has been cancelled
Go / build (riscv64, linux, linux-riscv64) (push) Has been cancelled
Go / build (riscv64, openbsd, openbsd-riscv64) (push) Has been cancelled
Go / build (s390x, linux, linux-s390x) (push) Has been cancelled
Docker Image / docker (push) Has been cancelled
Go / merge-artifacts (push) Has been cancelled
docs: 补充中文代码注释
2026-06-27 20:15:29 +08:00

125 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// cmd/gateway/websocket.go 把 WebSocket 会话适配为 net.Conn让浏览器客户端复用网关请求路径。
package main
import (
"errors"
"fmt"
"io"
"net/http"
"sync"
"time"
"github.com/gorilla/websocket"
"github.com/rs/zerolog/log"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
// 当前网关把 WebSocket 当作传输层入口,先允许所有来源;生产暴露时应在反向代理层收紧来源。
return true
},
}
type (
// WebSocket 连接适配器,实现 net.Conn 接口
webSocketConn struct {
*websocket.Conn
reader io.Reader
}
)
// WebSocket 处理函数
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
// 升级 HTTP 连接为 WebSocket
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Err(err).Msg("Failed to upgrade WebSocket connection")
return
}
defer conn.Close()
gatewayMetrics.WebSocketConnectionStarted()
// WebSocket 连接包装为 net.Conn 后进入同一个 handleRequest复用插件、路由和转发逻辑。
handleRequest(&webSocketConn{Conn: conn})
}
func (w *webSocketConn) Read(b []byte) (n int, err error) {
for {
if w.reader != nil {
// 当前消息帧没读完前持续从同一个 reader 读取,模拟流式 net.Conn。
n, err = w.reader.Read(b)
if errors.Is(err, io.EOF) {
w.reader = nil
if n > 0 {
return n, nil
}
continue
}
return n, err
}
messageType, reader, err := w.NextReader()
if err != nil {
return 0, err
}
if messageType != websocket.BinaryMessage && messageType != websocket.TextMessage {
// 控制帧不进入 Minecraft 协议流。
continue
}
w.reader = reader
}
}
func (w *webSocketConn) Write(b []byte) (n int, err error) {
// 每次 Write 输出一个二进制 WebSocket 消息,保持与 Minecraft packet 边界无关的字节流语义。
writer, err := w.NextWriter(websocket.BinaryMessage)
if err != nil {
return 0, err
}
n, err = writer.Write(b)
closeErr := writer.Close()
if err != nil {
return n, err
}
if closeErr != nil {
return n, closeErr
}
if n != len(b) {
return n, io.ErrShortWrite
}
return n, nil
}
func (w *webSocketConn) SetDeadline(t time.Time) error {
if err := w.SetReadDeadline(t); err != nil {
return err
}
return w.SetWriteDeadline(t)
}
func newWebSocketHandler() http.Handler {
mux := http.NewServeMux()
// 路径来自运行态服务配置,允许管理端把 WebSocket 入口挂到子路径。
mux.HandleFunc(normalizedWebSocketPath(), handleWebSocket)
return mux
}
// 启动 WebSocket 服务器
func runWebSocket(wg *sync.WaitGroup) {
if wg != nil {
defer wg.Done()
}
port := normalizedWebSocketPort()
path := normalizedWebSocketPath()
log.Info().Int("port", port).Str("path", path).Msg("Starting WebSocket server")
server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: newWebSocketHandler()}
if err := server.ListenAndServe(); err != nil {
log.Fatal().Err(err).Msg("Failed to start WebSocket server")
}
}