-
-
Notifications
You must be signed in to change notification settings - Fork 15
/
main.go
82 lines (75 loc) · 2.16 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package main
import (
"flag"
"fmt"
"log"
"net/http"
"os"
"github.com/blueimp/mjpeg-server/internal/registry"
"github.com/blueimp/mjpeg-server/internal/request"
)
var (
// Version provides the program version information.
// It is provided at build time via -ldflags="-X main.Version=VERSION".
Version = "dev"
showVersion = flag.Bool("v", false, "Output version and exit")
directStart = flag.Bool("d", false, "Start command directly")
addr = flag.String("a", ":9000", "TCP listen address")
urlPath = flag.String("p", "/", "URL path")
boundary = flag.String("b", "ffmpeg", "Multipart boundary")
command string
args []string
reg registry.Registry
)
func setHeaders(header http.Header) {
// Provide the multipart boundary via MJPEG over HTTP content-type header.
// See also:
// - https://en.wikipedia.org/wiki/Motion_JPEG#M-JPEG_over_HTTP
// - https://tools.ietf.org/html/rfc2046#section-5.1.1
header.Set(
"Content-Type",
fmt.Sprintf("multipart/x-mixed-replace;boundary=%s", *boundary),
)
// Prevent client caches from storing the response.
// See also: https://tools.ietf.org/html/rfc7234#section-5.2.1.5
header.Set("Cache-Control", "no-store")
// Signal to the client that the connection will be closed after completion of
// the response.
// See also: https://tools.ietf.org/html/rfc2616#section-14.10
header.Set("Connection", "close")
}
func requestHandler(res http.ResponseWriter, req *http.Request) {
id := reg.GenerateID()
request.Log(req, id)
if req.Method != "GET" {
res.Header().Set("Allow", "GET")
res.WriteHeader(http.StatusMethodNotAllowed)
return
}
if req.URL.Path != *urlPath {
res.WriteHeader(http.StatusNotFound)
return
}
setHeaders(res.Header())
reg.Add(id, res)
// Wait until the client connection is closed.
<-req.Context().Done()
reg.Remove(id, res)
}
func parseArgs() {
flag.Parse()
command = flag.Arg(0)
if command != "" {
args = flag.Args()[1:]
}
}
func main() {
log.SetOutput(os.Stderr)
parseArgs()
if *showVersion {
fmt.Println(Version)
os.Exit(0)
}
reg = registry.New(command, args, *directStart)
log.Fatalln(http.ListenAndServe(*addr, http.HandlerFunc(requestHandler)))
}