1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-28 05:15:54 +00:00
FrankerFaceZ/socketserver/server/types.go
2016-04-28 14:36:59 -07:00

266 lines
6.4 KiB
Go

package server
import (
"encoding/json"
"fmt"
"net"
"sync"
"github.com/satori/go.uuid"
)
const NegativeOne = ^uint64(0)
type ConfigFile struct {
// Numeric server id known to the backend
ServerID int
// Address to bind the HTTP server to on startup.
ListenAddr string
// Address to bind the TLS server to on startup.
SSLListenAddr string
// URL to the backend server
BackendURL string
// Minimum memory to accept a new connection
MinMemoryKBytes uint64
// Maximum # of clients that can be connected. 0 to disable.
MaxClientCount uint64
// SSL/TLS
// Enable the use of SSL.
UseSSL bool
// Path to certificate file.
SSLCertificateFile string
// Path to key file.
SSLKeyFile string
UseESLogStashing bool
ESServer string
ESIndexPrefix string
ESHostName string
// Nacl keys
OurPrivateKey []byte
OurPublicKey []byte
BackendPublicKey []byte
// Request username validation from all new clients.
SendAuthToNewClients bool
}
type ClientMessage struct {
// Message ID. Increments by 1 for each message sent from the client.
// When replying to a command, the message ID must be echoed.
// When sending a server-initiated message, this is -1.
MessageID int `json:"m"`
// The command that the client wants from the server.
// When sent from the server, the literal string 'True' indicates success.
// Before sending, a blank Command will be converted into SuccessCommand.
Command Command `json:"c"`
// Result of json.Unmarshal on the third field send from the client
Arguments interface{} `json:"a"`
origArguments string
}
type AuthInfo struct {
// The client's claimed username on Twitch.
TwitchUsername string
// Whether or not the server has validated the client's claimed username.
UsernameValidated bool
}
type ClientVersion struct {
Major int
Minor int
Revision int
}
type ClientInfo struct {
// The client ID.
// This must be written once by the owning goroutine before the struct is passed off to any other goroutines.
ClientID uuid.UUID
// 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.
VersionString string
Version ClientVersion
// This mutex protects writable data in this struct.
// If it seems to be a performance problem, we can split this.
Mutex sync.Mutex
// Info about the client's username and whether or not we have verified it.
AuthInfo
RemoteAddr net.Addr
// Username validation nonce.
ValidationNonce string
// The list of chats this client is currently in.
// Protected by Mutex.
CurrentChannels []string
// List of channels that we have not yet checked current chat-related channel info for.
// This lets us batch the backlog requests.
// Protected by Mutex.
PendingSubscriptionsBacklog []string
// A timer that, when fired, will make the pending backlog requests.
// Usually nil. Protected by Mutex.
MakePendingRequests *time.Timer
// Server-initiated messages should be sent here
// This field will be nil before it is closed.
MessageChannel chan<- ClientMessage
MsgChannelIsDone <-chan struct{}
// Take out an Add() on this during a command if you need to use the MessageChannel later.
MsgChannelKeepalive sync.WaitGroup
// The number of pings sent without a response.
// Protected by Mutex
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
func (bct BacklogCacheType) Name() string {
switch bct {
case CacheTypeInvalid:
return ""
case CacheTypeNever:
return "never"
case CacheTypeLastOnly:
return "last"
case CacheTypePersistent:
return "persist"
}
panic("Invalid BacklogCacheType value")
}
var CacheTypesByName = map[string]BacklogCacheType{
"never": CacheTypeNever,
"last": CacheTypeLastOnly,
"persist": CacheTypePersistent,
}
func BacklogCacheTypeByName(name string) (bct BacklogCacheType) {
// CacheTypeInvalid is the zero value so it doesn't matter
bct, _ = CacheTypesByName[name]
return
}
// String implements Stringer
func (bct BacklogCacheType) String() string { return bct.Name() }
// MarshalJSON implements json.Marshaler
func (bct BacklogCacheType) MarshalJSON() ([]byte, error) {
return json.Marshal(bct.Name())
}
// UnmarshalJSON implements json.Unmarshaler
func (bct *BacklogCacheType) UnmarshalJSON(data []byte) error {
var str string
err := json.Unmarshal(data, &str)
if err != nil {
return err
}
if str == "" {
*bct = CacheTypeInvalid
return nil
}
newBct := BacklogCacheTypeByName(str)
if newBct != CacheTypeInvalid {
*bct = newBct
return nil
}
return ErrorUnrecognizedCacheType
}
func (mtt MessageTargetType) Name() string {
switch mtt {
case MsgTargetTypeInvalid:
return ""
case MsgTargetTypeChat:
return "chat"
case MsgTargetTypeMultichat:
return "multichat"
case MsgTargetTypeGlobal:
return "global"
}
panic("Invalid MessageTargetType value")
}
var TargetTypesByName = map[string]MessageTargetType{
"chat": MsgTargetTypeChat,
"multichat": MsgTargetTypeMultichat,
"global": MsgTargetTypeGlobal,
}
func MessageTargetTypeByName(name string) (mtt MessageTargetType) {
// MsgTargetTypeInvalid is the zero value so it doesn't matter
mtt, _ = TargetTypesByName[name]
return
}
// String implements Stringer
func (mtt MessageTargetType) String() string { return mtt.Name() }
// MarshalJSON implements json.Marshaler
func (mtt MessageTargetType) MarshalJSON() ([]byte, error) {
return json.Marshal(mtt.Name())
}
// UnmarshalJSON implements json.Unmarshaler
func (mtt *MessageTargetType) UnmarshalJSON(data []byte) error {
var str string
err := json.Unmarshal(data, &str)
if err != nil {
return err
}
if str == "" {
*mtt = MsgTargetTypeInvalid
return nil
}
newMtt := MessageTargetTypeByName(str)
if newMtt != MsgTargetTypeInvalid {
*mtt = newMtt
return nil
}
return ErrorUnrecognizedTargetType
}