Skip to content

Commit 90544ba

Browse files
committed
Fix panic for concurrent streams map read and map write #1612
1 parent e55c2e9 commit 90544ba

File tree

5 files changed

+45
-28
lines changed

5 files changed

+45
-28
lines changed

internal/homekit/api.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func apiUnpair(id string) error {
112112
return errors.New(api.StreamNotFound)
113113
}
114114

115-
rawURL := findHomeKitURL(stream)
115+
rawURL := findHomeKitURL(stream.Sources())
116116
if rawURL == "" {
117117
return errors.New("not homekit source")
118118
}
@@ -128,10 +128,10 @@ func apiUnpair(id string) error {
128128

129129
func findHomeKitURLs() map[string]*url.URL {
130130
urls := map[string]*url.URL{}
131-
for id, stream := range streams.Streams() {
132-
if rawURL := findHomeKitURL(stream); rawURL != "" {
131+
for name, sources := range streams.GetAllSources() {
132+
if rawURL := findHomeKitURL(sources); rawURL != "" {
133133
if u, err := url.Parse(rawURL); err == nil {
134-
urls[id] = u
134+
urls[name] = u
135135
}
136136
}
137137
}

internal/homekit/homekit.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func Init() {
7979
Handler: homekit.ServerHandler(srv),
8080
}
8181

82-
if url := findHomeKitURL(stream); url != "" {
82+
if url := findHomeKitURL(stream.Sources()); url != "" {
8383
// 1. Act as transparent proxy for HomeKit camera
8484
dial := func() (net.Conn, error) {
8585
client, err := homekit.Dial(url, srtp.Server)
@@ -186,8 +186,7 @@ func hapPairVerify(w http.ResponseWriter, r *http.Request) {
186186
}
187187
}
188188

189-
func findHomeKitURL(stream *streams.Stream) string {
190-
sources := stream.Sources()
189+
func findHomeKitURL(sources []string) string {
191190
if len(sources) == 0 {
192191
return ""
193192
}

internal/onvif/onvif.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ func onvifDeviceService(w http.ResponseWriter, r *http.Request) {
9999
})
100100

101101
case onvif.MediaGetVideoSources:
102-
b = onvif.GetVideoSourcesResponse(streams.GetAll())
102+
b = onvif.GetVideoSourcesResponse(streams.GetAllNames())
103103

104104
case onvif.MediaGetProfiles:
105105
// important for Hass: H264 codec, width, height
106-
b = onvif.GetProfilesResponse(streams.GetAll())
106+
b = onvif.GetProfilesResponse(streams.GetAllNames())
107107

108108
case onvif.MediaGetProfile:
109109
token := onvif.FindTagValue(b, "ProfileToken")

internal/streams/stream.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@ func NewStream(source any) *Stream {
4747
}
4848
}
4949

50-
func (s *Stream) Sources() (sources []string) {
50+
func (s *Stream) Sources() []string {
51+
sources := make([]string, 0, len(s.producers))
5152
for _, prod := range s.producers {
5253
sources = append(sources, prod.url)
5354
}
54-
return
55+
return sources
5556
}
5657

5758
func (s *Stream) SetSource(source string) {

internal/streams/streams.go

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ func Init() {
4242
})
4343
}
4444

45-
func Get(name string) *Stream {
46-
return streams[name]
47-
}
48-
4945
var sanitize = regexp.MustCompile(`\s`)
5046

5147
// Validate - not allow creating dynamic streams with spaces in the source
@@ -68,6 +64,7 @@ func New(name string, sources ...string) *Stream {
6864
streamsMu.Lock()
6965
streams[name] = stream
7066
streamsMu.Unlock()
67+
7168
return stream
7269
}
7370

@@ -124,7 +121,7 @@ func GetOrPatch(query url.Values) *Stream {
124121
}
125122

126123
// check if src is stream name
127-
if stream, ok := streams[source]; ok {
124+
if stream := Get(source); stream != nil {
128125
return stream
129126
}
130127

@@ -139,21 +136,41 @@ func GetOrPatch(query url.Values) *Stream {
139136
return Patch(source, source)
140137
}
141138

142-
func GetAll() (names []string) {
143-
for name := range streams {
144-
names = append(names, name)
145-
}
146-
return
139+
var log zerolog.Logger
140+
141+
// streams map
142+
143+
var streams = map[string]*Stream{}
144+
var streamsMu sync.Mutex
145+
146+
func Get(name string) *Stream {
147+
streamsMu.Lock()
148+
defer streamsMu.Unlock()
149+
return streams[name]
147150
}
148151

149-
func Streams() map[string]*Stream {
150-
return streams
152+
func Delete(name string) {
153+
streamsMu.Lock()
154+
defer streamsMu.Unlock()
155+
delete(streams, name)
151156
}
152157

153-
func Delete(id string) {
154-
delete(streams, id)
158+
func GetAllNames() []string {
159+
streamsMu.Lock()
160+
names := make([]string, 0, len(streams))
161+
for name := range streams {
162+
names = append(names, name)
163+
}
164+
streamsMu.Unlock()
165+
return names
155166
}
156167

157-
var log zerolog.Logger
158-
var streams = map[string]*Stream{}
159-
var streamsMu sync.Mutex
168+
func GetAllSources() map[string][]string {
169+
streamsMu.Lock()
170+
sources := make(map[string][]string, len(streams))
171+
for name, stream := range streams {
172+
sources[name] = stream.Sources()
173+
}
174+
streamsMu.Unlock()
175+
return sources
176+
}

0 commit comments

Comments
 (0)