server

package
v0.0.0-...-38e557e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2024 License: Apache-2.0 Imports: 36 Imported by: 0

Documentation

Index

Examples

Constants

View Source
const AuthChannel = "#" + AuthChannelName
View Source
const AuthChannelName = "frankerfacezauthorizer"
View Source
const AuthCommand = "AUTH"
View Source
const AuthorizationFailedErrorString = "Failed to verify your Twitch username."
View Source
const AuthorizationNeededError = "You must be signed in to use that command."
View Source
const CounterPrecision uint8 = 12
View Source
const NegativeOne = ^uint64(0)
View Source
const ReapingDelay = 1 * time.Minute
View Source
const StatsDataVersion = 8

StatsDataVersion is the version of the StatsData struct.

View Source
const UsersDailyFmt = "daily-%d-%d-%d.gob" // d-m-y

Variables

View Source
var AnonymousClientID = uuid.FromStringOrNil("683b45e4-f853-4c45-bf96-7d799cc93e34")
View Source
var Backend *backendInfo
View Source
var BannerHTML []byte

BannerHTML is the content served to web browsers viewing the socket server website. Memes go here.

View Source
var CachedLSMLock sync.RWMutex
View Source
var CachedLastMessages = make(map[Command]map[string]LastSavedMessage)

CachedLastMessages is of CacheTypeLastOnly. Not actually cleaned up by reaper goroutine every ~hour.

View Source
var ChatSubscriptionInfo map[string]*SubscriberList = make(map[string]*SubscriberList)
View Source
var ChatSubscriptionLock sync.RWMutex
View Source
var CloseFirstMessageNotHello = websocket.CloseError{
	Text: "Error - the first message sent must be a 'hello'",
	Code: websocket.ClosePolicyViolation,
}

CloseFirstMessageNotHello is the termination reason

View Source
var CloseGoingAway = websocket.CloseError{Code: websocket.CloseGoingAway, Text: "server restarting"}

CloseGoingAway is sent when the server is restarting.

View Source
var CloseGotBinaryMessage = websocket.CloseError{Code: websocket.CloseUnsupportedData, Text: "got binary packet"}

CloseGotBinaryMessage is the termination reason when the client sends a binary websocket frame.

View Source
var CloseNonUTF8Data = websocket.CloseError{
	Code: websocket.CloseUnsupportedData,
	Text: "Non UTF8 data recieved. Network corruption likely.",
}
View Source
var CloseRebalance = websocket.CloseError{Code: websocket.CloseGoingAway, Text: "kicked for rebalancing, please select a new server"}

CloseRebalance is sent when the server has too many clients and needs to shunt some to another server.

View Source
var CloseTimedOut = websocket.CloseError{Code: 3003, Text: "no ping replies for 5 minutes"}

CloseTimedOut is the termination reason when the client fails to send or respond to ping frames.

View Source
var CloseTooManyBufferedMessages = websocket.CloseError{Code: websocket.CloseMessageTooBig, Text: "too many pending messages"}

CloseTooManyBufferedMessages is the termination reason when the sending thread buffers too many messages.

View Source
var CommandCounter = make(chan Command, 10)

CommandCounter is a channel for race-free counting of command usage.

View Source
var CounterLocation *time.Location = time.FixedZone("UTC-5", int((time.Hour*-5)/time.Second))
View Source
var ErrAuthorizationNeeded = errors.New("Must authenticate Twitch username to use this command")

ErrAuthorizationNeeded is emitted when the backend replies with HTTP 401.

Indicates that an attempt to validate `ClientInfo.TwitchUsername` should be attempted.

View Source
var ErrExpectedSingleInt = errors.New("Error: Expected single integer as arguments.")

ErrExpectedSingleInt is sent in a ErrorCommand Reply when the Arguments are of the wrong type.

View Source
var ErrExpectedSingleString = errors.New("Error: Expected single string as arguments.")

ErrExpectedSingleString is sent in a ErrorCommand Reply when the Arguments are of the wrong type.

View Source
var ErrExpectedStringAndBool = errors.New("Error: Expected array of string, bool as arguments.")

