mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-03 16:38:31 +00:00
Source cleanup, and some string copies
This commit is contained in:
parent
387ada9c9c
commit
7654dcdf8d
10 changed files with 47 additions and 89 deletions
|
@ -17,7 +17,7 @@ import (
|
|||
// The Commands sent from Client -> Server and Server -> Client are disjoint sets.
|
||||
type Command string
|
||||
|
||||
// CommandHandler is a RPC handler assosciated with a Command.
|
||||
// CommandHandler is a RPC handler associated with a Command.
|
||||
type CommandHandler func(*websocket.Conn, *ClientInfo, ClientMessage) (ClientMessage, error)
|
||||
|
||||
var commandHandlers = map[Command]CommandHandler{
|
||||
|
@ -43,10 +43,10 @@ var commandHandlers = map[Command]CommandHandler{
|
|||
|
||||
func internCommands() {
|
||||
CommandPool = NewStringPool()
|
||||
CommandPool._Intern_Setup(HelloCommand)
|
||||
CommandPool._Intern_Setup(string(HelloCommand))
|
||||
CommandPool._Intern_Setup("ping")
|
||||
CommandPool._Intern_Setup(SetUserCommand)
|
||||
CommandPool._Intern_Setup(ReadyCommand)
|
||||
CommandPool._Intern_Setup(string(SetUserCommand))
|
||||
CommandPool._Intern_Setup(string(ReadyCommand))
|
||||
CommandPool._Intern_Setup("sub")
|
||||
CommandPool._Intern_Setup("unsub")
|
||||
CommandPool._Intern_Setup("track_follow")
|
||||
|
@ -155,8 +155,8 @@ func C2SSetUser(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rm
|
|||
}
|
||||
|
||||
client.Mutex.Lock()
|
||||
client.TwitchUsername = username
|
||||
client.UsernameValidated = false
|
||||
client.TwitchUsername = username
|
||||
client.Mutex.Unlock()
|
||||
|
||||
if Configuration.SendAuthToNewClients {
|
||||
|
@ -262,7 +262,7 @@ func C2STrackFollow(conn *websocket.Conn, client *ClientInfo, msg ClientMessage)
|
|||
now := time.Now()
|
||||
|
||||
followEventsLock.Lock()
|
||||
followEvents = append(followEvents, followEvent{client.TwitchUsername, channel, following, now})
|
||||
followEvents = append(followEvents, followEvent{User: client.TwitchUsername, Channel: channel, NowFollowing: following, Timestamp: now})
|
||||
followEventsLock.Unlock()
|
||||
|
||||
return ResponseSuccess, nil
|
||||
|
|
|
@ -60,7 +60,7 @@ var Configuration *ConfigFile
|
|||
|
||||
var janitorsOnce sync.Once
|
||||
|
||||
var CommandPool StringPool
|
||||
var CommandPool *StringPool
|
||||
|
||||
// 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.
|
||||
|
@ -573,7 +573,7 @@ func MarshalClientMessage(clientMessage interface{}) (payloadType int, data []by
|
|||
return websocket.TextMessage, []byte(dataStr), nil
|
||||
}
|
||||
|
||||
// Convenience method: Parse the arguments of the ClientMessage as a single string.
|
||||
// ArgumentsAsString parses the arguments of the ClientMessage as a single string.
|
||||
func (cm *ClientMessage) ArgumentsAsString() (string1 string, err error) {
|
||||
var ok bool
|
||||
string1, ok = cm.Arguments.(string)
|
||||
|
@ -585,7 +585,7 @@ func (cm *ClientMessage) ArgumentsAsString() (string1 string, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Convenience method: Parse the arguments of the ClientMessage as a single int.
|
||||
// ArgumentsAsInt parses the arguments of the ClientMessage as a single int.
|
||||
func (cm *ClientMessage) ArgumentsAsInt() (int1 int64, err error) {
|
||||
var ok bool
|
||||
var num float64
|
||||
|
@ -599,7 +599,7 @@ func (cm *ClientMessage) ArgumentsAsInt() (int1 int64, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Convenience method: Parse the arguments of the ClientMessage as an array of two strings.
|
||||
// ArgumentsAsTwoStrings parses the arguments of the ClientMessage as an array of two strings.
|
||||
func (cm *ClientMessage) ArgumentsAsTwoStrings() (string1, string2 string, err error) {
|
||||
var ok bool
|
||||
var ary []interface{}
|
||||
|
@ -630,7 +630,7 @@ func (cm *ClientMessage) ArgumentsAsTwoStrings() (string1, string2 string, err e
|
|||
}
|
||||
}
|
||||
|
||||
// Convenience method: Parse the arguments of the ClientMessage as an array of a string and an int.
|
||||
// ArgumentsAsStringAndInt parses the arguments of the ClientMessage as an array of a string and an int.
|
||||
func (cm *ClientMessage) ArgumentsAsStringAndInt() (string1 string, int int64, err error) {
|
||||
var ok bool
|
||||
var ary []interface{}
|
||||
|
@ -663,7 +663,7 @@ func (cm *ClientMessage) ArgumentsAsStringAndInt() (string1 string, int int64, e
|
|||
}
|
||||
}
|
||||
|
||||
// Convenience method: Parse the arguments of the ClientMessage as an array of a string and an int.
|
||||
// ArgumentsAsStringAndBool parses the arguments of the ClientMessage as an array of a string and an int.
|
||||
func (cm *ClientMessage) ArgumentsAsStringAndBool() (str string, flag bool, err error) {
|
||||
var ok bool
|
||||
var ary []interface{}
|
||||
|
|
|
@ -32,6 +32,7 @@ func (p *StringPool) Intern(s string) Command {
|
|||
if exists {
|
||||
return ss
|
||||
}
|
||||
p.lookup[s] = Command(string([]byte(s)))
|
||||
return s
|
||||
ss = Command(string([]byte(s))) // make a copy
|
||||
p.lookup[s] = ss
|
||||
return ss
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
irc "github.com/fluffle/goirc/client"
|
||||
"log"
|
||||
"strings"
|
||||
|
@ -87,10 +86,6 @@ const AuthChannelName = "frankerfacezauthorizer"
|
|||
const AuthChannel = "#" + AuthChannelName
|
||||
const AuthCommand = "AUTH"
|
||||
|
||||
const DEBUG = "DEBUG"
|
||||
|
||||
var errChallengeNotFound = errors.New("did not find a challenge solved by that message")
|
||||
|
||||
// is_init_func
|
||||
func ircConnection() {
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -33,36 +32,37 @@ var S2CCommandsCacheInfo = map[Command]PushCommandCacheInfo{
|
|||
type BacklogCacheType int
|
||||
|
||||
const (
|
||||
// This is not a cache type.
|
||||
// CacheTypeInvalid is the sentinel value.
|
||||
CacheTypeInvalid BacklogCacheType = iota
|
||||
// This message cannot be cached.
|
||||
// CacheTypeNever is a message that cannot be cached.
|
||||
CacheTypeNever
|
||||
// Save only the last copy of this message, and always send it when the backlog is requested.
|
||||
// CacheTypeLastOnly means to save only the last copy of this message,
|
||||
// and always send it when the backlog is requested.
|
||||
CacheTypeLastOnly
|
||||
// Save this backlog data to disk with its timestamp.
|
||||
// Send it when the backlog is requested, or after a reconnect if it was updated.
|
||||
// CacheTypePersistent means to save the last copy of this message,
|
||||
// and always send it when the backlog is requested, but do not clean it periodically.
|
||||
CacheTypePersistent
|
||||
)
|
||||
|
||||
type MessageTargetType int
|
||||
|
||||
const (
|
||||
// This is not a message target.
|
||||
// MsgTargetTypeInvalid is the sentinel value.
|
||||
MsgTargetTypeInvalid MessageTargetType = iota
|
||||
// This message is targeted to all users in a chat
|
||||
// MsgTargetTypeChat is a message is targeted to all users in a particular chat.
|
||||
MsgTargetTypeChat
|
||||
// This message is targeted to all users in multiple chats
|
||||
// MsgTargetTypeMultichat is a message is targeted to all users in multiple chats.
|
||||
MsgTargetTypeMultichat
|
||||
// This message is sent to all FFZ users.
|
||||
// MsgTargetTypeGlobal is a message sent to all FFZ users.
|
||||
MsgTargetTypeGlobal
|
||||
)
|
||||
|
||||
// note: see types.go for methods on these
|
||||
|
||||
// Returned by BacklogCacheType.UnmarshalJSON()
|
||||
// ErrorUnrecognizedCacheType is returned by BacklogCacheType.UnmarshalJSON()
|
||||
var ErrorUnrecognizedCacheType = errors.New("Invalid value for cachetype")
|
||||
|
||||
// Returned by MessageTargetType.UnmarshalJSON()
|
||||
// ErrorUnrecognizedTargetType is returned by MessageTargetType.UnmarshalJSON()
|
||||
var ErrorUnrecognizedTargetType = errors.New("Invalid value for message target")
|
||||
|
||||
type LastSavedMessage struct {
|
||||
|
@ -72,11 +72,11 @@ type LastSavedMessage struct {
|
|||
|
||||
// map is command -> channel -> data
|
||||
|
||||
// CacheTypeLastOnly. Cleaned up by reaper goroutine every ~hour.
|
||||
// CachedLastMessages is of CacheTypeLastOnly. Cleaned up by reaper goroutine every ~hour.
|
||||
var CachedLastMessages = make(map[Command]map[string]LastSavedMessage)
|
||||
var CachedLSMLock sync.RWMutex
|
||||
|
||||
// CacheTypePersistent. Never cleaned.
|
||||
// PersistentLastMessages is of CacheTypePersistent. Never cleaned.
|
||||
var PersistentLastMessages = make(map[Command]map[string]LastSavedMessage)
|
||||
var PersistentLSMLock sync.RWMutex
|
||||
|
||||
|
@ -135,50 +135,11 @@ func SendBacklogForNewClient(client *ClientInfo) {
|
|||
CachedLSMLock.RUnlock()
|
||||
}
|
||||
|
||||
// insertionSort implements insertion sort.
|
||||
// CacheTypeTimestamps should use insertion sort for O(N) average performance.
|
||||
// (The average case is the array is still sorted after insertion of the new item.)
|
||||
func insertionSort(ary sort.Interface) {
|
||||
for i := 1; i < ary.Len(); i++ {
|
||||
for j := i; j > 0 && ary.Less(j, j-1); j-- {
|
||||
ary.Swap(j, j-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type timestampArray interface {
|
||||
Len() int
|
||||
GetTime(int) time.Time
|
||||
}
|
||||
|
||||
func findFirstNewMessage(ary timestampArray, disconnectTime time.Time) (idx int) {
|
||||
len := ary.Len()
|
||||
i := len
|
||||
|
||||
// Walk backwards until we find GetTime() before disconnectTime
|
||||
step := 1
|
||||
for i > 0 {
|
||||
i -= step
|
||||
if i < 0 {
|
||||
i = 0
|
||||
}
|
||||
if !ary.GetTime(i).After(disconnectTime) {
|
||||
break
|
||||
}
|
||||
step = int(float64(step)*1.5) + 1
|
||||
}
|
||||
|
||||
// Walk forwards until we find GetTime() after disconnectTime
|
||||
for i < len && !ary.GetTime(i).After(disconnectTime) {
|
||||
i++
|
||||
}
|
||||
|
||||
if i == len {
|
||||
return -1
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func SaveLastMessage(which map[Command]map[string]LastSavedMessage, locker sync.Locker, cmd Command, channel string, timestamp time.Time, data string, deleting bool) {
|
||||
locker.Lock()
|
||||
defer locker.Unlock()
|
||||
|
@ -195,7 +156,7 @@ func SaveLastMessage(which map[Command]map[string]LastSavedMessage, locker sync.
|
|||
if deleting {
|
||||
delete(chanMap, channel)
|
||||
} else {
|
||||
chanMap[channel] = LastSavedMessage{timestamp, data}
|
||||
chanMap[channel] = LastSavedMessage{Timestamp: timestamp, Data: data}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +185,8 @@ func HTTPBackendDropBacklog(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// Publish a message to clients, and update the in-server cache for the message.
|
||||
// HTTPBackendCachedPublish handles the /cached_pub route.
|
||||
// It publishes a message to clients, and then updates the in-server cache for the message.
|
||||
// notes:
|
||||
// `scope` is implicit in the command
|
||||
func HTTPBackendCachedPublish(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -73,7 +73,7 @@ func commandCounter() {
|
|||
}
|
||||
}
|
||||
|
||||
// StatsDataVersion
|
||||
// StatsDataVersion is the version of the StatsData struct.
|
||||
const StatsDataVersion = 5
|
||||
const pageSize = 4096
|
||||
|
||||
|
|
|
@ -99,7 +99,9 @@ func UnsubscribeSingleChat(client *ClientInfo, channelName string) {
|
|||
ChatSubscriptionLock.RUnlock()
|
||||
}
|
||||
|
||||
// Unsubscribe the client from all channels, AND clear the CurrentChannels / WatchingChannels fields.
|
||||
// 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
|
||||
|
|
|
@ -30,9 +30,9 @@ func TestSubscriptionAndPublish(t *testing.T) {
|
|||
const TestData3 = false
|
||||
var TestData4 = []interface{}{"str1", "str2", "str3"}
|
||||
|
||||
S2CCommandsCacheInfo[TestCommandChan] = PushCommandCacheInfo{CacheTypeLastOnly, MsgTargetTypeChat}
|
||||
S2CCommandsCacheInfo[TestCommandMulti] = PushCommandCacheInfo{CacheTypeLastOnly, MsgTargetTypeMultichat}
|
||||
S2CCommandsCacheInfo[TestCommandGlobal] = PushCommandCacheInfo{CacheTypeLastOnly, MsgTargetTypeGlobal}
|
||||
S2CCommandsCacheInfo[TestCommandChan] = PushCommandCacheInfo{Caching: CacheTypeLastOnly, Target: MsgTargetTypeChat}
|
||||
S2CCommandsCacheInfo[TestCommandMulti] = PushCommandCacheInfo{Caching: CacheTypeLastOnly, Target: MsgTargetTypeMultichat}
|
||||
S2CCommandsCacheInfo[TestCommandGlobal] = PushCommandCacheInfo{Caching: CacheTypeLastOnly, Target: MsgTargetTypeGlobal}
|
||||
|
||||
var server *httptest.Server
|
||||
var urls TURLs
|
||||
|
|
|
@ -9,8 +9,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const CryptoBoxKeyLength = 32
|
||||
|
||||
const NegativeOne = ^uint64(0)
|
||||
|
||||
type ConfigFile struct {
|
||||
|
@ -94,7 +92,7 @@ type ClientInfo struct {
|
|||
// If it seems to be a performance problem, we can split this.
|
||||
Mutex sync.Mutex
|
||||
|
||||
// TODO(riking) - does this need to be protected cross-thread?
|
||||
// Info about the client's username and whether or not we have verified it.
|
||||
AuthInfo
|
||||
|
||||
RemoteAddr net.Addr
|
||||
|
@ -187,15 +185,15 @@ func BacklogCacheTypeByName(name string) (bct BacklogCacheType) {
|
|||
return
|
||||
}
|
||||
|
||||
// Implements Stringer
|
||||
// String implements Stringer
|
||||
func (bct BacklogCacheType) String() string { return bct.Name() }
|
||||
|
||||
// Implements json.Marshaler
|
||||
// MarshalJSON implements json.Marshaler
|
||||
func (bct BacklogCacheType) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(bct.Name())
|
||||
}
|
||||
|
||||
// Implements json.Unmarshaler
|
||||
// UnmarshalJSON implements json.Unmarshaler
|
||||
func (bct *BacklogCacheType) UnmarshalJSON(data []byte) error {
|
||||
var str string
|
||||
err := json.Unmarshal(data, &str)
|
||||
|
@ -240,15 +238,15 @@ func MessageTargetTypeByName(name string) (mtt MessageTargetType) {
|
|||
return
|
||||
}
|
||||
|
||||
// Implements Stringer
|
||||
// String implements Stringer
|
||||
func (mtt MessageTargetType) String() string { return mtt.Name() }
|
||||
|
||||
// Implements json.Marshaler
|
||||
// MarshalJSON implements json.Marshaler
|
||||
func (mtt MessageTargetType) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(mtt.Name())
|
||||
}
|
||||
|
||||
// Implements json.Unmarshaler
|
||||
// UnmarshalJSON implements json.Unmarshaler
|
||||
func (mtt *MessageTargetType) UnmarshalJSON(data []byte) error {
|
||||
var str string
|
||||
err := json.Unmarshal(data, &str)
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
// uuidHash implements a hash for uuid.UUID by XORing the random bits.
|
||||
// UuidHash implements a hash for uuid.UUID by XORing the random bits.
|
||||
type UuidHash uuid.UUID
|
||||
|
||||
func (u UuidHash) Sum64() uint64 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue