123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- package server
- import (
- "errors"
- "fmt"
- "net"
- "net/http"
- "os"
- "os/signal"
- "sync"
- "syscall"
- "time"
- )
- type StoppableListener struct {
- *net.TCPListener //Wrapped listener
- stop chan int //Channel used only to indicate listener should shutdown
- }
- var quit chan os.Signal
- func New(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)
- }
- func TerminateServer() {
- quit <- syscall.SIGTERM
- }
- func Start(port string, r http.Handler) {
- orgLst, err := net.Listen("tcp", ":"+port)
- if err != nil {
- panic(err)
- }
- sl, err := New(orgLst)
- if err != nil {
- panic(err)
- }
- server := http.Server{
- Handler: r,
- ReadTimeout: 5 * time.Second,
- WriteTimeout: 10 * time.Second,
- }
- server.SetKeepAlivesEnabled(false)
- quit = make(chan os.Signal)
- signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
- var wg sync.WaitGroup
- go func(wg sync.WaitGroup) {
- wg.Add(1)
- defer wg.Done()
- server.Serve(sl)
- }(wg)
- fmt.Printf("Started at port : " + port + "\n")
- select {
- case signal := <-quit:
- // wait for a few seconds
- time.Sleep(1000 * time.Millisecond)
- fmt.Printf("Got signal:%v\n", signal)
- }
- fmt.Printf("Stopping listener\n")
- sl.Stop()
- fmt.Printf("Waiting on server\n")
- wg.Wait()
- }
|