1package xmpp
2
3import (
4	"encoding/hex"
5	"io"
6	"io/ioutil"
7	"log"
8	"net"
9
10	"github.com/coyim/coyim/i18n"
11	"github.com/coyim/coyim/xmpp/data"
12	"github.com/coyim/coyim/xmpp/errors"
13	"github.com/coyim/gotk3adapter/glib_mock"
14
15	. "gopkg.in/check.v1"
16)
17
18type TCPSuite struct{}
19
20func (*TCPSuite) SetUpSuite(c *C) {
21	log.SetOutput(ioutil.Discard)
22	i18n.InitLocalization(&glib_mock.Mock{})
23}
24
25var _ = Suite(&TCPSuite{})
26
27func (s *TCPSuite) Test_newTCPConn_SkipsSRVAndConnectsToOriginDomain(c *C) {
28	p := &mockProxy{}
29	d := &dialer{
30		JID: "foo@jabber.com",
31
32		proxy: p,
33		config: data.Config{
34			SkipSRVLookup: true,
35		},
36	}
37
38	expectedConn := &net.TCPConn{}
39	p.Expects(func(network, addr string) (net.Conn, error) {
40		c.Check(network, Equals, "tcp")
41		c.Check(addr, Equals, "jabber.com:5222")
42
43		return expectedConn, nil
44	})
45
46	conn, err := d.newTCPConn()
47	c.Check(err, IsNil)
48	c.Check(conn, Equals, expectedConn)
49
50	c.Check(p, MatchesExpectations)
51}
52
53func (s *TCPSuite) Test_newTCPConn_SkipsSRVAndConnectsToConfiguredServerAddress(c *C) {
54	p := &mockProxy{}
55	d := &dialer{
56		JID:           "foo@jabber.com",
57		serverAddress: "jabber.im:5333",
58
59		proxy: p,
60	}
61
62	expectedConn := &net.TCPConn{}
63	p.Expects(func(network, addr string) (net.Conn, error) {
64		c.Check(network, Equals, "tcp")
65		c.Check(addr, Equals, "jabber.im:5333")
66
67		return expectedConn, nil
68	})
69
70	conn, err := d.newTCPConn()
71	c.Check(err, IsNil)
72	c.Check(conn, Equals, expectedConn)
73	c.Check(d.config.SkipSRVLookup, Equals, true)
74
75	c.Check(p, MatchesExpectations)
76}
77
78func (s *TCPSuite) Test_newTCPConn_ErrorsIfServiceIsNotAvailable(c *C) {
79	p := &mockProxy{}
80	d := &dialer{
81		JID: "foo@jabber.com",
82
83		proxy: p,
84	}
85
86	// We exploit ResolveSRVWithProxy forwarding conn errors
87	// to fake an error it should generated.
88	p.Expects(func(network, addr string) (net.Conn, error) {
89		c.Check(network, Equals, "tcp")
90		c.Check(addr, Equals, "208.67.222.222:53")
91
92		return nil, ErrServiceNotAvailable
93	})
94
95	_, err := d.newTCPConn()
96	c.Check(err, Equals, ErrServiceNotAvailable)
97
98	c.Check(p, MatchesExpectations)
99}
100
101func (s *TCPSuite) Test_newTCPConn_DefaultsToOriginDomainAtDefaultPortAfterSRVFails(c *C) {
102	p := &mockProxy{}
103	d := &dialer{
104		JID: "foo@jabber.com",
105
106		proxy: p,
107	}
108
109	p.Expects(func(network, addr string) (net.Conn, error) {
110		c.Check(network, Equals, "tcp")
111		c.Check(addr, Equals, "208.67.222.222:53")
112
113		return nil, io.EOF
114	})
115
116	expectedConn := &net.TCPConn{}
117	p.Expects(func(network, addr string) (net.Conn, error) {
118		c.Check(network, Equals, "tcp")
119		c.Check(addr, Equals, "jabber.com:5222")
120
121		return expectedConn, nil
122	})
123
124	conn, err := d.newTCPConn()
125	c.Check(err, IsNil)
126	c.Check(conn, Equals, expectedConn)
127
128	c.Check(p, MatchesExpectations)
129}
130
131func (s *TCPSuite) Test_newTCPConn_ErrorsWhenTCPBindingFails(c *C) {
132	p := &mockProxy{}
133	d := &dialer{
134		JID: "foo@jabber.com",
135
136		proxy: p,
137	}
138
139	p.Expects(func(network, addr string) (net.Conn, error) {
140		c.Check(network, Equals, "tcp")
141		c.Check(addr, Equals, "208.67.222.222:53")
142
143		return nil, io.EOF
144	})
145
146	p.Expects(func(network, addr string) (net.Conn, error) {
147		c.Check(network, Equals, "tcp")
148		c.Check(addr, Equals, "jabber.com:5222")
149
150		return nil, io.EOF
151	})
152
153	_, err := d.newTCPConn()
154	c.Check(err, Equals, errors.ErrTCPBindingFailed)
155
156	c.Check(p, MatchesExpectations)
157}
158
159func (s *TCPSuite) Test_newTCPConn_ErrorsWhenTCPBindingSucceedsButConnectionFails(c *C) {
160	dec, _ := hex.DecodeString("00511eea818000010001000000000c5f786d70702d636c69656e74045f746370076f6c6162696e690273650000210001c00c0021000100000258001700000005146604786d7070076f6c6162696e6902736500")
161
162	p := &mockProxy{}
163	d := &dialer{
164		JID: "foo@olabini.se",
165
166		proxy: p,
167	}
168
169	p.Expects(func(network, addr string) (net.Conn, error) {
170		c.Check(network, Equals, "tcp")
171		c.Check(addr, Equals, "208.67.222.222:53")
172
173		return fakeTCPConnToDNS(dec)
174	})
175
176	p.Expects(func(network, addr string) (net.Conn, error) {
177		c.Check(network, Equals, "tcp")
178		c.Check(addr, Equals, "xmpp.olabini.se:5222")
179
180		return nil, io.EOF
181	})
182
183	_, err := d.newTCPConn()
184	c.Check(err, Equals, errors.ErrConnectionFailed)
185	c.Check(p, MatchesExpectations)
186}
187