From a36582b29451fe37aa659ac676a2fd3fa96abbf8 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Mon, 15 Aug 2016 18:16:54 +0800 Subject: [PATCH] Added stopable listener --- transport/internet/ws/stopablehttplistener.go | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 transport/internet/ws/stopablehttplistener.go diff --git a/transport/internet/ws/stopablehttplistener.go b/transport/internet/ws/stopablehttplistener.go new file mode 100644 index 00000000..832b04e2 --- /dev/null +++ b/transport/internet/ws/stopablehttplistener.go @@ -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) +}