ErrExpectedStringAndBool is sent in a ErrorCommand Reply when the Arguments are of the wrong type.

View Source
var ErrExpectedStringAndInt = errors.New("Error: Expected array of string, int as arguments.")

ErrExpectedStringAndInt is sent in a ErrorCommand Reply when the Arguments are of the wrong type.

View Source
var ErrExpectedStringAndIntGotFloat = errors.New("Error: Second argument was a float, expected an integer.")

ErrExpectedStringAndIntGotFloat is sent in a ErrorCommand Reply when the Arguments are of the wrong type.

View Source
var ErrExpectedTwoStrings = errors.New("Error: Expected array of string, string as arguments.")

ErrExpectedTwoStrings is sent in a ErrorCommand Reply when the Arguments are of the wrong type.

View Source
var ErrProtocolGeneric error = fatalDecodeError("FFZ Socket protocol error.")

ErrProtocolGeneric is sent in a ErrorCommand Reply.

View Source
var ErrProtocolNegativeMsgID error = fatalDecodeError("FFZ Socket protocol error: negative or zero message ID.")

ErrProtocolNegativeMsgID is sent in a ErrorCommand Reply when a negative MessageID is received.

View Source
var GlobalSubscriptionInfo []*ClientInfo
View Source
var GlobalSubscriptionLock sync.RWMutex
View Source
var PendingAuthLock sync.Mutex
View Source
var PendingAuths []PendingAuthorization
View Source
var ResponseSuccess = ClientMessage{Command: SuccessCommand}

ResponseSuccess is a Reply ClientMessage with the MessageID not yet filled out.

View Source
var SocketUpgrader = websocket.Upgrader{
	ReadBufferSize:  160,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		origin := r.Header.Get("Origin")
		if origin == "" || !Configuration.UseOriginChecks {
			return true
		}

		for _, allowedOrigin := range Configuration.AllowedOrigins {
			if strings.Contains(origin, allowedOrigin) {
				return true
			}
		}

		return false
	},
}

SocketUpgrader is the websocket.Upgrader currently in use.

View Source
var Statistics = newStatsData()

Statistics is several variables that get incremented during normal operation of the server. Its structure should be versioned as it is exposed via JSON.

Note as to threaded access - this is soft/fun data and not critical to data integrity. Fix anything that -race turns up, but otherwise it's not too much of a problem.

View Source
var StopAcceptingConnectionsCh = make(chan struct{})

StopAcceptingConnectionsCh is closed while the server is shutting down.

Functions

func AddPendingAuthorization

func AddPendingAuthorization(client *ClientInfo, challenge string, callback AuthCallback)

func AddToSliceCl

func AddToSliceCl(ary *[]*ClientInfo, val *ClientInfo) bool

func AddToSliceS

func AddToSliceS(ary *[]string, val string) bool

func CountSubscriptions

func CountSubscriptions(channels []string) int

func DispatchC2SCommand

func DispatchC2SCommand(conn *websocket.Conn, client *ClientInfo, msg ClientMessage)

DispatchC2SCommand handles a C2S Command in the provided ClientMessage. It calls the correct CommandHandler function, catching panics. It sends either the returned Reply ClientMessage, setting the correct messageID, or sends an ErrorCommand

func DumpBacklogData

func DumpBacklogData()

DumpBacklogData drops all /cached_pub data.

func GenerateKeys

func GenerateKeys(outputFile, serverID, theirPublicStr string)

GenerateKeys generates a new NaCl keypair for the server and writes out the default configuration file.

func GetAllTopics

func GetAllTopics() []string

func GetCounterPeriod

func GetCounterPeriod(at time.Time) (start time.Time, end time.Time)

GetCounterPeriod calculates the start and end timestamps for the HLL measurement period that includes the 'at' timestamp.

func GetHLLFilename

func GetHLLFilename(at time.Time) string

GetHLLFilename returns the filename for the saved HLL whose measurement period covers the given time.

func HTTPBackendCachedPublish

func HTTPBackendCachedPublish(w http.ResponseWriter, r *http.Request)

