@@ -45,34 +45,23 @@ type connection struct {
45
45
compressor wiremessage.CompressorID
46
46
zliblevel int
47
47
connected int32 // must be accessed using the sync/atomic package
48
+ connectDone chan struct {}
49
+ connectErr error
50
+ config * connectionConfig
48
51
49
52
// pool related fields
50
53
pool * pool
51
54
poolID uint64
52
55
generation uint64
53
56
}
54
57
55
- // newConnection handles the creation of a connection. It will dial, configure TLS, and perform
56
- // initialization handshakes.
58
+ // newConnection handles the creation of a connection. It does not connect the connection.
57
59
func newConnection (ctx context.Context , addr address.Address , opts ... ConnectionOption ) (* connection , error ) {
58
60
cfg , err := newConnectionConfig (opts ... )
59
61
if err != nil {
60
62
return nil , err
61
63
}
62
64
63
- nc , err := cfg .dialer .DialContext (ctx , addr .Network (), addr .String ())
64
- if err != nil {
65
- return nil , ConnectionError {Wrapped : err , init : true }
66
- }
67
-
68
- if cfg .tlsConfig != nil {
69
- tlsConfig := cfg .tlsConfig .Clone ()
70
- nc , err = configureTLS (ctx , nc , addr , tlsConfig )
71
- if err != nil {
72
- return nil , ConnectionError {Wrapped : err , init : true }
73
- }
74
- }
75
-
76
65
var lifetimeDeadline time.Time
77
66
if cfg .lifeTimeout > 0 {
78
67
lifetimeDeadline = time .Now ().Add (cfg .lifeTimeout )
@@ -82,32 +71,64 @@ func newConnection(ctx context.Context, addr address.Address, opts ...Connection
82
71
83
72
c := & connection {
84
73
id : id ,
85
- nc : nc ,
86
74
addr : addr ,
87
75
idleTimeout : cfg .idleTimeout ,
88
76
lifetimeDeadline : lifetimeDeadline ,
89
77
readTimeout : cfg .readTimeout ,
90
78
writeTimeout : cfg .writeTimeout ,
79
+ connectDone : make (chan struct {}),
80
+ config : cfg ,
81
+ }
82
+ atomic .StoreInt32 (& c .connected , initialized )
83
+
84
+ return c , nil
85
+ }
86
+
87
+ // connect handles the I/O for a connection. It will dial, configure TLS, and perform
88
+ // initialization handshakes.
89
+ func (c * connection ) connect (ctx context.Context ) {
90
+ if ! atomic .CompareAndSwapInt32 (& c .connected , initialized , connected ) {
91
+ return
92
+ }
93
+ defer close (c .connectDone )
94
+
95
+ var err error
96
+ c .nc , err = c .config .dialer .DialContext (ctx , c .addr .Network (), c .addr .String ())
97
+ if err != nil {
98
+ atomic .StoreInt32 (& c .connected , disconnected )
99
+ c .connectErr = ConnectionError {Wrapped : err , init : true }
100
+ return
101
+ }
102
+
103
+ if c .config .tlsConfig != nil {
104
+ tlsConfig := c .config .tlsConfig .Clone ()
105
+ c .nc , err = configureTLS (ctx , c .nc , c .addr , tlsConfig )
106
+ if err != nil {
107
+ atomic .StoreInt32 (& c .connected , disconnected )
108
+ c .connectErr = ConnectionError {Wrapped : err , init : true }
109
+ return
110
+ }
91
111
}
92
- atomic .StoreInt32 (& c .connected , connected )
93
112
94
113
c .bumpIdleDeadline ()
95
114
96
115
// running isMaster and authentication is handled by a handshaker on the configuration instance.
97
- if cfg .handshaker != nil {
98
- c .desc , err = cfg .handshaker .Handshake (ctx , c .addr , initConnection {c })
116
+ if c . config .handshaker != nil {
117
+ c .desc , err = c . config .handshaker .Handshake (ctx , c .addr , initConnection {c })
99
118
if err != nil {
100
119
if c .nc != nil {
101
120
_ = c .nc .Close ()
102
121
}
103
- return nil , ConnectionError {Wrapped : err , init : true }
122
+ atomic .StoreInt32 (& c .connected , disconnected )
123
+ c .connectErr = ConnectionError {Wrapped : err , init : true }
124
+ return
104
125
}
105
- if cfg .descCallback != nil {
106
- cfg .descCallback (c .desc )
126
+ if c . config .descCallback != nil {
127
+ c . config .descCallback (c .desc )
107
128
}
108
129
if len (c .desc .Compression ) > 0 {
109
130
clientMethodLoop:
110
- for _ , method := range cfg .compressors {
131
+ for _ , method := range c . config .compressors {
111
132
for _ , serverMethod := range c .desc .Compression {
112
133
if method != serverMethod {
113
134
continue
@@ -119,16 +140,20 @@ func newConnection(ctx context.Context, addr address.Address, opts ...Connection
119
140
case "zlib" :
120
141
c .compressor = wiremessage .CompressorZLib
121
142
c .zliblevel = wiremessage .DefaultZlibLevel
122
- if cfg .zlibLevel != nil {
123
- c .zliblevel = * cfg .zlibLevel
143
+ if c . config .zlibLevel != nil {
144
+ c .zliblevel = * c . config .zlibLevel
124
145
}
125
146
}
126
147
break clientMethodLoop
127
148
}
128
149
}
129
150
}
130
151
}
131
- return c , nil
152
+ }
153
+
154
+ func (c * connection ) connectWait () error {
155
+ <- c .connectDone
156
+ return c .connectErr
132
157
}
133
158
134
159
func (c * connection ) writeWireMessage (ctx context.Context , wm []byte ) error {
0 commit comments