Document exported code (#49)
parent
04d33fd100
commit
7e72caa092
6
auth.go
6
auth.go
|
@ -5,7 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var authIface AuthBackend
|
var authIface authBackend
|
||||||
var ErrAuthBackendExists = errors.New("auth backend already set")
|
var ErrAuthBackendExists = errors.New("auth backend already set")
|
||||||
|
|
||||||
type user struct {
|
type user struct {
|
||||||
|
@ -15,7 +15,7 @@ type user struct {
|
||||||
timestamp time.Time
|
timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthBackend interface {
|
type authBackend interface {
|
||||||
Exists(name string) bool
|
Exists(name string) bool
|
||||||
Passwd(name string) (salt, verifier []byte, err error)
|
Passwd(name string) (salt, verifier []byte, err error)
|
||||||
SetPasswd(name string, salt, verifier []byte) error
|
SetPasswd(name string, salt, verifier []byte) error
|
||||||
|
@ -24,7 +24,7 @@ type AuthBackend interface {
|
||||||
Export() ([]user, error)
|
Export() ([]user, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetAuthBackend(ab AuthBackend) error {
|
func setAuthBackend(ab authBackend) error {
|
||||||
if authIface != nil {
|
if authIface != nil {
|
||||||
return ErrAuthBackendExists
|
return ErrAuthBackendExists
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,12 @@ import (
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthSQLite3 struct {
|
type authSQLite3 struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthSQLite3) Exists(name string) bool {
|
// Exists reports whether a user is registered.
|
||||||
|
func (a authSQLite3) Exists(name string) bool {
|
||||||
if err := a.init(); err != nil {
|
if err := a.init(); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -24,7 +25,8 @@ func (a AuthSQLite3) Exists(name string) bool {
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthSQLite3) Passwd(name string) (salt, verifier []byte, err error) {
|
// Passwd returns the SRP salt and verifier of a user or an error.
|
||||||
|
func (a authSQLite3) Passwd(name string) (salt, verifier []byte, err error) {
|
||||||
if err = a.init(); err != nil {
|
if err = a.init(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -35,7 +37,9 @@ func (a AuthSQLite3) Passwd(name string) (salt, verifier []byte, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthSQLite3) SetPasswd(name string, salt, verifier []byte) error {
|
// SetPasswd creates a password entry if necessary
|
||||||
|
// and sets the password of a user.
|
||||||
|
func (a authSQLite3) SetPasswd(name string, salt, verifier []byte) error {
|
||||||
if err := a.init(); err != nil {
|
if err := a.init(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -50,7 +54,9 @@ func (a AuthSQLite3) SetPasswd(name string, salt, verifier []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthSQLite3) Timestamp(name string) (time.Time, error) {
|
// Timestamp returns the last time an authentication entry was accessed
|
||||||
|
// or an error.
|
||||||
|
func (a authSQLite3) Timestamp(name string) (time.Time, error) {
|
||||||
if err := a.init(); err != nil {
|
if err := a.init(); err != nil {
|
||||||
return time.Time{}, err
|
return time.Time{}, err
|
||||||
}
|
}
|
||||||
|
@ -65,7 +71,9 @@ func (a AuthSQLite3) Timestamp(name string) (time.Time, error) {
|
||||||
return time.Parse("2006-01-02 15:04:05", tstr)
|
return time.Parse("2006-01-02 15:04:05", tstr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthSQLite3) Import(in []user) {
|
// Import clears the database and and refills it with the passed
|
||||||
|
// users.
|
||||||
|
func (a authSQLite3) Import(in []user) {
|
||||||
if err := a.init(); err != nil {
|
if err := a.init(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -78,7 +86,9 @@ func (a AuthSQLite3) Import(in []user) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthSQLite3) Export() ([]user, error) {
|
// Export returns data that can be processed by Import
|
||||||
|
// or an error.
|
||||||
|
func (a authSQLite3) Export() ([]user, error) {
|
||||||
if err := a.init(); err != nil {
|
if err := a.init(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -119,11 +129,11 @@ func (a AuthSQLite3) Export() ([]user, error) {
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthSQLite3) updateTimestamp(name string) {
|
func (a authSQLite3) updateTimestamp(name string) {
|
||||||
a.db.Exec(`UPDATE user SET timestamp = datetime("now") WHERE name = ?;`, name)
|
a.db.Exec(`UPDATE user SET timestamp = datetime("now") WHERE name = ?;`, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AuthSQLite3) init() error {
|
func (a *authSQLite3) init() error {
|
||||||
executable, err := os.Executable()
|
executable, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -148,6 +158,6 @@ func (a *AuthSQLite3) init() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthSQLite3) close() error {
|
func (a authSQLite3) close() error {
|
||||||
return a.db.Close()
|
return a.db.Close()
|
||||||
}
|
}
|
||||||
|
|
2
chat.go
2
chat.go
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/anon55555/mt"
|
"github.com/anon55555/mt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SendChatMsg sends a chat message to the ClientConn.
|
||||||
func (cc *ClientConn) SendChatMsg(msg ...string) {
|
func (cc *ClientConn) SendChatMsg(msg ...string) {
|
||||||
cc.SendCmd(&mt.ToCltChatMsg{
|
cc.SendCmd(&mt.ToCltChatMsg{
|
||||||
Type: mt.SysMsg,
|
Type: mt.SysMsg,
|
||||||
|
@ -16,6 +17,7 @@ func (cc *ClientConn) SendChatMsg(msg ...string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Colorize returns the minetest-colorized version of the input.
|
||||||
func Colorize(text, color string) string {
|
func Colorize(text, color string) string {
|
||||||
return string(0x1b) + "(c@" + color + ")" + text + string(0x1b) + "(c@#FFF)"
|
return string(0x1b) + "(c@" + color + ")" + text + string(0x1b) + "(c@#FFF)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ const (
|
||||||
csSudo
|
csSudo
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A ClientConn is a connection to a minetest client.
|
||||||
type ClientConn struct {
|
type ClientConn struct {
|
||||||
mt.Peer
|
mt.Peer
|
||||||
srv *ServerConn
|
srv *ServerConn
|
||||||
|
@ -60,6 +61,7 @@ type ClientConn struct {
|
||||||
modChs map[string]struct{}
|
modChs map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the player name of the ClientConn.
|
||||||
func (cc *ClientConn) Name() string { return cc.name }
|
func (cc *ClientConn) Name() string { return cc.name }
|
||||||
|
|
||||||
func (cc *ClientConn) server() *ServerConn {
|
func (cc *ClientConn) server() *ServerConn {
|
||||||
|
@ -69,6 +71,8 @@ func (cc *ClientConn) server() *ServerConn {
|
||||||
return cc.srv
|
return cc.srv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServerName returns the name of the current upstream server
|
||||||
|
// of the ClientConn. It is empty if there is no upstream connection.
|
||||||
func (cc *ClientConn) ServerName() string {
|
func (cc *ClientConn) ServerName() string {
|
||||||
srv := cc.server()
|
srv := cc.server()
|
||||||
if srv != nil {
|
if srv != nil {
|
||||||
|
@ -92,8 +96,12 @@ func (cc *ClientConn) setState(state clientState) {
|
||||||
cc.cstate = state
|
cc.cstate = state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init returns a channel that is closed
|
||||||
|
// when the ClientConn enters the csActive state.
|
||||||
func (cc *ClientConn) Init() <-chan struct{} { return cc.initCh }
|
func (cc *ClientConn) Init() <-chan struct{} { return cc.initCh }
|
||||||
|
|
||||||
|
// Log logs an interaction with the ClientConn.
|
||||||
|
// dir indicates the direction of the interaction.
|
||||||
func (cc *ClientConn) Log(dir string, v ...interface{}) {
|
func (cc *ClientConn) Log(dir string, v ...interface{}) {
|
||||||
if cc.Name() != "" {
|
if cc.Name() != "" {
|
||||||
format := "{%s, %s} %s {←|⇶}"
|
format := "{%s, %s} %s {←|⇶}"
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/*
|
||||||
|
mt-multiserver-proxy starts the reverse proxy.
|
||||||
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/HimbeerserverDE/mt-multiserver-proxy"
|
import "github.com/HimbeerserverDE/mt-multiserver-proxy"
|
||||||
|
|
13
config.go
13
config.go
|
@ -8,12 +8,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
const latestSerializeVer = 28
|
|
||||||
const latestProtoVer = 39
|
|
||||||
const maxPlayerNameLen = 20
|
|
||||||
const playerNameChars = "^[a-zA-Z0-9-_]+$"
|
|
||||||
const bytesPerMediaBunch = 5000
|
|
||||||
|
|
||||||
const defaultCmdPrefix = ">"
|
const defaultCmdPrefix = ">"
|
||||||
const defaultSendInterval = 0.09
|
const defaultSendInterval = 0.09
|
||||||
const defaultUserLimit = 10
|
const defaultUserLimit = 10
|
||||||
|
@ -23,6 +17,8 @@ const defaultBindAddr = ":40000"
|
||||||
var config Config
|
var config Config
|
||||||
var configMu sync.RWMutex
|
var configMu sync.RWMutex
|
||||||
|
|
||||||
|
// A Config contains information from the configuration file
|
||||||
|
// that affects the way the proxy works.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
NoPlugins bool
|
NoPlugins bool
|
||||||
CmdPrefix string
|
CmdPrefix string
|
||||||
|
@ -48,6 +44,8 @@ type Config struct {
|
||||||
UserGroups map[string]string
|
UserGroups map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conf returns a copy of the Config used by the proxy.
|
||||||
|
// Any modifications will not affect the original Config.
|
||||||
func Conf() Config {
|
func Conf() Config {
|
||||||
configMu.RLock()
|
configMu.RLock()
|
||||||
defer configMu.RUnlock()
|
defer configMu.RUnlock()
|
||||||
|
@ -55,6 +53,9 @@ func Conf() Config {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadConfig attempts to parse the configuration file.
|
||||||
|
// It leaves the config unchanged if there is an error
|
||||||
|
// and returns the error.
|
||||||
func LoadConfig() error {
|
func LoadConfig() error {
|
||||||
configMu.Lock()
|
configMu.Lock()
|
||||||
defer configMu.Unlock()
|
defer configMu.Unlock()
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/anon55555/mt"
|
"github.com/anon55555/mt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Connect(conn net.Conn, name string, cc *ClientConn) *ServerConn {
|
func connect(conn net.Conn, name string, cc *ClientConn) *ServerConn {
|
||||||
cc.mu.RLock()
|
cc.mu.RLock()
|
||||||
if cc.srv != nil {
|
if cc.srv != nil {
|
||||||
cc.Log("<->", "already connected to server")
|
cc.Log("<->", "already connected to server")
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//go:build ignore
|
//go:build ignore
|
||||||
|
|
||||||
// This program generates default_textures.go. It can be invoked
|
// gen_textures generates default_textures.go. It can be invoked
|
||||||
// by running go generate
|
// by running go generate.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -23,6 +23,7 @@ func main() {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
f.WriteString("// Code generated by gen_textures.go. DO NOT EDIT.\n")
|
||||||
f.WriteString("package proxy\n")
|
f.WriteString("package proxy\n")
|
||||||
f.WriteString("\n")
|
f.WriteString("\n")
|
||||||
f.WriteString("var defaultTextures = []mediaFile{\n")
|
f.WriteString("var defaultTextures = []mediaFile{\n")
|
||||||
|
|
7
hop.go
7
hop.go
|
@ -8,6 +8,9 @@ import (
|
||||||
"github.com/anon55555/mt"
|
"github.com/anon55555/mt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Hop connects the ClientConn to the specified upstream server.
|
||||||
|
// At the moment the ClientConn is NOT fixed if an error occurs
|
||||||
|
// so the player may have to reconnect.
|
||||||
func (cc *ClientConn) Hop(serverName string) error {
|
func (cc *ClientConn) Hop(serverName string) error {
|
||||||
cc.hopMu.Lock()
|
cc.hopMu.Lock()
|
||||||
defer cc.hopMu.Unlock()
|
defer cc.hopMu.Unlock()
|
||||||
|
@ -32,7 +35,7 @@ func (cc *ClientConn) Hop(serverName string) error {
|
||||||
return fmt.Errorf("inexistent server")
|
return fmt.Errorf("inexistent server")
|
||||||
}
|
}
|
||||||
|
|
||||||
// This needs to be done before the serverConn is closed
|
// This needs to be done before the ServerConn is closed
|
||||||
// so the clientConn isn't closed by the packet handler
|
// so the clientConn isn't closed by the packet handler
|
||||||
cc.server().mu.Lock()
|
cc.server().mu.Lock()
|
||||||
cc.server().clt = nil
|
cc.server().clt = nil
|
||||||
|
@ -144,7 +147,7 @@ func (cc *ClientConn) Hop(serverName string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
Connect(conn, serverName, cc)
|
connect(conn, serverName, cc)
|
||||||
|
|
||||||
for ch := range cc.modChs {
|
for ch := range cc.modChs {
|
||||||
cc.server().SendCmd(&mt.ToSrvJoinModChan{Channel: ch})
|
cc.server().SendCmd(&mt.ToSrvJoinModChan{Channel: ch})
|
||||||
|
|
|
@ -32,7 +32,7 @@ type listener struct {
|
||||||
clts map[*ClientConn]struct{}
|
clts map[*ClientConn]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Listen(pc net.PacketConn) *listener {
|
func listen(pc net.PacketConn) *listener {
|
||||||
l := &listener{
|
l := &listener{
|
||||||
Listener: mt.Listen(pc),
|
Listener: mt.Listen(pc),
|
||||||
clts: make(map[*ClientConn]struct{}),
|
clts: make(map[*ClientConn]struct{}),
|
||||||
|
@ -49,7 +49,7 @@ func Listen(pc net.PacketConn) *listener {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *listener) Clts() map[*ClientConn]struct{} {
|
func (l *listener) clients() map[*ClientConn]struct{} {
|
||||||
clts := make(map[*ClientConn]struct{})
|
clts := make(map[*ClientConn]struct{})
|
||||||
|
|
||||||
l.mu.RLock()
|
l.mu.RLock()
|
||||||
|
@ -62,7 +62,7 @@ func (l *listener) Clts() map[*ClientConn]struct{} {
|
||||||
return clts
|
return clts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *listener) Accept() (*ClientConn, error) {
|
func (l *listener) accept() (*ClientConn, error) {
|
||||||
p, err := l.Listener.Accept()
|
p, err := l.Listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
2
log.go
2
log.go
|
@ -10,6 +10,8 @@ type LogWriter struct {
|
||||||
f *os.File
|
f *os.File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write writes the input data to os.Stderr and the log file.
|
||||||
|
// It returns the number of bytes written and an error.
|
||||||
func (lw *LogWriter) Write(p []byte) (n int, err error) {
|
func (lw *LogWriter) Write(p []byte) (n int, err error) {
|
||||||
n, err = os.Stderr.Write(p)
|
n, err = os.Stderr.Write(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
5
perms.go
5
perms.go
|
@ -1,7 +1,6 @@
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import ()
|
// Perms returns the permissions of the ClientConn.
|
||||||
|
|
||||||
func (cc *ClientConn) Perms() []string {
|
func (cc *ClientConn) Perms() []string {
|
||||||
if cc.Name() == "" {
|
if cc.Name() == "" {
|
||||||
return []string{}
|
return []string{}
|
||||||
|
@ -19,6 +18,8 @@ func (cc *ClientConn) Perms() []string {
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasPerms returns true if the ClientConn has all
|
||||||
|
// of the specified permissions. Otherwise it returns false.
|
||||||
func (cc *ClientConn) HasPerms(want ...string) bool {
|
func (cc *ClientConn) HasPerms(want ...string) bool {
|
||||||
has := make(map[string]struct{})
|
has := make(map[string]struct{})
|
||||||
for _, perm := range cc.Perms() {
|
for _, perm := range cc.Perms() {
|
||||||
|
|
|
@ -5,6 +5,8 @@ import "sync"
|
||||||
var players = make(map[string]struct{})
|
var players = make(map[string]struct{})
|
||||||
var playersMu sync.RWMutex
|
var playersMu sync.RWMutex
|
||||||
|
|
||||||
|
// Players returns the names of all players
|
||||||
|
// that are currently connected to the proxy.
|
||||||
func Players() map[string]struct{} {
|
func Players() map[string]struct{} {
|
||||||
playersMu.RLock()
|
playersMu.RLock()
|
||||||
defer playersMu.RUnlock()
|
defer playersMu.RUnlock()
|
||||||
|
@ -17,11 +19,12 @@ func Players() map[string]struct{} {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clts returns all ClientConns currently connected to the proxy.
|
||||||
func Clts() map[*ClientConn]struct{} {
|
func Clts() map[*ClientConn]struct{} {
|
||||||
clts := make(map[*ClientConn]struct{})
|
clts := make(map[*ClientConn]struct{})
|
||||||
lm := allListeners()
|
lm := allListeners()
|
||||||
for l := range lm {
|
for l := range lm {
|
||||||
for clt := range l.Clts() {
|
for clt := range l.clients() {
|
||||||
clts[clt] = struct{}{}
|
clts[clt] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +32,8 @@ func Clts() map[*ClientConn]struct{} {
|
||||||
return clts
|
return clts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find returns the ClientConn that has the specified player name.
|
||||||
|
// If no ClientConn is found, nil is returned.
|
||||||
func Find(name string) *ClientConn {
|
func Find(name string) *ClientConn {
|
||||||
for clt := range Clts() {
|
for clt := range Clts() {
|
||||||
if clt.Name() == name {
|
if clt.Name() == name {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package proxy
|
||||||
|
|
||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
|
// A ChatCmd holds information on how to handle a chat command.
|
||||||
type ChatCmd struct {
|
type ChatCmd struct {
|
||||||
Name string
|
Name string
|
||||||
Perm string
|
Perm string
|
||||||
|
@ -14,6 +15,7 @@ var chatCmds map[string]ChatCmd
|
||||||
var chatCmdsMu sync.RWMutex
|
var chatCmdsMu sync.RWMutex
|
||||||
var chatCmdsOnce sync.Once
|
var chatCmdsOnce sync.Once
|
||||||
|
|
||||||
|
// ChatCmds returns a map of all ChatCmds indexed by their names.
|
||||||
func ChatCmds() map[string]ChatCmd {
|
func ChatCmds() map[string]ChatCmd {
|
||||||
initChatCmds()
|
initChatCmds()
|
||||||
|
|
||||||
|
@ -28,12 +30,14 @@ func ChatCmds() map[string]ChatCmd {
|
||||||
return cmds
|
return cmds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChatCmdExists reports if a ChatCmd exists.
|
||||||
func ChatCmdExists(name string) bool {
|
func ChatCmdExists(name string) bool {
|
||||||
cmds := ChatCmds()
|
_, ok := ChatCmds()[name]
|
||||||
_, ok := cmds[name]
|
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterChatCmd adds a new ChatCmd. It returns true on success
|
||||||
|
// and false if a command with the same name already exists.
|
||||||
func RegisterChatCmd(cmd ChatCmd) bool {
|
func RegisterChatCmd(cmd ChatCmd) bool {
|
||||||
initChatCmds()
|
initChatCmds()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
Package proxy is a minetest reverse proxy for multiple servers.
|
||||||
|
It also provides an API for plugins.
|
||||||
|
*/
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
const latestSerializeVer = 28
|
||||||
|
const latestProtoVer = 39
|
||||||
|
const maxPlayerNameLen = 20
|
||||||
|
const playerNameChars = "^[a-zA-Z0-9-_]+$"
|
||||||
|
const bytesPerMediaBunch = 5000
|
12
run.go
12
run.go
|
@ -12,6 +12,8 @@ import (
|
||||||
"github.com/anon55555/mt"
|
"github.com/anon55555/mt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Run initializes the proxy andstarts the main listener loop.
|
||||||
|
// It blocks forever.
|
||||||
func Run() {
|
func Run() {
|
||||||
if err := LoadConfig(); err != nil {
|
if err := LoadConfig(); err != nil {
|
||||||
log.Fatal("{←|⇶} ", err)
|
log.Fatal("{←|⇶} ", err)
|
||||||
|
@ -24,7 +26,7 @@ func Run() {
|
||||||
var err error
|
var err error
|
||||||
switch Conf().AuthBackend {
|
switch Conf().AuthBackend {
|
||||||
case "sqlite3":
|
case "sqlite3":
|
||||||
SetAuthBackend(AuthSQLite3{})
|
setAuthBackend(authSQLite3{})
|
||||||
default:
|
default:
|
||||||
log.Fatal("{←|⇶} invalid auth backend")
|
log.Fatal("{←|⇶} invalid auth backend")
|
||||||
}
|
}
|
||||||
|
@ -39,7 +41,7 @@ func Run() {
|
||||||
log.Fatal("{←|⇶} ", err)
|
log.Fatal("{←|⇶} ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
l := Listen(pc)
|
l := listen(pc)
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
log.Print("{←|⇶} listen ", l.Addr())
|
log.Print("{←|⇶} listen ", l.Addr())
|
||||||
|
@ -49,7 +51,7 @@ func Run() {
|
||||||
signal.Notify(sig, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
|
signal.Notify(sig, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
|
||||||
<-sig
|
<-sig
|
||||||
|
|
||||||
clts := l.Clts()
|
clts := l.clients()
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(len(clts))
|
wg.Add(len(clts))
|
||||||
|
@ -75,7 +77,7 @@ func Run() {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
cc, err := l.Accept()
|
cc, err := l.accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, net.ErrClosed) {
|
if errors.Is(err, net.ErrClosed) {
|
||||||
log.Print("{←|⇶} stop listening")
|
log.Print("{←|⇶} stop listening")
|
||||||
|
@ -139,7 +141,7 @@ func Run() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Connect(conn, Conf().Servers[0].Name, cc)
|
connect(conn, Conf().Servers[0].Name, cc)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/anon55555/mt/rudp"
|
"github.com/anon55555/mt/rudp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A ServerConn is a connection to a minetest server.
|
||||||
type ServerConn struct {
|
type ServerConn struct {
|
||||||
mt.Peer
|
mt.Peer
|
||||||
clt *ClientConn
|
clt *ClientConn
|
||||||
|
@ -63,8 +64,12 @@ func (sc *ServerConn) setState(state clientState) {
|
||||||
sc.cstate = state
|
sc.cstate = state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init returns a channel that is closed
|
||||||
|
// when the ServerConn enters the csActive state.
|
||||||
func (sc *ServerConn) Init() <-chan struct{} { return sc.initCh }
|
func (sc *ServerConn) Init() <-chan struct{} { return sc.initCh }
|
||||||
|
|
||||||
|
// Log logs an interaction with the ServerConn.
|
||||||
|
// dir indicates the direction of the interaction.
|
||||||
func (sc *ServerConn) Log(dir string, v ...interface{}) {
|
func (sc *ServerConn) Log(dir string, v ...interface{}) {
|
||||||
if sc.client() != nil {
|
if sc.client() != nil {
|
||||||
format := "%s {%s}"
|
format := "%s {%s}"
|
||||||
|
|
Loading…
Reference in New Issue