HTTPBackendCachedPublish handles the /cached_pub route. It publishes a message to clients, and then updates the in-server cache for the message.

The 'channel' parameter is a comma-separated list of topics to publish the message to. The 'args' parameter is the JSON-encoded command data. If the 'delete' parameter is present, an entry is removed from the cache instead of publishing a message. If the 'expires' parameter is not specified, the message will not expire (though it is only kept in-memory).

func HTTPBackendDropBacklog

func HTTPBackendDropBacklog(w http.ResponseWriter, r *http.Request)

func HTTPBackendUncachedPublish

func HTTPBackendUncachedPublish(w http.ResponseWriter, r *http.Request)

HTTPBackendUncachedPublish handles the /uncached_pub route. The backend can POST here to publish a message to clients with no caching. The POST arguments are `cmd`, `args`, `channel`, and `scope`. If "scope" is "global", then "channel" is not used.

func HTTPGetSubscriberCount

func HTTPGetSubscriberCount(w http.ResponseWriter, r *http.Request)

HTTPGetSubscriberCount handles the /get_sub_count route. It replies with the number of clients subscribed to a pub/sub topic. A "global" option is not available, use fetch(/stats).CurrentClientCount instead.

func HTTPHandleRootURL

func HTTPHandleRootURL(w http.ResponseWriter, r *http.Request)

HTTPHandleRootURL is the http.HandleFunc for requests on `/`. It either uses the SocketUpgrader or writes out the BannerHTML.

func HTTPListAllTopics

func HTTPListAllTopics(w http.ResponseWriter, r *http.Request)

func HTTPSayOK

func HTTPSayOK(w http.ResponseWriter, _ *http.Request)

HTTPSayOK replies with 200 and a body of "ok\n".

func HTTPShowHLL

func HTTPShowHLL(w http.ResponseWriter, r *http.Request)

func HTTPShowStatistics

func HTTPShowStatistics(w http.ResponseWriter, _ *http.Request)

HTTPShowStatistics handles the /stats endpoint. It writes out the Statistics object as indented JSON.

func HTTPWriteHLL

func HTTPWriteHLL(w http.ResponseWriter, _ *http.Request)

func MarshalClientMessage

func MarshalClientMessage(clientMessage interface{}) (int, []byte, error)

returns payloadType, data, err

Example
var cm ClientMessage = ClientMessage{
	MessageID: -1,
	Command:   "do_authorize",
	Arguments: "1234567890",
}
payloadType, data, err := MarshalClientMessage(&cm)
fmt.Println(err)
fmt.Println(payloadType == websocket.TextMessage)
fmt.Println(string(data))
Output:

<nil>
true
-1 do_authorize "1234567890"

func ProxyHandler

func ProxyHandler(route ProxyRoute) *httputil.ReverseProxy

ProxyHandler sets up a ReverseProxy for serving content on a route.

func PublishToAll

func PublishToAll(msg ClientMessage, rl rate.Limiter) (count int)

func PublishToChannel

func PublishToChannel(channel string, msg ClientMessage, rl rate.Limiter) (count int)

func PublishToMultiple

func PublishToMultiple(channels []string, msg ClientMessage, rl rate.Limiter) (count int)

func RemoveFromSliceCl

func RemoveFromSliceCl(ary *[]*ClientInfo, val *ClientInfo) bool

func RemoveFromSliceS

func RemoveFromSliceS(ary *[]string, val string) bool

func RunSocketConnection

func RunSocketConnection(conn *websocket.Conn)

RunSocketConnection contains the main run loop of a websocket connection.

First, it sets up the channels, the ClientInfo object, and the pong frame handler. It starts the reader goroutine pointing at the newly created channels. The function then enters the run loop (a `for{select{}}`). The run loop is broken when an object is received on errorChan, or if `hello` is not the first C2S Command.

After the run loop stops, the function launches a goroutine to drain client.MessageChannel, signals the reader goroutine to stop, unsubscribes from all pub/sub channels, waits on MsgChannelKeepalive (remember, the messages are being drained), and finally closes client.MessageChannel (which ends the drainer goroutine).

