From 7a5ca971ce194f1aa6da6f88ce2998e730063b17 Mon Sep 17 00:00:00 2001 From: Flowing Date: Sun, 9 Feb 2020 10:38:55 +0900 Subject: [PATCH 1/2] "F" flag support (playcast "http://example.com/match/id/HIDDEN" f10) --- server/src/handlers/handlers.go | 109 +++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 30 deletions(-) diff --git a/server/src/handlers/handlers.go b/server/src/handlers/handlers.go index f08ecaf..0cd796b 100644 --- a/server/src/handlers/handlers.go +++ b/server/src/handlers/handlers.go @@ -18,6 +18,7 @@ func SyncHandler(c *gin.Context) { c.String(http.StatusBadRequest, "Unknown Request") return } + t := c.Params.ByName("token") m, err := Matches.GetMatchByToken(t) if err != nil { @@ -25,22 +26,46 @@ func SyncHandler(c *gin.Context) { c.String(http.StatusNotFound, "NotFound") return } - full, err := m.GetFullFrame(m.Fragment) - delayedfull, err := m.GetFullFrame(m.Fragment - Matches.Delay) - if err != nil { - log.Printf("ERR : %v\n", err) - c.String(http.StatusNotFound, "NotFound") - return + if c.Query("fragment") != "" { + frag, err := strconv.Atoi(c.Query("fragment")) + if err != nil { + c.String(http.StatusBadRequest, "fragment should be int") + return + } + full, err := m.GetFullFrame(m.Fragment) + specifiedfull, err := m.GetFullFrame(uint32(frag)) + if err != nil { + log.Printf("ERR : %v\n", err) + c.String(http.StatusNotFound, "NotFound") + return + } + c.JSON(http.StatusOK, gin.H{ + "tick": specifiedfull.Tick, + "rtdelay": time.Since(specifiedfull.At).Seconds(), + "rcvage": time.Since(full.At).Seconds(), + "fragment": frag, + "signup_fragment": m.SignupFragment, + "tps": m.Tps, + "protocol": m.Protocol, + }) + } else { + full, err := m.GetFullFrame(m.Fragment) + delayedfull, err := m.GetFullFrame(m.Fragment - Matches.Delay) + if err != nil { + log.Printf("ERR : %v\n", err) + c.String(http.StatusNotFound, "NotFound") + return + } + c.JSON(http.StatusOK, gin.H{ + "tick": full.Tick, + "rtdelay": time.Since(delayedfull.At).Seconds(), + "rcvage": time.Since(full.At).Seconds(), + "fragment": m.Fragment - Matches.Delay, + "signup_fragment": m.SignupFragment, + "tps": m.Tps, + "protocol": m.Protocol, + }) } - c.JSON(http.StatusOK, gin.H{ - "tick": full.Tick, - "rtdelay": time.Since(delayedfull.At).Seconds(), - "rcvage": time.Since(full.At).Seconds(), - "fragment": m.Fragment - Matches.Delay, - "signup_fragment": m.SignupFragment, - "tps": m.Tps, - "protocol": m.Protocol, - }) } // SyncByIDHandler handlers request against /match/:token/sync by ID @@ -56,22 +81,46 @@ func SyncByIDHandler(c *gin.Context) { c.String(http.StatusNotFound, "NotFound") return } - full, err := m.GetFullFrame(m.Fragment) - delayedfull, err := m.GetFullFrame(m.Fragment - Matches.Delay) - if err != nil { - log.Printf("ERR : %v\n", err) - c.String(http.StatusNotFound, "NotFound") - return + if c.Query("fragment") != "" { + frag, err := strconv.Atoi(c.Query("fragment")) + if err != nil { + c.String(http.StatusBadRequest, "fragment should be int") + return + } + full, err := m.GetFullFrame(m.Fragment) + specifiedfull, err := m.GetFullFrame(uint32(frag)) + if err != nil { + log.Printf("ERR : %v\n", err) + c.String(http.StatusNotFound, "NotFound") + return + } + c.JSON(http.StatusOK, gin.H{ + "tick": specifiedfull.Tick, + "rtdelay": time.Since(specifiedfull.At).Seconds(), + "rcvage": time.Since(full.At).Seconds(), + "fragment": frag, + "signup_fragment": m.SignupFragment, + "tps": m.Tps, + "protocol": m.Protocol, + }) + } else { + full, err := m.GetFullFrame(m.Fragment) + delayedfull, err := m.GetFullFrame(m.Fragment - Matches.Delay) + if err != nil { + log.Printf("ERR : %v\n", err) + c.String(http.StatusNotFound, "NotFound") + return + } + c.JSON(http.StatusOK, gin.H{ + "tick": full.Tick, + "rtdelay": time.Since(delayedfull.At).Seconds(), + "rcvage": time.Since(full.At).Seconds(), + "fragment": m.Fragment - Matches.Delay, + "signup_fragment": m.SignupFragment, + "tps": m.Tps, + "protocol": m.Protocol, + }) } - c.JSON(http.StatusOK, gin.H{ - "tick": full.Tick, - "rtdelay": time.Since(delayedfull.At).Seconds(), - "rcvage": time.Since(full.At).Seconds(), - "fragment": m.Fragment - Matches.Delay, - "signup_fragment": m.SignupFragment, - "tps": m.Tps, - "protocol": m.Protocol, - }) } // GetBodyHandler handles fragment request from CS:GO client From ec544be41f6e31410ac7c13722094274f5ff9f5c Mon Sep 17 00:00:00 2001 From: Flowing Date: Sun, 9 Feb 2020 11:46:00 +0900 Subject: [PATCH 2/2] fixed map concurrent protection --- server/main.go | 3 +++ server/src/handlers/handlers.go | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/server/main.go b/server/main.go index 669ca79..b831731 100644 --- a/server/main.go +++ b/server/main.go @@ -5,6 +5,7 @@ import ( grpc "github.com/FlowingSPDG/gotv-plus-go/server/src/grpc" "github.com/FlowingSPDG/gotv-plus-go/server/src/handlers" "github.com/gin-gonic/gin" + "io/ioutil" "log" "net/http" ) @@ -23,6 +24,8 @@ func init() { log.Printf("DEBUG MODE : %v\n", *debug) if *debug == true { gin.SetMode(gin.ReleaseMode) + } else { + gin.DefaultWriter = ioutil.Discard } handlers.InitMatchEngine(*auth, uint32(*delay)) go grpc.StartGRPC(*grpcaddr) diff --git a/server/src/handlers/handlers.go b/server/src/handlers/handlers.go index 0cd796b..c6fbbd0 100644 --- a/server/src/handlers/handlers.go +++ b/server/src/handlers/handlers.go @@ -207,6 +207,7 @@ func PostBodyByIDHandler(c *gin.Context) { c.String(http.StatusBadRequest, "fragment,tps,protocol should be float or int") return } + log.Printf("Received START Fragment. Register match... Token[%s] Tps[%f] Protocol[%d]\n", t, tps, protocol) Matches.Register(&Match{ ID: id, Token: t, @@ -224,6 +225,13 @@ func PostBodyByIDHandler(c *gin.Context) { // Fragment: uint32(fragment), }) m, err := Matches.GetMatchByToken(t) + if err != nil { + log.Printf("ERR : %v\n", err) + c.String(http.StatusNotFound, "") + return + } + m.Lock() + defer m.Unlock() m.Startframe[uint32(fragment)] = &Startframe{ At: time.Now(), Body: reqBody, @@ -236,6 +244,8 @@ func PostBodyByIDHandler(c *gin.Context) { c.String(http.StatusResetContent, "") return } + m.Lock() + defer m.Unlock() tick, err := strconv.Atoi(c.Query("tick")) if err != nil { c.String(http.StatusBadRequest, "tick should be float or int") @@ -258,6 +268,8 @@ func PostBodyByIDHandler(c *gin.Context) { c.String(http.StatusResetContent, "") return } + m.Lock() + defer m.Unlock() endtick, err := strconv.Atoi(c.Query("endtick")) if err != nil { c.String(http.StatusBadRequest, "endtick should be float or int") @@ -330,6 +342,13 @@ func PostBodyHandler(c *gin.Context) { // Fragment: uint32(fragment), }) m, err := Matches.GetMatchByToken(t) + if err != nil { + log.Printf("ERR : %v\n", err) + c.String(http.StatusNotFound, "") + return + } + m.Lock() + defer m.Unlock() m.Startframe[uint32(fragment)] = &Startframe{ At: time.Now(), Body: reqBody, @@ -342,6 +361,8 @@ func PostBodyHandler(c *gin.Context) { c.String(http.StatusResetContent, "") return } + m.Lock() + defer m.Unlock() tick, err := strconv.Atoi(c.Query("tick")) if err != nil { c.String(http.StatusBadRequest, "tick should be float or int") @@ -364,6 +385,8 @@ func PostBodyHandler(c *gin.Context) { c.String(http.StatusResetContent, "") return } + m.Lock() + defer m.Unlock() endtick, err := strconv.Atoi(c.Query("endtick")) if err != nil { c.String(http.StatusBadRequest, "endtick should be float or int")