mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-07 06:40:54 +00:00
Implement version comparisons
This commit is contained in:
parent
d3fa1e6894
commit
71f08f3c53
3 changed files with 59 additions and 7 deletions
|
@ -84,6 +84,8 @@ func callHandler(handler CommandHandler, conn *websocket.Conn, client *ClientInf
|
||||||
return handler(conn, client, cmsg)
|
return handler(conn, client, cmsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var lastVersionWithoutReplyWithServerTime = VersionFromString("ffz_3.5.78")
|
||||||
|
|
||||||
// C2SHello implements the `hello` C2S Command.
|
// C2SHello implements the `hello` C2S Command.
|
||||||
// It calls SubscribeGlobal() and SubscribeDefaults() with the client, and fills out ClientInfo.Version and ClientInfo.ClientID.
|
// 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) {
|
func C2SHello(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) {
|
||||||
|
@ -92,7 +94,9 @@ func C2SHello(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Version = version
|
client.VersionString = version
|
||||||
|
client.Version = VersionFromString(version)
|
||||||
|
|
||||||
client.ClientID = uuid.FromStringOrNil(clientID)
|
client.ClientID = uuid.FromStringOrNil(clientID)
|
||||||
if client.ClientID == uuid.Nil {
|
if client.ClientID == uuid.Nil {
|
||||||
client.ClientID = uuid.NewV4()
|
client.ClientID = uuid.NewV4()
|
||||||
|
@ -101,9 +105,18 @@ func C2SHello(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg
|
||||||
SubscribeGlobal(client)
|
SubscribeGlobal(client)
|
||||||
SubscribeDefaults(client)
|
SubscribeDefaults(client)
|
||||||
|
|
||||||
return ClientMessage{
|
if client.Version.After(lastVersionWithoutReplyWithServerTime) {
|
||||||
Arguments: client.ClientID.String(),
|
return ClientMessage{
|
||||||
}, nil
|
Arguments: []interface{}{
|
||||||
|
client.ClientID.String(),
|
||||||
|
time.Now().Unix(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ClientMessage{
|
||||||
|
Arguments: client.ClientID.String(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func C2SReady(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) {
|
func C2SReady(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) {
|
||||||
|
|
|
@ -261,7 +261,7 @@ RunLoop:
|
||||||
break RunLoop
|
break RunLoop
|
||||||
|
|
||||||
case msg := <-clientChan:
|
case msg := <-clientChan:
|
||||||
if client.Version == "" && msg.Command != HelloCommand {
|
if client.VersionString == "" && msg.Command != HelloCommand {
|
||||||
CloseConnection(conn, &CloseFirstMessageNotHello)
|
CloseConnection(conn, &CloseFirstMessageNotHello)
|
||||||
Statistics.FirstNotHelloDisconnects++
|
Statistics.FirstNotHelloDisconnects++
|
||||||
break RunLoop
|
break RunLoop
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const CryptoBoxKeyLength = 32
|
const CryptoBoxKeyLength = 32
|
||||||
|
@ -55,14 +56,22 @@ type AuthInfo struct {
|
||||||
UsernameValidated bool
|
UsernameValidated bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClientVersion struct {
|
||||||
|
Major int
|
||||||
|
Minor int
|
||||||
|
Revision int
|
||||||
|
}
|
||||||
|
|
||||||
type ClientInfo struct {
|
type ClientInfo struct {
|
||||||
// The client ID.
|
// The client ID.
|
||||||
// This must be written once by the owning goroutine before the struct is passed off to any other goroutines.
|
// This must be written once by the owning goroutine before the struct is passed off to any other goroutines.
|
||||||
ClientID uuid.UUID
|
ClientID uuid.UUID
|
||||||
|
|
||||||
// The client's version.
|
// The client's literal version string.
|
||||||
// This must be written once by the owning goroutine before the struct is passed off to any other goroutines.
|
// This must be written once by the owning goroutine before the struct is passed off to any other goroutines.
|
||||||
Version string
|
VersionString string
|
||||||
|
|
||||||
|
Version ClientVersion
|
||||||
|
|
||||||
// This mutex protects writable data in this struct.
|
// This mutex protects writable data in this struct.
|
||||||
// If it seems to be a performance problem, we can split this.
|
// If it seems to be a performance problem, we can split this.
|
||||||
|
@ -103,6 +112,36 @@ type ClientInfo struct {
|
||||||
pingCount int
|
pingCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func VersionFromString(v string) ClientVersion {
|
||||||
|
var cv ClientVersion
|
||||||
|
fmt.Sscanf(v, "ffz_%d.%d.%d", &cv.Major, &cv.Minor, &cv.Revision)
|
||||||
|
return cv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cv *ClientVersion) After(cv2 *ClientVersion) bool {
|
||||||
|
if cv.Major > cv2.Major {
|
||||||
|
return true
|
||||||
|
} else if cv.Major < cv2.Major {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if cv.Minor > cv2.Minor {
|
||||||
|
return true
|
||||||
|
} else if cv.Minor < cv2.Minor {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if cv.Revision > cv2.Revision {
|
||||||
|
return true
|
||||||
|
} else if cv.Revision < cv2.Revision {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false // equal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cv *ClientVersion) Equal(cv2 *ClientVersion) bool {
|
||||||
|
return cv.Major == cv2.Major && cv.Minor == cv2.Minor && cv.Revision == cv2.Revision
|
||||||
|
}
|
||||||
|
|
||||||
const usePendingSubscrptionsBacklog = false
|
const usePendingSubscrptionsBacklog = false
|
||||||
|
|
||||||
type tgmarray []TimestampedGlobalMessage
|
type tgmarray []TimestampedGlobalMessage
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue