@@ -281,12 +281,14 @@ func (h *auto) Announce(network, local string) (protect.PacketConn, error) {
281281 return nil , err
282282 }
283283
284+ // TODO: settings.AutoDialsParallel
285+ remoteOnly := settings .AutoAlwaysRemote ()
286+
284287 exit , exerr := h .pxr .ProxyFor (Exit )
285288 win , winerr := h .pxr .mainRpnProxyOf (RpnWin )
286289
287290 previdx , recent := h .exp .Get (local )
288291
289- // TODO: announceIfHealthy
290292 c , who , err := core .Race (
291293 network + ".announce-auto." + local ,
292294 tlsHandshakeTimeout ,
@@ -295,6 +297,9 @@ func (h *auto) Announce(network, local string) (protect.PacketConn, error) {
295297 if exit == nil {
296298 return nil , exerr
297299 }
300+ if remoteOnly {
301+ return nil , errNotRemote
302+ }
298303 if recent {
299304 if previdx != myidx {
300305 return nil , errNotPinned
@@ -315,10 +320,13 @@ func (h *auto) Announce(network, local string) (protect.PacketConn, error) {
315320 // ip pinned to this proxy
316321 return h .announceIfHealthy (win , network , local )
317322 }
318- select {
319- case <- ctx .Done ():
320- return nil , ctx .Err ()
321- case <- time .After (shortdelay * myidx ): // 100ms
323+ // delay if not dialing remote exclusively
324+ if ! remoteOnly {
325+ select {
326+ case <- ctx .Done ():
327+ return nil , ctx .Err ()
328+ case <- time .After (shortdelay * myidx ): // 100ms
329+ }
322330 }
323331 return h .announceIfHealthy (win , network , local )
324332 },
@@ -330,41 +338,113 @@ func (h *auto) Announce(network, local string) (protect.PacketConn, error) {
330338}
331339
332340// Accept implements Proxy.
333- func (h * auto ) Accept (network , local string ) (l protect.Listener , err error ) {
341+ func (h * auto ) Accept (network , local string ) (protect.Listener , error ) {
334342 if err := candial (h .status ); err != nil {
335343 return nil , err
336344 }
337- if settings .AutoAlwaysRemote () {
338- log .E ("proxy: auto: accept(%s) on %s remote-dial unimplemented" , network , local )
339- return nil , errNoAutoSupport
340- }
341- exit , err := h .pxr .ProxyFor (Exit )
342- if err == nil {
343- l , err = exit .Dialer ().Accept (network , local )
344- }
345+
346+ // TODO: settings.AutoDialsParallel
347+ remoteOnly := settings .AutoAlwaysRemote ()
348+
349+ exit , exerr := h .pxr .ProxyFor (Exit )
350+ win , winerr := h .pxr .mainRpnProxyOf (RpnWin )
351+
352+ previdx , recent := h .exp .Get (local )
353+
354+ l , who , err := core .Race (
355+ network + ".accept-auto." + local ,
356+ tlsHandshakeTimeout ,
357+ func (ctx context.Context ) (protect.Listener , error ) {
358+ const myidx = 0
359+ if exit == nil {
360+ return nil , exerr
361+ }
362+ if remoteOnly {
363+ return nil , errNotRemote
364+ }
365+ if recent {
366+ if previdx != myidx {
367+ return nil , errNotPinned
368+ }
369+ return h .acceptIfHealthy (exit , network , local )
370+ }
371+ return h .acceptIfHealthy (exit , network , local )
372+ }, func (ctx context.Context ) (protect.Listener , error ) {
373+ const myidx = 1
374+ if win == nil {
375+ return nil , winerr
376+ }
377+ if recent {
378+ if previdx != myidx {
379+ return nil , errNotPinned
380+ }
381+ return h .acceptIfHealthy (win , network , local )
382+ }
383+ // delay if not dialing remote exclusively
384+ if ! remoteOnly {
385+ select {
386+ case <- ctx .Done ():
387+ return nil , ctx .Err ()
388+ case <- time .After (shortdelay * myidx ): // 100ms
389+ }
390+ }
391+ return h .acceptIfHealthy (win , network , local )
392+ },
393+ )
345394 defer localDialStatus (h .status , err )
346395
347- log .I ("proxy: auto: accept(%s) on %s; err? %v" , network , local , err )
396+ log .I ("proxy: auto: w(%d) accept(%s) on %s; err? %v" , who , network , local , err )
348397 return l , err
349398}
350399
351400// Probe implements Proxy.
352- func (h * auto ) Probe (network , local string ) (pc protect.PacketConn , err error ) {
401+ func (h * auto ) Probe (network , local string ) (protect.PacketConn , error ) {
353402 if err := candial (h .status ); err != nil {
354403 return nil , err
355404 }
356- if settings .AutoAlwaysRemote () {
357- log .E ("proxy: auto: probe(%s) on %s remote-dial unimplemented" , network , local )
358- return nil , errNoAutoSupport
359- }
360- // todo: rpnwg, rpnamz, rpnwin
361- exit , err := h .pxr .ProxyFor (Exit )
362- if err == nil {
363- pc , err = exit .Dialer ().Probe (network , local )
364- }
405+
406+ exit , exerr := h .pxr .ProxyFor (Exit )
407+ win , winerr := h .pxr .mainRpnProxyOf (RpnWin )
408+
409+ previdx , recent := h .exp .Get (local )
410+
411+ pc , who , err := core .Race (
412+ network + ".probe-auto." + local ,
413+ tlsHandshakeTimeout ,
414+ func (ctx context.Context ) (protect.PacketConn , error ) {
415+ const myidx = 0
416+ if exit == nil {
417+ return nil , exerr
418+ }
419+ if recent {
420+ if previdx != myidx {
421+ return nil , errNotPinned
422+ }
423+ return h .probeIfHealthy (exit , network , local )
424+ }
425+ return h .probeIfHealthy (exit , network , local )
426+ }, func (ctx context.Context ) (protect.PacketConn , error ) {
427+ const myidx = 1
428+ if win == nil {
429+ return nil , winerr
430+ }
431+ if recent {
432+ if previdx != myidx {
433+ return nil , errNotPinned
434+ }
435+ return h .probeIfHealthy (win , network , local )
436+ }
437+ select {
438+ case <- ctx .Done ():
439+ return nil , ctx .Err ()
440+ case <- time .After (shortdelay * myidx ): // 100ms
441+ }
442+ return h .probeIfHealthy (win , network , local )
443+ },
444+ )
365445 defer localDialStatus (h .status , err )
366446
367- log .I ("proxy: auto: probe(%s) on %s; err? %v" , network , local , err )
447+ log .I ("proxy: auto: w(%d) probe(%s) on %s; err? %v" , who , network , local , err )
368448 return pc , err
369449}
370450
@@ -495,6 +575,22 @@ func (*auto) announceIfHealthy(p Proxy, network, local string) (net.PacketConn,
495575 return p .Dialer ().Announce (network , local )
496576}
497577
578+ func (* auto ) acceptIfHealthy (p Proxy , network , local string ) (net.Listener , error ) {
579+ if err := healthy (p ); err != nil {
580+ log .E ("auto accept; %s %s not ok; %v: %s" , p .ID (), network , err , local )
581+ time .Sleep (delayForUnhealthyProxies )
582+ }
583+ return p .Dialer ().Accept (network , local )
584+ }
585+
586+ func (* auto ) probeIfHealthy (p Proxy , network , local string ) (net.PacketConn , error ) {
587+ if err := healthy (p ); err != nil {
588+ log .E ("auto probe; %s %s not ok; %v: %s" , p .ID (), network , err , local )
589+ time .Sleep (delayForUnhealthyProxies )
590+ }
591+ return p .Dialer ().Probe (network , local )
592+ }
593+
498594func maybeKeepAlive (c net.Conn ) (keepingalive bool ) {
499595 keepingalive , _ = maybeKeepAlive2 (c )
500596 return
0 commit comments