summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Matveev <stargrave@stargrave.org>2014-08-19 18:11:56 +0400
committerSergey Matveev <stargrave@stargrave.org>2014-08-19 18:11:56 +0400
commit990937d451208b0299246c46dd29adf7a35f97ee (patch)
treec68f04771257eb7d39957f42967d51f6a5379439
parent85e6538f2f610ad66bf0be0eff5bdcf05f1b8e3c (diff)
downloadgoircd-990937d451208b0299246c46dd29adf7a35f97ee.tar.xz
Remove signal processor for password reloading and use pointers to strings1.0
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.
-rw-r--r--client.go6
-rw-r--r--client_test.go6
-rw-r--r--daemon.go81
-rw-r--r--daemon_test.go11
-rw-r--r--goircd.go22
-rw-r--r--room.go10
-rw-r--r--room_test.go12
7 files changed, 66 insertions, 82 deletions
diff --git a/client.go b/client.go
index 4f48daf..3637d49 100644
--- 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
diff --git a/client_test.go b/client_test.go
index f9e3887..5369bbe 100644
--- a/client_test.go
+++ b/client_test.go
@@ -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")
diff --git a/daemon.go b/daemon.go
index 2bf696c..9b0d77f 100644
--- 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()
-}
diff --git a/daemon_test.go b/daemon_test.go
index d049e42..ac9bc4c 100644
--- a/daemon_test.go
+++ b/daemon_test.go
@@ -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") {
diff --git a/goircd.go b/goircd.go
index b0f5e07..13efe2c 100644
--- 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 ccfdb07..ff57231 100644
--- 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:
diff --git a/room_test.go b/room_test.go
index 6bd1cb0..3de4195 100644
--- a/room_test.go
+++ b/room_test.go
@@ -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"