mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 00:42:24 -05:00 
			
		
		
		
	
		
			
	
	
		
			55 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			55 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | // Copyright 2019 The Go Authors. All rights reserved. | ||
|  | // Use of this source code is governed by a BSD-style | ||
|  | // license that can be found in the LICENSE file. | ||
|  | 
 | ||
|  | package proxy | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"context" | ||
|  | 	"net" | ||
|  | ) | ||
|  | 
 | ||
|  | // A ContextDialer dials using a context. | ||
|  | type ContextDialer interface { | ||
|  | 	DialContext(ctx context.Context, network, address string) (net.Conn, error) | ||
|  | } | ||
|  | 
 | ||
|  | // Dial works like DialContext on net.Dialer but using a dialer returned by FromEnvironment. | ||
|  | // | ||
|  | // The passed ctx is only used for returning the Conn, not the lifetime of the Conn. | ||
|  | // | ||
|  | // Custom dialers (registered via RegisterDialerType) that do not implement ContextDialer | ||
|  | // can leak a goroutine for as long as it takes the underlying Dialer implementation to timeout. | ||
|  | // | ||
|  | // A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. | ||
|  | func Dial(ctx context.Context, network, address string) (net.Conn, error) { | ||
|  | 	d := FromEnvironment() | ||
|  | 	if xd, ok := d.(ContextDialer); ok { | ||
|  | 		return xd.DialContext(ctx, network, address) | ||
|  | 	} | ||
|  | 	return dialContext(ctx, d, network, address) | ||
|  | } | ||
|  | 
 | ||
|  | // WARNING: this can leak a goroutine for as long as the underlying Dialer implementation takes to timeout | ||
|  | // A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. | ||
|  | func dialContext(ctx context.Context, d Dialer, network, address string) (net.Conn, error) { | ||
|  | 	var ( | ||
|  | 		conn net.Conn | ||
|  | 		done = make(chan struct{}, 1) | ||
|  | 		err  error | ||
|  | 	) | ||
|  | 	go func() { | ||
|  | 		conn, err = d.Dial(network, address) | ||
|  | 		close(done) | ||
|  | 		if conn != nil && ctx.Err() != nil { | ||
|  | 			conn.Close() | ||
|  | 		} | ||
|  | 	}() | ||
|  | 	select { | ||
|  | 	case <-ctx.Done(): | ||
|  | 		err = ctx.Err() | ||
|  | 	case <-done: | ||
|  | 	} | ||
|  | 	return conn, err | ||
|  | } |