diff --git a/irc/client.go b/irc/client.go index ab096af5..83528fad 100644 --- a/irc/client.go +++ b/irc/client.go @@ -67,6 +67,8 @@ func (client *Client) readCommands() { msg.SetClient(client) client.server.commands <- msg } + + client.server.toDestroy <- client } func (client *Client) Touch() { @@ -117,9 +119,8 @@ func (client *Client) connectionClosed() { func (client *Client) Destroy() { if DEBUG_CLIENT { - log.Printf("%s destroy", client) + log.Printf("%s: destroying", client) } - // clean up self client.socket.Close() @@ -143,7 +144,7 @@ func (client *Client) Destroy() { client.server.clients.Remove(client) if DEBUG_CLIENT { - log.Printf("%s destroyed", client) + log.Printf("%s: destroyed", client) } } @@ -203,7 +204,7 @@ func (c *Client) Id() string { } func (c *Client) String() string { - return c.UserHost() + return c.Id() } func (client *Client) AddFriend(friend *Client) { @@ -240,5 +241,5 @@ func (client *Client) Quit(message string) { } client.Reply(RplError(client.server, client)) - client.Destroy() + client.socket.Close() } diff --git a/irc/commands.go b/irc/commands.go index 9662f91a..088f5efb 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -460,14 +460,14 @@ func (changes ModeChanges) String() string { type ModeCommand struct { BaseCommand nickname string - changes []ModeChange + changes ModeChanges } // MODE *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) ) func NewUserModeCommand(args []string) (editableCommand, error) { cmd := &ModeCommand{ nickname: args[0], - changes: make([]ModeChange, 0), + changes: make(ModeChanges, 0), } for _, modeChange := range args[1:] { diff --git a/irc/server.go b/irc/server.go index a876bd19..c4be8079 100644 --- a/irc/server.go +++ b/irc/server.go @@ -23,6 +23,7 @@ type Server struct { name string operators map[string]string password string + toDestroy chan *Client } func NewServer(config *Config) *Server { @@ -36,6 +37,7 @@ func NewServer(config *Config) *Server { name: config.Name, operators: make(map[string]string), password: config.Password, + toDestroy: make(chan *Client), } for _, opConf := range config.Operators { @@ -55,6 +57,9 @@ func (server *Server) ReceiveCommands() { case conn := <-server.conns: NewClient(server, conn) + case client := <-server.toDestroy: + client.Destroy() + case cmd := <-server.commands: client := cmd.Client() if DEBUG_SERVER { @@ -65,7 +70,7 @@ func (server *Server) ReceiveCommands() { case Authorization: authCmd, ok := cmd.(AuthServerCommand) if !ok { - client.Destroy() + client.socket.Close() continue } authCmd.HandleAuthServer(server) @@ -73,7 +78,7 @@ func (server *Server) ReceiveCommands() { case Registration: regCmd, ok := cmd.(RegServerCommand) if !ok { - client.Destroy() + client.socket.Close() continue } regCmd.HandleRegServer(server) @@ -249,7 +254,7 @@ func (m *PassCommand) HandleAuthServer(s *Server) { if s.password != m.password { client.Reply(ErrPasswdMismatch(s)) - client.Destroy() + client.socket.Close() return } diff --git a/irc/socket.go b/irc/socket.go index 113710a1..5c2fa78a 100644 --- a/irc/socket.go +++ b/irc/socket.go @@ -13,7 +13,6 @@ const ( ) type Socket struct { - closed bool conn net.Conn done chan bool reader *bufio.Reader @@ -43,13 +42,7 @@ func (socket *Socket) String() string { } func (socket *Socket) Close() { - if socket.closed { - return - } - - socket.closed = true socket.done <- true - close(socket.done) } func (socket *Socket) Read() <-chan string { @@ -82,6 +75,7 @@ func (socket *Socket) readLines() { } close(socket.receive) + socket.Close() if DEBUG_NET { log.Printf("%s closed", socket) } @@ -114,10 +108,16 @@ func (socket *Socket) writeLines() { if DEBUG_NET { log.Printf("%s closing", socket) } - socket.conn.Close() + if done { + socket.conn.Close() + } - for _ = range socket.send { - // discard lines + // read incoming messages and discard to avoid hangs + for { + select { + case <-socket.send: + case <-socket.done: + } } }