Golinting

This commit is contained in:
Sergey Matveev 2014-08-09 16:42:19 +04:00
parent def74ddc09
commit cfeaaad88f
7 changed files with 157 additions and 157 deletions

View File

@ -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{}

View File

@ -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
View File

@ -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
} }
} }
} }

View File

@ -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()

View File

@ -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
View File

@ -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}
} }
} }
} }

View File

@ -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)
} }