func SendBacklogForChannel

func SendBacklogForChannel(client *ClientInfo, channel string)

func SendBacklogForNewClient

func SendBacklogForNewClient(client *ClientInfo)

SendBacklogForNewClient sends any backlog data relevant to a new client. This should be done when the client sends a `ready` message. This will only send data for CacheTypePersistent and CacheTypeLastOnly because those do not involve timestamps.

func SendMessage

func SendMessage(conn *websocket.Conn, msg ClientMessage)

SendMessage sends a ClientMessage over the websocket connection with a timeout. If marshalling the ClientMessage fails, this function will panic.

func SetBuildStamp

func SetBuildStamp(buildTime, buildHash string)

SetBuildStamp should be called from the main package to identify the git build hash and build time.

func SetupServerAndHandle

func SetupServerAndHandle(config *ConfigFile, serveMux *http.ServeMux)

SetupServerAndHandle starts all background goroutines and registers HTTP listeners on the given ServeMux. Essentially, this function completely preps the server for a http.ListenAndServe call. (Uses http.DefaultServeMux if `serveMux` is nil.)

func Shutdown

func Shutdown(wg *sync.WaitGroup)

Shutdown disconnects all clients.

func SubscribeChannel

func SubscribeChannel(client *ClientInfo, channelName string)

func SubscribeGlobal

func SubscribeGlobal(client *ClientInfo)

func UnmarshalClientMessage

func UnmarshalClientMessage(data []byte, _ int, v interface{}) (err error)

UnmarshalClientMessage unpacks websocket TextMessage into a ClientMessage provided in the `v` parameter.

Example
sourceData := []byte("100 hello [\"ffz_3.5.30\",\"898b5bfa-b577-47bb-afb4-252c703b67d6\"]")
var cm ClientMessage
err := UnmarshalClientMessage(sourceData, websocket.TextMessage, &cm)
fmt.Println(err)
fmt.Println(cm.MessageID)
fmt.Println(cm.Command)
fmt.Println(cm.Arguments)
Output:

<nil>
100
hello
[ffz_3.5.30 898b5bfa-b577-47bb-afb4-252c703b67d6]

func UnsubscribeAll

func UnsubscribeAll(client *ClientInfo)

UnsubscribeAll will unsubscribe the client from all channels, AND clear the CurrentChannels / WatchingChannels fields.

Locks:

  • read lock to top-level maps
  • write lock to SubscriptionInfos
  • write lock to ClientInfo

func UnsubscribeSingleChat

func UnsubscribeSingleChat(client *ClientInfo, channelName string)

Types

type AuthCallback

type AuthCallback func(client *ClientInfo, successful bool)

type AuthInfo

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 ClientInfo

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

	// 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

	// 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

	// True if the client has already sent the 'ready' command
	ReadyComplete bool

	// Closed when the client is shutting down.
	MsgChannelIsDone <-chan struct{}

	// Take out an Add() on this during a command if you need to call Send() later.
	MsgChannelKeepalive sync.WaitGroup
	// contains filtered or unexported fields
}

func (*ClientInfo) Send

func (client *ClientInfo) Send(msg ClientMessage) bool

Send a message to the client. Drops if buffer is full.

func (*ClientInfo) StartAuthorization

func (client *ClientInfo) StartAuthorization(callback AuthCallback)

type ClientMessage

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"`
	// contains filtered or unexported fields
}

func C2SEmoticonUses

func C2SEmoticonUses(*websocket.Conn, *ClientInfo, ClientMessage) (ClientMessage, error)

C2SEmoticonUses implements the `emoticon_uses` C2S Command. msg.Arguments are in the JSON format of [1]map[emoteID]map[ChatroomName]float64.

func C2SHandleBunchedCommand

func C2SHandleBunchedCommand(_ *websocket.Conn, client *ClientInfo, msg ClientMessage) (ClientMessage, error)

C2SHandleBunchedCommand handles C2S Commands such as `get_link`. It makes a request to the backend server for the data, but any other requests coming in while the first is pending also get the responses from the first one.

func C2SHandleRemoteCommand

