Golinting
This commit is contained in:
parent
def74ddc09
commit
cfeaaad88f
22
client.go
22
client.go
@ -26,8 +26,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CRLF = "\x0d\x0a"
|
CRLF = "\x0d\x0a"
|
||||||
BUF_SIZE = 1380
|
BufSize = 1380
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
@ -40,7 +40,7 @@ type Client struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ClientAlivenessState struct {
|
type ClientAlivenessState struct {
|
||||||
ping_sent bool
|
pingSent bool
|
||||||
timestamp time.Time
|
timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,26 +56,26 @@ func NewClient(hostname string, conn net.Conn) *Client {
|
|||||||
// splits messages by CRLF and send them to Daemon gorouting for processing
|
// splits messages by CRLF and send them to Daemon gorouting for processing
|
||||||
// it futher. Also it can signalize that client is unavailable (disconnected).
|
// it futher. Also it can signalize that client is unavailable (disconnected).
|
||||||
func (client *Client) Processor(sink chan<- ClientEvent) {
|
func (client *Client) Processor(sink chan<- ClientEvent) {
|
||||||
var buf_net []byte
|
var bufNet []byte
|
||||||
buf := make([]byte, 0)
|
buf := make([]byte, 0)
|
||||||
log.Println(client, "New client")
|
log.Println(client, "New client")
|
||||||
sink <- ClientEvent{client, EVENT_NEW, ""}
|
sink <- ClientEvent{client, EventNew, ""}
|
||||||
for {
|
for {
|
||||||
buf_net = make([]byte, BUF_SIZE)
|
bufNet = make([]byte, BufSize)
|
||||||
_, err := client.conn.Read(buf_net)
|
_, err := client.conn.Read(bufNet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(client, "connection lost", err)
|
log.Println(client, "connection lost", err)
|
||||||
sink <- ClientEvent{client, EVENT_DEL, ""}
|
sink <- ClientEvent{client, EventDel, ""}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
buf_net = bytes.TrimRight(buf_net, "\x00")
|
bufNet = bytes.TrimRight(bufNet, "\x00")
|
||||||
buf = append(buf, buf_net...)
|
buf = append(buf, bufNet...)
|
||||||
if !bytes.HasSuffix(buf, []byte(CRLF)) {
|
if !bytes.HasSuffix(buf, []byte(CRLF)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, msg := range bytes.Split(buf[:len(buf)-2], []byte(CRLF)) {
|
for _, msg := range bytes.Split(buf[:len(buf)-2], []byte(CRLF)) {
|
||||||
if len(msg) > 0 {
|
if len(msg) > 0 {
|
||||||
sink <- ClientEvent{client, EVENT_MSG, string(msg)}
|
sink <- ClientEvent{client, EventMsg, string(msg)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf = []byte{}
|
buf = []byte{}
|
||||||
|
@ -100,22 +100,22 @@ func TestNewClient(t *testing.T) {
|
|||||||
go client.Processor(sink)
|
go client.Processor(sink)
|
||||||
|
|
||||||
event := <-sink
|
event := <-sink
|
||||||
if event.event_type != EVENT_NEW {
|
if event.eventType != EventNew {
|
||||||
t.Fatal("no NEW event", event)
|
t.Fatal("no NEW event", event)
|
||||||
}
|
}
|
||||||
conn.inbound <- "foo"
|
conn.inbound <- "foo"
|
||||||
event = <-sink
|
event = <-sink
|
||||||
if (event.event_type != EVENT_MSG) || (event.text != "foo") {
|
if (event.eventType != EventMsg) || (event.text != "foo") {
|
||||||
t.Fatal("no first MSG", event)
|
t.Fatal("no first MSG", event)
|
||||||
}
|
}
|
||||||
conn.inbound <- "bar"
|
conn.inbound <- "bar"
|
||||||
event = <-sink
|
event = <-sink
|
||||||
if (event.event_type != EVENT_MSG) || (event.text != "bar") {
|
if (event.eventType != EventMsg) || (event.text != "bar") {
|
||||||
t.Fatal("no second MSG", event)
|
t.Fatal("no second MSG", event)
|
||||||
}
|
}
|
||||||
conn.inbound <- ""
|
conn.inbound <- ""
|
||||||
event = <-sink
|
event = <-sink
|
||||||
if event.event_type != EVENT_DEL {
|
if event.eventType != EventDel {
|
||||||
t.Fatal("no client termination", event)
|
t.Fatal("no client termination", event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
120
daemon.go
120
daemon.go
@ -29,36 +29,36 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PING_TIMEOUT = time.Second * 180 // Max time deadline for client's unresponsiveness
|
PingTimeout = time.Second * 180 // Max time deadline for client's unresponsiveness
|
||||||
PING_THRESHOLD = time.Second * 90 // Max idle client's time before PING are sent
|
PingThreshold = time.Second * 90 // Max idle client's time before PING are sent
|
||||||
ALIVENESS_CHECK = time.Second * 10 // Client's aliveness check period
|
AlivenessCheck = time.Second * 10 // Client's aliveness check period
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
RE_NICKNAME = regexp.MustCompile("^[a-zA-Z0-9-]{1,9}$")
|
RENickname = regexp.MustCompile("^[a-zA-Z0-9-]{1,9}$")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Daemon struct {
|
type Daemon struct {
|
||||||
Verbose bool
|
Verbose bool
|
||||||
hostname string
|
hostname string
|
||||||
motd string
|
motd string
|
||||||
clients map[*Client]bool
|
clients map[*Client]bool
|
||||||
client_aliveness map[*Client]*ClientAlivenessState
|
clientAliveness map[*Client]*ClientAlivenessState
|
||||||
rooms map[string]*Room
|
rooms map[string]*Room
|
||||||
room_sinks map[*Room]chan ClientEvent
|
roomSinks map[*Room]chan ClientEvent
|
||||||
last_aliveness_check time.Time
|
lastAlivenessCheck time.Time
|
||||||
log_sink chan<- LogEvent
|
logSink chan<- LogEvent
|
||||||
state_sink chan<- StateEvent
|
stateSink chan<- StateEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDaemon(hostname, motd string, log_sink chan<- LogEvent, state_sink chan<- StateEvent) *Daemon {
|
func NewDaemon(hostname, motd string, logSink chan<- LogEvent, stateSink chan<- StateEvent) *Daemon {
|
||||||
daemon := Daemon{hostname: hostname, motd: motd}
|
daemon := Daemon{hostname: hostname, motd: motd}
|
||||||
daemon.clients = make(map[*Client]bool)
|
daemon.clients = make(map[*Client]bool)
|
||||||
daemon.client_aliveness = make(map[*Client]*ClientAlivenessState)
|
daemon.clientAliveness = make(map[*Client]*ClientAlivenessState)
|
||||||
daemon.rooms = make(map[string]*Room)
|
daemon.rooms = make(map[string]*Room)
|
||||||
daemon.room_sinks = make(map[*Room]chan ClientEvent)
|
daemon.roomSinks = make(map[*Room]chan ClientEvent)
|
||||||
daemon.log_sink = log_sink
|
daemon.logSink = logSink
|
||||||
daemon.state_sink = state_sink
|
daemon.stateSink = stateSink
|
||||||
return &daemon
|
return &daemon
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,13 +160,13 @@ func (daemon *Daemon) ClientRegister(client *Client, command string, cols []stri
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
nickname := cols[1]
|
nickname := cols[1]
|
||||||
for existing_client := range daemon.clients {
|
for existingClient := range daemon.clients {
|
||||||
if existing_client.nickname == nickname {
|
if existingClient.nickname == nickname {
|
||||||
client.ReplyParts("433", "*", nickname, "Nickname is already in use")
|
client.ReplyParts("433", "*", nickname, "Nickname is already in use")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !RE_NICKNAME.MatchString(nickname) {
|
if !RENickname.MatchString(nickname) {
|
||||||
client.ReplyParts("432", "*", cols[1], "Erroneous nickname")
|
client.ReplyParts("432", "*", cols[1], "Erroneous nickname")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -198,13 +198,13 @@ func (daemon *Daemon) ClientRegister(client *Client, command string, cols []stri
|
|||||||
// Register new room in Daemon. Create an object, events sink, save pointers
|
// Register new room in Daemon. Create an object, events sink, save pointers
|
||||||
// to corresponding daemon's places and start room's processor goroutine.
|
// to corresponding daemon's places and start room's processor goroutine.
|
||||||
func (daemon *Daemon) RoomRegister(name string) (*Room, chan<- ClientEvent) {
|
func (daemon *Daemon) RoomRegister(name string) (*Room, chan<- ClientEvent) {
|
||||||
room_new := NewRoom(daemon.hostname, name, daemon.log_sink, daemon.state_sink)
|
roomNew := NewRoom(daemon.hostname, name, daemon.logSink, daemon.stateSink)
|
||||||
room_new.Verbose = daemon.Verbose
|
roomNew.Verbose = daemon.Verbose
|
||||||
room_sink := make(chan ClientEvent)
|
roomSink := make(chan ClientEvent)
|
||||||
daemon.rooms[name] = room_new
|
daemon.rooms[name] = roomNew
|
||||||
daemon.room_sinks[room_new] = room_sink
|
daemon.roomSinks[roomNew] = roomSink
|
||||||
go room_new.Processor(room_sink)
|
go roomNew.Processor(roomSink)
|
||||||
return room_new, room_sink
|
return roomNew, roomSink
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) HandlerJoin(client *Client, cmd string) {
|
func (daemon *Daemon) HandlerJoin(client *Client, cmd string) {
|
||||||
@ -229,12 +229,12 @@ func (daemon *Daemon) HandlerJoin(client *Client, cmd string) {
|
|||||||
}
|
}
|
||||||
denied := false
|
denied := false
|
||||||
joined := false
|
joined := false
|
||||||
for room_existing, room_sink := range daemon.room_sinks {
|
for roomExisting, roomSink := range daemon.roomSinks {
|
||||||
if room == room_existing.name {
|
if room == roomExisting.name {
|
||||||
if (room_existing.key != "") && (room_existing.key != key) {
|
if (roomExisting.key != "") && (roomExisting.key != key) {
|
||||||
denied = true
|
denied = true
|
||||||
} else {
|
} else {
|
||||||
room_sink <- ClientEvent{client, EVENT_NEW, ""}
|
roomSink <- ClientEvent{client, EventNew, ""}
|
||||||
joined = true
|
joined = true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@ -246,12 +246,12 @@ func (daemon *Daemon) HandlerJoin(client *Client, cmd string) {
|
|||||||
if denied || joined {
|
if denied || joined {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
room_new, room_sink := daemon.RoomRegister(room)
|
roomNew, roomSink := daemon.RoomRegister(room)
|
||||||
if key != "" {
|
if key != "" {
|
||||||
room_new.key = key
|
roomNew.key = key
|
||||||
room_new.StateSave()
|
roomNew.StateSave()
|
||||||
}
|
}
|
||||||
room_sink <- ClientEvent{client, EVENT_NEW, ""}
|
roomSink <- ClientEvent{client, EventNew, ""}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,41 +261,41 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
|
|||||||
client := event.client
|
client := event.client
|
||||||
|
|
||||||
// Check for clients aliveness
|
// Check for clients aliveness
|
||||||
if daemon.last_aliveness_check.Add(ALIVENESS_CHECK).Before(now) {
|
if daemon.lastAlivenessCheck.Add(AlivenessCheck).Before(now) {
|
||||||
for c := range daemon.clients {
|
for c := range daemon.clients {
|
||||||
aliveness, alive := daemon.client_aliveness[c]
|
aliveness, alive := daemon.clientAliveness[c]
|
||||||
if !alive {
|
if !alive {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if aliveness.timestamp.Add(PING_TIMEOUT).Before(now) {
|
if aliveness.timestamp.Add(PingTimeout).Before(now) {
|
||||||
log.Println(c, "ping timeout")
|
log.Println(c, "ping timeout")
|
||||||
c.conn.Close()
|
c.conn.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !aliveness.ping_sent && aliveness.timestamp.Add(PING_THRESHOLD).Before(now) {
|
if !aliveness.pingSent && aliveness.timestamp.Add(PingThreshold).Before(now) {
|
||||||
if c.registered {
|
if c.registered {
|
||||||
c.Msg("PING :" + daemon.hostname)
|
c.Msg("PING :" + daemon.hostname)
|
||||||
aliveness.ping_sent = true
|
aliveness.pingSent = true
|
||||||
} else {
|
} else {
|
||||||
log.Println(c, "ping timeout")
|
log.Println(c, "ping timeout")
|
||||||
c.conn.Close()
|
c.conn.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
daemon.last_aliveness_check = now
|
daemon.lastAlivenessCheck = now
|
||||||
}
|
}
|
||||||
|
|
||||||
switch event.event_type {
|
switch event.eventType {
|
||||||
case EVENT_NEW:
|
case EventNew:
|
||||||
daemon.clients[client] = true
|
daemon.clients[client] = true
|
||||||
daemon.client_aliveness[client] = &ClientAlivenessState{ping_sent: false, timestamp: now}
|
daemon.clientAliveness[client] = &ClientAlivenessState{pingSent: false, timestamp: now}
|
||||||
case EVENT_DEL:
|
case EventDel:
|
||||||
delete(daemon.clients, client)
|
delete(daemon.clients, client)
|
||||||
delete(daemon.client_aliveness, client)
|
delete(daemon.clientAliveness, client)
|
||||||
for _, room_sink := range daemon.room_sinks {
|
for _, roomSink := range daemon.roomSinks {
|
||||||
room_sink <- event
|
roomSink <- event
|
||||||
}
|
}
|
||||||
case EVENT_MSG:
|
case EventMsg:
|
||||||
cols := strings.SplitN(event.text, " ", 2)
|
cols := strings.SplitN(event.text, " ", 2)
|
||||||
command := strings.ToUpper(cols[0])
|
command := strings.ToUpper(cols[0])
|
||||||
if daemon.Verbose {
|
if daemon.Verbose {
|
||||||
@ -303,7 +303,7 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
|
|||||||
}
|
}
|
||||||
if command == "QUIT" {
|
if command == "QUIT" {
|
||||||
delete(daemon.clients, client)
|
delete(daemon.clients, client)
|
||||||
delete(daemon.client_aliveness, client)
|
delete(daemon.clientAliveness, client)
|
||||||
client.conn.Close()
|
client.conn.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -345,9 +345,9 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(cols) == 1 {
|
if len(cols) == 1 {
|
||||||
daemon.room_sinks[r] <- ClientEvent{client, EVENT_MODE, ""}
|
daemon.roomSinks[r] <- ClientEvent{client, EventMode, ""}
|
||||||
} else {
|
} else {
|
||||||
daemon.room_sinks[r] <- ClientEvent{client, EVENT_MODE, cols[1]}
|
daemon.roomSinks[r] <- ClientEvent{client, EventMode, cols[1]}
|
||||||
}
|
}
|
||||||
case "MOTD":
|
case "MOTD":
|
||||||
go daemon.SendMotd(client)
|
go daemon.SendMotd(client)
|
||||||
@ -362,7 +362,7 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
|
|||||||
client.ReplyNoChannel(room)
|
client.ReplyNoChannel(room)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
daemon.room_sinks[r] <- ClientEvent{client, EVENT_DEL, ""}
|
daemon.roomSinks[r] <- ClientEvent{client, EventDel, ""}
|
||||||
}
|
}
|
||||||
case "PING":
|
case "PING":
|
||||||
if len(cols) == 1 {
|
if len(cols) == 1 {
|
||||||
@ -398,7 +398,7 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
|
|||||||
if !found {
|
if !found {
|
||||||
client.ReplyNoNickChan(target)
|
client.ReplyNoNickChan(target)
|
||||||
}
|
}
|
||||||
daemon.room_sinks[r] <- ClientEvent{client, EVENT_MSG, command + " " + strings.TrimLeft(cols[1], ":")}
|
daemon.roomSinks[r] <- ClientEvent{client, EventMsg, command + " " + strings.TrimLeft(cols[1], ":")}
|
||||||
case "TOPIC":
|
case "TOPIC":
|
||||||
if len(cols) == 1 {
|
if len(cols) == 1 {
|
||||||
client.ReplyNotEnoughParameters("TOPIC")
|
client.ReplyNotEnoughParameters("TOPIC")
|
||||||
@ -416,7 +416,7 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
|
|||||||
} else {
|
} else {
|
||||||
change = ""
|
change = ""
|
||||||
}
|
}
|
||||||
daemon.room_sinks[r] <- ClientEvent{client, EVENT_TOPIC, change}
|
daemon.roomSinks[r] <- ClientEvent{client, EventTopic, change}
|
||||||
case "WHO":
|
case "WHO":
|
||||||
if len(cols) == 1 || len(cols[1]) < 1 {
|
if len(cols) == 1 || len(cols[1]) < 1 {
|
||||||
client.ReplyNotEnoughParameters("WHO")
|
client.ReplyNotEnoughParameters("WHO")
|
||||||
@ -428,7 +428,7 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
|
|||||||
client.ReplyNoChannel(room)
|
client.ReplyNoChannel(room)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
daemon.room_sinks[r] <- ClientEvent{client, EVENT_WHO, ""}
|
daemon.roomSinks[r] <- ClientEvent{client, EventWho, ""}
|
||||||
case "WHOIS":
|
case "WHOIS":
|
||||||
if len(cols) == 1 || len(cols[1]) < 1 {
|
if len(cols) == 1 || len(cols[1]) < 1 {
|
||||||
client.ReplyNotEnoughParameters("WHOIS")
|
client.ReplyNotEnoughParameters("WHOIS")
|
||||||
@ -441,9 +441,9 @@ func (daemon *Daemon) Processor(events <-chan ClientEvent) {
|
|||||||
client.ReplyNicknamed("421", command, "Unknown command")
|
client.ReplyNicknamed("421", command, "Unknown command")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if aliveness, alive := daemon.client_aliveness[client]; alive {
|
if aliveness, alive := daemon.clientAliveness[client]; alive {
|
||||||
aliveness.timestamp = now
|
aliveness.timestamp = now
|
||||||
aliveness.ping_sent = false
|
aliveness.pingSent = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
events.go
28
events.go
@ -27,26 +27,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EVENT_NEW = iota
|
EventNew = iota
|
||||||
EVENT_DEL = iota
|
EventDel = iota
|
||||||
EVENT_MSG = iota
|
EventMsg = iota
|
||||||
EVENT_TOPIC = iota
|
EventTopic = iota
|
||||||
EVENT_WHO = iota
|
EventWho = iota
|
||||||
EVENT_MODE = iota
|
EventMode = iota
|
||||||
FORMAT_MSG = "[%s] <%s> %s\n"
|
FormatMsg = "[%s] <%s> %s\n"
|
||||||
FORMAT_META = "[%s] * %s %s\n"
|
FormatMeta = "[%s] * %s %s\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client events going from each of client
|
// Client events going from each of client
|
||||||
// They can be either NEW, DEL or unparsed MSG
|
// They can be either NEW, DEL or unparsed MSG
|
||||||
type ClientEvent struct {
|
type ClientEvent struct {
|
||||||
client *Client
|
client *Client
|
||||||
event_type int
|
eventType int
|
||||||
text string
|
text string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m ClientEvent) String() string {
|
func (m ClientEvent) String() string {
|
||||||
return string(m.event_type) + ": " + m.client.String() + ": " + m.text
|
return string(m.eventType) + ": " + m.client.String() + ": " + m.text
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging in-room events
|
// Logging in-room events
|
||||||
@ -73,9 +73,9 @@ func Logger(logdir string, events <-chan LogEvent) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if event.meta {
|
if event.meta {
|
||||||
format = FORMAT_META
|
format = FormatMeta
|
||||||
} else {
|
} else {
|
||||||
format = FORMAT_MSG
|
format = FormatMsg
|
||||||
}
|
}
|
||||||
_, err = fd.WriteString(fmt.Sprintf(format, time.Now(), event.who, event.what))
|
_, err = fd.WriteString(fmt.Sprintf(format, time.Now(), event.who, event.what))
|
||||||
fd.Close()
|
fd.Close()
|
||||||
|
14
goircd.go
14
goircd.go
@ -46,11 +46,11 @@ func Run() {
|
|||||||
events := make(chan ClientEvent)
|
events := make(chan ClientEvent)
|
||||||
log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
|
log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
|
||||||
|
|
||||||
log_sink := make(chan LogEvent)
|
logSink := make(chan LogEvent)
|
||||||
if *logdir == "" {
|
if *logdir == "" {
|
||||||
// Dummy logger
|
// Dummy logger
|
||||||
go func() {
|
go func() {
|
||||||
for _ = range log_sink {
|
for _ = range logSink {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
} else {
|
} else {
|
||||||
@ -58,17 +58,17 @@ func Run() {
|
|||||||
log.Fatalln("Need absolute path for logdir")
|
log.Fatalln("Need absolute path for logdir")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go Logger(*logdir, log_sink)
|
go Logger(*logdir, logSink)
|
||||||
log.Println(*logdir, "logger initialized")
|
log.Println(*logdir, "logger initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
state_sink := make(chan StateEvent)
|
stateSink := make(chan StateEvent)
|
||||||
daemon := NewDaemon(*hostname, *motd, log_sink, state_sink)
|
daemon := NewDaemon(*hostname, *motd, logSink, stateSink)
|
||||||
daemon.Verbose = *verbose
|
daemon.Verbose = *verbose
|
||||||
if *statedir == "" {
|
if *statedir == "" {
|
||||||
// Dummy statekeeper
|
// Dummy statekeeper
|
||||||
go func() {
|
go func() {
|
||||||
for _ = range state_sink {
|
for _ = range stateSink {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
} else {
|
} else {
|
||||||
@ -94,7 +94,7 @@ func Run() {
|
|||||||
log.Println("Loaded state for room", room.name)
|
log.Println("Loaded state for room", room.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
go StateKeeper(*statedir, state_sink)
|
go StateKeeper(*statedir, stateSink)
|
||||||
log.Println(*statedir, "statekeeper initialized")
|
log.Println(*statedir, "statekeeper initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
62
room.go
62
room.go
@ -26,34 +26,34 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
RE_ROOM = regexp.MustCompile("^#[^\x00\x07\x0a\x0d ,:/]{1,200}$")
|
RERoom = regexp.MustCompile("^#[^\x00\x07\x0a\x0d ,:/]{1,200}$")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sanitize room's name. It can consist of 1 to 50 ASCII symbols
|
// Sanitize room's name. It can consist of 1 to 50 ASCII symbols
|
||||||
// with some exclusions. All room names will have "#" prefix.
|
// with some exclusions. All room names will have "#" prefix.
|
||||||
func RoomNameValid(name string) bool {
|
func RoomNameValid(name string) bool {
|
||||||
return RE_ROOM.MatchString(name)
|
return RERoom.MatchString(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Room struct {
|
type Room struct {
|
||||||
Verbose bool
|
Verbose bool
|
||||||
name string
|
name string
|
||||||
topic string
|
topic string
|
||||||
key string
|
key string
|
||||||
members map[*Client]bool
|
members map[*Client]bool
|
||||||
hostname string
|
hostname string
|
||||||
log_sink chan<- LogEvent
|
logSink chan<- LogEvent
|
||||||
state_sink chan<- StateEvent
|
stateSink chan<- StateEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRoom(hostname, name string, log_sink chan<- LogEvent, state_sink chan<- StateEvent) *Room {
|
func NewRoom(hostname, name string, logSink chan<- LogEvent, stateSink chan<- StateEvent) *Room {
|
||||||
room := Room{name: name}
|
room := Room{name: name}
|
||||||
room.members = make(map[*Client]bool)
|
room.members = make(map[*Client]bool)
|
||||||
room.topic = ""
|
room.topic = ""
|
||||||
room.key = ""
|
room.key = ""
|
||||||
room.hostname = hostname
|
room.hostname = hostname
|
||||||
room.log_sink = log_sink
|
room.logSink = logSink
|
||||||
room.state_sink = state_sink
|
room.stateSink = stateSink
|
||||||
return &room
|
return &room
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,9 +66,9 @@ func (room *Room) SendTopic(client *Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send message to all room's subscribers, possibly excluding someone
|
// Send message to all room's subscribers, possibly excluding someone
|
||||||
func (room *Room) Broadcast(msg string, client_to_ignore ...*Client) {
|
func (room *Room) Broadcast(msg string, clientToIgnore ...*Client) {
|
||||||
for member := range room.members {
|
for member := range room.members {
|
||||||
if (len(client_to_ignore) > 0) && member == client_to_ignore[0] {
|
if (len(clientToIgnore) > 0) && member == clientToIgnore[0] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
member.Msg(msg)
|
member.Msg(msg)
|
||||||
@ -76,22 +76,22 @@ func (room *Room) Broadcast(msg string, client_to_ignore ...*Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) StateSave() {
|
func (room *Room) StateSave() {
|
||||||
room.state_sink <- StateEvent{room.name, room.topic, room.key}
|
room.stateSink <- StateEvent{room.name, room.topic, room.key}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) Processor(events <-chan ClientEvent) {
|
func (room *Room) Processor(events <-chan ClientEvent) {
|
||||||
var client *Client
|
var client *Client
|
||||||
for event := range events {
|
for event := range events {
|
||||||
client = event.client
|
client = event.client
|
||||||
switch event.event_type {
|
switch event.eventType {
|
||||||
case EVENT_NEW:
|
case EventNew:
|
||||||
room.members[client] = true
|
room.members[client] = true
|
||||||
if room.Verbose {
|
if room.Verbose {
|
||||||
log.Println(client, "joined", room.name)
|
log.Println(client, "joined", room.name)
|
||||||
}
|
}
|
||||||
room.SendTopic(client)
|
room.SendTopic(client)
|
||||||
room.Broadcast(fmt.Sprintf(":%s JOIN %s", client, room.name))
|
room.Broadcast(fmt.Sprintf(":%s JOIN %s", client, room.name))
|
||||||
room.log_sink <- LogEvent{room.name, client.nickname, "joined", true}
|
room.logSink <- LogEvent{room.name, client.nickname, "joined", true}
|
||||||
nicknames := []string{}
|
nicknames := []string{}
|
||||||
for member := range room.members {
|
for member := range room.members {
|
||||||
nicknames = append(nicknames, member.nickname)
|
nicknames = append(nicknames, member.nickname)
|
||||||
@ -99,7 +99,7 @@ func (room *Room) Processor(events <-chan ClientEvent) {
|
|||||||
sort.Strings(nicknames)
|
sort.Strings(nicknames)
|
||||||
client.ReplyNicknamed("353", "=", room.name, strings.Join(nicknames, " "))
|
client.ReplyNicknamed("353", "=", room.name, strings.Join(nicknames, " "))
|
||||||
client.ReplyNicknamed("366", room.name, "End of NAMES list")
|
client.ReplyNicknamed("366", room.name, "End of NAMES list")
|
||||||
case EVENT_DEL:
|
case EventDel:
|
||||||
if _, subscribed := room.members[client]; !subscribed {
|
if _, subscribed := room.members[client]; !subscribed {
|
||||||
client.ReplyNicknamed("442", room.name, "You are not on that channel")
|
client.ReplyNicknamed("442", room.name, "You are not on that channel")
|
||||||
continue
|
continue
|
||||||
@ -107,8 +107,8 @@ func (room *Room) Processor(events <-chan ClientEvent) {
|
|||||||
delete(room.members, client)
|
delete(room.members, client)
|
||||||
msg := fmt.Sprintf(":%s PART %s :%s", client, room.name, client.nickname)
|
msg := fmt.Sprintf(":%s PART %s :%s", client, room.name, client.nickname)
|
||||||
room.Broadcast(msg)
|
room.Broadcast(msg)
|
||||||
room.log_sink <- LogEvent{room.name, client.nickname, "left", true}
|
room.logSink <- LogEvent{room.name, client.nickname, "left", true}
|
||||||
case EVENT_TOPIC:
|
case EventTopic:
|
||||||
if _, subscribed := room.members[client]; !subscribed {
|
if _, subscribed := room.members[client]; !subscribed {
|
||||||
client.ReplyParts("442", room.name, "You are not on that channel")
|
client.ReplyParts("442", room.name, "You are not on that channel")
|
||||||
continue
|
continue
|
||||||
@ -120,14 +120,14 @@ func (room *Room) Processor(events <-chan ClientEvent) {
|
|||||||
room.topic = strings.TrimLeft(event.text, ":")
|
room.topic = strings.TrimLeft(event.text, ":")
|
||||||
msg := fmt.Sprintf(":%s TOPIC %s :%s", client, room.name, room.topic)
|
msg := fmt.Sprintf(":%s TOPIC %s :%s", client, room.name, room.topic)
|
||||||
go room.Broadcast(msg)
|
go room.Broadcast(msg)
|
||||||
room.log_sink <- LogEvent{room.name, client.nickname, "set topic to " + room.topic, true}
|
room.logSink <- LogEvent{room.name, client.nickname, "set topic to " + room.topic, true}
|
||||||
room.StateSave()
|
room.StateSave()
|
||||||
case EVENT_WHO:
|
case EventWho:
|
||||||
for m := range room.members {
|
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")
|
client.ReplyNicknamed("315", room.name, "End of /WHO list")
|
||||||
case EVENT_MODE:
|
case EventMode:
|
||||||
if event.text == "" {
|
if event.text == "" {
|
||||||
mode := "+"
|
mode := "+"
|
||||||
if room.key != "" {
|
if room.key != "" {
|
||||||
@ -146,7 +146,7 @@ func (room *Room) Processor(events <-chan ClientEvent) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var msg string
|
var msg string
|
||||||
var msg_log string
|
var msgLog string
|
||||||
if strings.HasPrefix(event.text, "+k") {
|
if strings.HasPrefix(event.text, "+k") {
|
||||||
cols := strings.Split(event.text, " ")
|
cols := strings.Split(event.text, " ")
|
||||||
if len(cols) == 1 {
|
if len(cols) == 1 {
|
||||||
@ -155,19 +155,19 @@ func (room *Room) Processor(events <-chan ClientEvent) {
|
|||||||
}
|
}
|
||||||
room.key = cols[1]
|
room.key = cols[1]
|
||||||
msg = fmt.Sprintf(":%s MODE %s +k %s", client, room.name, room.key)
|
msg = fmt.Sprintf(":%s MODE %s +k %s", client, room.name, room.key)
|
||||||
msg_log = "set channel key to " + room.key
|
msgLog = "set channel key to " + room.key
|
||||||
} else if strings.HasPrefix(event.text, "-k") {
|
} else if strings.HasPrefix(event.text, "-k") {
|
||||||
room.key = ""
|
room.key = ""
|
||||||
msg = fmt.Sprintf(":%s MODE %s -k", client, room.name)
|
msg = fmt.Sprintf(":%s MODE %s -k", client, room.name)
|
||||||
msg_log = "removed channel key"
|
msgLog = "removed channel key"
|
||||||
}
|
}
|
||||||
go room.Broadcast(msg)
|
go room.Broadcast(msg)
|
||||||
room.log_sink <- LogEvent{room.name, client.nickname, msg_log, true}
|
room.logSink <- LogEvent{room.name, client.nickname, msgLog, true}
|
||||||
room.StateSave()
|
room.StateSave()
|
||||||
case EVENT_MSG:
|
case EventMsg:
|
||||||
sep := strings.Index(event.text, " ")
|
sep := strings.Index(event.text, " ")
|
||||||
room.Broadcast(fmt.Sprintf(":%s %s %s :%s", client, event.text[:sep], room.name, event.text[sep+1:]), client)
|
room.Broadcast(fmt.Sprintf(":%s %s %s :%s", client, event.text[:sep], room.name, event.text[sep+1:]), client)
|
||||||
room.log_sink <- LogEvent{room.name, client.nickname, event.text[sep+1:], false}
|
room.logSink <- LogEvent{room.name, client.nickname, event.text[sep+1:], false}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
60
room_test.go
60
room_test.go
@ -5,28 +5,28 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func no_nickchan(t *testing.T, c *TestingConn) {
|
func noNickchan(t *testing.T, c *TestingConn) {
|
||||||
if r := <-c.outbound; !strings.HasPrefix(r, ":foohost 401") {
|
if r := <-c.outbound; !strings.HasPrefix(r, ":foohost 401") {
|
||||||
t.Fatal("no nick/channel", r)
|
t.Fatal("no nick/channel", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func no_chan(t *testing.T, c *TestingConn) {
|
func noChan(t *testing.T, c *TestingConn) {
|
||||||
if r := <-c.outbound; !strings.HasPrefix(r, ":foohost 403") {
|
if r := <-c.outbound; !strings.HasPrefix(r, ":foohost 403") {
|
||||||
t.Fatal("no channel", r)
|
t.Fatal("no channel", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func not_enough_params(t *testing.T, c *TestingConn) {
|
func notEnoughParams(t *testing.T, c *TestingConn) {
|
||||||
if r := <-c.outbound; !strings.HasPrefix(r, ":foohost 461") {
|
if r := <-c.outbound; !strings.HasPrefix(r, ":foohost 461") {
|
||||||
t.Fatal("not enough params", r)
|
t.Fatal("not enough params", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTwoUsers(t *testing.T) {
|
func TestTwoUsers(t *testing.T) {
|
||||||
log_sink := make(chan LogEvent, 8)
|
logSink := make(chan LogEvent, 8)
|
||||||
state_sink := make(chan StateEvent, 8)
|
stateSink := make(chan StateEvent, 8)
|
||||||
daemon := NewDaemon("foohost", "", log_sink, state_sink)
|
daemon := NewDaemon("foohost", "", logSink, stateSink)
|
||||||
events := make(chan ClientEvent)
|
events := make(chan ClientEvent)
|
||||||
go daemon.Processor(events)
|
go daemon.Processor(events)
|
||||||
|
|
||||||
@ -50,9 +50,9 @@ func TestTwoUsers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn1.inbound <- "WHOIS"
|
conn1.inbound <- "WHOIS"
|
||||||
not_enough_params(t, conn1)
|
notEnoughParams(t, conn1)
|
||||||
conn1.inbound <- "WHOIS nick3"
|
conn1.inbound <- "WHOIS nick3"
|
||||||
no_nickchan(t, conn1)
|
noNickchan(t, conn1)
|
||||||
conn1.inbound <- "WHOIS nick2"
|
conn1.inbound <- "WHOIS nick2"
|
||||||
if r := <-conn1.outbound; r != ":foohost 311 nick1 nick2 foo2 Unknown * :Long name2\r\n" {
|
if r := <-conn1.outbound; r != ":foohost 311 nick1 nick2 foo2 Unknown * :Long name2\r\n" {
|
||||||
t.Fatal("first WHOIS 311", r)
|
t.Fatal("first WHOIS 311", r)
|
||||||
@ -73,9 +73,9 @@ func TestTwoUsers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn1.inbound <- "WHO"
|
conn1.inbound <- "WHO"
|
||||||
not_enough_params(t, conn1)
|
notEnoughParams(t, conn1)
|
||||||
conn1.inbound <- "WHO #fooroom"
|
conn1.inbound <- "WHO #fooroom"
|
||||||
no_chan(t, conn1)
|
noChan(t, conn1)
|
||||||
|
|
||||||
conn1.inbound <- "JOIN #foo"
|
conn1.inbound <- "JOIN #foo"
|
||||||
conn2.inbound <- "JOIN #foo"
|
conn2.inbound <- "JOIN #foo"
|
||||||
@ -98,9 +98,9 @@ func TestTwoUsers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestJoin(t *testing.T) {
|
func TestJoin(t *testing.T) {
|
||||||
log_sink := make(chan LogEvent, 8)
|
logSink := make(chan LogEvent, 8)
|
||||||
state_sink := make(chan StateEvent, 8)
|
stateSink := make(chan StateEvent, 8)
|
||||||
daemon := NewDaemon("foohost", "", log_sink, state_sink)
|
daemon := NewDaemon("foohost", "", logSink, stateSink)
|
||||||
events := make(chan ClientEvent)
|
events := make(chan ClientEvent)
|
||||||
go daemon.Processor(events)
|
go daemon.Processor(events)
|
||||||
conn := NewTestingConn()
|
conn := NewTestingConn()
|
||||||
@ -113,11 +113,11 @@ func TestJoin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn.inbound <- "JOIN"
|
conn.inbound <- "JOIN"
|
||||||
not_enough_params(t, conn)
|
notEnoughParams(t, conn)
|
||||||
conn.inbound <- "JOIN bla/bla/bla"
|
conn.inbound <- "JOIN bla/bla/bla"
|
||||||
no_chan(t, conn)
|
noChan(t, conn)
|
||||||
conn.inbound <- "JOIN bla:bla:bla"
|
conn.inbound <- "JOIN bla:bla:bla"
|
||||||
no_chan(t, conn)
|
noChan(t, conn)
|
||||||
|
|
||||||
conn.inbound <- "JOIN #foo"
|
conn.inbound <- "JOIN #foo"
|
||||||
if r := <-conn.outbound; r != ":foohost 331 nick2 #foo :No topic is set\r\n" {
|
if r := <-conn.outbound; r != ":foohost 331 nick2 #foo :No topic is set\r\n" {
|
||||||
@ -132,7 +132,7 @@ func TestJoin(t *testing.T) {
|
|||||||
if r := <-conn.outbound; r != ":foohost 366 nick2 #foo :End of NAMES list\r\n" {
|
if r := <-conn.outbound; r != ":foohost 366 nick2 #foo :End of NAMES list\r\n" {
|
||||||
t.Fatal("no end of NAMES list", r)
|
t.Fatal("no end of NAMES list", r)
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "joined") || (r.where != "#foo") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "joined") || (r.where != "#foo") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("invalid join log event", r)
|
t.Fatal("invalid join log event", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,10 +146,10 @@ func TestJoin(t *testing.T) {
|
|||||||
if _, ok := daemon.rooms["#baz"]; !ok {
|
if _, ok := daemon.rooms["#baz"]; !ok {
|
||||||
t.Fatal("#baz does not exist")
|
t.Fatal("#baz does not exist")
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "joined") || (r.where != "#bar") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "joined") || (r.where != "#bar") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("invalid join log event #bar", r)
|
t.Fatal("invalid join log event #bar", r)
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "joined") || (r.where != "#baz") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "joined") || (r.where != "#baz") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("invalid join log event #baz", r)
|
t.Fatal("invalid join log event #baz", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,16 +163,16 @@ func TestJoin(t *testing.T) {
|
|||||||
if daemon.rooms["#bazenc"].key != "key2" {
|
if daemon.rooms["#bazenc"].key != "key2" {
|
||||||
t.Fatal("no room with key2")
|
t.Fatal("no room with key2")
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "joined") || (r.where != "#barenc") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "joined") || (r.where != "#barenc") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("invalid join log event #barenc", r)
|
t.Fatal("invalid join log event #barenc", r)
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "joined") || (r.where != "#bazenc") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "joined") || (r.where != "#bazenc") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("invalid join log event #bazenc", r)
|
t.Fatal("invalid join log event #bazenc", r)
|
||||||
}
|
}
|
||||||
if r := <-state_sink; (r.topic != "") || (r.where != "#barenc") || (r.key != "key1") {
|
if r := <-stateSink; (r.topic != "") || (r.where != "#barenc") || (r.key != "key1") {
|
||||||
t.Fatal("set channel key1 state", r)
|
t.Fatal("set channel key1 state", r)
|
||||||
}
|
}
|
||||||
if r := <-state_sink; (r.topic != "") || (r.where != "#bazenc") || (r.key != "key2") {
|
if r := <-stateSink; (r.topic != "") || (r.where != "#bazenc") || (r.key != "key2") {
|
||||||
t.Fatal("set channel key2 state", r)
|
t.Fatal("set channel key2 state", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,10 +183,10 @@ func TestJoin(t *testing.T) {
|
|||||||
if daemon.rooms["#barenc"].key != "" {
|
if daemon.rooms["#barenc"].key != "" {
|
||||||
t.Fatal("removing key from #barenc")
|
t.Fatal("removing key from #barenc")
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "removed channel key") || (r.where != "#barenc") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "removed channel key") || (r.where != "#barenc") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("removed channel key log", r)
|
t.Fatal("removed channel key log", r)
|
||||||
}
|
}
|
||||||
if r := <-state_sink; (r.topic != "") || (r.where != "#barenc") || (r.key != "") {
|
if r := <-stateSink; (r.topic != "") || (r.where != "#barenc") || (r.key != "") {
|
||||||
t.Fatal("removed channel key state", r)
|
t.Fatal("removed channel key state", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ func TestJoin(t *testing.T) {
|
|||||||
if r := <-conn.outbound; r != ":foohost 442 #bazenc :You are not on that channel\r\n" {
|
if r := <-conn.outbound; r != ":foohost 442 #bazenc :You are not on that channel\r\n" {
|
||||||
t.Fatal("not on that channel", r)
|
t.Fatal("not on that channel", r)
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "left") || (r.where != "#bazenc") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "left") || (r.where != "#bazenc") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("left #bazenc log", r)
|
t.Fatal("left #bazenc log", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,10 +207,10 @@ func TestJoin(t *testing.T) {
|
|||||||
if r := <-conn.outbound; r != ":nick2!foo2@someclient MODE #barenc +k newkey\r\n" {
|
if r := <-conn.outbound; r != ":nick2!foo2@someclient MODE #barenc +k newkey\r\n" {
|
||||||
t.Fatal("+k MODE setting", r)
|
t.Fatal("+k MODE setting", r)
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "set channel key to newkey") || (r.where != "#barenc") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "set channel key to newkey") || (r.where != "#barenc") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("set channel key", r)
|
t.Fatal("set channel key", r)
|
||||||
}
|
}
|
||||||
if r := <-state_sink; (r.topic != "") || (r.where != "#barenc") || (r.key != "newkey") {
|
if r := <-stateSink; (r.topic != "") || (r.where != "#barenc") || (r.key != "newkey") {
|
||||||
t.Fatal("set channel newkey state", r)
|
t.Fatal("set channel newkey state", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,10 +218,10 @@ func TestJoin(t *testing.T) {
|
|||||||
if r := <-conn.outbound; r != ":nick2!foo2@someclient TOPIC #barenc :New topic\r\n" {
|
if r := <-conn.outbound; r != ":nick2!foo2@someclient TOPIC #barenc :New topic\r\n" {
|
||||||
t.Fatal("set TOPIC", r)
|
t.Fatal("set TOPIC", r)
|
||||||
}
|
}
|
||||||
if r := <-log_sink; (r.what != "set topic to New topic") || (r.where != "#barenc") || (r.who != "nick2") || (r.meta != true) {
|
if r := <-logSink; (r.what != "set topic to New topic") || (r.where != "#barenc") || (r.who != "nick2") || (r.meta != true) {
|
||||||
t.Fatal("set TOPIC log", r)
|
t.Fatal("set TOPIC log", r)
|
||||||
}
|
}
|
||||||
if r := <-state_sink; (r.topic != "New topic") || (r.where != "#barenc") || (r.key != "newkey") {
|
if r := <-stateSink; (r.topic != "New topic") || (r.where != "#barenc") || (r.key != "newkey") {
|
||||||
t.Fatal("set channel TOPIC state", r)
|
t.Fatal("set channel TOPIC state", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user