You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

169 lines
4.4 KiB

package server
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/golang/protobuf/proto"
"github.com/gorilla/websocket"
"log"
"net/http"
"texas-poker-bk/api"
"texas-poker-bk/internal/session"
"time"
)
func Upgrade(ctx *gin.Context) {
//token, exists := ctx.GetQuery("t")
//if !exists {
// ctx.JSON(http.StatusUnauthorized, gin.H{"api": "unauth"})
// return
//}
//subject, err := service.DecodeSubject(token)
//if err != nil {
// ctx.JSON(http.StatusUnauthorized, gin.H{"api": "token failed"})
// return
//}
conn, err := upgradeWs(ctx.Writer, ctx.Request)
if err != nil {
fmt.Println(err)
http.Error(ctx.Writer, "Not a websocket handshake", 400)
return
}
client := session.NewNetClient(conn)
go handleNetClient(client)
}
func upgradeWs(resWriter http.ResponseWriter, req *http.Request) (*websocket.Conn, error) {
upgrader := websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
HandshakeTimeout: 3 * time.Second,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
return upgrader.Upgrade(resWriter, req, nil)
}
const (
// Time allowed to write a message to the peer.
writeWait = 10 * time.Second
// Time allowed to read the next pong message from the peer.
pongWait = 60 * time.Second
// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10
// Maximum message size allowed from peer.
maxMessageSize = 512
)
// 处理新建的websocket
func handleNetClient(client *session.NetClient) {
//defer (func() {
// client.Close("conn finish")
//})()
//var account *session.NetAccount
//var player *session.Player
// https://github.com/gorilla/websocket/blob/a68708917c6a4f06314ab4e52493cc61359c9d42/examples/chat/conn.go#L50
client.Conn.SetReadLimit(maxMessageSize)
// TODO readDeadLine 读取超时后关闭连接
// err := client.Conn.SetReadDeadline(time.Now().Add(pongWait))
//if err != nil {
// log.Printf("set deadline error: %v", err)
// return
//}
client.Conn.SetPongHandler(func(string) error {
return client.Conn.SetReadDeadline(time.Now().Add(pongWait))
})
// TODO 1分钟后过期
for {
// 阻塞读取消息
_, bytes, err := client.Conn.ReadMessage()
if err != nil {
// websocket.IsCloseError(err, websocket.CloseGoingAway) TODO 连接关闭,进行中游戏处理等逻辑
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Printf("error: %v", err)
} else {
// 读失败
log.Printf("ReadMessage error: %T, %v", err, err)
client.Close("read conn err:" + err.Error())
}
return
}
wrap := &api.ProtoWrap{}
err = proto.Unmarshal(bytes, wrap)
if err != nil {
client.Close("api unmarshal fail! " + err.Error())
return
}
msg, err := api.NewProtoInstance(wrap.Op)
if err != nil {
client.Close(err.Error())
return
}
err = proto.Unmarshal(wrap.Body, msg)
if err != nil {
client.Close("api body unmarshal fail! " + err.Error())
return
}
log.Println(fmt.Sprintf("ws msg: %T{%v}", msg, msg))
// TODO queue channel -> msg -> handler
var called bool
var res proto.Message
var resErr error
handleNetClient := NetClientHandlers[wrap.Op]
if called = handleNetClient != nil; called {
// 调用 netUser handler
res, resErr = handleNetClient(client, msg)
} else {
// account process
handlerNetAccount := NetAccountHandlers[wrap.Op]
if called = handlerNetAccount != nil; called {
// account 检查连接是否认证
if client.Account == nil {
res = &api.ResFail{Code: 401, Msg: "请登录后操作"}
} else {
// 调用 account handler
res, resErr = handlerNetAccount(client.Account, msg)
}
} else {
// player process
handlerPlayer := PlayerHandlers[wrap.Op]
if called = handlerPlayer != nil; called {
// 检查 player 对象,是否加入牌桌
if client.Account == nil || client.Account.Player == nil {
res = &api.ResFail{Code: 402, Msg: "请加入牌桌后操作"}
} else {
// 调用 player handler
res, resErr = handlerPlayer(client.Account.Player, msg)
}
}
}
}
// 处理请求对应消息响应
// fmt.Println(called, res, resErr)
if resErr != nil {
// 错误消息
client.WriteSeq(false, wrap.Seq, &api.ResFail{Msg: resErr.Error()})
return
}
if res != nil {
// 响应消息
client.WriteSeq(true, wrap.Seq, res)
}
if !called {
// log not found handler wrap.Op
fmt.Printf("not found handler for op %d, msg: %v", wrap.Op, msg)
}
}
}