]> code.octet-stream.net Git - broadcaster/blob - server/radio_sync.go
3dfd4ed5395c008b6cdfe9889fda4d8e6de240ae
[broadcaster] / server / radio_sync.go
1 package main
2
3 import (
4 "code.octet-stream.net/broadcaster/protocol"
5 "encoding/json"
6 "golang.org/x/net/websocket"
7 "log"
8 )
9
10 func RadioSync(ws *websocket.Conn) {
11 log.Println("A websocket connected, I think")
12 buf := make([]byte, 16384)
13
14 badRead := false
15 isAuthenticated := false
16 var radio Radio
17 for {
18 // Ignore any massively oversize messages
19 n, err := ws.Read(buf)
20 if err != nil {
21 if radio.Name != "" {
22 log.Println("Lost websocket to radio:", radio.Name)
23 status.RadioDisconnected(radio.Id)
24 } else {
25 log.Println("Lost unauthenticated websocket")
26 }
27 return
28 }
29 if n == len(buf) {
30 badRead = true
31 continue
32 } else if badRead {
33 badRead = false
34 continue
35 }
36
37 t, msg, err := protocol.ParseMessage(buf[:n])
38 if err != nil {
39 log.Println(err)
40 return
41 }
42
43 if !isAuthenticated && t != protocol.AuthenticateType {
44 continue
45 }
46
47 if t == protocol.AuthenticateType && !isAuthenticated {
48 authMsg := msg.(protocol.AuthenticateMessage)
49 r, err := db.GetRadioByToken(authMsg.Token)
50 if err != nil {
51 log.Println("Could not find radio for offered token", authMsg.Token)
52 }
53 radio = r
54 log.Println("Radio authenticated:", radio.Name)
55 isAuthenticated = true
56
57 go KeepFilesUpdated(ws)
58
59 // send initial file message
60 err = sendFilesMessageToRadio(ws)
61 if err != nil {
62 return
63 }
64
65 go KeepPlaylistsUpdated(ws)
66
67 // send initial playlists message
68 err = sendPlaylistsMessageToRadio(ws)
69 if err != nil {
70 return
71 }
72 }
73
74 if t == protocol.StatusType {
75 statusMsg := msg.(protocol.StatusMessage)
76 log.Println("Received Status from", radio.Name, ":", statusMsg)
77 status.MergeStatus(radio.Id, statusMsg)
78 }
79 }
80 }
81
82 func sendPlaylistsMessageToRadio(ws *websocket.Conn) error {
83 playlistSpecs := make([]protocol.PlaylistSpec, 0)
84 for _, v := range db.GetPlaylists() {
85 if v.Enabled {
86 entrySpecs := make([]protocol.EntrySpec, 0)
87 for _, e := range db.GetEntriesForPlaylist(v.Id) {
88 entrySpecs = append(entrySpecs, protocol.EntrySpec{Filename: e.Filename, DelaySeconds: e.DelaySeconds, IsRelative: e.IsRelative})
89 }
90 playlistSpecs = append(playlistSpecs, protocol.PlaylistSpec{Id: v.Id, Name: v.Name, StartTime: v.StartTime, Entries: entrySpecs})
91 }
92 }
93 playlists := protocol.PlaylistsMessage{
94 T: protocol.PlaylistsType,
95 Playlists: playlistSpecs,
96 }
97 msg, _ := json.Marshal(playlists)
98 _, err := ws.Write(msg)
99 return err
100 }
101
102 func KeepPlaylistsUpdated(ws *websocket.Conn) {
103 for {
104 <-playlistChangeWait
105 err := sendPlaylistsMessageToRadio(ws)
106 if err != nil {
107 return
108 }
109 }
110 }
111
112 func sendFilesMessageToRadio(ws *websocket.Conn) error {
113 specs := make([]protocol.FileSpec, 0)
114 for _, v := range files.Files() {
115 specs = append(specs, protocol.FileSpec{Name: v.Name, Hash: v.Hash})
116 }
117 files := protocol.FilesMessage{
118 T: protocol.FilesType,
119 Files: specs,
120 }
121 msg, _ := json.Marshal(files)
122 _, err := ws.Write(msg)
123 return err
124 }
125
126 func KeepFilesUpdated(ws *websocket.Conn) {
127 for {
128 <-files.ChangeChannel()
129 err := sendFilesMessageToRadio(ws)
130 if err != nil {
131 return
132 }
133 }
134 }