diff --git a/.gitignore b/.gitignore index f690797..1ec2a5f 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,7 @@ profile.cov # Go workspace file go.work go.work.sum - +stresser.go # env file .env diff --git a/main.go b/main.go index 8961f57..d12b68d 100644 --- a/main.go +++ b/main.go @@ -777,8 +777,7 @@ func joinChannel(c *Client, name string) { // reject duplicate join if _, exists := ch.members[c.nick]; exists { ch.mu.Unlock() - c.fwrite(":server 443 %s %s %s :is already on channel\r\n", - c.nick, c.nick, name) + c.fwrite(":server 443 %s %s %s :is already on channel\r\n", c.nick, c.nick, name) return } // clean up stale empty nick @@ -788,28 +787,26 @@ func joinChannel(c *Client, name string) { c.channels[name] = ch ch.mu.Unlock() - // echo JOIN to client fmt.Fprintf(c.conn, ":%s JOIN %s\r\n", c.nick, name) - // broadcast JOIN to others - for _, member := range ch.members { + ch.mu.RLock() + members := make([]*Client, 0, len(ch.members)) + for _, m := range ch.members { + members = append(members, m) + } + ch.mu.RUnlock() + for _, member := range members { if member != c { fmt.Fprintf(member.conn, ":%s JOIN %s\r\n", c.nick, name) } } - - // topic if ch.description != "" { c.fwrite(":server 332 %s %s :%s\r\n", c.nick, name, ch.description) } else { c.fwrite(":server 331 %s %s :No topic is set\r\n", c.nick, name) } - - // names list c.sendNames(ch) - - // MODE if op if ch.ops[c.nick] { - for _, member := range ch.members { + for _, member := range members { member.fwrite(":server MODE %s +o %s\r\n", name, c.nick) } } @@ -831,7 +828,7 @@ func (c *Client) partChannel(name string) { fmt.Fprintf(member.conn, ":%s PART %s\r\n", c.nick, name) } ch.mu.Unlock() - broadcastNames(ch) + //broadcastNames(ch) } func addChannel(name string, description string) { name = normalizeChannelName(name) @@ -899,7 +896,7 @@ func (c *Client) checkRegistration() { } else { c.fwrite("%s :MOTD File is missing", c.nick) } - fmt.Fprintf(c.conn, ":server 376 %s :End of MOTD\r\n", c.nick) + c.fwrite(":server 376 %s :End of MOTD\r\n", c.nick) } } func reloadMOTD() { @@ -943,7 +940,7 @@ func showWho(c *Client, name string) { for _, member := range ch.members { c.fwrite(":server 352 %s %s %s server %s H :0 %s\r\n", c.nick, name, member.host, member.nick, member.nick) } - fmt.Fprintf(c.conn, ":server 315 %s %s :End of WHO list\r\n", c.nick, name) + c.fwrite(":server 315 %s %s :End of WHO list\r\n", c.nick, name) } func (c *Client) handleList() { chMu.Lock() @@ -1017,18 +1014,30 @@ func (c *Client) cleanup() { ch.mu.Lock() delete(ch.members, c.nick) ch.mu.Unlock() - for nick, member := range ch.members { - if nick != c.nick { + ch.mu.RLock() + snapshot := make([]*Client, 0, len(ch.members)) + for _, member := range ch.members { + snapshot = append(snapshot, member) + } + ch.mu.RUnlock() + for _, member := range snapshot { + if member.nick != c.nick { member.fwrite(":%s PART %s\r\n", c.nick, name) } } + delete(c.channels, name) } cliMu.RLock() + snapshot := make([]*Client, 0, len(clients)) for _, other := range clients { - other.fwrite(":%s QUIT :Client disconnected\r\n", c.nick) + snapshot = append(snapshot, other) } cliMu.RUnlock() + + for _, other := range snapshot { + other.fwrite(":%s QUIT :Client disconnected\r\n", c.nick) + } } func broadcastNames(ch *Channel) {