WIP on config parser before attempting to learn FSMs

This commit is contained in:
Alex Bramley 2010-11-27 14:12:12 +00:00
parent b3f98e762e
commit 377fbcd3af
4 changed files with 142 additions and 24 deletions

View File

@ -6,11 +6,19 @@ port 6697 { ssl = true }
port 7011 { port 7011 {
ssl = true ssl = true
class = "server" class = "server"
bind_ip = "87.237.63.85"
} }
oper fluffle { oper fluffle {
pass = "foobar" password = "foobar"
hostmask = "*camelid@*" hostmask = "*camelid@*"
link = true link = true
} }
oper "bb101" {
password = "dongs"
hostmask = "*bb10@*.enta.net"
hostmask = "*bb@*.dongs.com"
renick = true
}

View File

@ -36,7 +36,7 @@ type keywordMap map[string]func(*Config, interface{})
var configKeywords = configMap{ var configKeywords = configMap{
"port": (*Config).parsePort, "port": (*Config).parsePort,
// "oper": (*Config).parseOper, "oper": (*Config).parseOper,
// "link": (*Config).parseLink, // "link": (*Config).parseLink,
// "ban": (*Config).parseBan, // "ban": (*Config).parseBan,
// "info": (*Config).parseInfo, // "info": (*Config).parseInfo,
@ -142,6 +142,15 @@ func (conf *Config) expectInt() (int, bool) {
return num, true return num, true
} }
func (conf *Config) expectString() (string, bool) {
tok, text := conf.next()
if tok != scanner.String && tok != scanner.Ident {
conf.parseError("Expected string, got '%s'", text)
return "", false
}
return text, true
}
func (conf *Config) expect(str string) bool { func (conf *Config) expect(str string) bool {
_, text := conf.next() _, text := conf.next()
if text != str { if text != str {

View File

@ -1,16 +1,106 @@
package config package config
import (
"fmt"
"strings"
"scanner"
)
type cOper struct { type cOper struct {
Username, Password string Username, Password string
HostMask []string HostMask []string
// Permissions for oper // Permissions for oper
CanKill, CanBan, CanNick, CanLink bool CanKill, CanBan, CanRenick, CanLink bool
} }
var cOperDefaults = &cOper{ var operKeywords = keywordMap{
HostMask: []string{"*@*"}, "password": (*Config).parseOperPassword,
CanKill: true, CanBan: true, "hostmask": (*Config).parseOperHostMask,
CanNick: false, CanLink: false, "kill": (*Config).parseOperKill,
"ban": (*Config).parseOperBan,
"renick": (*Config).parseOperRenick,
"link": (*Config).parseOperLink,
} }
func defaultOper() *cOper {
return &cOper{
HostMask: []string{},
CanKill: true, CanBan: true,
CanRenick: false, CanLink: false,
}
}
func (o *cOper) String() string {
str := []string{fmt.Sprintf("oper \"%s\" {", o.Username)}
str = append(str, fmt.Sprintf("\tpassword = \"%s\"", o.Password))
if len(o.HostMask) == 0 {
str = append(str, fmt.Sprintf("\thostmask = \"*@*\""))
} else {
for _, h := range o.HostMask {
str = append(str, fmt.Sprintf("\thostmask = \"%s\"", h))
}
}
str = append(str,
fmt.Sprintf("\tkill = %t", o.CanKill),
fmt.Sprintf("\tban = %t", o.CanBan),
fmt.Sprintf("\trenick = %t", o.CanRenick),
fmt.Sprintf("\tlink = %t", o.CanLink),
"}",
)
return strings.Join(str, "\n")
}
func (conf *Config) parseOper() {
oper := defaultOper()
tok, text := conf.next()
if tok != scanner.String && tok != scanner.Ident {
conf.parseError("Invalid username '%s'", text)
return
}
oper.Username = text
conf.parseKwBlock(oper, "oper", operKeywords)
fmt.Println(oper.String())
}
func (conf *Config) parseOperPassword(oi interface{}) {
oper := oi.(*cOper)
if pass, ok := conf.expectString(); ok {
oper.Password = pass
}
}
func (conf *Config) parseOperHostMask(oi interface{}) {
oper := oi.(*cOper)
if mask, ok := conf.expectString(); ok {
oper.HostMask = append(oper.HostMask, mask)
}
}
func (conf *Config) parseOperKill(oi interface{}) {
oper := oi.(*cOper)
if kill, ok := conf.expectBool(); ok {
oper.CanKill = kill
}
}
func (conf *Config) parseOperBan(oi interface{}) {
oper := oi.(*cOper)
if ban, ok := conf.expectBool(); ok {
oper.CanBan = ban
}
}
func (conf *Config) parseOperRenick(oi interface{}) {
oper := oi.(*cOper)
if renick, ok := conf.expectBool(); ok {
oper.CanRenick = renick
}
}
func (conf *Config) parseOperLink(oi interface{}) {
oper := oi.(*cOper)
if link, ok := conf.expectBool(); ok {
oper.CanLink = link
}
}

View File

@ -1,6 +1,7 @@
package config package config
import ( import (
"net"
"fmt" "fmt"
"strings" "strings"
"scanner" "scanner"
@ -8,40 +9,34 @@ import (
type cPort struct { type cPort struct {
Port int Port int
BindIP, Family, Class string BindIP net.IP // bind to a specific IP for listen port
Class string // "server" or "client"
// Is port a tls.Listener? Does it support compression (no)? // Is port a tls.Listener? Does it support compression (no)?
SSL, Zip bool SSL, Zip bool
// address == "<BindIP>:<Port>"
address string
} }
var portKeywords = keywordMap{ var portKeywords = keywordMap{
// "bind_ip": (*Config).parsePortBindIP, "bind_ip": (*Config).parsePortBindIP,
// "family": (*Config).parsePortFamily,
"class": (*Config).parsePortClass, "class": (*Config).parsePortClass,
"ssl": (*Config).parsePortSSL, "ssl": (*Config).parsePortSSL,
// "zip": (*Config).parsePortZip, "zip": (*Config).parsePortZip,
}
var cPortDefaults = cPort{
BindIP: "", Family: "tcp", Class: "client",
SSL: false, Zip: false,
} }
func defaultPort() *cPort { func defaultPort() *cPort {
p := cPortDefaults return &cPort{
return &p BindIP: nil, Class: "client",
SSL: false, Zip: false,
}
} }
func (p *cPort) String() string { func (p *cPort) String() string {
str := []string{fmt.Sprintf("port %d {", p.Port)} str := []string{fmt.Sprintf("port %d {", p.Port)}
if p.BindIP != "" { if p.BindIP != nil {
str = append(str, "\tbind_ip = " + p.BindIP) str = append(str,
fmt.Sprintf("\tbind_ip = \"%s\"", p.BindIP.String()))
} }
str = append(str, str = append(str,
fmt.Sprintf("\tfamily = \"%s\"",p.Family),
fmt.Sprintf("\tclass = \"%s\"", p.Class), fmt.Sprintf("\tclass = \"%s\"", p.Class),
fmt.Sprintf("\tssl = %t", p.SSL), fmt.Sprintf("\tssl = %t", p.SSL),
fmt.Sprintf("\tzip = %t", p.Zip), fmt.Sprintf("\tzip = %t", p.Zip),
@ -66,6 +61,16 @@ func (conf *Config) parsePort() {
fmt.Println(port.String()) fmt.Println(port.String())
} }
func (conf *Config) parsePortBindIP(pi interface{}) {
port := pi.(*cPort)
_, text := conf.next()
if ip := net.ParseIP(text); ip != nil {
port.BindIP = ip
} else {
conf.parseError("'%s' is not a valid IP address", text)
}
}
func (conf *Config) parsePortClass(pi interface{}) { func (conf *Config) parsePortClass(pi interface{}) {
port := pi.(*cPort) port := pi.(*cPort)
tok, text := conf.next() tok, text := conf.next()
@ -84,3 +89,9 @@ func (conf *Config) parsePortSSL(pi interface{}) {
} }
} }
func (conf *Config) parsePortZip(pi interface{}) {
port := pi.(*cPort)
if zip, ok := conf.expectBool(); ok {
port.Zip = zip
}
}