Soe Thu 5 years ago
parent
commit
47b43c516b
1 changed files with 114 additions and 0 deletions
  1. 114 0
      server.go

+ 114 - 0
server.go

@@ -0,0 +1,114 @@
+package go-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()
+}
+