mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	Make TCP read timeouts configurable.
This should be helpful on high-latency networks, like Tor or I2P. Also gofmt.
This commit is contained in:
		
							parent
							
								
									dc0c3f9f8b
								
							
						
					
					
						commit
						d171552577
					
				
					 4 changed files with 25 additions and 15 deletions
				
			
		| 
						 | 
					@ -5,6 +5,7 @@ type NodeConfig struct {
 | 
				
			||||||
	Listen                      string   `comment:"Listen address for peer connections. Default is to listen for all\nTCP connections over IPv4 and IPv6 with a random port."`
 | 
						Listen                      string   `comment:"Listen address for peer connections. Default is to listen for all\nTCP connections over IPv4 and IPv6 with a random port."`
 | 
				
			||||||
	AdminListen                 string   `comment:"Listen address for admin connections Default is to listen for local\nconnections either on TCP/9001 or a UNIX socket depending on your\nplatform. Use this value for yggdrasilctl -endpoint=X."`
 | 
						AdminListen                 string   `comment:"Listen address for admin connections Default is to listen for local\nconnections either on TCP/9001 or a UNIX socket depending on your\nplatform. Use this value for yggdrasilctl -endpoint=X."`
 | 
				
			||||||
	Peers                       []string `comment:"List of connection strings for static peers in URI format, i.e.\ntcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j"`
 | 
						Peers                       []string `comment:"List of connection strings for static peers in URI format, i.e.\ntcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j"`
 | 
				
			||||||
 | 
						ReadTimeout                 int32    `comment:"Read timeout for connections, specified in milliseconds. If less than 6000 and not negative, 6000 (the default) is used. If negative, reads won't time out."`
 | 
				
			||||||
	AllowedEncryptionPublicKeys []string `comment:"List of peer encryption public keys to allow or incoming TCP\nconnections from. If left empty/undefined then all connections\nwill be allowed by default."`
 | 
						AllowedEncryptionPublicKeys []string `comment:"List of peer encryption public keys to allow or incoming TCP\nconnections from. If left empty/undefined then all connections\nwill be allowed by default."`
 | 
				
			||||||
	EncryptionPublicKey         string   `comment:"Your public encryption key. Your peers may ask you for this to put\ninto their AllowedEncryptionPublicKeys configuration."`
 | 
						EncryptionPublicKey         string   `comment:"Your public encryption key. Your peers may ask you for this to put\ninto their AllowedEncryptionPublicKeys configuration."`
 | 
				
			||||||
	EncryptionPrivateKey        string   `comment:"Your private encryption key. DO NOT share this with anyone!"`
 | 
						EncryptionPrivateKey        string   `comment:"Your private encryption key. DO NOT share this with anyone!"`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,7 +97,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
 | 
				
			||||||
	c.init(&boxPub, &boxPriv, &sigPub, &sigPriv)
 | 
						c.init(&boxPub, &boxPriv, &sigPub, &sigPriv)
 | 
				
			||||||
	c.admin.init(c, nc.AdminListen)
 | 
						c.admin.init(c, nc.AdminListen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.tcp.init(c, nc.Listen); err != nil {
 | 
						if err := c.tcp.init(c, nc.Listen, nc.ReadTimeout); err != nil {
 | 
				
			||||||
		c.log.Println("Failed to start TCP interface")
 | 
							c.log.Println("Failed to start TCP interface")
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,8 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense
 | 
					const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense
 | 
				
			||||||
const tcp_timeout = 6 * time.Second
 | 
					const default_tcp_timeout = 6 * time.Second
 | 
				
			||||||
 | 
					const tcp_ping_interval = (default_tcp_timeout * 2 / 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Wrapper function for non tcp/ip connections.
 | 
					// Wrapper function for non tcp/ip connections.
 | 
				
			||||||
func setNoDelay(c net.Conn, delay bool) {
 | 
					func setNoDelay(c net.Conn, delay bool) {
 | 
				
			||||||
| 
						 | 
					@ -42,6 +43,7 @@ func setNoDelay(c net.Conn, delay bool) {
 | 
				
			||||||
type tcpInterface struct {
 | 
					type tcpInterface struct {
 | 
				
			||||||
	core        *Core
 | 
						core        *Core
 | 
				
			||||||
	serv        net.Listener
 | 
						serv        net.Listener
 | 
				
			||||||
 | 
						tcp_timeout time.Duration
 | 
				
			||||||
	mutex       sync.Mutex // Protecting the below
 | 
						mutex       sync.Mutex // Protecting the below
 | 
				
			||||||
	calls       map[string]struct{}
 | 
						calls       map[string]struct{}
 | 
				
			||||||
	conns       map[tcpInfo](chan struct{})
 | 
						conns       map[tcpInfo](chan struct{})
 | 
				
			||||||
| 
						 | 
					@ -72,9 +74,14 @@ func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Initializes the struct.
 | 
					// Initializes the struct.
 | 
				
			||||||
func (iface *tcpInterface) init(core *Core, addr string) (err error) {
 | 
					func (iface *tcpInterface) init(core *Core, addr string, readTimeout int32) (err error) {
 | 
				
			||||||
	iface.core = core
 | 
						iface.core = core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iface.tcp_timeout = time.Duration(readTimeout) * time.Millisecond
 | 
				
			||||||
 | 
						if iface.tcp_timeout >= 0 && iface.tcp_timeout < default_tcp_timeout {
 | 
				
			||||||
 | 
							iface.tcp_timeout = default_tcp_timeout
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	iface.serv, err = net.Listen("tcp", addr)
 | 
						iface.serv, err = net.Listen("tcp", addr)
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		iface.calls = make(map[string]struct{})
 | 
							iface.calls = make(map[string]struct{})
 | 
				
			||||||
| 
						 | 
					@ -113,7 +120,7 @@ func (iface *tcpInterface) call(saddr string, socksaddr *string) {
 | 
				
			||||||
			iface.calls[saddr] = struct{}{}
 | 
								iface.calls[saddr] = struct{}{}
 | 
				
			||||||
			defer func() {
 | 
								defer func() {
 | 
				
			||||||
				// Block new calls for a little while, to mitigate livelock scenarios
 | 
									// Block new calls for a little while, to mitigate livelock scenarios
 | 
				
			||||||
				time.Sleep(tcp_timeout)
 | 
									time.Sleep(default_tcp_timeout)
 | 
				
			||||||
				time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
 | 
									time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
 | 
				
			||||||
				iface.mutex.Lock()
 | 
									iface.mutex.Lock()
 | 
				
			||||||
				delete(iface.calls, saddr)
 | 
									delete(iface.calls, saddr)
 | 
				
			||||||
| 
						 | 
					@ -168,8 +175,9 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	timeout := time.Now().Add(tcp_timeout)
 | 
						if iface.tcp_timeout > 0 {
 | 
				
			||||||
	sock.SetReadDeadline(timeout)
 | 
							sock.SetReadDeadline(time.Now().Add(iface.tcp_timeout))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	_, err = sock.Read(metaBytes)
 | 
						_, err = sock.Read(metaBytes)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
| 
						 | 
					@ -254,7 +262,7 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
 | 
				
			||||||
			atomic.AddUint64(&p.bytesSent, uint64(len(tcp_msg)+len(msgLen)+len(msg)))
 | 
								atomic.AddUint64(&p.bytesSent, uint64(len(tcp_msg)+len(msgLen)+len(msg)))
 | 
				
			||||||
			util_putBytes(msg)
 | 
								util_putBytes(msg)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		timerInterval := tcp_timeout * 2 / 3
 | 
							timerInterval := tcp_ping_interval
 | 
				
			||||||
		timer := time.NewTimer(timerInterval)
 | 
							timer := time.NewTimer(timerInterval)
 | 
				
			||||||
		defer timer.Stop()
 | 
							defer timer.Stop()
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
| 
						 | 
					@ -321,8 +329,9 @@ func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) error {
 | 
				
			||||||
	bs := make([]byte, 2*tcp_msgSize)
 | 
						bs := make([]byte, 2*tcp_msgSize)
 | 
				
			||||||
	frag := bs[:0]
 | 
						frag := bs[:0]
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		timeout := time.Now().Add(tcp_timeout)
 | 
							if iface.tcp_timeout > 0 {
 | 
				
			||||||
		sock.SetReadDeadline(timeout)
 | 
								sock.SetReadDeadline(time.Now().Add(iface.tcp_timeout))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		n, err := sock.Read(bs[len(frag):])
 | 
							n, err := sock.Read(bs[len(frag):])
 | 
				
			||||||
		if n > 0 {
 | 
							if n > 0 {
 | 
				
			||||||
			frag = bs[:len(frag)+n]
 | 
								frag = bs[:len(frag)+n]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue