mirror of https://github.com/fluffle/goirc
Ragel based config file parser, ftw.
This commit is contained in:
parent
377fbcd3af
commit
22ccce6bb2
|
@ -7,11 +7,10 @@ include $(GOROOT)/src/Make.inc
|
||||||
TARG=irc/server/config
|
TARG=irc/server/config
|
||||||
GOFILES=\
|
GOFILES=\
|
||||||
config.go\
|
config.go\
|
||||||
port.go\
|
parser.go\
|
||||||
oper.go\
|
|
||||||
link.go\
|
|
||||||
ban.go\
|
|
||||||
info.go\
|
|
||||||
settings.go\
|
|
||||||
|
|
||||||
include $(GOROOT)/src/Make.pkg
|
include $(GOROOT)/src/Make.pkg
|
||||||
|
|
||||||
|
parser.go: parser.rl
|
||||||
|
ragel -Z -G2 -o parser.go parser.rl
|
||||||
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"net"
|
||||||
"scanner"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
fn string
|
fn string
|
||||||
scan *scanner.Scanner
|
|
||||||
|
|
||||||
// Ports we listen on.
|
// Ports we listen on.
|
||||||
Ports map[int]*cPort
|
Ports map[int]*cPort
|
||||||
|
@ -31,17 +29,6 @@ type Config struct {
|
||||||
Errors []os.Error
|
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 {
|
func LoadConfig(filename string) *Config {
|
||||||
conf := &Config{fn: filename}
|
conf := &Config{fn: filename}
|
||||||
|
@ -74,103 +61,129 @@ func (conf *Config) Rehash() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *Config) Parse(io io.Reader) {
|
/* Port configuration */
|
||||||
s := &scanner.Scanner{}
|
type cPort struct {
|
||||||
s.Init(io)
|
Port int
|
||||||
s.Filename = conf.fn
|
BindIP net.IP // bind to a specific IP for listen port
|
||||||
conf.scan = s
|
Class string // "server" or "client"
|
||||||
tok, text := conf.next()
|
|
||||||
for tok != scanner.EOF {
|
// Is port a tls.Listener? Does it support compression (no)?
|
||||||
// This external loop should only parse Config things
|
SSL, Zip bool
|
||||||
if f, ok := configKeywords[text]; ok {
|
}
|
||||||
f(conf)
|
|
||||||
} else {
|
func defaultPort() *cPort {
|
||||||
conf.parseError("Invalid top-level keyword '%s'", text)
|
return &cPort{
|
||||||
|
BindIP: nil, Class: "client",
|
||||||
|
SSL: false, Zip: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *cPort) String() string {
|
||||||
|
str := []string{fmt.Sprintf("port %d {", p.Port)}
|
||||||
|
if p.BindIP != nil {
|
||||||
|
str = append(str,
|
||||||
|
fmt.Sprintf("\tbind_ip = %s", p.BindIP.String()))
|
||||||
|
}
|
||||||
|
str = append(str,
|
||||||
|
fmt.Sprintf("\tclass = %s", p.Class),
|
||||||
|
fmt.Sprintf("\tssl = %t", p.SSL),
|
||||||
|
fmt.Sprintf("\tzip = %t", p.Zip),
|
||||||
|
"}",
|
||||||
|
)
|
||||||
|
return strings.Join(str, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Oper configuration */
|
||||||
|
type cOper struct {
|
||||||
|
Username, Password string
|
||||||
|
HostMask []string
|
||||||
|
|
||||||
|
// Permissions for oper
|
||||||
|
CanKill, CanBan, CanRenick, CanLink bool
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
}
|
}
|
||||||
fmt.Printf("Token: '%s', type %s\n", s.TokenText(), scanner.TokenString(tok))
|
|
||||||
tok, text = conf.next()
|
|
||||||
}
|
}
|
||||||
|
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) parseKwBlock(dst interface{}, bt string, kw keywordMap) {
|
/* Link configuration */
|
||||||
if ok := conf.expect("{"); !ok {
|
type cLink struct {
|
||||||
conf.parseError("Expected %s configuration block.", bt)
|
Server string // Server name for link
|
||||||
return
|
Address string // {ip,ip6,host}:port
|
||||||
}
|
ReceivePass string // Password when server connects to us
|
||||||
tok, text := conf.next()
|
ConnectPass string // Password when we connect to server
|
||||||
for tok != scanner.EOF {
|
|
||||||
if f, ok := kw[text]; ok {
|
// Do we use tls.Dial? or compression (no)? Do we auto-connect on start?
|
||||||
if ok = conf.expect("="); ok {
|
SSL, Zip, Auto bool
|
||||||
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 {
|
/* Static ban configuration */
|
||||||
"true": true,
|
type cBan interface {
|
||||||
"yes": true,
|
Match(string) bool
|
||||||
"on": true,
|
Reason() string
|
||||||
"1": true,
|
|
||||||
"false": false,
|
|
||||||
"no": false,
|
|
||||||
"off": false,
|
|
||||||
"0": false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *Config) expectBool() (bool, bool) {
|
// G-Line etc;
|
||||||
tok, text := conf.next()
|
type cBanNick struct {
|
||||||
if val, ok := booleans[text]; tok == scanner.Ident && ok {
|
NickMask string // nick!ident@host
|
||||||
return val, ok
|
Reason string
|
||||||
}
|
|
||||||
conf.parseError("Expected boolean, got '%s'", text)
|
|
||||||
return false, false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *Config) expectInt() (int, bool) {
|
// Z-Line
|
||||||
tok, text := conf.next()
|
type cBanIP struct {
|
||||||
num, err := strconv.Atoi(text)
|
Address string // ip (or hostname), plus optional CIDR netmask
|
||||||
if tok != scanner.Int || err != nil {
|
Reason string
|
||||||
conf.parseError("Expected integer, got '%s'", text)
|
ip string // parsed into these
|
||||||
return 0, false
|
cidr int
|
||||||
}
|
|
||||||
return num, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *Config) expectString() (string, bool) {
|
// CTCP version ban
|
||||||
tok, text := conf.next()
|
type cBanVersion struct {
|
||||||
if tok != scanner.String && tok != scanner.Ident {
|
VersionRegex string // regex to match against version reply
|
||||||
conf.parseError("Expected string, got '%s'", text)
|
Reason string
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
return text, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *Config) expect(str string) bool {
|
// Ban server from linking to network
|
||||||
_, text := conf.next()
|
type cBanServer struct {
|
||||||
if text != str {
|
ServerMask string // matched against name of linked server
|
||||||
conf.parseError("Expected '%s', got '%s'", str, text)
|
Reason string
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *Config) next() (int, string) {
|
/* IRCd settings */
|
||||||
tok := conf.scan.Scan()
|
type cSettings struct {
|
||||||
text := conf.scan.TokenText()
|
SSLKey, SSLCert, SSLCACert string
|
||||||
if tok == scanner.String {
|
MaxChans, MaxConnsPerIP int
|
||||||
// drop "quotes" -> quotes
|
LogFile string
|
||||||
text = text[1:len(text)-1]
|
|
||||||
}
|
|
||||||
return tok, text
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *Config) parseError(err string, args ...interface{}) {
|
/* IRCd information */
|
||||||
err = conf.scan.Pos().String() + ": " + err
|
type cInfo struct {
|
||||||
conf.Errors = append(conf.Errors, os.NewError(fmt.Sprintf(err, args...)))
|
Name, Network, Info, MOTDFile string
|
||||||
|
Admins []string
|
||||||
|
Numeric int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package config
|
|
||||||
|
|
||||||
type cInfo struct {
|
|
||||||
Name, Network, Info, MOTDFile string
|
|
||||||
Admins []string
|
|
||||||
Numeric int
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"scanner"
|
|
||||||
)
|
|
||||||
|
|
||||||
type cOper struct {
|
|
||||||
Username, Password string
|
|
||||||
HostMask []string
|
|
||||||
|
|
||||||
// Permissions for oper
|
|
||||||
CanKill, CanBan, CanRenick, CanLink bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var operKeywords = keywordMap{
|
|
||||||
"password": (*Config).parseOperPassword,
|
|
||||||
"hostmask": (*Config).parseOperHostMask,
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
%% machine config;
|
||||||
|
%% write data;
|
||||||
|
|
||||||
|
var booleans = map[string]bool {
|
||||||
|
"true": true,
|
||||||
|
"yes": true,
|
||||||
|
"on": true,
|
||||||
|
"1": true,
|
||||||
|
"false": false,
|
||||||
|
"no": false,
|
||||||
|
"off": false,
|
||||||
|
"0": false,
|
||||||
|
}
|
||||||
|
|
||||||
|
%%{
|
||||||
|
# mark the current position for acquiring data
|
||||||
|
action mark { mark = p }
|
||||||
|
|
||||||
|
# acceptable boolean values
|
||||||
|
true = "yes" | "on" | "1" | "true" ;
|
||||||
|
false = "no" | "off" | "0" | "false" ;
|
||||||
|
boolean = true | false ;
|
||||||
|
|
||||||
|
# IP addresses, v4 and v6
|
||||||
|
octet = digit # 0-9
|
||||||
|
| digit digit # 00-99
|
||||||
|
| [01] digit digit # 000-199
|
||||||
|
| "2" [0-4] digit # 200-249
|
||||||
|
| "2" "5" [0-5] ; # 250-255
|
||||||
|
ipv4addr = octet "." octet "." octet "." octet ;
|
||||||
|
ipv6addr = ( xdigit{1,4} ":" ){7} xdigit{1,4} # all 8 blocks
|
||||||
|
| xdigit{0,4} "::" # special case
|
||||||
|
| ( xdigit{1,4} ":" ){1,6} ":" # first 1-6, ::
|
||||||
|
| ":" ( ":" xdigit{1,4} ){1,6} # ::, final 1-6
|
||||||
|
| xdigit{1,4} ":" ( ":" xdigit{1,4} ){1,6} # 1::1-6
|
||||||
|
| ( xdigit{1,4} ":" ){2}( ":" xdigit{1,4} ){1,5} # 2::1-5
|
||||||
|
| ( xdigit{1,4} ":" ){3}( ":" xdigit{1,4} ){1,4} # 3::1-4
|
||||||
|
| ( xdigit{1,4} ":" ){4}( ":" xdigit{1,4} ){1,5} # 4::1-3
|
||||||
|
| ( xdigit{1,4} ":" ){5}( ":" xdigit{1,4} ){1,2} # 5::1-2
|
||||||
|
| ( xdigit{1,4} ":" ){6}( ":" xdigit{1,4} ) ; # 6::1
|
||||||
|
|
||||||
|
# Actions to create a cPort and save it into the Config struct
|
||||||
|
action new_port { cur = defaultPort() }
|
||||||
|
action save_port {
|
||||||
|
port := cur.(*cPort)
|
||||||
|
conf.Ports[port.Port] = port
|
||||||
|
cur = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
# parse and save the port number
|
||||||
|
action set_portnum {
|
||||||
|
cur.(*cPort).Port, _ = strconv.Atoi(string(data[mark:p]))
|
||||||
|
}
|
||||||
|
portnum = digit+ >mark %set_portnum ;
|
||||||
|
|
||||||
|
# parse a bind_ip statement and save the IP
|
||||||
|
action set_bindip {
|
||||||
|
cur.(*cPort).BindIP = net.ParseIP(string(data[mark:p]))
|
||||||
|
}
|
||||||
|
bindip = (ipv4addr | ipv6addr) >mark %set_bindip ;
|
||||||
|
portbindip = "bind_ip" " "+ "=" " "+ bindip ;
|
||||||
|
|
||||||
|
# parse a class statement and save it
|
||||||
|
action set_class {
|
||||||
|
cur.(*cPort).Class = string(data[mark:p])
|
||||||
|
}
|
||||||
|
portclass = "class" " "+ "=" " "+ ("server" | "client" >mark %set_class) ;
|
||||||
|
|
||||||
|
# parse SSL and Zip booleans
|
||||||
|
action set_ssl {
|
||||||
|
cur.(*cPort).SSL = booleans[string(data[mark:p])]
|
||||||
|
}
|
||||||
|
portssl = "ssl" " "+ "=" " "+ (boolean >mark %set_ssl) ;
|
||||||
|
action set_zip {
|
||||||
|
cur.(*cPort).Zip = booleans[string(data[mark:p])]
|
||||||
|
}
|
||||||
|
portzip = "zip" " "+ "=" " "+ (boolean >mark %set_zip) ;
|
||||||
|
|
||||||
|
portstmt = ( portbindip | portclass | portssl | portzip ) ;
|
||||||
|
portblock = "{" space* ( portstmt | (portstmt " "* "\n" space* )+ ) space* "}" ;
|
||||||
|
|
||||||
|
# a port configuration can either be:
|
||||||
|
# port <portnum>\n
|
||||||
|
# port <portnum> { portblock }
|
||||||
|
basicport = "port" >new_port " "+ portnum " "* "\n" %save_port;
|
||||||
|
portdefn = "port" >new_port " "+ portnum " "+ portblock %save_port ;
|
||||||
|
portconfig = space* ( basicport | portdefn ) space*;
|
||||||
|
|
||||||
|
# config = portconfig+
|
||||||
|
# | operconfig+
|
||||||
|
# | linkconfig*
|
||||||
|
# | infoconfig
|
||||||
|
# | settings ;
|
||||||
|
|
||||||
|
main := portconfig+;
|
||||||
|
}%%
|
||||||
|
|
||||||
|
func (conf *Config) Parse(r io.Reader) {
|
||||||
|
cs, p, mark, pe, eof, buflen := 0, 0, 0, 0, 0, 16384
|
||||||
|
done := false
|
||||||
|
var cur interface{}
|
||||||
|
data := make([]byte, buflen)
|
||||||
|
|
||||||
|
%% write init;
|
||||||
|
|
||||||
|
for !done {
|
||||||
|
n, err := r.Read(data)
|
||||||
|
pe = p + n
|
||||||
|
if err == os.EOF {
|
||||||
|
fmt.Println("yeahhhhh.")
|
||||||
|
done = true
|
||||||
|
eof = pe
|
||||||
|
}
|
||||||
|
|
||||||
|
%% write exec;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if cs < config_first_final {
|
||||||
|
fmt.Printf("Parse error at %d near '%s'\n", p, data[p:p+10])
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, port := range conf.Ports {
|
||||||
|
fmt.Println(port.String())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,97 +0,0 @@
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"scanner"
|
|
||||||
)
|
|
||||||
|
|
||||||
type cPort struct {
|
|
||||||
Port int
|
|
||||||
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)?
|
|
||||||
SSL, Zip bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var portKeywords = keywordMap{
|
|
||||||
"bind_ip": (*Config).parsePortBindIP,
|
|
||||||
"class": (*Config).parsePortClass,
|
|
||||||
"ssl": (*Config).parsePortSSL,
|
|
||||||
"zip": (*Config).parsePortZip,
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultPort() *cPort {
|
|
||||||
return &cPort{
|
|
||||||
BindIP: nil, Class: "client",
|
|
||||||
SSL: false, Zip: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *cPort) String() string {
|
|
||||||
str := []string{fmt.Sprintf("port %d {", p.Port)}
|
|
||||||
if p.BindIP != nil {
|
|
||||||
str = append(str,
|
|
||||||
fmt.Sprintf("\tbind_ip = \"%s\"", p.BindIP.String()))
|
|
||||||
}
|
|
||||||
str = append(str,
|
|
||||||
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) 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{}) {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (conf *Config) parsePortZip(pi interface{}) {
|
|
||||||
port := pi.(*cPort)
|
|
||||||
if zip, ok := conf.expectBool(); ok {
|
|
||||||
port.Zip = zip
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
package config
|
|
||||||
|
|
||||||
type cSettings struct {
|
|
||||||
SSLKey, SSLCert, SSLCACert string
|
|
||||||
MaxChans, MaxConnsPerIP int
|
|
||||||
LogFile string
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue