Changeset 532 in code for trunk/downstream.go
- Timestamp:
- May 25, 2021, 2:42:51 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/downstream.go
r529 r532 58 58 }} 59 59 60 func parseBouncerNetID(s string) (int64, error) { 61 id, err := strconv.ParseInt(s, 10, 64) 62 if err != nil { 63 return 0, ircError{&irc.Message{ 64 Command: "FAIL", 65 Params: []string{"BOUNCER", "INVALID_NETID", s, "Invalid network ID"}, 66 }} 67 } 68 return id, nil 69 } 70 60 71 // ' ' and ':' break the IRC message wire format, '@' and '!' break prefixes, 61 72 // '*' and '?' break masks … … 65 76 // capabilities. 66 77 var permanentDownstreamCaps = map[string]string{ 67 "batch": "", 68 "cap-notify": "", 69 "echo-message": "", 70 "invite-notify": "", 71 "message-tags": "", 72 "sasl": "PLAIN", 73 "server-time": "", 78 "batch": "", 79 "soju.im/bouncer-networks": "", 80 "cap-notify": "", 81 "echo-message": "", 82 "invite-notify": "", 83 "message-tags": "", 84 "sasl": "PLAIN", 85 "server-time": "", 74 86 } 75 87 … … 169 181 if dc.network != nil { 170 182 f(dc.network) 171 } else {183 } else if !dc.caps["soju.im/bouncer-networks"] { 172 184 dc.user.forEachNetwork(f) 173 185 } … … 175 187 176 188 func (dc *downstreamConn) forEachUpstream(f func(*upstreamConn)) { 189 if dc.network == nil && dc.caps["soju.im/bouncer-networks"] { 190 return 191 } 177 192 dc.user.forEachUpstream(func(uc *upstreamConn) { 178 193 if dc.network != nil && uc.network != dc.network { … … 558 573 }) 559 574 } 575 case "BOUNCER": 576 var subcommand string 577 if err := parseMessageParams(msg, &subcommand); err != nil { 578 return err 579 } 580 581 switch strings.ToUpper(subcommand) { 582 case "BIND": 583 var idStr string 584 if err := parseMessageParams(msg, nil, &idStr); err != nil { 585 return err 586 } 587 588 if dc.registered { 589 return ircError{&irc.Message{ 590 Command: "FAIL", 591 Params: []string{"BOUNCER", "REGISTRATION_IS_COMPLETED", "BIND", "Cannot bind bouncer network after registration"}, 592 }} 593 } 594 if dc.user == nil { 595 return ircError{&irc.Message{ 596 Command: "FAIL", 597 Params: []string{"BOUNCER", "ACCOUNT_REQUIRED", "BIND", "Authentication needed to bind to bouncer network"}, 598 }} 599 } 600 601 id, err := parseBouncerNetID(idStr) 602 if err != nil { 603 return err 604 } 605 606 var match *network 607 dc.user.forEachNetwork(func(net *network) { 608 if net.ID == id { 609 match = net 610 } 611 }) 612 if match == nil { 613 return ircError{&irc.Message{ 614 Command: "FAIL", 615 Params: []string{"BOUNCER", "INVALID_NETID", idStr, "Unknown network ID"}, 616 }} 617 } 618 619 dc.networkName = match.GetName() 620 } 560 621 default: 561 622 dc.logger.Printf("unhandled message: %v", msg) … … 910 971 fmt.Sprintf("CHATHISTORY=%v", dc.srv.HistoryLimit), 911 972 "CASEMAPPING=ascii", 973 } 974 975 if dc.network != nil { 976 isupport = append(isupport, fmt.Sprintf("BOUNCER_NETID=%v", dc.network.ID)) 912 977 } 913 978 … … 1907 1972 Params: []string{"-" + batchRef}, 1908 1973 }) 1974 case "BOUNCER": 1975 var subcommand string 1976 if err := parseMessageParams(msg, &subcommand); err != nil { 1977 return err 1978 } 1979 1980 switch strings.ToUpper(subcommand) { 1981 case "LISTNETWORKS": 1982 dc.SendMessage(&irc.Message{ 1983 Prefix: dc.srv.prefix(), 1984 Command: "BATCH", 1985 Params: []string{"+networks", "bouncer-networks"}, 1986 }) 1987 dc.user.forEachNetwork(func(network *network) { 1988 id := fmt.Sprintf("%v", network.ID) 1989 1990 state := "disconnected" 1991 if uc := network.conn; uc != nil { 1992 state = "connected" 1993 } 1994 1995 attrs := irc.Tags{ 1996 "name": irc.TagValue(network.GetName()), 1997 "state": irc.TagValue(state), 1998 } 1999 2000 dc.SendMessage(&irc.Message{ 2001 Tags: irc.Tags{"batch": irc.TagValue("networks")}, 2002 Prefix: dc.srv.prefix(), 2003 Command: "BOUNCER", 2004 Params: []string{"NETWORK", id, attrs.String()}, 2005 }) 2006 }) 2007 dc.SendMessage(&irc.Message{ 2008 Prefix: dc.srv.prefix(), 2009 Command: "BATCH", 2010 Params: []string{"-networks"}, 2011 }) 2012 case "ADDNETWORK": 2013 var attrsStr string 2014 if err := parseMessageParams(msg, nil, &attrsStr); err != nil { 2015 return err 2016 } 2017 attrs := irc.ParseTags(attrsStr) 2018 2019 host, ok := attrs.GetTag("host") 2020 if !ok { 2021 return ircError{&irc.Message{ 2022 Command: "FAIL", 2023 Params: []string{"BOUNCER", "NEED_ATTRIBUTE", subcommand, "host", "Missing required host attribute"}, 2024 }} 2025 } 2026 2027 addr := host 2028 if port, ok := attrs.GetTag("port"); ok { 2029 addr += ":" + port 2030 } 2031 2032 if tlsStr, ok := attrs.GetTag("tls"); ok && tlsStr == "0" { 2033 addr = "irc+insecure://" + tlsStr 2034 } 2035 2036 nick, ok := attrs.GetTag("nickname") 2037 if !ok { 2038 nick = dc.nick 2039 } 2040 2041 username, _ := attrs.GetTag("username") 2042 realname, _ := attrs.GetTag("realname") 2043 2044 // TODO: reject unknown attributes 2045 2046 record := &Network{ 2047 Addr: addr, 2048 Nick: nick, 2049 Username: username, 2050 Realname: realname, 2051 } 2052 network, err := dc.user.createNetwork(record) 2053 if err != nil { 2054 return ircError{&irc.Message{ 2055 Command: "FAIL", 2056 Params: []string{"BOUNCER", "UNKNOWN_ERROR", subcommand, fmt.Sprintf("Failed to create network: %v", err)}, 2057 }} 2058 } 2059 2060 dc.SendMessage(&irc.Message{ 2061 Prefix: dc.srv.prefix(), 2062 Command: "BOUNCER", 2063 Params: []string{"ADDNETWORK", fmt.Sprintf("%v", network.ID)}, 2064 }) 2065 case "CHANGENETWORK": 2066 var idStr, attrsStr string 2067 if err := parseMessageParams(msg, nil, &idStr, &attrsStr); err != nil { 2068 return err 2069 } 2070 id, err := parseBouncerNetID(idStr) 2071 if err != nil { 2072 return err 2073 } 2074 attrs := irc.ParseTags(attrsStr) 2075 2076 net := dc.user.getNetworkByID(id) 2077 if net == nil { 2078 return ircError{&irc.Message{ 2079 Command: "FAIL", 2080 Params: []string{"BOUNCER", "INVALID_NETID", idStr, "Invalid network ID"}, 2081 }} 2082 } 2083 2084 record := net.Network // copy network record because we'll mutate it 2085 for k, v := range attrs { 2086 s := string(v) 2087 switch k { 2088 // TODO: host, port, tls 2089 case "nickname": 2090 record.Nick = s 2091 case "username": 2092 record.Username = s 2093 case "realname": 2094 record.Realname = s 2095 default: 2096 return ircError{&irc.Message{ 2097 Command: "FAIL", 2098 Params: []string{"BOUNCER", "UNKNOWN_ATTRIBUTE", subcommand, k, "Unknown attribute"}, 2099 }} 2100 } 2101 } 2102 2103 _, err = dc.user.updateNetwork(&record) 2104 if err != nil { 2105 return ircError{&irc.Message{ 2106 Command: "FAIL", 2107 Params: []string{"BOUNCER", "UNKNOWN_ERROR", subcommand, fmt.Sprintf("Failed to update network: %v", err)}, 2108 }} 2109 } 2110 2111 dc.SendMessage(&irc.Message{ 2112 Prefix: dc.srv.prefix(), 2113 Command: "BOUNCER", 2114 Params: []string{"CHANGENETWORK", idStr}, 2115 }) 2116 case "DELNETWORK": 2117 var idStr string 2118 if err := parseMessageParams(msg, nil, &idStr); err != nil { 2119 return err 2120 } 2121 id, err := parseBouncerNetID(idStr) 2122 if err != nil { 2123 return err 2124 } 2125 2126 net := dc.user.getNetworkByID(id) 2127 if net == nil { 2128 return ircError{&irc.Message{ 2129 Command: "FAIL", 2130 Params: []string{"BOUNCER", "INVALID_NETID", idStr, "Invalid network ID"}, 2131 }} 2132 } 2133 2134 if err := dc.user.deleteNetwork(net.ID); err != nil { 2135 return err 2136 } 2137 2138 dc.SendMessage(&irc.Message{ 2139 Prefix: dc.srv.prefix(), 2140 Command: "BOUNCER", 2141 Params: []string{"DELNETWORK", idStr}, 2142 }) 2143 default: 2144 return ircError{&irc.Message{ 2145 Command: "FAIL", 2146 Params: []string{"BOUNCER", "UNKNOWN_COMMAND", subcommand, "Unknown subcommand"}, 2147 }} 2148 } 1909 2149 default: 1910 2150 dc.logger.Printf("unhandled message: %v", msg)
Note:
See TracChangeset
for help on using the changeset viewer.