Guest User

Untitled

a guest
Jan 4th, 2021
286
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 3.74 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "flag"
  5.     "io"
  6.     "log"
  7.     "net/http"
  8.     "sync"
  9.  
  10.     "github.com/gorilla/mux"
  11. )
  12.  
  13. type Client struct {
  14.     w         http.ResponseWriter
  15.     r         *http.Request
  16.     connected bool
  17.     closed    bool
  18.     chbuf     chan []byte
  19. }
  20.  
  21. func newClient(w http.ResponseWriter, r *http.Request) *Client {
  22.     chbuf := make(chan []byte, 0)
  23.     c := Client{w, r, true, false, chbuf}
  24.  
  25.     return &c
  26. }
  27.  
  28. type Channel struct {
  29.     value []*Client
  30.     mu    sync.Mutex
  31. }
  32.  
  33. func newChannel() *Channel {
  34.     c := &Channel{}
  35.  
  36.     return c
  37. }
  38.  
  39. func main() {
  40.     key := flag.String("key", "", "Global stream key")
  41.     flag.Parse()
  42.     if *key == "" {
  43.         panic("Supply a stream key")
  44.     }
  45.  
  46.     rtr := mux.NewRouter()
  47.     channelsmu := sync.Mutex{}
  48.     channels := map[string]*Channel{}
  49.  
  50.     rtr.HandleFunc("/ingest/{name}", func(w http.ResponseWriter, r *http.Request) {
  51.         vars := mux.Vars(r)
  52.         log.Printf("[%s] Producer connected to channel '%s'.\n", remoteAddr(r), vars["name"])
  53.  
  54.         keys, ok := r.URL.Query()["key"]
  55.         if !ok || len(keys[0]) < 1 {
  56.             log.Printf("[%s] No stream key supplied.", remoteAddr(r))
  57.             w.WriteHeader(http.StatusForbidden)
  58.             return
  59.         }
  60.         suppliedkey := keys[0]
  61.         if *key != suppliedkey {
  62.             log.Printf("[%s] Invalid stream key supplied.", remoteAddr(r))
  63.             w.WriteHeader(http.StatusForbidden)
  64.             return
  65.         }
  66.  
  67.         channelsmu.Lock()
  68.         channels[vars["name"]] = newChannel()
  69.         channel := channels[vars["name"]]
  70.         channelsmu.Unlock()
  71.         defer (func() {
  72.             log.Printf("Removing channel '%s'", vars["name"])
  73.             channelsmu.Lock()
  74.             delete(channels, vars["name"])
  75.             channelsmu.Unlock()
  76.             channel.mu.Lock()
  77.             for _, v := range channel.value {
  78.                 close(v.chbuf)
  79.             }
  80.             channel.mu.Unlock()
  81.         })()
  82.  
  83.         if r.Body == nil {
  84.             log.Printf("[%s] No body from connected producer.\n", remoteAddr(r))
  85.             return
  86.         }
  87.  
  88.         buf := make([]byte, 4096)
  89.  
  90.         for {
  91.             n, err := r.Body.Read(buf)
  92.  
  93.             tmp := make([]byte, n)
  94.             copy(tmp, buf[:n])
  95.  
  96.             if err == io.EOF {
  97.                 log.Printf("[%s] Producer EOF'd dropping.\n", remoteAddr(r))
  98.                 break
  99.             }
  100.             if err != nil && err != io.EOF {
  101.                 log.Printf("[%s] Producer error: %v.\n", remoteAddr(r), err)
  102.                 break
  103.             }
  104.             channel.mu.Lock()
  105.             for _, v := range channel.value {
  106.                 if v.connected {
  107.                     v.chbuf <- tmp
  108.                 } else if !v.connected && !v.closed {
  109.                     close(v.chbuf)
  110.                     v.closed = true
  111.                 }
  112.  
  113.             }
  114.             channel.mu.Unlock()
  115.         }
  116.  
  117.     })
  118.  
  119.     rtr.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
  120.         vars := mux.Vars(r)
  121.         log.Printf("[%s] Consumer connected to channel '%s'.\n", remoteAddr(r), vars["name"])
  122.         channelsmu.Lock()
  123.         channel := channels[vars["name"]]
  124.         channelsmu.Unlock()
  125.         if channel == nil {
  126.             log.Printf("Channel '%s' does not exist.\n", vars["name"])
  127.             w.WriteHeader(http.StatusNotFound)
  128.             return
  129.         }
  130.  
  131.         cl := newClient(w, r)
  132.  
  133.         channel.mu.Lock()
  134.         channel.value = append(channel.value, cl)
  135.         channel.mu.Unlock()
  136.         for dat := range cl.chbuf {
  137.             if !cl.connected {
  138.                 continue
  139.             }
  140.             _, err := w.Write(dat)
  141.             if err != nil {
  142.                 log.Printf("[%s] Couldn't write to consumer. Error: %s. Flagging connection.\n", remoteAddr(r), err)
  143.                 cl.connected = false
  144.                 continue
  145.             }
  146.             if f, ok := w.(http.Flusher); ok {
  147.                 f.Flush()
  148.             }
  149.         }
  150.  
  151.         channel.mu.Lock()
  152.         newClients := make([]*Client, 0)
  153.         for _, v := range channel.value {
  154.             if v != cl {
  155.                 newClients = append(newClients, v)
  156.             } else {
  157.                 log.Printf("[%s] Dropped consumer.\n", remoteAddr(v.r))
  158.             }
  159.         }
  160.         channel.value = newClients
  161.         channel.mu.Unlock()
  162.     })
  163.  
  164.     srv := &http.Server{
  165.         Handler: rtr,
  166.         Addr:    ":4242",
  167.     }
  168.  
  169.     srv.ListenAndServe()
  170. }
  171.  
  172. func remoteAddr(r *http.Request) string {
  173.     ip := r.Header.Get("x-forwarded-for")
  174.     if ip == "" {
  175.         ip = r.RemoteAddr
  176.     }
  177.     return ip
  178. }
  179.  
Advertisement
Add Comment
Please, Sign In to add comment