@cryptotaxi247 / kubo / commits / 87458f6d6

p2p/net/dial: fixed data race

Juan Batiz-Benet committed Jan 24, 2015 at 00:09 UTC 87458f6d6a9d52d52a72d6b97f1433beda3c4fb1
1 file changed +11 -8
p2p/net/conn/dial.go
+11 -8
@@ -89,10 +89,17 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee
89 laddr := pickLocalAddr(d.LocalAddrs, raddr)
90 log.Debugf("%s dialing %s -- %s --> %s", d.LocalPeer, remote, laddr, raddr)
91
92 + // make a copy of the manet.Dialer, we may need to change its timeout.
93 + madialer := d.Dialer
94 +
95 if laddr != nil && reuseport.Available() {
96 + // we're perhaps going to dial twice. half the timeout, so we can afford to.
97 + // otherwise our context would expire right after the first dial.
98 + madialer.Dialer.Timeout = (madialer.Dialer.Timeout / 2)
99 +
100 // dial using reuseport.Dialer, because we're probably reusing addrs.
101 // this is optimistic, as the reuseDial may fail to bind the port.
95 - if nconn, retry, reuseErr := d.reuseDial(laddr, raddr); reuseErr == nil {
102 + if nconn, retry, reuseErr := reuseDial(madialer.Dialer, laddr, raddr); reuseErr == nil {
103 // if it worked, wrap the raw net.Conn with our manet.Conn
104 log.Debugf("%s reuse worked! %s %s %s", d.LocalPeer, laddr, nconn.RemoteAddr(), nconn)
105 return manet.WrapNetConn(nconn)
@@ -105,22 +112,18 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee
112 }
113 }
114
108 - // no local addr, or reuseport failed. just dial straight with a new port.
109 - return d.Dialer.Dial(raddr)
115 + return madialer.Dial(raddr)
116 }
117
112 -func (d *Dialer) reuseDial(laddr, raddr ma.Multiaddr) (conn net.Conn, retry bool, err error) {
118 +func reuseDial(dialer net.Dialer, laddr, raddr ma.Multiaddr) (conn net.Conn, retry bool, err error) {
119 if laddr == nil {
120 // if we're given no local address no sense in using reuseport to dial, dial out as usual.
121 return nil, true, reuseport.ErrReuseFailed
122 }
123
118 - // half the timeout so we can retry regularly if this fails.
119 - d.Dialer.Dialer.Timeout = (d.Dialer.Dialer.Timeout / 2)
120 -
124 // give reuse.Dialer the manet.Dialer's Dialer.
125 // (wow, Dialer should've so been an interface...)
123 - rd := reuseport.Dialer{d.Dialer.Dialer}
126 + rd := reuseport.Dialer{dialer}
127
128 // get the local net.Addr manually
129 rd.D.LocalAddr, err = manet.ToNetAddr(laddr)