mirror of
https://github.com/fluffle/goirc
synced 2025-05-12 18:44:50 +00:00
Initial commit of vague hackery for a go IRCd.
This commit is contained in:
parent
83e1f9ca74
commit
b2539c0063
22 changed files with 1104 additions and 0 deletions
17
server/config/Makefile
Normal file
17
server/config/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include $(GOROOT)/src/Make.inc
|
||||
|
||||
TARG=irc/server/config
|
||||
GOFILES=\
|
||||
config.go\
|
||||
port.go\
|
||||
oper.go\
|
||||
link.go\
|
||||
ban.go\
|
||||
info.go\
|
||||
settings.go\
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
33
server/config/ban.go
Normal file
33
server/config/ban.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package config
|
||||
|
||||
type cBan interface {
|
||||
Match(string) bool
|
||||
Reason() string
|
||||
}
|
||||
|
||||
// G-Line etc;
|
||||
type cBanNick struct {
|
||||
NickMask string // nick!ident@host
|
||||
Reason string
|
||||
}
|
||||
|
||||
// Z-Line
|
||||
type cBanIP struct {
|
||||
Address string // ip (or hostname), plus optional CIDR netmask
|
||||
Reason string
|
||||
ip string // parsed into these
|
||||
cidr int
|
||||
}
|
||||
|
||||
// CTCP version ban
|
||||
type cBanVersion struct {
|
||||
VersionRegex string // regex to match against version reply
|
||||
Reason string
|
||||
}
|
||||
|
||||
// Ban server from linking to network
|
||||
type cBanServer struct {
|
||||
ServerMask string // matched against name of linked server
|
||||
Reason string
|
||||
}
|
||||
|
167
server/config/config.go
Normal file
167
server/config/config.go
Normal file
|
@ -0,0 +1,167 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"scanner"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
fn string
|
||||
scan *scanner.Scanner
|
||||
|
||||
// Ports we listen on.
|
||||
Ports map[int]*cPort
|
||||
// People with teh p0wer.
|
||||
Opers map[string]*cOper
|
||||
// Servers we link to on the network.
|
||||
Links map[string]*cLink
|
||||
// Servers/nickmasks/IPs that are unwanted.
|
||||
Bans []*cBan
|
||||
|
||||
// Server info (name, admins, etc.)
|
||||
Info *cInfo
|
||||
|
||||
// Server settings
|
||||
Settings *cSettings
|
||||
|
||||
// Parse errors
|
||||
Errors []os.Error
|
||||
}
|
||||
|
||||
type configMap map[string]func(*Config)
|
||||
type keywordMap map[string]func(*Config, interface{})
|
||||
|
||||
var configKeywords = configMap{
|
||||
"port": (*Config).parsePort,
|
||||
// "oper": (*Config).parseOper,
|
||||
// "link": (*Config).parseLink,
|
||||
// "ban": (*Config).parseBan,
|
||||
// "info": (*Config).parseInfo,
|
||||
// "set": (*Config).parseSettings,
|
||||
}
|
||||
|
||||
func LoadConfig(filename string) *Config {
|
||||
conf := &Config{fn: filename}
|
||||
conf.initialise()
|
||||
if fh, err := os.Open(conf.fn, os.O_RDONLY, 0644); err == nil {
|
||||
conf.Parse(fh)
|
||||
fh.Close()
|
||||
} else {
|
||||
conf.Errors = append(conf.Errors, err)
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
func (conf *Config) initialise() {
|
||||
conf.Ports = make(map[int]*cPort)
|
||||
conf.Opers = make(map[string]*cOper)
|
||||
conf.Links = make(map[string]*cLink)
|
||||
conf.Bans = make([]*cBan, 0)
|
||||
conf.Info = &cInfo{}
|
||||
conf.Settings = &cSettings{}
|
||||
conf.Errors = make([]os.Error, 0)
|
||||
}
|
||||
|
||||
func (conf *Config) Rehash() {
|
||||
neu := LoadConfig(conf.fn)
|
||||
if len(neu.Errors) > 0 {
|
||||
conf.Errors = neu.Errors
|
||||
} else {
|
||||
conf = neu
|
||||
}
|
||||
}
|
||||
|
||||
func (conf *Config) Parse(io io.Reader) {
|
||||
s := &scanner.Scanner{}
|
||||
s.Init(io)
|
||||
s.Filename = conf.fn
|
||||
conf.scan = s
|
||||
tok, text := conf.next()
|
||||
for tok != scanner.EOF {
|
||||
// This external loop should only parse Config things
|
||||
if f, ok := configKeywords[text]; ok {
|
||||
f(conf)
|
||||
} else {
|
||||
conf.parseError("Invalid top-level keyword '%s'", text)
|
||||
}
|
||||
fmt.Printf("Token: '%s', type %s\n", s.TokenText(), scanner.TokenString(tok))
|
||||
tok, text = conf.next()
|
||||
}
|
||||
}
|
||||
|
||||
func (conf *Config) parseKwBlock(dst interface{}, bt string, kw keywordMap) {
|
||||
if ok := conf.expect("{"); !ok {
|
||||
conf.parseError("Expected %s configuration block.", bt)
|
||||
return
|
||||
}
|
||||
tok, text := conf.next()
|
||||
for tok != scanner.EOF {
|
||||
if f, ok := kw[text]; ok {
|
||||
if ok = conf.expect("="); ok {
|
||||
f(conf, dst)
|
||||
}
|
||||
} else if text == "}" {
|
||||
break
|
||||
} else {
|
||||
conf.parseError("Invalid %s keyword '%s'", bt, text)
|
||||
}
|
||||
tok, text = conf.next()
|
||||
}
|
||||
}
|
||||
|
||||
var booleans = map[string]bool {
|
||||
"true": true,
|
||||
"yes": true,
|
||||
"on": true,
|
||||
"1": true,
|
||||
"false": false,
|
||||
"no": false,
|
||||
"off": false,
|
||||
"0": false,
|
||||
}
|
||||
|
||||
func (conf *Config) expectBool() (bool, bool) {
|
||||
tok, text := conf.next()
|
||||
if val, ok := booleans[text]; tok == scanner.Ident && ok {
|
||||
return val, ok
|
||||
}
|
||||
conf.parseError("Expected boolean, got '%s'", text)
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (conf *Config) expectInt() (int, bool) {
|
||||
tok, text := conf.next()
|
||||
num, err := strconv.Atoi(text)
|
||||
if tok != scanner.Int || err != nil {
|
||||
conf.parseError("Expected integer, got '%s'", text)
|
||||
return 0, false
|
||||
}
|
||||
return num, true
|
||||
}
|
||||
|
||||
func (conf *Config) expect(str string) bool {
|
||||
_, text := conf.next()
|
||||
if text != str {
|
||||
conf.parseError("Expected '%s', got '%s'", str, text)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (conf *Config) next() (int, string) {
|
||||
tok := conf.scan.Scan()
|
||||
text := conf.scan.TokenText()
|
||||
if tok == scanner.String {
|
||||
// drop "quotes" -> quotes
|
||||
text = text[1:len(text)-1]
|
||||
}
|
||||
return tok, text
|
||||
}
|
||||
|
||||
func (conf *Config) parseError(err string, args ...interface{}) {
|
||||
err = conf.scan.Pos().String() + ": " + err
|
||||
conf.Errors = append(conf.Errors, os.NewError(fmt.Sprintf(err, args...)))
|
||||
}
|
8
server/config/info.go
Normal file
8
server/config/info.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package config
|
||||
|
||||
type cInfo struct {
|
||||
Name, Network, Info, MOTDFile string
|
||||
Admins []string
|
||||
Numeric int
|
||||
}
|
||||
|
12
server/config/link.go
Normal file
12
server/config/link.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package config
|
||||
|
||||
type cLink struct {
|
||||
Server string // Server name for link
|
||||
Address string // {ip,ip6,host}:port
|
||||
ReceivePass string // Password when server connects to us
|
||||
ConnectPass string // Password when we connect to server
|
||||
|
||||
// Do we use tls.Dial? or compression (no)? Do we auto-connect on start?
|
||||
SSL, Zip, Auto bool
|
||||
}
|
||||
|
16
server/config/oper.go
Normal file
16
server/config/oper.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package config
|
||||
|
||||
type cOper struct {
|
||||
Username, Password string
|
||||
HostMask []string
|
||||
|
||||
// Permissions for oper
|
||||
CanKill, CanBan, CanNick, CanLink bool
|
||||
}
|
||||
|
||||
var cOperDefaults = &cOper{
|
||||
HostMask: []string{"*@*"},
|
||||
CanKill: true, CanBan: true,
|
||||
CanNick: false, CanLink: false,
|
||||
}
|
||||
|
86
server/config/port.go
Normal file
86
server/config/port.go
Normal file
|
@ -0,0 +1,86 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"scanner"
|
||||
)
|
||||
|
||||
type cPort struct {
|
||||
Port int
|
||||
BindIP, Family, Class string
|
||||
|
||||
// Is port a tls.Listener? Does it support compression (no)?
|
||||
SSL, Zip bool
|
||||
|
||||
// address == "<BindIP>:<Port>"
|
||||
address string
|
||||
}
|
||||
|
||||
var portKeywords = keywordMap{
|
||||
// "bind_ip": (*Config).parsePortBindIP,
|
||||
// "family": (*Config).parsePortFamily,
|
||||
"class": (*Config).parsePortClass,
|
||||
"ssl": (*Config).parsePortSSL,
|
||||
// "zip": (*Config).parsePortZip,
|
||||
}
|
||||
|
||||
var cPortDefaults = cPort{
|
||||
BindIP: "", Family: "tcp", Class: "client",
|
||||
SSL: false, Zip: false,
|
||||
}
|
||||
|
||||
func defaultPort() *cPort {
|
||||
p := cPortDefaults
|
||||
return &p
|
||||
}
|
||||
|
||||
func (p *cPort) String() string {
|
||||
str := []string{fmt.Sprintf("port %d {", p.Port)}
|
||||
if p.BindIP != "" {
|
||||
str = append(str, "\tbind_ip = " + p.BindIP)
|
||||
}
|
||||
str = append(str,
|
||||
fmt.Sprintf("\tfamily = \"%s\"",p.Family),
|
||||
fmt.Sprintf("\tclass = \"%s\"", p.Class),
|
||||
fmt.Sprintf("\tssl = %t", p.SSL),
|
||||
fmt.Sprintf("\tzip = %t", p.Zip),
|
||||
"}",
|
||||
)
|
||||
return strings.Join(str, "\n")
|
||||
}
|
||||
|
||||
func (conf *Config) parsePort() {
|
||||
port := defaultPort()
|
||||
portnum, ok := conf.expectInt()
|
||||
if !ok || portnum > 65535 || portnum < 1024 {
|
||||
conf.parseError("Invalid port '%s'", portnum)
|
||||
port = nil
|
||||
} else {
|
||||
port.Port = portnum
|
||||
conf.Ports[portnum] = port
|
||||
}
|
||||
if conf.scan.Peek() != '\n' {
|
||||
conf.parseKwBlock(port, "port", portKeywords)
|
||||
}
|
||||
fmt.Println(port.String())
|
||||
}
|
||||
|
||||
func (conf *Config) parsePortClass(pi interface{}) {
|
||||
port := pi.(*cPort)
|
||||
tok, text := conf.next()
|
||||
if tok == scanner.String && (text == "server" || text == "client") {
|
||||
port.Class = text
|
||||
} else {
|
||||
conf.parseError(
|
||||
"Port class must be \"server\" or \"client\", got '%s'", text)
|
||||
}
|
||||
}
|
||||
|
||||
func (conf *Config) parsePortSSL(pi interface{}) {
|
||||
port := pi.(*cPort)
|
||||
if ssl, ok := conf.expectBool(); ok {
|
||||
port.SSL = ssl
|
||||
}
|
||||
}
|
||||
|
8
server/config/settings.go
Normal file
8
server/config/settings.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package config
|
||||
|
||||
type cSettings struct {
|
||||
SSLKey, SSLCert, SSLCACert string
|
||||
MaxChans, MaxConnsPerIP int
|
||||
LogFile string
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue