You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							128 lines
						
					
					
						
							2.7 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							128 lines
						
					
					
						
							2.7 KiB
						
					
					
				| package util | |
| 
 | |
| import ( | |
| 	"github.com/seaweedfs/seaweedfs/weed/glog" | |
| 	"net" | |
| 	"time" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/stats" | |
| ) | |
| 
 | |
| // Listener wraps a net.Listener, and gives a place to store the timeout | |
| // parameters. On Accept, it will wrap the net.Conn with our own Conn for us. | |
| type Listener struct { | |
| 	net.Listener | |
| 	ReadTimeout  time.Duration | |
| 	WriteTimeout time.Duration | |
| } | |
| 
 | |
| func (l *Listener) Accept() (net.Conn, error) { | |
| 	c, err := l.Listener.Accept() | |
| 	if err != nil { | |
| 		return nil, err | |
| 	} | |
| 	stats.ConnectionOpen() | |
| 	tc := &Conn{ | |
| 		Conn:         c, | |
| 		ReadTimeout:  l.ReadTimeout, | |
| 		WriteTimeout: l.WriteTimeout, | |
| 	} | |
| 	return tc, nil | |
| } | |
| 
 | |
| // Conn wraps a net.Conn, and sets a deadline for every read | |
| // and write operation. | |
| type Conn struct { | |
| 	net.Conn | |
| 	ReadTimeout  time.Duration | |
| 	WriteTimeout time.Duration | |
| 	isClosed     bool | |
| 	bytesRead    int64 | |
| 	bytesWritten int64 | |
| } | |
| 
 | |
| func (c *Conn) Read(b []byte) (count int, e error) { | |
| 	if c.ReadTimeout != 0 { | |
| 		err := c.Conn.SetReadDeadline(time.Now().Add(c.ReadTimeout * time.Duration(c.bytesRead/40000+1))) | |
| 		if err != nil { | |
| 			return 0, err | |
| 		} | |
| 	} | |
| 	count, e = c.Conn.Read(b) | |
| 	if e == nil { | |
| 		stats.BytesIn(int64(count)) | |
| 		c.bytesRead += int64(count) | |
| 	} | |
| 	return | |
| } | |
| 
 | |
| func (c *Conn) Write(b []byte) (count int, e error) { | |
| 	if c.WriteTimeout != 0 { | |
| 		// minimum 4KB/s | |
| 		err := c.Conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout * time.Duration(c.bytesWritten/40000+1))) | |
| 		if err != nil { | |
| 			return 0, err | |
| 		} | |
| 	} | |
| 	count, e = c.Conn.Write(b) | |
| 	if e == nil { | |
| 		stats.BytesOut(int64(count)) | |
| 		c.bytesWritten += int64(count) | |
| 	} | |
| 	return | |
| } | |
| 
 | |
| func (c *Conn) Close() error { | |
| 	err := c.Conn.Close() | |
| 	if err == nil { | |
| 		if !c.isClosed { | |
| 			stats.ConnectionClose() | |
| 			c.isClosed = true | |
| 		} | |
| 	} | |
| 	return err | |
| } | |
| 
 | |
| func NewListener(addr string, timeout time.Duration) (ipListener net.Listener, err error) { | |
| 	listener, err := net.Listen("tcp", addr) | |
| 	if err != nil { | |
| 		return | |
| 	} | |
| 
 | |
| 	ipListener = &Listener{ | |
| 		Listener:     listener, | |
| 		ReadTimeout:  timeout, | |
| 		WriteTimeout: timeout, | |
| 	} | |
| 
 | |
| 	return | |
| } | |
| 
 | |
| func NewIpAndLocalListeners(host string, port int, timeout time.Duration) (ipListener net.Listener, localListener net.Listener, err error) { | |
| 	listener, err := net.Listen("tcp", JoinHostPort(host, port)) | |
| 	if err != nil { | |
| 		return | |
| 	} | |
| 
 | |
| 	ipListener = &Listener{ | |
| 		Listener:     listener, | |
| 		ReadTimeout:  timeout, | |
| 		WriteTimeout: timeout, | |
| 	} | |
| 
 | |
| 	if host != "localhost" && host != "" && host != "0.0.0.0" && host != "127.0.0.1" && host != "[::]" && host != "[::1]" { | |
| 		listener, err = net.Listen("tcp", JoinHostPort("localhost", port)) | |
| 		if err != nil { | |
| 			glog.V(0).Infof("skip starting on %s:%d: %v", host, port, err) | |
| 			return ipListener, nil, nil | |
| 		} | |
| 
 | |
| 		localListener = &Listener{ | |
| 			Listener:     listener, | |
| 			ReadTimeout:  timeout, | |
| 			WriteTimeout: timeout, | |
| 		} | |
| 	} | |
| 
 | |
| 	return | |
| }
 |