@@ -66,52 +66,60 @@ func NewComponent(opts ComponentOptions, r *Router) (*Component, error) {
66
66
// Connect triggers component connection to XMPP server component port.
67
67
// TODO: Failed handshake should be a permanent error
68
68
func (c * Component ) Connect () error {
69
+ var state SMState
70
+ return c .Resume (state )
71
+ }
72
+ func (c * Component ) Resume (sm SMState ) error {
69
73
var conn net.Conn
70
74
var err error
71
75
if conn , err = net .DialTimeout ("tcp" , c .Address , time .Duration (5 )* time .Second ); err != nil {
72
76
return err
73
77
}
74
78
c .conn = conn
79
+ c .updateState (StateConnected )
75
80
76
81
// 1. Send stream open tag
77
82
if _ , err := fmt .Fprintf (conn , componentStreamOpen , c .Domain , stanza .NSComponent , stanza .NSStream ); err != nil {
78
- return errors .New ("cannot send stream open " + err .Error ())
83
+ c .updateState (StateStreamError )
84
+ return NewConnError (errors .New ("cannot send stream open " + err .Error ()), false )
79
85
}
80
86
c .decoder = xml .NewDecoder (conn )
81
87
82
88
// 2. Initialize xml decoder and extract streamID from reply
83
89
streamId , err := stanza .InitStream (c .decoder )
84
90
if err != nil {
85
- return errors .New ("cannot init decoder " + err .Error ())
91
+ c .updateState (StateStreamError )
92
+ return NewConnError (errors .New ("cannot init decoder " + err .Error ()), false )
86
93
}
87
94
88
95
// 3. Authentication
89
96
if _ , err := fmt .Fprintf (conn , "<handshake>%s</handshake>" , c .handshake (streamId )); err != nil {
90
- return errors .New ("cannot send handshake " + err .Error ())
97
+ c .updateState (StateStreamError )
98
+ return NewConnError (errors .New ("cannot send handshake " + err .Error ()), false )
91
99
}
92
100
93
101
// 4. Check server response for authentication
94
102
val , err := stanza .NextPacket (c .decoder )
95
103
if err != nil {
96
- return err
104
+ c .updateState (StateDisconnected )
105
+ return NewConnError (err , true )
97
106
}
98
107
99
108
switch v := val .(type ) {
100
109
case stanza.StreamError :
101
- return errors .New ("handshake failed " + v .Error .Local )
110
+ c .streamError ("conflict" , "no auth loop" )
111
+ return NewConnError (errors .New ("handshake failed " + v .Error .Local ), true )
102
112
case stanza.Handshake :
103
113
// Start the receiver go routine
114
+ c .updateState (StateSessionEstablished )
104
115
go c .recv ()
105
116
return nil
106
117
default :
107
- return errors .New ("expecting handshake result, got " + v .Name ())
118
+ c .updateState (StateStreamError )
119
+ return NewConnError (errors .New ("expecting handshake result, got " + v .Name ()), true )
108
120
}
109
121
}
110
122
111
- func (c * Component ) Resume (SMState ) error {
112
- return errors .New ("components do not support stream management" )
113
- }
114
-
115
123
func (c * Component ) Disconnect () {
116
124
_ = c .SendRaw ("</stream:stream>" )
117
125
// TODO: Add a way to wait for stream close acknowledgement from the server for clean disconnect
0 commit comments