hid: bringup of what we have this far

This commit is contained in:
Přemysl Eric Janouch 2018-07-31 21:13:30 +02:00
parent b103d5e2eb
commit 33969ac86e
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 36 additions and 24 deletions

View File

@ -421,7 +421,7 @@ func ircFnmatch(pattern string, s string) bool {
} }
var reMsg = regexp.MustCompile( var reMsg = regexp.MustCompile(
`^(?:@[^ ]* +)(?::([^! ]*)(?:!([^@]*)@([^ ]*))? +)?([^ ]+)(.*)?$`) `^(@[^ ]* +)?(?::([^! ]*)(?:!([^@]*)@([^ ]*))? +)?([^ ]+)(.*)?$`)
var reArgs = regexp.MustCompile(`:.*| [^: ][^ ]*`) var reArgs = regexp.MustCompile(`:.*| [^: ][^ ]*`)
type message struct { type message struct {
@ -514,7 +514,7 @@ var (
// behaviour seems to be unstated in the documentation. // behaviour seems to be unstated in the documentation.
reUsername = regexp.MustCompile(`^[^\0\r\n @]+$`) reUsername = regexp.MustCompile(`^[^\0\r\n @]+$`)
reChannelName = regexp.MustCompile(`^[^\0\7\r\n ,:]+$`) reChannelName = regexp.MustCompile(`^[^\0\007\r\n ,:]+$`)
reKey = regexp.MustCompile(`^[^\r\n\f\t\v ]{1,23}$`) reKey = regexp.MustCompile(`^[^\r\n\f\t\v ]{1,23}$`)
reUserMask = regexp.MustCompile(`^[^!@]+![^!@]+@[^@!]+$`) reUserMask = regexp.MustCompile(`^[^!@]+![^!@]+@[^@!]+$`)
reFingerprint = regexp.MustCompile(`^[a-fA-F0-9]{64}$`) reFingerprint = regexp.MustCompile(`^[a-fA-F0-9]{64}$`)
@ -754,17 +754,16 @@ type writeEvent struct {
var ( var (
started time.Time // when has the server been started started time.Time // when has the server been started
users map[string]*client // maps nicknames to clients users = make(map[string]*client) // maps nicknames to clients
channels map[string]*channel // maps channel names to data channels = make(map[string]*channel) // maps channel names to data
whowas = make(map[string]*whowasInfo) // WHOWAS registry
whowas map[string]*whowasInfo // WHOWAS registry config simpleConfig // server configuration
serverName string // our server name
config simpleConfig // server configuration pingInterval uint // ping interval in seconds
serverName string // our server name maxConnections int // max connections allowed or 0
pingInterval uint // ping interval in seconds motd []string // MOTD (none if empty)
maxConnections int // max connections allowed or 0 operators = make(map[string]bool) // TLS cert. fingerprints for IRCops
motd []string // MOTD (none if empty)
operators map[string]bool // TLS certificate fingerprints for IRCops
) )
var ( var (
@ -814,8 +813,9 @@ func initiateQuit() {
func ircChannelCreate(name string) *channel { func ircChannelCreate(name string) *channel {
ch := &channel{ ch := &channel{
name: name, name: name,
created: time.Now(),
userLimit: -1, userLimit: -1,
created: time.Now(),
userModes: make(map[*client]uint),
} }
channels[ircToCanon(name)] = ch channels[ircToCanon(name)] = ch
return ch return ch
@ -1046,10 +1046,15 @@ func (c *client) sendReplyVector(id int, items []string, args ...interface{}) {
// We always send at least one message (there might be a client that // We always send at least one message (there might be a client that
// expects us to send this message at least once). // expects us to send this message at least once).
if len(items) == 0 {
items = append(items, "")
}
for len(items) > 0 { for len(items) > 0 {
// If not even a single item fits in the limit (which may happen, // If not even a single item fits in the limit (which may happen,
// in theory) it just gets cropped. We could also skip it. // in theory) it just gets cropped. We could also skip it.
reply := append([]byte(common), items[0]...) reply := append([]byte(common), items[0]...)
items = items[1:]
// Append as many items as fits in a single message. // Append as many items as fits in a single message.
for len(items) > 0 && for len(items) > 0 &&
@ -1120,10 +1125,10 @@ func isThisMe(target string) bool {
} }
func (c *client) sendISUPPORT() { func (c *client) sendISUPPORT() {
// Only # channels, +e supported, +I supported, unlimited arguments to MODE // Only # channels, +e supported, +I supported, unlimited arguments to MODE.
c.sendReply(RPL_ISUPPORT, "CHANTYPES=# EXCEPTS INVEX MODES"+ c.sendReply(RPL_ISUPPORT, fmt.Sprintf("CHANTYPES=# EXCEPTS INVEX MODES"+
" TARGMAX=WHOIS:,LIST:,NAMES:,PRIVMSG:1,NOTICE:1,KICK:"+ " TARGMAX=WHOIS:,LIST:,NAMES:,PRIVMSG:1,NOTICE:1,KICK:"+
" NICKLEN=%d CHANNELLEN=%d", ircMaxNickname, ircMaxChannelName) " NICKLEN=%d CHANNELLEN=%d", ircMaxNickname, ircMaxChannelName))
} }
func (c *client) tryFinishRegistration() { func (c *client) tryFinishRegistration() {
@ -2170,8 +2175,7 @@ func ircSendWHOISReply(c, target *client) {
nick := target.nickname nick := target.nickname
c.sendReply(RPL_WHOISUSER, nick, c.sendReply(RPL_WHOISUSER, nick,
target.username, target.hostname, target.realname) target.username, target.hostname, target.realname)
c.sendReply(RPL_WHOISSERVER, nick, c.sendReply(RPL_WHOISSERVER, nick, serverName, config["server_info"])
serverName, "TODO server_info from configuration")
if 0 != target.mode&ircUserModeOperator { if 0 != target.mode&ircUserModeOperator {
c.sendReply(RPL_WHOISOPERATOR, nick) c.sendReply(RPL_WHOISOPERATOR, nick)
} }
@ -2257,7 +2261,7 @@ func ircHandleWHOWAS(msg *message, c *client) {
c.sendReply(RPL_WHOWASUSER, nick, c.sendReply(RPL_WHOWASUSER, nick,
info.username, info.hostname, info.realname) info.username, info.hostname, info.realname)
c.sendReply(RPL_WHOISSERVER, nick, c.sendReply(RPL_WHOISSERVER, nick,
serverName, "TODO server_info from configuration") serverName, config["server_info"])
} }
c.sendReply(RPL_ENDOFWHOWAS, nick) c.sendReply(RPL_ENDOFWHOWAS, nick)
} }
@ -2689,7 +2693,7 @@ func ircHandleLINKS(msg *message, c *client) {
if ircFnmatch(mask, serverName) { if ircFnmatch(mask, serverName) {
c.sendReply(RPL_LINKS, mask, serverName, c.sendReply(RPL_LINKS, mask, serverName,
0 /* hop count */, "TODO server_info from configuration") 0 /* hop count */, config["server_info"])
} }
c.sendReply(RPL_ENDOFLINKS, mask) c.sendReply(RPL_ENDOFLINKS, mask)
} }
@ -2799,11 +2803,16 @@ func ircProcessMessage(c *client, msg *message, raw string) {
// Handle the results from initializing the client's connection. // Handle the results from initializing the client's connection.
func (c *client) onPrepared(host string, isTLS bool) { func (c *client) onPrepared(host string, isTLS bool) {
if isTLS { if !isTLS {
c.conn = c.transport.(connCloseWrite)
} else if tlsConf != nil {
c.tls = tls.Server(c.transport, tlsConf) c.tls = tls.Server(c.transport, tlsConf)
c.conn = c.tls c.conn = c.tls
} else { } else {
c.conn = c.transport.(connCloseWrite) log.Printf("could not initialize TLS for %s: TLS support disabled\n",
c.address)
c.kill("TLS support disabled")
return
} }
c.hostname = host c.hostname = host
@ -2949,7 +2958,7 @@ func prepare(client *client) {
// This is just for the TLS detection and doesn't need to be fatal. // This is just for the TLS detection and doesn't need to be fatal.
log.Println(err) log.Println(err)
} else { } else {
isTLS = tlsConf != nil && detectTLS(sysconn) isTLS = detectTLS(sysconn)
} }
// FIXME: When the client sends no data, we still initialize its conn. // FIXME: When the client sends no data, we still initialize its conn.
@ -2993,7 +3002,7 @@ func processOneEvent() {
forceQuit("timeout") forceQuit("timeout")
case conn := <-conns: case conn := <-conns:
if len(clients) >= maxConnections { if maxConnections > 0 && len(clients) >= maxConnections {
log.Println("connection limit reached, refusing connection") log.Println("connection limit reached, refusing connection")
conn.Close() conn.Close()
break break
@ -3014,6 +3023,8 @@ func processOneEvent() {
hostname: host, hostname: host,
port: port, port: port,
capVersion: 301, capVersion: 301,
opened: time.Now(),
lastActive: time.Now(),
// TODO: Make this configurable and more fine-grained. // TODO: Make this configurable and more fine-grained.
antiflood: newFloodDetector(10*time.Second, 20), antiflood: newFloodDetector(10*time.Second, 20),
} }
@ -3223,6 +3234,7 @@ func main() {
} }
config = make(simpleConfig) config = make(simpleConfig)
config.loadDefaults(configTable)
if err := config.updateFromFile(); err != nil && !os.IsNotExist(err) { if err := config.updateFromFile(); err != nil && !os.IsNotExist(err) {
log.Println("error loading configuration", err) log.Println("error loading configuration", err)
os.Exit(1) os.Exit(1)