1
0
Fork 0
forked from External/ergo

Merge pull request #247 from slingamn/vhosts.3

initial vhosts implementation, #183
This commit is contained in:
Daniel Oaks 2018-05-19 08:51:16 +10:00 committed by GitHub
commit de7b679fc5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1069 additions and 375 deletions

View file

@ -46,7 +46,6 @@ type Client struct {
capVersion caps.Version
certfp string
channels ChannelSet
class *OperClass
ctime time.Time
exitedSnomaskSent bool
fakelag *Fakelag
@ -65,7 +64,7 @@ type Client struct {
nickMaskCasefolded string
nickMaskString string // cache for nickmask string since it's used with lots of replies
nickTimer *NickTimer
operName string
oper *Oper
preregNick string
proxiedIP net.IP // actual remote IP if using the PROXY protocol
quitMessage string
@ -81,7 +80,6 @@ type Client struct {
stateMutex sync.RWMutex // tier 1
username string
vhost string
whoisLine string
}
// NewClient returns a client with all the appropriate info setup.
@ -312,10 +310,6 @@ func (client *Client) Ping() {
}
//
// server goroutine
//
// Register sets the client details as appropriate when entering the network.
func (client *Client) Register() {
client.stateMutex.Lock()
@ -495,12 +489,13 @@ func (client *Client) HasUsername() bool {
// HasRoleCapabs returns true if client has the given (role) capabilities.
func (client *Client) HasRoleCapabs(capabs ...string) bool {
if client.class == nil {
oper := client.Oper()
if oper == nil {
return false
}
for _, capab := range capabs {
if !client.class.Capabilities[capab] {
if !oper.Class.Capabilities[capab] {
return false
}
}
@ -547,12 +542,45 @@ func (client *Client) Friends(capabs ...caps.Capability) ClientSet {
return friends
}
// XXX: CHGHOST requires prefix nickmask to have original hostname,
// this is annoying to do correctly
func (client *Client) sendChghost(oldNickMask string, vhost string) {
username := client.Username()
for fClient := range client.Friends(caps.ChgHost) {
fClient.sendFromClientInternal("", client, oldNickMask, nil, "CHGHOST", username, vhost)
}
}
// choose the correct vhost to display
func (client *Client) getVHostNoMutex() string {
// hostserv vhost OR operclass vhost OR nothing (i.e., normal rdns hostmask)
if client.vhost != "" {
return client.vhost
} else if client.oper != nil {
return client.oper.Vhost
} else {
return ""
}
}
// SetVHost updates the client's hostserv-based vhost
func (client *Client) SetVHost(vhost string) (updated bool) {
client.stateMutex.Lock()
defer client.stateMutex.Unlock()
updated = (client.vhost != vhost)
client.vhost = vhost
if updated {
client.updateNickMaskNoMutex()
}
return
}
// updateNick updates `nick` and `nickCasefolded`.
func (client *Client) updateNick(nick string) {
casefoldedName, err := CasefoldName(nick)
if err != nil {
log.Println(fmt.Sprintf("ERROR: Nick [%s] couldn't be casefolded... this should never happen. Printing stacktrace.", client.nick))
debug.PrintStack()
client.server.logger.Error("internal", "nick couldn't be casefolded", nick, err.Error())
return
}
client.stateMutex.Lock()
client.nick = nick
@ -573,19 +601,18 @@ func (client *Client) updateNickMask(nick string) {
client.updateNickMaskNoMutex()
}
// updateNickMask updates the casefolded nickname and nickmask, not holding any mutexes.
// updateNickMask updates the casefolded nickname and nickmask, not acquiring any mutexes.
func (client *Client) updateNickMaskNoMutex() {
if len(client.vhost) > 0 {
client.hostname = client.vhost
} else {
client.hostname = client.getVHostNoMutex()
if client.hostname == "" {
client.hostname = client.rawHostname
}
nickMaskString := fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.hostname)
nickMaskCasefolded, err := Casefold(nickMaskString)
if err != nil {
log.Println(fmt.Sprintf("ERROR: Nickmask [%s] couldn't be casefolded... this should never happen. Printing stacktrace.", client.nickMaskString))
debug.PrintStack()
client.server.logger.Error("internal", "nickmask couldn't be casefolded", nickMaskString, err.Error())
return
}
client.nickMaskString = nickMaskString
@ -598,19 +625,26 @@ func (client *Client) AllNickmasks() []string {
var mask string
var err error
if len(client.vhost) > 0 {
mask, err = Casefold(fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.vhost))
client.stateMutex.RLock()
nick := client.nick
username := client.username
rawHostname := client.rawHostname
vhost := client.getVHostNoMutex()
client.stateMutex.RUnlock()
if len(vhost) > 0 {
mask, err = Casefold(fmt.Sprintf("%s!%s@%s", nick, username, vhost))
if err == nil {
masks = append(masks, mask)
}
}
mask, err = Casefold(fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.rawHostname))
mask, err = Casefold(fmt.Sprintf("%s!%s@%s", nick, username, rawHostname))
if err == nil {
masks = append(masks, mask)
}
mask2, err := Casefold(fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.IPString()))
mask2, err := Casefold(fmt.Sprintf("%s!%s@%s", nick, username, client.IPString()))
if err == nil && mask2 != mask {
masks = append(masks, mask2)
}
@ -772,6 +806,12 @@ func (client *Client) SendSplitMsgFromClient(msgid string, from *Client, tags *m
// SendFromClient sends an IRC line coming from a specific client.
// Adds account-tag to the line as well.
func (client *Client) SendFromClient(msgid string, from *Client, tags *map[string]ircmsg.TagValue, command string, params ...string) error {
return client.sendFromClientInternal(msgid, from, from.NickMaskString(), tags, command, params...)
}
// XXX this is a hack where we allow overriding the client's nickmask
// this is to support CHGHOST, which requires that we send the *original* nickmask with the response
func (client *Client) sendFromClientInternal(msgid string, from *Client, nickmask string, tags *map[string]ircmsg.TagValue, command string, params ...string) error {
// attach account-tag
if client.capabilities.Has(caps.AccountTag) && from.LoggedIntoAccount() {
if tags == nil {
@ -789,7 +829,7 @@ func (client *Client) SendFromClient(msgid string, from *Client, tags *map[strin
}
}
return client.Send(tags, from.nickMaskString, command, params...)
return client.Send(tags, nickmask, command, params...)
}
var (