|  | @@ -0,0 +1,62 @@
 | 
											
												
													
														|  | 
 |  | +package ws
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +import (
 | 
											
												
													
														|  | 
 |  | +	"errors"
 | 
											
												
													
														|  | 
 |  | +	"net"
 | 
											
												
													
														|  | 
 |  | +	"time"
 | 
											
												
													
														|  | 
 |  | +)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +type StoppableListener struct {
 | 
											
												
													
														|  | 
 |  | +	*net.TCPListener          //Wrapped listener
 | 
											
												
													
														|  | 
 |  | +	stop             chan int //Channel used only to indicate listener should shutdown
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +func NewStoppableListener(l net.Listener) (*StoppableListener, error) {
 | 
											
												
													
														|  | 
 |  | +	tcpL, ok := l.(*net.TCPListener)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	if !ok {
 | 
											
												
													
														|  | 
 |  | +		return nil, errors.New("Cannot wrap listener")
 | 
											
												
													
														|  | 
 |  | +	}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	retval := &StoppableListener{}
 | 
											
												
													
														|  | 
 |  | +	retval.TCPListener = tcpL
 | 
											
												
													
														|  | 
 |  | +	retval.stop = make(chan int)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	return retval, nil
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +var StoppedError = errors.New("Listener stopped")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +func (sl *StoppableListener) Accept() (net.Conn, error) {
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	for {
 | 
											
												
													
														|  | 
 |  | +		//Wait up to one second for a new connection
 | 
											
												
													
														|  | 
 |  | +		sl.SetDeadline(time.Now().Add(time.Second))
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +		newConn, err := sl.TCPListener.Accept()
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +		//Check for the channel being closed
 | 
											
												
													
														|  | 
 |  | +		select {
 | 
											
												
													
														|  | 
 |  | +		case <-sl.stop:
 | 
											
												
													
														|  | 
 |  | +			return nil, StoppedError
 | 
											
												
													
														|  | 
 |  | +		default:
 | 
											
												
													
														|  | 
 |  | +			//If the channel is still open, continue as normal
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +		if err != nil {
 | 
											
												
													
														|  | 
 |  | +			netErr, ok := err.(net.Error)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +			//If this is a timeout, then continue to wait for
 | 
											
												
													
														|  | 
 |  | +			//new connections
 | 
											
												
													
														|  | 
 |  | +			if ok && netErr.Timeout() && netErr.Temporary() {
 | 
											
												
													
														|  | 
 |  | +				continue
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +		return newConn, err
 | 
											
												
													
														|  | 
 |  | +	}
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +func (sl *StoppableListener) Stop() {
 | 
											
												
													
														|  | 
 |  | +	close(sl.stop)
 | 
											
												
													
														|  | 
 |  | +}
 |