~samwhited/xmpp

1e5ebbe6703c621b09599b3f332b1b85437241c3 — Sam Whited 1 year, 7 months ago 9020012
examples/echobot: add graceful shutdown
2 files changed, 32 insertions(+), 9 deletions(-)

M examples/echobot/echo.go
M examples/echobot/main.go
M examples/echobot/echo.go => examples/echobot/echo.go +14 -8
@@ 20,18 20,18 @@ import (
	"mellium.im/xmpp/stanza"
)

func echo(addr, pass string, xmlIn, xmlOut io.Writer, logger, debug *log.Logger) error {
func echo(ctx context.Context, addr, pass string, xmlIn, xmlOut io.Writer, logger, debug *log.Logger) error {
	j, err := jid.Parse(addr)
	if err != nil {
		return fmt.Errorf("Error parsing address %q: %w", addr, err)
	}

	conn, err := dial.Client(context.TODO(), "tcp", j)
	conn, err := dial.Client(ctx, "tcp", j)
	if err != nil {
		return fmt.Errorf("Error dialing sesion: %w", err)
	}

	s, err := xmpp.NegotiateSession(context.TODO(), j.Domain(), j, conn, false, xmpp.NewNegotiator(xmpp.StreamConfig{
	s, err := xmpp.NegotiateSession(ctx, j.Domain(), j, conn, false, xmpp.NewNegotiator(xmpp.StreamConfig{
		Lang: "en",
		Features: []xmpp.StreamFeature{
			xmpp.BindResource(),


@@ 47,18 47,24 @@ func echo(addr, pass string, xmlIn, xmlOut io.Writer, logger, debug *log.Logger)
		return fmt.Errorf("Error establishing a session: %w", err)
	}
	defer func() {
		logger.Println("Closing session…")
		if err := s.Close(); err != nil {
			logger.Printf("Error closing session: %q", err)
		}
		logger.Println("Closing conn…")
		if err := s.Conn().Close(); err != nil {
			logger.Printf("Error closing connection: %q", err)
		}
	}()

	go func() {
		select {
		case <-ctx.Done():
			logger.Println("Closing session…")
			if err := s.Close(); err != nil {
				logger.Printf("Error closing session: %q", err)
			}
		}
	}()

	// Send initial presence to let the server know we want to receive messages.
	err = s.Send(context.TODO(), stanza.WrapPresence(jid.JID{}, stanza.AvailablePresence, nil))
	err = s.Send(ctx, stanza.WrapPresence(jid.JID{}, stanza.AvailablePresence, nil))
	if err != nil {
		return fmt.Errorf("Error sending initial presence: %w", err)
	}

M examples/echobot/main.go => examples/echobot/main.go +18 -1
@@ 11,12 11,14 @@
package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
)

const (


@@ 84,7 86,22 @@ func main() {
		debug.Printf("The environment variable $%s is empty", envPass)
	}

	if err := echo(addr, pass, xmlIn, xmlOut, logger, debug); err != nil {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Handle SIGINT and gracefully shut down the bot.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)

	go func() {
		select {
		case <-ctx.Done():
		case <-c:
			cancel()
		}
	}()

	if err := echo(ctx, addr, pass, xmlIn, xmlOut, logger, debug); err != nil {
		logger.Fatal(err)
	}
}