@@ -98,25 +98,25 @@ func (d *RDial) ID() string {
9898 if d .owner != "" {
9999 return d .owner
100100 }
101- return "xdial" // ownerless
101+ return core . LocStr ( d ) // ownerless
102102}
103103
104104// Dial implements RDialer.
105105func (d * RDial ) Dial (network , addr string ) (net.Conn , error ) {
106+ if d .dialer == nil {
107+ return nil , errNoDialer
108+ }
106109 return d .dialer .DialContext (d .context (), network , addr )
107110}
108111
109- func (d * RDial ) cloneDialer () * net.Dialer {
110- var rd * net.Dialer = new (net.Dialer )
111- // shallow copy: go.dev/play/p/tuadSFN3glj
112- * rd = * d .dialer
113- return rd
114- }
115-
116112// DialBind implements RDialer.
117113func (d * RDial ) DialBind (network , local , remote string ) (net.Conn , error ) {
114+ if d .dialer == nil {
115+ return nil , errNoDialer
116+ }
118117 var onlyport netip.AddrPort
119- rd := d .cloneDialer ()
118+ // shallow copy: go.dev/play/p/tuadSFN3glj
119+ rd := * d .dialer
120120
121121 if _ , port , err := net .SplitHostPort (local ); err == nil {
122122 // uport may be 0, which is "valid"
@@ -143,7 +143,7 @@ func (d *RDial) DialBind(network, local, remote string) (net.Conn, error) {
143143 onlyport = netip .AddrPortFrom (anyaddr , uint16 (uport ))
144144 } else { // okay for local to be invalid; called by retrier.DialTCP
145145 log .VV ("xdial: DialBind: (o: %s); %s %s=>%s; why: laddr nil" ,
146- d .owner , network , local , remote )
146+ d .ID () , network , local , remote )
147147 }
148148
149149 switch network {
@@ -154,7 +154,7 @@ func (d *RDial) DialBind(network, local, remote string) (net.Conn, error) {
154154 if onlyport .IsValid () { // valid even when port is 0
155155 rd .LocalAddr = net .TCPAddrFromAddrPort (onlyport )
156156 log .V ("xdial: DialBind: (o: %s); %s %s=>%s" ,
157- d .owner , network , rd .LocalAddr , remote )
157+ d .ID () , network , rd .LocalAddr , remote )
158158 }
159159 case "udp" , "udp4" , "udp6" :
160160 if alwaysDualStack {
@@ -163,11 +163,11 @@ func (d *RDial) DialBind(network, local, remote string) (net.Conn, error) {
163163 if onlyport .IsValid () { // valid even when port is 0
164164 rd .LocalAddr = net .UDPAddrFromAddrPort (onlyport )
165165 log .V ("xdial: DialBind: (o: %s); %s %s=>%s" ,
166- d .owner , network , rd .LocalAddr , remote )
166+ d .ID () , network , rd .LocalAddr , remote )
167167 }
168168 default :
169169 log .W ("xdial: DialBind: (o: %s); %s %s=>%s; err: unsupported network" ,
170- d .owner , network , local , remote )
170+ d .ID () , network , local , remote )
171171 }
172172
173173 // equivalent to d.dial() if LocalAddr is not set
@@ -176,6 +176,9 @@ func (d *RDial) DialBind(network, local, remote string) (net.Conn, error) {
176176
177177// Accept implements RDialer interface.
178178func (d * RDial ) Accept (network , local string ) (net.Listener , error ) {
179+ if d .listen == nil {
180+ return nil , errAccept
181+ }
179182 if network != "tcp" && network != "tcp4" && network != "tcp6" {
180183 return nil , errAccept
181184 }
@@ -184,10 +187,14 @@ func (d *RDial) Accept(network, local string) (net.Listener, error) {
184187
185188// Announce implements RDialer.
186189func (d * RDial ) Announce (network , local string ) (net.PacketConn , error ) {
190+ if d .listen == nil {
191+ return nil , errAnnounce
192+ }
187193 if network != "udp" && network != "udp4" && network != "udp6" {
188- log .T ("xdial: Announce: invalid network %s" , network )
194+ log .T ("xdial: (o: %s) Announce: invalid network %s" , d . ID () , network )
189195 return nil , errAnnounce
190196 }
197+ // skip alwaysDualStack and honor client's Announce request network as-is
191198 // todo: check if local is a local address or empty (any)
192199 // diailing (proxy.Dial/net.Dial/etc) on wildcard addresses (ex: ":8080" or "" or "localhost:1025")
193200 // is not equivalent to listening/announcing. see: github.com/golang/go/issues/22827
@@ -196,8 +203,8 @@ func (d *RDial) Announce(network, local string) (net.PacketConn, error) {
196203 case * net.UDPConn :
197204 return x , nil
198205 default :
199- log .T ("xdial: Announce (o: %s): addr(%s) failed; %T is not net.UDPConn; other errs: %v " ,
200- d .owner , local , x , err )
206+ log .T ("xdial: Announce (o: %s): addr(%s) failed; %T is not net.UDPConn" ,
207+ d .ID () , local , x )
201208 clos (pc )
202209 return nil , errNoUDPMux
203210 }
@@ -208,13 +215,22 @@ func (d *RDial) Announce(network, local string) (net.PacketConn, error) {
208215
209216// Probe implements RDialer.
210217func (d * RDial ) Probe (network , local string ) (PacketConn , error ) {
218+ if d .listenICMP == nil {
219+ return nil , errAnnounce
220+ }
211221 if network == "udp" {
212- ip , _ := netip .ParseAddrPort (local )
213- ipok := ip .IsValid ()
214- if ipok && ip .Addr ().Is4 () {
215- network = "udp4"
216- } else if ipok && ip .Addr ().Is6 () {
217- network = "udp6"
222+ if ip , err := netip .ParseAddr (local ); err == nil && ip .IsValid () {
223+ if ip .Is4 () {
224+ network = "udp4"
225+ } else {
226+ network = "udp6"
227+ }
228+ } else if ipp , err := netip .ParseAddrPort (local ); err == nil && ipp .IsValid () {
229+ if ipp .Addr ().Is4 () {
230+ network = "udp4"
231+ } else if ipp .Addr ().Is6 () {
232+ network = "udp6"
233+ }
218234 }
219235 }
220236 if network != "udp4" && network != "udp6" {
0 commit comments