draft/resume-0.2 implementation, message history support

This commit is contained in:
Shivaram Lingamneni
2018-11-26 05:23:27 -05:00
parent 70364f5f67
commit a0bf548fc5
28 changed files with 1294 additions and 317 deletions
+17 -105
View File
@@ -430,6 +430,8 @@ func (server *Server) tryRegister(c *Client) {
// continue registration
server.logger.Debug("localconnect", fmt.Sprintf("Client connected [%s] [u:%s] [r:%s]", c.nick, c.username, c.realname))
server.snomasks.Send(sno.LocalConnects, fmt.Sprintf("Client connected [%s] [u:%s] [h:%s] [ip:%s] [r:%s]", c.nick, c.username, c.rawHostname, c.IPString(), c.realname))
// "register"; this includes the initial phase of session resumption
c.Register()
// send welcome text
@@ -455,41 +457,7 @@ func (server *Server) tryRegister(c *Client) {
}
// if resumed, send fake channel joins
if c.resumeDetails != nil {
for _, name := range c.resumeDetails.SendFakeJoinsFor {
channel := server.channels.Get(name)
if channel == nil {
continue
}
if c.capabilities.Has(caps.ExtendedJoin) {
c.Send(nil, c.nickMaskString, "JOIN", channel.name, c.AccountName(), c.realname)
} else {
c.Send(nil, c.nickMaskString, "JOIN", channel.name)
}
// reuse the last rb
channel.SendTopic(c, rb)
channel.Names(c, rb)
rb.Send()
// construct and send fake modestring if necessary
c.stateMutex.RLock()
myModes := channel.members[c]
c.stateMutex.RUnlock()
if myModes == nil {
continue
}
oldModes := myModes.String()
if 0 < len(oldModes) {
params := []string{channel.name, "+" + oldModes}
for range oldModes {
params = append(params, c.nick)
}
c.Send(nil, server.name, "MODE", params...)
}
}
}
c.tryResumeChannels()
}
// t returns the translated version of the given string, based on the languages configured by the client.
@@ -519,69 +487,6 @@ func (server *Server) MOTD(client *Client, rb *ResponseBuffer) {
rb.Add(nil, server.name, RPL_ENDOFMOTD, client.nick, client.t("End of MOTD command"))
}
// wordWrap wraps the given text into a series of lines that don't exceed lineWidth characters.
func wordWrap(text string, lineWidth int) []string {
var lines []string
var cacheLine, cacheWord string
for _, char := range text {
if char == '\r' {
continue
} else if char == '\n' {
cacheLine += cacheWord
lines = append(lines, cacheLine)
cacheWord = ""
cacheLine = ""
} else if (char == ' ' || char == '-') && len(cacheLine)+len(cacheWord)+1 < lineWidth {
// natural word boundary
cacheLine += cacheWord + string(char)
cacheWord = ""
} else if lineWidth <= len(cacheLine)+len(cacheWord)+1 {
// time to wrap to next line
if len(cacheLine) < (lineWidth / 2) {
// this word takes up more than half a line... just split in the middle of the word
cacheLine += cacheWord + string(char)
cacheWord = ""
} else {
cacheWord += string(char)
}
lines = append(lines, cacheLine)
cacheLine = ""
} else {
// normal character
cacheWord += string(char)
}
}
if 0 < len(cacheWord) {
cacheLine += cacheWord
}
if 0 < len(cacheLine) {
lines = append(lines, cacheLine)
}
return lines
}
// SplitMessage represents a message that's been split for sending.
type SplitMessage struct {
For512 []string
ForMaxLine string
}
func (server *Server) splitMessage(original string, origIs512 bool) SplitMessage {
var newSplit SplitMessage
newSplit.ForMaxLine = original
if !origIs512 {
newSplit.For512 = wordWrap(original, 400)
} else {
newSplit.For512 = []string{original}
}
return newSplit
}
// WhoisChannelsNames returns the common channel names between two users.
func (client *Client) WhoisChannelsNames(target *Client) []string {
isMultiPrefix := client.capabilities.Has(caps.MultiPrefix)
@@ -817,6 +722,20 @@ func (server *Server) applyConfig(config *Config, initial bool) (err error) {
updatedCaps.Add(caps.STS)
}
// resize history buffers as needed
if oldConfig != nil {
if oldConfig.History.ChannelLength != config.History.ChannelLength {
for _, channel := range server.channels.Channels() {
channel.history.Resize(config.History.ChannelLength)
}
}
if oldConfig.History.ClientLength != config.History.ClientLength {
for _, client := range server.clients.AllClients() {
client.history.Resize(config.History.ClientLength)
}
}
}
// burst new and removed caps
var capBurstClients ClientSet
added := make(map[caps.Version]string)
@@ -1107,13 +1026,6 @@ func (target *Client) RplList(channel *Channel, rb *ResponseBuffer) {
rb.Add(nil, target.server.name, RPL_LIST, target.nick, channel.name, strconv.Itoa(memberCount), channel.topic)
}
// ResumeDetails are the details that we use to resume connections.
type ResumeDetails struct {
OldNick string
Timestamp *time.Time
SendFakeJoinsFor []string
}
var (
infoString1 = strings.Split(` ▄▄▄ ▄▄▄· ▄▄ • ▐ ▄
▪ ▀▄ █·▐█ ▀█ ▐█ ▀ ▪▪ •█▌▐█▪