Wait for the server closing the stream before closing the connection.

This commit is contained in:
Martin Dosch 2024-03-02 14:17:47 +01:00
parent 2c4708e724
commit aed021cf3e

29
xmpp.go
View File

@ -331,6 +331,21 @@ func NewClientNoTLS(host, user, passwd string, debug bool) (*Client, error) {
func (c *Client) Close() error { func (c *Client) Close() error {
if c.conn != (*tls.Conn)(nil) { if c.conn != (*tls.Conn)(nil) {
fmt.Fprintf(c.stanzaWriter, "</stream:stream>\n") fmt.Fprintf(c.stanzaWriter, "</stream:stream>\n")
// Wait for the server also closing the stream.
for {
select {
case <-time.After(10 * time.Second):
break
default:
ee, err := nextEnd(c.p)
if err != nil {
return err
}
if ee.Name.Local == "stream" {
return c.conn.Close()
}
}
}
return c.conn.Close() return c.conn.Close()
} }
return nil return nil
@ -1421,6 +1436,20 @@ func nextStart(p *xml.Decoder) (xml.StartElement, error) {
} }
} }
// Scan XML token stream to find next EndElement
func nextEnd(p *xml.Decoder) (xml.EndElement, error) {
for {
t, err := p.Token()
if err != nil || t == nil {
return xml.EndElement{}, err
}
switch t := t.(type) {
case xml.EndElement:
return t, nil
}
}
}
// Scan XML token stream for next element and save into val. // Scan XML token stream for next element and save into val.
// If val == nil, allocate new element based on proto map. // If val == nil, allocate new element based on proto map.
// Either way, return val. // Either way, return val.