3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-12-22 10:42:52 +01:00

add client compatibility switches

This commit is contained in:
Shivaram Lingamneni 2019-05-09 14:18:30 -04:00
parent 939729a7c0
commit fbc6c84a01
6 changed files with 54 additions and 17 deletions

View File

@ -1085,7 +1085,8 @@ var (
func (session *Session) SendRawMessage(message ircmsg.IrcMessage, blocking bool) error { func (session *Session) SendRawMessage(message ircmsg.IrcMessage, blocking bool) error {
// use dumb hack to force the last param to be a trailing param if required // use dumb hack to force the last param to be a trailing param if required
var usedTrailingHack bool var usedTrailingHack bool
if commandsThatMustUseTrailing[message.Command] && len(message.Params) > 0 { config := session.client.server.Config()
if config.Server.Compatibility.forceTrailing && commandsThatMustUseTrailing[message.Command] && len(message.Params) > 0 {
lastParam := message.Params[len(message.Params)-1] lastParam := message.Params[len(message.Params)-1]
// to force trailing, we ensure the final param contains a space // to force trailing, we ensure the final param contains a space
if strings.IndexByte(lastParam, ' ') == -1 { if strings.IndexByte(lastParam, ' ') == -1 {

View File

@ -286,9 +286,14 @@ type Config struct {
WebIRC []webircConfig `yaml:"webirc"` WebIRC []webircConfig `yaml:"webirc"`
MaxSendQString string `yaml:"max-sendq"` MaxSendQString string `yaml:"max-sendq"`
MaxSendQBytes int MaxSendQBytes int
AllowPlaintextResume bool `yaml:"allow-plaintext-resume"` AllowPlaintextResume bool `yaml:"allow-plaintext-resume"`
ConnectionLimiter connection_limits.LimiterConfig `yaml:"connection-limits"` Compatibility struct {
ConnectionThrottler connection_limits.ThrottlerConfig `yaml:"connection-throttling"` ForceTrailing *bool `yaml:"force-trailing"`
forceTrailing bool
SendUnprefixedSasl bool `yaml:"send-unprefixed-sasl"`
}
ConnectionLimiter connection_limits.LimiterConfig `yaml:"connection-limits"`
ConnectionThrottler connection_limits.ThrottlerConfig `yaml:"connection-throttling"`
} }
Languages struct { Languages struct {
@ -698,6 +703,13 @@ func LoadConfig(filename string) (config *Config, err error) {
config.Channels.Registration.MaxChannelsPerAccount = 15 config.Channels.Registration.MaxChannelsPerAccount = 15
} }
forceTrailingPtr := config.Server.Compatibility.ForceTrailing
if forceTrailingPtr != nil {
config.Server.Compatibility.forceTrailing = *forceTrailingPtr
} else {
config.Server.Compatibility.forceTrailing = true
}
// in the current implementation, we disable history by creating a history buffer // in the current implementation, we disable history by creating a history buffer
// with zero capacity. but the `enabled` config option MUST be respected regardless // with zero capacity. but the `enabled` config option MUST be respected regardless
// of this detail // of this detail

View File

@ -4,7 +4,9 @@
package irc package irc
import ( import (
"sync/atomic"
"time" "time"
"unsafe"
"github.com/oragono/oragono/irc/isupport" "github.com/oragono/oragono/irc/isupport"
"github.com/oragono/oragono/irc/languages" "github.com/oragono/oragono/irc/languages"
@ -12,10 +14,11 @@ import (
) )
func (server *Server) Config() (config *Config) { func (server *Server) Config() (config *Config) {
server.configurableStateMutex.RLock() return (*Config)(atomic.LoadPointer(&server.config))
config = server.config }
server.configurableStateMutex.RUnlock()
return func (server *Server) SetConfig(config *Config) {
atomic.StorePointer(&server.config, unsafe.Pointer(config))
} }
func (server *Server) ISupport() *isupport.List { func (server *Server) ISupport() *isupport.List {
@ -53,9 +56,7 @@ func (server *Server) GetOperator(name string) (oper *Oper) {
if err != nil { if err != nil {
return return
} }
server.configurableStateMutex.RLock() return server.Config().operators[name]
defer server.configurableStateMutex.RUnlock()
return server.config.operators[name]
} }
func (server *Server) Languages() (lm *languages.Manager) { func (server *Server) Languages() (lm *languages.Manager) {

View File

@ -298,7 +298,9 @@ func accVerifyHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb
// AUTHENTICATE [<mechanism>|<data>|*] // AUTHENTICATE [<mechanism>|<data>|*]
func authenticateHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool { func authenticateHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
config := server.Config()
details := client.Details() details := client.Details()
if details.account != "" { if details.account != "" {
rb.Add(nil, server.name, ERR_SASLALREADY, details.nick, client.t("You're already logged into an account")) rb.Add(nil, server.name, ERR_SASLALREADY, details.nick, client.t("You're already logged into an account"))
return false return false
@ -321,7 +323,14 @@ func authenticateHandler(server *Server, client *Client, msg ircmsg.IrcMessage,
if mechanismIsEnabled { if mechanismIsEnabled {
client.saslInProgress = true client.saslInProgress = true
client.saslMechanism = mechanism client.saslMechanism = mechanism
rb.Add(nil, server.name, "AUTHENTICATE", "+") if !config.Server.Compatibility.SendUnprefixedSasl {
// normal behavior
rb.Add(nil, server.name, "AUTHENTICATE", "+")
} else {
// gross hack: send a raw message to ensure no tags or prefix
rb.Flush(true)
rb.session.SendRawMessage(ircmsg.MakeMessage(nil, "", "AUTHENTICATE", "+"), true)
}
} else { } else {
rb.Add(nil, server.name, ERR_SASLFAIL, details.nick, client.t("SASL authentication failed")) rb.Add(nil, server.name, ERR_SASLFAIL, details.nick, client.t("SASL authentication failed"))
} }

View File

@ -19,6 +19,7 @@ import (
"sync" "sync"
"syscall" "syscall"
"time" "time"
"unsafe"
"github.com/goshuirc/irc-go/ircfmt" "github.com/goshuirc/irc-go/ircfmt"
"github.com/oragono/oragono/irc/caps" "github.com/oragono/oragono/irc/caps"
@ -65,7 +66,7 @@ type Server struct {
channels ChannelManager channels ChannelManager
channelRegistry ChannelRegistry channelRegistry ChannelRegistry
clients ClientManager clients ClientManager
config *Config config unsafe.Pointer
configFilename string configFilename string
configurableStateMutex sync.RWMutex // tier 1; generic protection for server state modified by rehash() configurableStateMutex sync.RWMutex // tier 1; generic protection for server state modified by rehash()
connectionLimiter *connection_limits.Limiter connectionLimiter *connection_limits.Limiter
@ -602,7 +603,7 @@ func (server *Server) applyConfig(config *Config, initial bool) (err error) {
return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted") return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted")
} else if server.name != config.Server.Name { } else if server.name != config.Server.Name {
return fmt.Errorf("Server name cannot be changed after launching the server, rehash aborted") return fmt.Errorf("Server name cannot be changed after launching the server, rehash aborted")
} else if server.config.Datastore.Path != config.Datastore.Path { } else if server.Config().Datastore.Path != config.Datastore.Path {
return fmt.Errorf("Datastore path cannot be changed after launching the server, rehash aborted") return fmt.Errorf("Datastore path cannot be changed after launching the server, rehash aborted")
} }
} }
@ -776,9 +777,7 @@ func (server *Server) applyConfig(config *Config, initial bool) (err error) {
server.loadMOTD(config.Server.MOTD, config.Server.MOTDFormatting) server.loadMOTD(config.Server.MOTD, config.Server.MOTDFormatting)
// save a pointer to the new config // save a pointer to the new config
server.configurableStateMutex.Lock() server.SetConfig(config)
server.config = config
server.configurableStateMutex.Unlock()
server.logger.Info("server", "Using datastore", config.Datastore.Path) server.logger.Info("server", "Using datastore", config.Datastore.Path)
if initial { if initial {

View File

@ -125,6 +125,21 @@ server:
# this should be big enough to hold bursts of channel/direct messages # this should be big enough to hold bursts of channel/direct messages
max-sendq: 16k max-sendq: 16k
# compatibility with legacy clients
compatibility:
# many clients require that the final parameter of certain messages be an
# RFC1459 trailing parameter, i.e., prefixed with :, whether or not this is
# actually required. this forces Oragono to send those parameters
# as trailings. this is recommended unless you're testing clients for conformance;
# defaults to true when unset for that reason.
force-trailing: true
# some clients (ZNC 1.6.x and lower, Pidgin 2.12 and lower, Adium) do not
# respond correctly to SASL messages with the server name as a prefix:
# https://github.com/znc/znc/issues/1212
# this works around that bug, allowing them to use SASL.
send-unprefixed-sasl: true
# maximum number of connections per subnet # maximum number of connections per subnet
connection-limits: connection-limits:
# whether to enforce connection limits or not # whether to enforce connection limits or not