func C2SHandleRemoteCommand(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (ClientMessage, error)

func C2SHello

func C2SHello(_ *websocket.Conn, client *ClientInfo, msg ClientMessage) (_ ClientMessage, err error)

C2SHello implements the `hello` C2S Command. It calls SubscribeGlobal() and SubscribeDefaults() with the client, and fills out ClientInfo.Version and ClientInfo.ClientID.

func C2SReady

func C2SReady(_ *websocket.Conn, client *ClientInfo, msg ClientMessage) (ClientMessage, error)

func C2SSetUser

func C2SSetUser(_ *websocket.Conn, client *ClientInfo, msg ClientMessage) (ClientMessage, error)

func C2SSubscribe

func C2SSubscribe(_ *websocket.Conn, client *ClientInfo, msg ClientMessage) (ClientMessage, error)

func C2SSurvey

C2SSurvey implements the survey C2S Command.

func C2STrackFollow

func C2STrackFollow(_ *websocket.Conn, client *ClientInfo, msg ClientMessage) (_ ClientMessage, err error)

C2STrackFollow implements the `track_follow` C2S Command. It adds the record to `followEvents`, which is submitted to the backend on a timer.

func C2SUnsubscribe

func C2SUnsubscribe(_ *websocket.Conn, client *ClientInfo, msg ClientMessage) (ClientMessage, error)

C2SUnsubscribe implements the `unsub` C2S Command. It removes the channel from ClientInfo.CurrentChannels and calls UnsubscribeSingleChat.

func (*ClientMessage) ArgumentsAsInt

func (cm *ClientMessage) ArgumentsAsInt() (int1 int64, err error)

ArgumentsAsInt parses the arguments of the ClientMessage as a single int.

func (*ClientMessage) ArgumentsAsString

func (cm *ClientMessage) ArgumentsAsString() (string1 string, err error)

ArgumentsAsString parses the arguments of the ClientMessage as a single string.

func (*ClientMessage) ArgumentsAsStringAndBool

func (cm *ClientMessage) ArgumentsAsStringAndBool() (str string, flag bool, err error)

ArgumentsAsStringAndBool parses the arguments of the ClientMessage as an array of a string and an int.

func (*ClientMessage) ArgumentsAsStringAndInt

func (cm *ClientMessage) ArgumentsAsStringAndInt() (string1 string, int int64, err error)

ArgumentsAsStringAndInt parses the arguments of the ClientMessage as an array of a string and an int.

func (*ClientMessage) ArgumentsAsTwoStrings

func (cm *ClientMessage) ArgumentsAsTwoStrings() (string1, string2 string, err error)

ArgumentsAsTwoStrings parses the arguments of the ClientMessage as an array of two strings.

func (ClientMessage) Reply

func (cm ClientMessage) Reply(cmd Command, args interface{}) ClientMessage

func (ClientMessage) ReplyJSON

func (cm ClientMessage) ReplyJSON(cmd Command, argsJSON string) ClientMessage

type ClientVersion

type ClientVersion struct {
	Major    int
	Minor    int
	Revision int
}

func VersionFromString

func VersionFromString(v string) ClientVersion

func (*ClientVersion) After

func (cv *ClientVersion) After(cv2 *ClientVersion) bool

func (*ClientVersion) Equal

func (cv *ClientVersion) Equal(cv2 *ClientVersion) bool

type Command

type Command string

Command is a string indicating which RPC is requested. The Commands sent from Client -> Server and Server -> Client are disjoint sets.

const AsyncResponseCommand Command = "_async"

AsyncResponseCommand is a pseudo-Reply Command. It indicates that the Reply Command to the client's C2S Command will be delivered on a goroutine over the ClientInfo.MessageChannel and should not be delivered immediately.

const AuthorizeCommand Command = "do_authorize"

AuthorizeCommand is a S2C Command sent as part of Twitch username validation.

const ErrorCommand Command = "error"

ErrorCommand is a Reply Command to indicate that a C2S Command failed.

const HelloCommand Command = "hello"

HelloCommand is a C2S Command. HelloCommand must be the Command of the first ClientMessage sent during a connection. Sending any other command will result in a CloseFirstMessageNotHello.

const ReadyCommand Command = "ready"

ReadyCommand is a C2S Command. It indicates that the client is finished sending the initial 'sub' commands and the server should send the backlog.

const SetUserCommand Command = "setuser"
const SuccessCommand Command = "ok"

SuccessCommand is a Reply Command to indicate success in reply to a C2S Command.

type CommandHandler

type CommandHandler func(*websocket.Conn, *ClientInfo, ClientMessage) (ClientMessage, error)

CommandHandler is a RPC handler associated with a Command.

type ConfigFile

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

	// Origin Checking
	UseOriginChecks bool

	// Allowed Origins
	AllowedOrigins []string

	// Nacl keys
	OurPrivateKey    []byte
	OurPublicKey     []byte
	BackendPublicKey []byte

	// Request username validation from all new clients.
	SendAuthToNewClients bool

	// Proxy Routes
	ProxyRoutes []ProxyRoute
}
var Configuration *ConfigFile

