diff --git a/pkg/config/loader.go b/pkg/config/loader.go index 99ae6e7c..a2fb6bd8 100644 --- a/pkg/config/loader.go +++ b/pkg/config/loader.go @@ -88,6 +88,9 @@ func (e *Env) Read() (Kv, error) { mp := make(Kv) for _, k := range keys { parts := strings.SplitN(k, "=", 2) + if parts == nil { + continue + } n := strings.ToLower(strings.TrimPrefix(parts[0], string(*e))) if n == "" { continue @@ -102,7 +105,9 @@ func (e *Env) Read() (Kv, error) { } else { key = strings.Replace(n[:x+1], "_", ".", -1) + n[x+2:] } - mp[key] = parts[1] + if len(parts) > 1 { + mp[key] = parts[1] + } } return maps.Unflatten(mp, "."), nil } diff --git a/pkg/coordinator/userhandlers.go b/pkg/coordinator/userhandlers.go index 81b6bf4f..d754109d 100644 --- a/pkg/coordinator/userhandlers.go +++ b/pkg/coordinator/userhandlers.go @@ -127,14 +127,16 @@ func (u *User) handleGetWorkerList(debug bool, info HasServerInfo) { if debug { response.Servers = servers } else { - // not sure if []byte to string always reversible :/ unique := map[string]*api.Server{} for _, s := range servers { mid := s.Machine if _, ok := unique[mid]; !ok { unique[mid] = &api.Server{Addr: s.Addr, PingURL: s.PingURL, Id: s.Id, InGroup: true} } - unique[mid].Replicas++ + v := unique[mid] + if v != nil { + v.Replicas++ + } } for _, v := range unique { response.Servers = append(response.Servers, *v) diff --git a/pkg/encoder/encoder.go b/pkg/encoder/encoder.go index a9f9003c..5378e47c 100644 --- a/pkg/encoder/encoder.go +++ b/pkg/encoder/encoder.go @@ -62,6 +62,9 @@ func NewVideoEncoder(w, h, dw, dh int, scale float64, conf config.Video, log *lo if err != nil { return nil, err } + if enc == nil { + return nil, fmt.Errorf("no encoder") + } return &Video{codec: enc, y: yuv.NewYuvConv(w, h, scale), log: log}, nil } @@ -86,6 +89,10 @@ func (v *Video) Info() string { } func (v *Video) SetPixFormat(f uint32) { + if v == nil { + return + } + switch f { case 1: v.pf = yuv.PixFmt(yuv.FourccArgb) @@ -98,15 +105,28 @@ func (v *Video) SetPixFormat(f uint32) { // SetRot sets the de-rotation angle of the frames. func (v *Video) SetRot(a uint) { + if v == nil { + return + } + if a > 0 { v.rot = (a + 180) % 360 } } // SetFlip tells the encoder to flip the frames vertically. -func (v *Video) SetFlip(b bool) { v.codec.SetFlip(b) } +func (v *Video) SetFlip(b bool) { + if v == nil { + return + } + v.codec.SetFlip(b) +} func (v *Video) Stop() { + if v == nil { + return + } + if v.stopped.Swap(true) { return } @@ -114,6 +134,8 @@ func (v *Video) Stop() { defer func() { v.codec = nil }() if err := v.codec.Shutdown(); err != nil { - v.log.Error().Err(err).Msg("failed to close the encoder") + if v.log != nil { + v.log.Error().Err(err).Msg("failed to close the encoder") + } } } diff --git a/pkg/encoder/h264/x264_test.go b/pkg/encoder/h264/x264_test.go index b13c0bc4..09f22ae3 100644 --- a/pkg/encoder/h264/x264_test.go +++ b/pkg/encoder/h264/x264_test.go @@ -6,6 +6,7 @@ func TestH264Encode(t *testing.T) { h264, err := NewEncoder(120, 120, 0, nil) if err != nil { t.Error(err) + return } data := make([]byte, 120*120*1.5) h264.LoadBuf(data) @@ -20,6 +21,7 @@ func Benchmark(b *testing.B) { h264, err := NewEncoder(w, h, 0, nil) if err != nil { b.Error(err) + return } data := make([]byte, int(float64(w)*float64(h)*1.5)) for i := 0; i < b.N; i++ { diff --git a/pkg/network/address.go b/pkg/network/address.go index 5fcaca49..318c9cd5 100644 --- a/pkg/network/address.go +++ b/pkg/network/address.go @@ -2,6 +2,7 @@ package network import ( "errors" + "net" "strconv" "strings" ) @@ -12,15 +13,17 @@ func (a *Address) Port() (int, error) { if len(string(*a)) == 0 { return 0, errors.New("no address") } - parts := strings.Split(string(*a), ":") - var port string - if len(parts) == 1 { - port = parts[0] - } else { - port = parts[len(parts)-1] + addr := replaceAllExceptLast(string(*a), ":", "_") + _, port, err := net.SplitHostPort(addr) + if err != nil { + return 0, err } if val, err := strconv.Atoi(port); err == nil { return val, nil } return 0, errors.New("port is not a number") } + +func replaceAllExceptLast(s, c, x string) string { + return strings.Replace(s, c, x, strings.Count(s, c)-1) +} diff --git a/pkg/network/httpx/server.go b/pkg/network/httpx/server.go index eb6e8c1e..5486c05c 100644 --- a/pkg/network/httpx/server.go +++ b/pkg/network/httpx/server.go @@ -120,12 +120,12 @@ func (s *Server) run() { s.log.Debug().Msgf("Starting %s server on %s", protocol, s.Addr) if s.opts.Https && s.opts.HttpsRedirect { - rdr, err := s.redirection() - if err != nil { + if rdr, err := s.redirection(); err == nil { + s.redirect = rdr + go s.redirect.Run() + } else { s.log.Error().Err(err).Msg("couldn't init redirection server") } - s.redirect = rdr - go s.redirect.Run() } var err error @@ -165,6 +165,7 @@ func (s *Server) redirection() (*Server, error) { address = s.opts.HttpsDomain } addr := buildAddress(address, s.opts.Zone, *s.listener) + s.log.Info().Str("addr", addr).Msg("Start HTTPS redirect server") srv, err := NewServer(s.opts.HttpsRedirectAddress, func(serv *Server) Handler { h := NewServeMux("") @@ -186,7 +187,6 @@ func (s *Server) redirection() (*Server, error) { }, WithLogger(s.log), ) - s.log.Info().Str("addr", addr).Msg("Start HTTPS redirect server") return srv, err } diff --git a/pkg/worker/caged/libretro/caged.go b/pkg/worker/caged/libretro/caged.go index a0b5f633..dea9bf5c 100644 --- a/pkg/worker/caged/libretro/caged.go +++ b/pkg/worker/caged/libretro/caged.go @@ -38,6 +38,7 @@ func (c *Caged) ReloadFrontend() { frontend, err := NewFrontend(c.conf.Emulator, c.log) if err != nil { c.log.Fatal().Err(err).Send() + return } c.Emulator = frontend c.base = frontend @@ -47,6 +48,9 @@ func (c *Caged) ReloadFrontend() { func (c *Caged) VideoChangeCb(fn func()) { c.base.SetVideoChangeCb(fn) } func (c *Caged) Load(game games.GameMetadata, path string) error { + if c.Emulator == nil { + return nil + } c.Emulator.LoadCore(game.System) if err := c.Emulator.LoadGame(game.FullPath(path)); err != nil { return err diff --git a/pkg/worker/caged/libretro/frontend.go b/pkg/worker/caged/libretro/frontend.go index dc8316d5..0386b0a8 100644 --- a/pkg/worker/caged/libretro/frontend.go +++ b/pkg/worker/caged/libretro/frontend.go @@ -217,6 +217,9 @@ func (f *Frontend) Shutdown() { func (f *Frontend) linkNano(nano *nanoarch.Nanoarch) { f.nano = nano + if nano == nil { + return + } f.nano.WaitReady() // start only when nano is available f.nano.OnKeyPress = f.input.isKeyPressed @@ -225,7 +228,11 @@ func (f *Frontend) linkNano(nano *nanoarch.Nanoarch) { f.nano.OnAudio = f.handleAudio } -func (f *Frontend) SetVideoChangeCb(fn func()) { f.nano.OnSystemAvInfo = fn } +func (f *Frontend) SetVideoChangeCb(fn func()) { + if f.nano != nil { + f.nano.OnSystemAvInfo = fn + } +} func (f *Frontend) Start() { f.log.Debug().Msgf("frontend start") diff --git a/pkg/worker/caged/libretro/graphics/opengl.go b/pkg/worker/caged/libretro/graphics/opengl.go index ea8b8c09..99eef10d 100644 --- a/pkg/worker/caged/libretro/graphics/opengl.go +++ b/pkg/worker/caged/libretro/graphics/opengl.go @@ -50,7 +50,7 @@ const ( var ( opt = offscreenSetup{} - buf []byte + buf = make([]byte, 1024*1024) ) func initContext(getProcAddr func(name string) unsafe.Pointer) { diff --git a/pkg/worker/caged/libretro/manager/grab.go b/pkg/worker/caged/libretro/manager/grab.go index a2ece967..f7d40a05 100644 --- a/pkg/worker/caged/libretro/manager/grab.go +++ b/pkg/worker/caged/libretro/manager/grab.go @@ -47,11 +47,15 @@ func (d GrabDownloader) Request(dest string, urls ...Download) (ok []string, noo r := resp.Request if err := resp.Err(); err != nil { d.log.Error().Err(err).Msgf("download [%s] %s has failed: %v", r.Label, r.URL(), err) - if resp.HTTPResponse.StatusCode == 404 { + if resp.HTTPResponse != nil && resp.HTTPResponse.StatusCode == 404 { nook = append(nook, resp.Request.Label) } } else { - d.log.Info().Msgf("Downloaded [%v] [%s] -> %s", resp.HTTPResponse.Status, r.Label, resp.Filename) + status := "" + if resp.HTTPResponse != nil { + status = resp.HTTPResponse.Status + } + d.log.Info().Msgf("Downloaded [%v] [%s] -> %s", status, r.Label, resp.Filename) ok = append(ok, resp.Filename) } } diff --git a/pkg/worker/media/media.go b/pkg/worker/media/media.go index 70758b1c..39c48442 100644 --- a/pkg/worker/media/media.go +++ b/pkg/worker/media/media.go @@ -145,6 +145,10 @@ func (wmp *WebrtcMediaPipe) Init() error { if err := wmp.initVideo(wmp.VideoW, wmp.VideoH, wmp.VideoScale, wmp.vConf); err != nil { return err } + if wmp.v == nil || wmp.a == nil { + return fmt.Errorf("could intit the encoders, v=%v a=%v", wmp.v != nil, wmp.a != nil) + } + wmp.log.Debug().Msgf("%v", wmp.v.Info()) wmp.initialized = true return nil @@ -179,7 +183,14 @@ func (wmp *WebrtcMediaPipe) encodeAudio(pcm samples) { func (wmp *WebrtcMediaPipe) initVideo(w, h int, scale float64, conf config.Video) (err error) { sw, sh := round(w, scale), round(h, scale) - wmp.v, err = encoder.NewVideoEncoder(w, h, sw, sh, scale, conf, wmp.log) + enc, err := encoder.NewVideoEncoder(w, h, sw, sh, scale, conf, wmp.log) + if err != nil { + return err + } + if enc == nil { + return fmt.Errorf("broken video encoder init") + } + wmp.v = enc wmp.log.Debug().Msgf("media scale: %vx%v -> %vx%v", w, h, sw, sh) return err } diff --git a/pkg/worker/media/media_test.go b/pkg/worker/media/media_test.go index 93568cc2..8db75e6c 100644 --- a/pkg/worker/media/media_test.go +++ b/pkg/worker/media/media_test.go @@ -66,6 +66,7 @@ func run(w, h int, cod encoder.VideoCodec, count int, a *image.RGBA, b *image.RG ve, err := encoder.NewVideoEncoder(w, h, w, h, 1, conf, l) if err != nil { backend.Error(err) + return } defer ve.Stop() diff --git a/pkg/worker/recorder/recorder.go b/pkg/worker/recorder/recorder.go index 4c3d1207..d0c1165b 100644 --- a/pkg/worker/recorder/recorder.go +++ b/pkg/worker/recorder/recorder.go @@ -98,11 +98,13 @@ func (r *Recording) Start() { audio, err := newWavStream(path, r.opts) if err != nil { r.log.Fatal().Err(err) + return } r.audio = audio video, err := newRawStream(path) if err != nil { r.log.Fatal().Err(err) + return } r.video = video } @@ -111,8 +113,12 @@ func (r *Recording) Stop() (err error) { r.Lock() defer r.Unlock() r.enabled = false - err = r.audio.Close() - err = r.video.Close() + if r.audio != nil { + err = r.audio.Close() + } + if r.video != nil { + err = r.video.Close() + } path := filepath.Join(r.dir, r.saveDir) // FFMPEG diff --git a/pkg/worker/room/room_test.go b/pkg/worker/room/room_test.go index e41004b9..c1459e0a 100644 --- a/pkg/worker/room/room_test.go +++ b/pkg/worker/room/room_test.go @@ -139,18 +139,15 @@ func TestAll(t *testing.T) { if renderFrames { rect := image.Rect(0, 0, frame.W, frame.H) var src image.Image - if test.color == 1 { - src1 := bgra.NewBGRA(rect) - src1.Pix = frame.Data - src1.Stride = frame.Stride - src = src1 - } else { - if test.color == 2 { - src1 := rgb565.NewRGB565(rect) - src1.Pix = frame.Data - src1.Stride = frame.Stride - src = src1 - } + src1 := bgra.NewBGRA(rect) + src1.Pix = frame.Data + src1.Stride = frame.Stride + src = src1 + if test.color == 2 { + src2 := rgb565.NewRGB565(rect) + src2.Pix = frame.Data + src2.Stride = frame.Stride + src = src2 } dst := rgba.ToRGBA(src, flip) tag := fmt.Sprintf("%v-%v-0x%08x", runtime.GOOS, test.game.Type, crc32.Checksum(frame.Data, crc32q))