blob: 1470428b54a0b9ba61ee5a98210924b66ab72253 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package pmhttp
import (
"fmt"
"net/http"
"sync"
"time"
"go.fuchsia.dev/fuchsia/src/sys/pkg/lib/sse"
)
type RemoteAddr string
type AutoServer struct {
mu sync.Mutex
clients map[http.ResponseWriter]RemoteAddr
}
func NewAutoServer() *AutoServer {
return &AutoServer{clients: map[http.ResponseWriter]RemoteAddr{}}
}
func (a *AutoServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Grab the lock first before starting the SSE server so we block
// broadcasting events until we've finished adding the client to our
// client set. Otherwise, a client could miss an event that came in
// during the registration process.
a.mu.Lock()
err := sse.Start(w, r)
if err != nil {
a.mu.Unlock()
fmt.Printf("%s [pm auto] SSE request failure: %s\n", time.Now().Format("2006-01-02 15:04:05"), err)
w.WriteHeader(http.StatusInternalServerError)
return
}
a.clients[w] = RemoteAddr(r.RemoteAddr)
fmt.Printf("%s [pm auto] adding client: %s\n", time.Now().Format("2006-01-02 15:04:05"), r.RemoteAddr)
fmt.Printf("%s [pm auto] client count: %d\n", time.Now().Format("2006-01-02 15:04:05"), len(a.clients))
defer func() {
a.mu.Lock()
delete(a.clients, w)
fmt.Printf("%s [pm auto] removing client: %s\n", time.Now().Format("2006-01-02 15:04:05"), r.RemoteAddr)
fmt.Printf("%s [pm auto] client count: %d\n", time.Now().Format("2006-01-02 15:04:05"), len(a.clients))
a.mu.Unlock()
}()
a.mu.Unlock()
<-r.Context().Done()
}
func (a *AutoServer) Broadcast(name, data string) {
a.mu.Lock()
defer a.mu.Unlock()
for w, remoteAddr := range a.clients {
fmt.Printf("%s [pm auto] notifying client: %s\n", time.Now().Format("2006-01-02 15:04:05"), remoteAddr)
sse.Write(w, &sse.Event{
Event: name,
Data: []byte(data),
})
}
}