Configuration is the active ConfigFile.

type ErrBackendNotOK

type ErrBackendNotOK struct {
	Response string
	Code     int
}

ErrBackendNotOK indicates that the backend replied with something other than the string "ok".

func (ErrBackendNotOK) Error

func (noe ErrBackendNotOK) Error() string

Error Implements the error interface.

type ErrForwardedFromBackend

type ErrForwardedFromBackend struct {
	JSONError interface{}
}

ErrForwardedFromBackend is an error returned by the backend server.

func (ErrForwardedFromBackend) Error

func (bfe ErrForwardedFromBackend) Error() string

type LastSavedMessage

type LastSavedMessage struct {
	Expires time.Time
	Data    string
}

LastSavedMessage contains a reply to a command along with an expiration time.

type PendingAuthorization

type PendingAuthorization struct {
	Client    *ClientInfo
	Challenge string
	Callback  AuthCallback
	EnteredAt time.Time
}

type PeriodUniqueUsers

type PeriodUniqueUsers struct {
	Start   time.Time
	End     time.Time
	Counter *hyperloglog.HyperLogLogPlus
}

type ProxyRoute

type ProxyRoute struct {
	Route  string
	Server string
}

type StatsData

type StatsData struct {
	StatsDataVersion int

	StartTime time.Time
	Uptime    string
	BuildTime string
	BuildHash string

	CachedStatsLastUpdate time.Time

	Health struct {
		IRC     bool
		Backend map[string]time.Time
	}

	CurrentClientCount uint64
	LiveClientCount    uint64

	PubSubChannelCount int

	SysMemTotalKB uint64
	SysMemFreeKB  uint64
	MemoryInUseKB uint64
	MemoryRSSKB   uint64

	ResponseCacheItems int
	MemPerClientBytes  uint64

	CpuUsagePct float64

	ClientConnectsTotal    uint64
	ClientDisconnectsTotal uint64

	ClientVersions map[string]uint64

	DisconnectCodes map[string]uint64

	CommandsIssuedTotal uint64
	CommandsIssuedMap   map[Command]uint64

	MessagesSent uint64

	EmotesReportedTotal uint64

	BackendVerifyFails uint64

	// DisconnectReasons is at the bottom because it has indeterminate size
	DisconnectReasons map[string]uint64
	// contains filtered or unexported fields
}

type StringPool

type StringPool struct {
	sync.RWMutex
	// contains filtered or unexported fields
}
var CommandPool *StringPool
var PubSubChannelPool *StringPool
var TwitchChannelPool *StringPool

func NewStringPool

func NewStringPool() *StringPool

func (*StringPool) Intern

func (p *StringPool) Intern(s string) string

func (*StringPool) InternCommand

func (p *StringPool) InternCommand(s string) Command

type SubscriberList

type SubscriberList struct {
	sync.RWMutex
	Members []*ClientInfo
}

type UuidHash

type UuidHash uuid.UUID

UuidHash implements a hash for uuid.UUID by XORing the random bits.

func (UuidHash) Sum64

func (u UuidHash) Sum64() uint64

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL