Commit e37e2703 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Implement graceful server shutdown.

This gives the user a friendly message when the server shuts down.
parent 7707775c
......@@ -12,3 +12,7 @@ type client interface {
pushConn(id string, conn upConnection, tracks []upTrack, label string) error
pushClient(id, username string, add bool) error
}
type kickable interface {
kick(message string) error
}
......@@ -64,7 +64,7 @@ type connectionFailedAction struct {
type permissionsChangedAction struct{}
type kickAction struct{
type kickAction struct {
message string
}
......@@ -288,6 +288,16 @@ func (g *group) Range(f func(c client) bool) {
}
}
func (g *group) shutdown(message string) {
g.Range(func(c client) bool {
cc, ok := c.(kickable)
if ok {
cc.kick(message)
}
return true
})
}
const maxChatHistory = 20
func (g *group) clearChatHistory() {
......
......@@ -87,6 +87,7 @@ func main() {
webserver()
terminate := make(chan os.Signal, 1)
signal.Notify(terminate, syscall.SIGINT)
signal.Notify(terminate, syscall.SIGINT, syscall.SIGTERM)
<-terminate
shutdown()
}
......@@ -943,6 +943,10 @@ func setPermissions(g *group, id string, perm string) error {
return c.action(permissionsChangedAction{})
}
func (c *webClient) kick(message string) error {
return c.action(kickAction{message})
}
func kickClient(g *group, id string, message string) error {
g.mu.Lock()
defer g.mu.Unlock()
......@@ -952,12 +956,12 @@ func kickClient(g *group, id string, message string) error {
return userError("no such user")
}
c, ok := client.(*webClient)
c, ok := client.(kickable)
if !ok {
return userError("this is not a real user")
return userError("this client is not kickable")
}
return c.action(kickAction{message})
return c.kick(message)
}
func handleClientMessage(c *webClient, m clientMessage) error {
......
......@@ -2,6 +2,7 @@ package main
import (
"bufio"
"context"
"encoding/json"
"errors"
"fmt"
......@@ -19,6 +20,8 @@ import (
"github.com/gorilla/websocket"
)
var server *http.Server
func webserver() {
http.Handle("/", mungeHandler{http.FileServer(http.Dir(staticRoot))})
http.HandleFunc("/group/", groupHandler)
......@@ -39,17 +42,24 @@ func webserver() {
http.HandleFunc("/stats", statsHandler)
go func() {
server := &http.Server{
server = &http.Server{
Addr: httpAddr,
ReadHeaderTimeout: 60 * time.Second,
IdleTimeout: 120 * time.Second,
}
server.RegisterOnShutdown(func() {
groups.mu.Lock()
defer groups.mu.Unlock()
for _, g := range groups.groups {
go g.shutdown("server is shutting down")
}
})
var err error
err = server.ListenAndServeTLS(
filepath.Join(dataDir, "cert.pem"),
filepath.Join(dataDir, "key.pem"),
)
if err != nil {
if err != nil && err != http.ErrServerClosed {
log.Printf("ListenAndServeTLS: %v", err)
}
}()
......@@ -457,3 +467,8 @@ func serveGroupRecordings(w http.ResponseWriter, r *http.Request, f *os.File, gr
fmt.Fprintf(w, "</table>\n")
fmt.Fprintf(w, "</body></html>\n")
}
func shutdown() {
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second)
server.Shutdown(ctx)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment