From 26ac45358e2f79cc782dd2cc782bb0a77ee3a588 Mon Sep 17 00:00:00 2001 From: Kane York Date: Fri, 15 Sep 2017 13:07:41 -0700 Subject: [PATCH 1/5] Separate CurrentClientCount and global subs --- socketserver/server/stats.go | 5 +++-- socketserver/server/types.go | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/socketserver/server/stats.go b/socketserver/server/stats.go index a9401248..8502a83e 100644 --- a/socketserver/server/stats.go +++ b/socketserver/server/stats.go @@ -27,6 +27,7 @@ type StatsData struct { } CurrentClientCount uint64 + LiveClientCount uint64 PubSubChannelCount int @@ -81,7 +82,7 @@ func commandCounter() { } // StatsDataVersion is the version of the StatsData struct. -const StatsDataVersion = 6 +const StatsDataVersion = 7 const pageSize = 4096 var cpuUsage struct { @@ -152,7 +153,7 @@ func updatePeriodicStats() { GlobalSubscriptionLock.RLock() - Statistics.CurrentClientCount = uint64(len(GlobalSubscriptionInfo)) + Statistics.LiveClientCount = uint64(len(GlobalSubscriptionInfo)) versions := make(map[string]uint64) for _, v := range GlobalSubscriptionInfo { versions[v.VersionString]++ diff --git a/socketserver/server/types.go b/socketserver/server/types.go index 365b91b6..1048434c 100644 --- a/socketserver/server/types.go +++ b/socketserver/server/types.go @@ -89,6 +89,9 @@ type ClientInfo struct { Version ClientVersion + // Set after a successful hello message. + HelloOK bool + // This mutex protects writable data in this struct. // If it seems to be a performance problem, we can split this. Mutex sync.Mutex From f31a93f790de75abab266e1f64d23ff93d3625bf Mon Sep 17 00:00:00 2001 From: Kane York Date: Fri, 15 Sep 2017 13:11:19 -0700 Subject: [PATCH 2/5] Fix failure-to-hello check --- socketserver/server/commands.go | 7 +++---- socketserver/server/handlecore.go | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/socketserver/server/commands.go b/socketserver/server/commands.go index 6f67fe4e..ca9fb803 100644 --- a/socketserver/server/commands.go +++ b/socketserver/server/commands.go @@ -128,9 +128,6 @@ func C2SHello(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg return } - client.VersionString = copyString(version) - client.Version = VersionFromString(version) - if clientIDStr, ok := ary[1].(string); ok { client.ClientID = uuid.FromStringOrNil(clientIDStr) if client.ClientID == uuid.Nil { @@ -146,9 +143,11 @@ func C2SHello(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg return } + client.VersionString = copyString(version) + client.Version = VersionFromString(version) uniqueUserChannel <- client.ClientID - SubscribeGlobal(client) + client.HelloOK = true jsTime := float64(time.Now().UnixNano()/1000) / 1000 return ClientMessage{ diff --git a/socketserver/server/handlecore.go b/socketserver/server/handlecore.go index 99f26459..7824b05c 100644 --- a/socketserver/server/handlecore.go +++ b/socketserver/server/handlecore.go @@ -430,7 +430,7 @@ func runSocketWriter(conn *websocket.Conn, client *ClientInfo, errorChan <-chan } case msg := <-clientChan: - if client.VersionString == "" && msg.Command != HelloCommand { + if !client.HelloOK && msg.Command != HelloCommand { return CloseFirstMessageNotHello } From d254435173a1b7ba28dc93f8a3d50e3418ad1ab4 Mon Sep 17 00:00:00 2001 From: Kane York Date: Fri, 15 Sep 2017 13:19:20 -0700 Subject: [PATCH 3/5] add hello error debugging, lock mutex during hello --- socketserver/server/commands.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/socketserver/server/commands.go b/socketserver/server/commands.go index ca9fb803..4f81c1f4 100644 --- a/socketserver/server/commands.go +++ b/socketserver/server/commands.go @@ -110,44 +110,63 @@ func callHandler(handler CommandHandler, conn *websocket.Conn, client *ClientInf return handler(conn, client, cmsg) } +var DebugHello = "" + // C2SHello implements the `hello` C2S Command. // It calls SubscribeGlobal() and SubscribeDefaults() with the client, and fills out ClientInfo.Version and ClientInfo.ClientID. func C2SHello(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { ary, ok := msg.Arguments.([]interface{}) if !ok { + if DebugHello != "" { + fmt.Println("Hello error: was not an array:", ary) + } err = ErrExpectedTwoStrings return } if len(ary) != 2 { + if DebugHello != "" { + fmt.Println("Hello error: array wrong length:", ary) + } err = ErrExpectedTwoStrings return } version, ok := ary[0].(string) if !ok { + if DebugHello != "" { + fmt.Println("Hello error: version not a string:", ary) + } err = ErrExpectedTwoStrings return } + var clientID uuid.UUID if clientIDStr, ok := ary[1].(string); ok { - client.ClientID = uuid.FromStringOrNil(clientIDStr) - if client.ClientID == uuid.Nil { - client.ClientID = uuid.NewV4() + clientID = uuid.FromStringOrNil(clientIDStr) + if clientID == uuid.Nil { + clientID = uuid.NewV4() } } else if _, ok := ary[1].(bool); ok { // opt out - client.ClientID = AnonymousClientID + clientID = AnonymousClientID } else if ary[1] == nil { - client.ClientID = uuid.NewV4() + clientID = uuid.NewV4() } else { + if DebugHello != "" { + fmt.Println("Hello error: client id not acceptable:", ary) + } err = ErrExpectedTwoStrings return } + client.Mutex.Lock() + client.ClientID = clientID client.VersionString = copyString(version) client.Version = VersionFromString(version) uniqueUserChannel <- client.ClientID - SubscribeGlobal(client) client.HelloOK = true + client.Mutex.Unlock() + + SubscribeGlobal(client) jsTime := float64(time.Now().UnixNano()/1000) / 1000 return ClientMessage{ From fd357ae6f23b5812242bf1ee1d284cbe47ddafa6 Mon Sep 17 00:00:00 2001 From: Kane York Date: Fri, 15 Sep 2017 13:19:33 -0700 Subject: [PATCH 4/5] reject pongs for non-set-up clients --- socketserver/server/handlecore.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/socketserver/server/handlecore.go b/socketserver/server/handlecore.go index 7824b05c..9cac001c 100644 --- a/socketserver/server/handlecore.go +++ b/socketserver/server/handlecore.go @@ -336,7 +336,9 @@ func RunSocketConnection(conn *websocket.Conn) { conn.SetPongHandler(func(pongBody string) error { client.Mutex.Lock() - client.pingCount = 0 + if client.HelloOK { // do not accept PONGs until hello sent + client.pingCount = 0 + } client.Mutex.Unlock() return nil }) From e0ae732f3569ca04b1250136b1dedcef8a309f45 Mon Sep 17 00:00:00 2001 From: Kane York Date: Fri, 15 Sep 2017 13:20:28 -0700 Subject: [PATCH 5/5] move send out of lock --- socketserver/server/commands.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/socketserver/server/commands.go b/socketserver/server/commands.go index 4f81c1f4..4b86b60b 100644 --- a/socketserver/server/commands.go +++ b/socketserver/server/commands.go @@ -162,10 +162,10 @@ func C2SHello(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg client.ClientID = clientID client.VersionString = copyString(version) client.Version = VersionFromString(version) - uniqueUserChannel <- client.ClientID client.HelloOK = true client.Mutex.Unlock() + uniqueUserChannel <- client.ClientID SubscribeGlobal(client) jsTime := float64(time.Now().UnixNano()/1000) / 1000