]> Cypherpunks.ru repositories - goircd.git/commitdiff
Remove signal processor for password reloading and use pointers to strings 1.0
authorSergey Matveev <stargrave@stargrave.org>
Tue, 19 Aug 2014 14:11:56 +0000 (18:11 +0400)
committerSergey Matveev <stargrave@stargrave.org>
Tue, 19 Aug 2014 14:11:56 +0000 (18:11 +0400)
Simplify code and server maintaining by removing password file caching
and refreshing it with HUP signal. Also use pointers to strings, already
presented after flag-module work.

client.go
client_test.go
daemon.go
daemon_test.go
goircd.go
room.go
room_test.go

index 4f48daf90be4f1f0981b96f6e30ca04fa1f438a0..3637d499da5e245990241eaffb0efad337214600 100644 (file)
--- a/client.go
+++ b/client.go
@@ -31,7 +31,7 @@ const (
 )
 
 type Client struct {
-       hostname   string
+       hostname   *string
        conn       net.Conn
        registered bool
        nickname   string
@@ -49,7 +49,7 @@ func (client Client) String() string {
        return client.nickname + "!" + client.username + "@" + client.conn.RemoteAddr().String()
 }
 
-func NewClient(hostname string, conn net.Conn) *Client {
+func NewClient(hostname *string, conn net.Conn) *Client {
        return &Client{hostname: hostname, conn: conn, nickname: "*", password: ""}
 }
 
@@ -89,7 +89,7 @@ func (client *Client) Msg(text string) {
 
 // Send message from server. It has ": servername" prefix.
 func (client *Client) Reply(text string) {
-       client.Msg(":" + client.hostname + " " + text)
+       client.Msg(":" + *client.hostname + " " + text)
 }
 
 // Send server message, concatenating all provided text parts and
index f9e3887b5b0fc782d99b7df5ddb020161bea830a..5369bbeff4888a40590fdced2f49ae31ccfc2289 100644 (file)
@@ -96,7 +96,8 @@ func (conn TestingConn) SetWriteDeadline(t time.Time) error {
 func TestNewClient(t *testing.T) {
        conn := NewTestingConn()
        sink := make(chan ClientEvent)
-       client := NewClient("foohost", conn)
+       host := "foohost"
+       client := NewClient(&host, conn)
        go client.Processor(sink)
 
        event := <-sink
@@ -123,7 +124,8 @@ func TestNewClient(t *testing.T) {
 // Test replies formatting
 func TestClientReplies(t *testing.T) {
        conn := NewTestingConn()
-       client := NewClient("foohost", conn)
+       host := "foohost"
+       client := NewClient(&host, conn)
        client.nickname = "мойник"
 
        client.Reply("hello")
index 2bf696ce31229c86a744f0ee64d4c9f287894d32..9b0d77f500c0614cafe33121e5b19c81bf9dae07 100644 (file)
--- a/daemon.go
+++ b/daemon.go
@@ -25,7 +25,6 @@ import (
        "regexp"
        "sort"
        "strings"
-       "sync"
        "time"
 )
 
@@ -39,13 +38,12 @@ var (
        RENickname = regexp.MustCompile("^[a-zA-Z0-9-]{1,9}$")
 )
 
-var passwordsRefreshLock sync.Mutex
-
 type Daemon struct {
        Verbose            bool
        version            string
-       hostname           string
-       motd               string
+       hostname           *string
+       motd               *string
+       passwords          *string
        clients            map[*Client]bool
        clientAliveness    map[*Client]*ClientAlivenessState
        rooms              map[string]*Room
@@ -53,11 +51,10 @@ type Daemon struct {
        lastAlivenessCheck time.Time
        logSink            chan<- LogEvent
        stateSink          chan<- StateEvent
-       passwords          map[string]string
 }
 
-func NewDaemon(version, hostname, motd string, logSink chan<- LogEvent, stateSink chan<- StateEvent) *Daemon {
-       daemon := Daemon{version: version, hostname: hostname, motd: motd}
+func NewDaemon(version string, hostname, motd, passwords *string, logSink chan<- LogEvent, stateSink chan<- StateEvent) *Daemon {
+       daemon := Daemon{version: version, hostname: hostname, motd: motd, passwords: passwords}
        daemon.clients = make(map[*Client]bool)
        daemon.clientAliveness = make(map[*Client]*ClientAlivenessState)
        daemon.rooms = make(map[string]*Room)
@@ -78,19 +75,19 @@ func (daemon *Daemon) SendLusers(client *Client) {
 }
 
 func (daemon *Daemon) SendMotd(client *Client) {
-       if len(daemon.motd) == 0 {
+       if daemon.motd == nil || *daemon.motd == "" {
                client.ReplyNicknamed("422", "MOTD File is missing")
                return
        }
 
-       motd, err := ioutil.ReadFile(daemon.motd)
+       motd, err := ioutil.ReadFile(*daemon.motd)
        if err != nil {
-               log.Printf("Can not read motd file %s: %v", daemon.motd, err)
+               log.Printf("Can not read motd file %s: %v", *daemon.motd, err)
                client.ReplyNicknamed("422", "Error reading MOTD File")
                return
        }
 
-       client.ReplyNicknamed("375", "- "+daemon.hostname+" Message of the day -")
+       client.ReplyNicknamed("375", "- "+*daemon.hostname+" Message of the day -")
        for _, s := range strings.Split(strings.Trim(string(motd), "\n"), "\n") {
                client.ReplyNicknamed("372", "- "+string(s))
        }
@@ -113,7 +110,7 @@ func (daemon *Daemon) SendWhois(client *Client, nicknames []string) {
                                h = "Unknown"
                        }
                        client.ReplyNicknamed("311", c.nickname, c.username, h, "*", c.realname)
-                       client.ReplyNicknamed("312", c.nickname, daemon.hostname, daemon.hostname)
+                       client.ReplyNicknamed("312", c.nickname, *daemon.hostname, *daemon.hostname)
                        subscriptions := []string{}
                        for _, room := range daemon.rooms {
                                for subscriber := range room.members {
@@ -196,19 +193,34 @@ func (daemon *Daemon) ClientRegister(client *Client, command string, cols []stri
                client.realname = strings.TrimLeft(args[3], ":")
        }
        if client.nickname != "*" && client.username != "" {
-               passwordsRefreshLock.Lock()
-               if daemon.passwords != nil && (client.password == "" || daemon.passwords[client.nickname] != client.password) {
-                       passwordsRefreshLock.Unlock()
-                       client.ReplyParts("462", "You may not register")
-                       client.conn.Close()
-                       return
+               if daemon.passwords != nil && *daemon.passwords != "" {
+                       if client.password == "" {
+                               client.ReplyParts("462", "You may not register")
+                               client.conn.Close()
+                               return
+                       }
+                       contents, err := ioutil.ReadFile(*daemon.passwords)
+                       if err != nil {
+                               log.Fatalf("Can no read passwords file %s: %s", *daemon.passwords, err)
+                               return
+                       }
+                       for _, entry := range strings.Split(string(contents), "\n") {
+                               if entry == "" {
+                                       continue
+                               }
+                               if lp := strings.Split(entry, ":"); lp[0] == client.nickname && lp[1] != client.password {
+                                       client.ReplyParts("462", "You may not register")
+                                       client.conn.Close()
+                                       return
+                               }
+                       }
                }
-               passwordsRefreshLock.Unlock()
+
                client.registered = true
                client.ReplyNicknamed("001", "Hi, welcome to IRC")
-               client.ReplyNicknamed("002", "Your host is "+daemon.hostname+", running goircd "+daemon.version)
+               client.ReplyNicknamed("002", "Your host is "+*daemon.hostname+", running goircd "+daemon.version)
                client.ReplyNicknamed("003", "This server was created sometime")
-               client.ReplyNicknamed("004", daemon.hostname+" goircd o o")
+               client.ReplyNicknamed("004", *daemon.hostname+" goircd o o")
                daemon.SendLusers(client)
                daemon.SendMotd(client)
                log.Println(client, "logged in")
@@ -295,7 +307,7 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
                                }
                                if !aliveness.pingSent && aliveness.timestamp.Add(PingThreshold).Before(now) {
                                        if c.registered {
-                                               c.Msg("PING :" + daemon.hostname)
+                                               c.Msg("PING :" + *daemon.hostname)
                                                aliveness.pingSent = true
                                        } else {
                                                log.Println(c, "ping timeout")
@@ -391,7 +403,7 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
                                        client.ReplyNicknamed("409", "No origin specified")
                                        continue
                                }
-                               client.Reply(fmt.Sprintf("PONG %s :%s", daemon.hostname, cols[1]))
+                               client.Reply(fmt.Sprintf("PONG %s :%s", *daemon.hostname, cols[1]))
                        case "PONG":
                                continue
                        case "NOTICE", "PRIVMSG":
@@ -466,7 +478,7 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
                                } else {
                                        debug = ""
                                }
-                               client.ReplyNicknamed("351", fmt.Sprintf("%s.%s %s :", daemon.version, debug, daemon.hostname))
+                               client.ReplyNicknamed("351", fmt.Sprintf("%s.%s %s :", daemon.version, debug, *daemon.hostname))
                        default:
                                client.ReplyNicknamed("421", command, "Unknown command")
                        }
@@ -477,22 +489,3 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
                }
        }
 }
-
-func (daemon *Daemon) PasswordsRefresh() {
-       contents, err := ioutil.ReadFile(*passwords)
-       if err != nil {
-               log.Fatalf("Can no read passwords file %s: %s", *passwords, err)
-               return
-       }
-       processed := make(map[string]string)
-       for _, entry := range strings.Split(string(contents), "\n") {
-               loginAndPassword := strings.Split(entry, ":")
-               if len(loginAndPassword) == 2 {
-                       processed[loginAndPassword[0]] = loginAndPassword[1]
-               }
-       }
-       log.Printf("Read %d passwords", len(processed))
-       passwordsRefreshLock.Lock()
-       daemon.passwords = processed
-       passwordsRefreshLock.Unlock()
-}
index d049e42be2f38abe06aad2806b85ed659adddb22..ac9bc4cfc3ec5c8ac351db2fe961134b6c98fc31 100644 (file)
@@ -25,11 +25,12 @@ import (
 )
 
 func TestRegistrationWorkflow(t *testing.T) {
-       daemon := NewDaemon("ver1", "foohost", "", nil, nil)
+       host := "foohost"
+       daemon := NewDaemon("ver1", &host, nil, nil, nil, nil)
        events := make(chan ClientEvent)
        go daemon.Processor(events)
        conn := NewTestingConn()
-       client := NewClient("foohost", conn)
+       client := NewClient(&host, conn)
        go client.Processor(events)
 
        conn.inbound <- "UNEXISTENT CMD" // should recieve nothing on this
@@ -119,8 +120,10 @@ func TestMotd(t *testing.T) {
        fd.WriteString("catched\n")
 
        conn := NewTestingConn()
-       client := NewClient("foohost", conn)
-       daemon := NewDaemon("ver1", "foohost", fd.Name(), nil, nil)
+       host := "foohost"
+       client := NewClient(&host, conn)
+       motdName := fd.Name()
+       daemon := NewDaemon("ver1", &host, &motdName, nil, nil, nil)
 
        daemon.SendMotd(client)
        if r := <-conn.outbound; !strings.HasPrefix(r, ":foohost 375") {
index b0f5e07716db40625c08378d046670c9154c68d8..13efe2c9c5cca7dc790e522cb7bb17032b493bd6 100644 (file)
--- a/goircd.go
+++ b/goircd.go
@@ -23,12 +23,9 @@ import (
        "io/ioutil"
        "log"
        "net"
-       "os"
-       "os/signal"
        "path"
        "path/filepath"
        "strings"
-       "syscall"
 )
 
 var (
@@ -53,7 +50,7 @@ func listenerLoop(sock net.Listener, events chan<- ClientEvent) {
                        log.Println("Error during accepting connection", err)
                        continue
                }
-               client := NewClient(*hostname, conn)
+               client := NewClient(hostname, conn)
                go client.Processor(events)
        }
 }
@@ -79,9 +76,9 @@ func Run() {
        }
 
        stateSink := make(chan StateEvent)
-       daemon := NewDaemon(version, *hostname, *motd, logSink, stateSink)
+       daemon := NewDaemon(version, hostname, motd, passwords, logSink, stateSink)
        daemon.Verbose = *verbose
-       log.Println("goircd "+daemon.version+" is starting")
+       log.Println("goircd " + daemon.version + " is starting")
        if *statedir == "" {
                // Dummy statekeeper
                go func() {
@@ -115,19 +112,6 @@ func Run() {
                log.Println(*statedir, "statekeeper initialized")
        }
 
-       if *passwords != "" {
-               daemon.PasswordsRefresh()
-               hups := make(chan os.Signal)
-               signal.Notify(hups, syscall.SIGHUP)
-               go func() {
-                       for {
-                               <-hups
-                               daemon.PasswordsRefresh()
-                       }
-               }()
-       }
-
-
        if *bind != "" {
                listener, err := net.Listen("tcp", *bind)
                if err != nil {
diff --git a/room.go b/room.go
index ccfdb077b24b638d3a83adf1bbaa692fc4ab49a7..ff572316134806fdf3474d046bb152ec7a322147 100644 (file)
--- a/room.go
+++ b/room.go
@@ -41,16 +41,16 @@ type Room struct {
        topic     string
        key       string
        members   map[*Client]bool
-       hostname  string
+       hostname  *string
        logSink   chan<- LogEvent
        stateSink chan<- StateEvent
 }
 
-func (r Room) String() string {
-       return r.name
+func (room Room) String() string {
+       return room.name
 }
 
-func NewRoom(hostname, name string, logSink chan<- LogEvent, stateSink chan<- StateEvent) *Room {
+func NewRoom(hostname *string, name string, logSink chan<- LogEvent, stateSink chan<- StateEvent) *Room {
        room := Room{name: name}
        room.members = make(map[*Client]bool)
        room.topic = ""
@@ -128,7 +128,7 @@ func (room *Room) Processor(events <-chan ClientEvent) {
                        room.StateSave()
                case EventWho:
                        for m := range room.members {
-                               client.ReplyNicknamed("352", room.name, m.username, m.conn.RemoteAddr().String(), room.hostname, m.nickname, "H", "0 "+m.realname)
+                               client.ReplyNicknamed("352", room.name, m.username, m.conn.RemoteAddr().String(), *room.hostname, m.nickname, "H", "0 "+m.realname)
                        }
                        client.ReplyNicknamed("315", room.name, "End of /WHO list")
                case EventMode:
index 6bd1cb06464af365622445d515a661ac78f36e91..3de419550ac0b0082b18776e8b45eb14ac467dc5 100644 (file)
@@ -26,14 +26,15 @@ func notEnoughParams(t *testing.T, c *TestingConn) {
 func TestTwoUsers(t *testing.T) {
        logSink := make(chan LogEvent, 8)
        stateSink := make(chan StateEvent, 8)
-       daemon := NewDaemon("ver1", "foohost", "", logSink, stateSink)
+       host := "foohost"
+       daemon := NewDaemon("ver1", &host, nil, nil, logSink, stateSink)
        events := make(chan ClientEvent)
        go daemon.Processor(events)
 
        conn1 := NewTestingConn()
        conn2 := NewTestingConn()
-       client1 := NewClient("foohost", conn1)
-       client2 := NewClient("foohost", conn2)
+       client1 := NewClient(&host, conn1)
+       client2 := NewClient(&host, conn2)
        go client1.Processor(events)
        go client2.Processor(events)
 
@@ -100,11 +101,12 @@ func TestTwoUsers(t *testing.T) {
 func TestJoin(t *testing.T) {
        logSink := make(chan LogEvent, 8)
        stateSink := make(chan StateEvent, 8)
-       daemon := NewDaemon("ver1", "foohost", "", logSink, stateSink)
+       host := "foohost"
+       daemon := NewDaemon("ver1", &host, nil, nil, logSink, stateSink)
        events := make(chan ClientEvent)
        go daemon.Processor(events)
        conn := NewTestingConn()
-       client := NewClient("foohost", conn)
+       client := NewClient(&host, conn)
        go client.Processor(events)
 
        conn.inbound <- "NICK nick2\r\nUSER foo2 bar2 baz2 :Long name2\r\n"