diff --git a/client.go b/client.go index 6a2a403..a196780 100644 --- a/client.go +++ b/client.go @@ -187,12 +187,13 @@ func (client *Client) Ready() bool { return client.ready } -// HasQuit returns true if the client had manually quit. +// HasQuit returns true if the client had manually quit. It should be checked before +// performing any reconnection logic. func (client *Client) HasQuit() bool { client.mutex.RLock() defer client.mutex.RUnlock() - return client.ready + return client.quit } func (client *Client) State() ClientState { @@ -234,7 +235,7 @@ func (client *Client) Connect(addr string, ssl bool) (err error) { var conn net.Conn if client.Connected() { - _ = client.Disconnect() + _ = client.Disconnect(false) } client.isupport.Reset() @@ -306,17 +307,21 @@ func (client *Client) Connect(addr string, ssl bool) (err error) { } // Disconnect disconnects from the server. It will either return the -// close error, or ErrNoConnection if there is no connection -func (client *Client) Disconnect() error { +// close error, or ErrNoConnection if there is no connection. If +// markAsQuit is specified, HasQuit will return true until the next +// connections. +func (client *Client) Disconnect(markAsQuit bool) error { client.mutex.Lock() defer client.mutex.Unlock() + if markAsQuit { + client.quit = true + } + if client.conn == nil { return ErrNoConnection } - client.quit = true - return client.conn.Close() } @@ -348,7 +353,7 @@ func (client *Client) Send(line string) error { _, err := conn.Write([]byte(line)) if err != nil { client.EmitNonBlocking(NewErrorEvent("write", err.Error())) - _ = client.Disconnect() + _ = client.Disconnect(false) } return err @@ -521,9 +526,12 @@ func (client *Client) SetValue(key string, value interface{}) { // Destroy destroys the client, which will lead to a disconnect. Cancelling the // parent context will do the same. func (client *Client) Destroy() { - _ = client.Disconnect() + _ = client.Disconnect(false) client.cancel() close(client.sends) + + client.Emit(NewEvent("client", "destroy")) + close(client.events) } @@ -781,14 +789,7 @@ end: ticker.Stop() - _ = client.Disconnect() - - event := NewEvent("client", "destroy") - event.ctx, event.cancel = context.WithCancel(client.ctx) - - client.handleEvent(&event) - - event.cancel() + _ = client.Disconnect(false) } func (client *Client) handleSendLoop() { diff --git a/client_test.go b/client_test.go index 6444381..6ed32d9 100644 --- a/client_test.go +++ b/client_test.go @@ -355,7 +355,7 @@ func TestClient(t *testing.T) { t.Fatal("Listen:", err) } - if err := client.Disconnect(); err != irc.ErrNoConnection { + if err := client.Disconnect(false); err != irc.ErrNoConnection { t.Errorf("It should fail to disconnect, got: %s", err) } diff --git a/cmd/ircrepl/main.go b/cmd/ircrepl/main.go index 00fed1d..53326db 100644 --- a/cmd/ircrepl/main.go +++ b/cmd/ircrepl/main.go @@ -9,7 +9,9 @@ import ( "github.com/gissleh/irc/handlers" "log" "os" + "os/signal" "strings" + "syscall" "github.com/gissleh/irc" ) @@ -95,6 +97,10 @@ func main() { target = client.Target(event.Arg(1), event.Arg(2)) } + if event.Name() == "client.disconnect" { + os.Exit(0) + } + j, err := json.MarshalIndent(event, "", " ") if err != nil { return @@ -103,6 +109,15 @@ func main() { fmt.Println(string(j)) }) + go func() { + exitSignal := make(chan os.Signal) + signal.Notify(exitSignal, os.Interrupt, os.Kill, syscall.SIGTERM) + + <-exitSignal + + client.Quit("Goodnight.") + }() + reader := bufio.NewReader(os.Stdin) for { line, err := reader.ReadString('\n')