Changeset 660 in code for trunk/downstream.go


Ignore:
Timestamp:
Nov 2, 2021, 5:25:43 PM (4 years ago)
Author:
contact
Message:

Add support for WHOX

This adds support for WHOX, without bothering about flags and mask2
because Solanum and Ergo [1] don't support it either.

The motivation is to allow clients to reliably query account names.

It's not possible to use WHOX tokens to route replies to the right
client, because RPL_ENDOFWHO doesn't contain it.

[1]: https://github.com/ergochat/ergo/pull/1184

Closes: https://todo.sr.ht/~emersion/soju/135

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/downstream.go

    r659 r660  
    237237        "USERLEN":       true,
    238238        "UTF8ONLY":      true,
     239        "WHOX":          true,
    239240}
    240241
     
    11561157        if dc.network != nil {
    11571158                isupport = append(isupport, fmt.Sprintf("BOUNCER_NETID=%v", dc.network.ID))
     1159        }
     1160
     1161        if dc.network == nil && dc.caps["soju.im/bouncer-networks"] {
     1162                isupport = append(isupport, "WHOX")
    11581163        }
    11591164
     
    18831888                        }
    18841889                }
     1890        // For WHOX docs, see:
     1891        // - http://faerion.sourceforge.net/doc/irc/whox.var
     1892        // - https://github.com/quakenet/snircd/blob/master/doc/readme.who
     1893        // Note, many features aren't widely implemented, such as flags and mask2
    18851894        case "WHO":
    18861895                if len(msg.Params) == 0 {
     
    18941903                }
    18951904
    1896                 // TODO: support WHO masks
    1897                 entity := msg.Params[0]
    1898                 entityCM := casemapASCII(entity)
    1899 
    1900                 if dc.network == nil && entityCM == dc.nickCM {
     1905                // Clients will use the first mask to match RPL_ENDOFWHO
     1906                endOfWhoToken := msg.Params[0]
     1907
     1908                // TODO: add support for WHOX mask2
     1909                mask := msg.Params[0]
     1910                var options string
     1911                if len(msg.Params) > 1 {
     1912                        options = msg.Params[1]
     1913                }
     1914
     1915                optionsParts := strings.SplitN(options, "%", 2)
     1916                // TODO: add support for WHOX flags in optionsParts[0]
     1917                var fields, whoxToken string
     1918                if len(optionsParts) == 2 {
     1919                        optionsParts := strings.SplitN(optionsParts[1], ",", 2)
     1920                        fields = strings.ToLower(optionsParts[0])
     1921                        if len(optionsParts) == 2 && strings.Contains(fields, "t") {
     1922                                whoxToken = optionsParts[1]
     1923                        }
     1924                }
     1925
     1926                // TODO: support mixed bouncer/upstream WHO queries
     1927                maskCM := casemapASCII(mask)
     1928                if dc.network == nil && maskCM == dc.nickCM {
    19011929                        // TODO: support AWAY (H/G) in self WHO reply
    19021930                        flags := "H"
     
    19041932                                flags += "*"
    19051933                        }
    1906                         dc.SendMessage(&irc.Message{
    1907                                 Prefix:  dc.srv.prefix(),
    1908                                 Command: irc.RPL_WHOREPLY,
    1909                                 Params:  []string{dc.nick, "*", dc.user.Username, dc.hostname, dc.srv.Hostname, dc.nick, flags, "0 " + dc.realname},
    1910                         })
     1934                        info := whoxInfo{
     1935                                Token:    whoxToken,
     1936                                Username: dc.user.Username,
     1937                                Hostname: dc.hostname,
     1938                                Server:   dc.srv.Hostname,
     1939                                Nickname: dc.nick,
     1940                                Flags:    flags,
     1941                                Realname: dc.realname,
     1942                        }
     1943                        dc.SendMessage(generateWHOXReply(dc.srv.prefix(), dc.nick, fields, &info))
    19111944                        dc.SendMessage(&irc.Message{
    19121945                                Prefix:  dc.srv.prefix(),
    19131946                                Command: irc.RPL_ENDOFWHO,
    1914                                 Params:  []string{dc.nick, dc.nick, "End of /WHO list"},
     1947                                Params:  []string{dc.nick, endOfWhoToken, "End of /WHO list"},
    19151948                        })
    19161949                        return nil
    19171950                }
    1918                 if entityCM == serviceNickCM {
    1919                         dc.SendMessage(&irc.Message{
    1920                                 Prefix:  dc.srv.prefix(),
    1921                                 Command: irc.RPL_WHOREPLY,
    1922                                 Params:  []string{serviceNick, "*", servicePrefix.User, servicePrefix.Host, dc.srv.Hostname, serviceNick, "H*", "0 " + serviceRealname},
    1923                         })
     1951                if maskCM == serviceNickCM {
     1952                        info := whoxInfo{
     1953                                Token:    whoxToken,
     1954                                Username: servicePrefix.User,
     1955                                Hostname: servicePrefix.Host,
     1956                                Server:   dc.srv.Hostname,
     1957                                Nickname: serviceNick,
     1958                                Flags:    "H*",
     1959                                Realname: serviceRealname,
     1960                        }
     1961                        dc.SendMessage(generateWHOXReply(dc.srv.prefix(), dc.nick, fields, &info))
    19241962                        dc.SendMessage(&irc.Message{
    19251963                                Prefix:  dc.srv.prefix(),
    19261964                                Command: irc.RPL_ENDOFWHO,
    1927                                 Params:  []string{dc.nick, serviceNick, "End of /WHO list"},
     1965                                Params:  []string{dc.nick, endOfWhoToken, "End of /WHO list"},
    19281966                        })
    19291967                        return nil
    19301968                }
    19311969
    1932                 uc, upstreamName, err := dc.unmarshalEntity(entity)
     1970                // TODO: properly support WHO masks
     1971                uc, upstreamMask, err := dc.unmarshalEntity(mask)
    19331972                if err != nil {
    19341973                        return err
    19351974                }
    19361975
    1937                 var params []string
    1938                 if len(msg.Params) == 2 {
    1939                         params = []string{upstreamName, msg.Params[1]}
    1940                 } else {
    1941                         params = []string{upstreamName}
     1976                params := []string{upstreamMask}
     1977                if options != "" {
     1978                        params = append(params, options)
    19421979                }
    19431980
Note: See TracChangeset for help on using the changeset viewer.