mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2026-03-14 14:35:44 +01:00
Merge pull request #1190 from strukturag/simplify-error-type
Simplify error type checks.
This commit is contained in:
commit
0b46f9d17c
8 changed files with 140 additions and 35 deletions
|
|
@ -54,6 +54,7 @@ import (
|
|||
"github.com/strukturag/nextcloud-spreed-signaling/config"
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/container"
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/geoip"
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/internal"
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/log"
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/proxy"
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/session"
|
||||
|
|
@ -1224,8 +1225,7 @@ func (s *ProxyServer) processCommand(ctx context.Context, client *ProxyClient, s
|
|||
defer cancel()
|
||||
|
||||
if err := publisher.PublishRemote(ctx2, session.PublicId(), cmd.Hostname, cmd.Port, cmd.RtcpPort); err != nil {
|
||||
var je *janusapi.ErrorMsg
|
||||
if !errors.As(err, &je) || je.Err.Code != janusapi.JANUS_VIDEOROOM_ERROR_ID_EXISTS {
|
||||
if je, ok := internal.AsErrorType[*janusapi.ErrorMsg](err); !ok || je.Err.Code != janusapi.JANUS_VIDEOROOM_ERROR_ID_EXISTS {
|
||||
s.logger.Printf("Error publishing %s %s to remote %s (port=%d, rtcpPort=%d): %s", publisher.StreamType(), cmd.ClientId, cmd.Hostname, cmd.Port, cmd.RtcpPort, err)
|
||||
session.sendMessage(message.NewWrappedErrorServerMessage(err))
|
||||
return
|
||||
|
|
|
|||
|
|
@ -22,11 +22,12 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/dlintw/goconf"
|
||||
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/internal"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -71,8 +72,7 @@ func GetStringOptions(config *goconf.ConfigFile, section string, ignoreErrors bo
|
|||
continue
|
||||
}
|
||||
|
||||
var ge goconf.GetError
|
||||
if errors.As(err, &ge) && ge.Reason == goconf.OptionNotFound {
|
||||
if ge, ok := internal.AsErrorType[goconf.GetError](err); ok && ge.Reason == goconf.OptionNotFound {
|
||||
// Skip options from "default" section.
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
50
internal/as_error.go
Normal file
50
internal/as_error.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Standalone signaling server for the Nextcloud Spreed app.
|
||||
* Copyright (C) 2026 struktur AG
|
||||
*
|
||||
* @author Joachim Bauch <bauch@struktur.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// AsErrorType finds the first error in err's tree that matches the type E,
|
||||
// and if one is found, returns that error value and true. Otherwise, it
|
||||
// returns the zero value of E and false.
|
||||
//
|
||||
// The tree consists of err itself, followed by the errors obtained by
|
||||
// repeatedly calling its Unwrap() error or Unwrap() []error method.
|
||||
// When err wraps multiple errors, AsErrorType examines err followed by a
|
||||
// depth-first traversal of its children.
|
||||
//
|
||||
// An error err matches the type E if the type assertion err.(E) holds,
|
||||
// or if the error has a method As(any) bool such that err.As(target)
|
||||
// returns true when target is a non-nil *E. In the latter case, the As
|
||||
// method is responsible for setting target.
|
||||
func AsErrorType[E error](err error) (E, bool) {
|
||||
var e E
|
||||
if err == nil {
|
||||
return e, false
|
||||
} else if errors.As(err, &e) {
|
||||
return e, true
|
||||
}
|
||||
|
||||
return e, false
|
||||
}
|
||||
61
internal/as_error_test.go
Normal file
61
internal/as_error_test.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Standalone signaling server for the Nextcloud Spreed app.
|
||||
* Copyright (C) 2026 struktur AG
|
||||
*
|
||||
* @author Joachim Bauch <bauch@struktur.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type testError struct{}
|
||||
|
||||
func (e testError) Error() string {
|
||||
return "test error"
|
||||
}
|
||||
|
||||
func TestAsErrorType(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
if e, ok := AsErrorType[*testError](nil); assert.False(ok) {
|
||||
assert.Nil(e)
|
||||
}
|
||||
|
||||
err1 := &testError{}
|
||||
if e, ok := AsErrorType[*testError](err1); assert.True(ok) {
|
||||
assert.Same(err1, e)
|
||||
}
|
||||
|
||||
err2 := errors.New("other error")
|
||||
if e, ok := AsErrorType[*testError](err2); assert.False(ok) {
|
||||
assert.Nil(e)
|
||||
}
|
||||
|
||||
err3 := fmt.Errorf("wrapped error: %w", err1)
|
||||
if e, ok := AsErrorType[*testError](err3); assert.True(ok) {
|
||||
assert.Same(err1, e)
|
||||
}
|
||||
}
|
||||
|
|
@ -831,9 +831,10 @@ func (b *BackendServer) startDialout(ctx context.Context, roomid string, backend
|
|||
response, err := b.startDialoutInSession(ctx, session, roomid, backend, backendUrl, request)
|
||||
if err != nil {
|
||||
b.logger.Printf("Error starting dialout request %+v in session %s: %+v", request.Dialout, session.PublicId(), err)
|
||||
var e *api.Error
|
||||
if sessionError == nil && errors.As(err, &e) {
|
||||
sessionError = e
|
||||
if sessionError == nil {
|
||||
if e, ok := internal.AsErrorType[*api.Error](err); ok {
|
||||
sessionError = e
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -469,8 +469,8 @@ func (c *FederationClient) writePump() {
|
|||
|
||||
func (c *FederationClient) closeWithError(err error) {
|
||||
c.Close()
|
||||
var e *api.Error
|
||||
if !errors.As(err, &e) {
|
||||
e, ok := internal.AsErrorType[*api.Error](err)
|
||||
if !ok {
|
||||
e = api.NewError("federation_error", err.Error())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1844,39 +1844,31 @@ func (h *Hub) processRoom(sess Session, message *api.ClientMessage) {
|
|||
if session.UserId() == "" && client == nil {
|
||||
h.startWaitAnonymousSessionRoom(session)
|
||||
}
|
||||
var ae *api.Error
|
||||
if errors.As(err, &ae) {
|
||||
if ae, ok := internal.AsErrorType[*api.Error](err); ok {
|
||||
session.SendMessage(message.NewErrorServerMessage(ae))
|
||||
return
|
||||
}
|
||||
|
||||
var details any
|
||||
var ce *tls.CertificateVerificationError
|
||||
if errors.As(err, &ce) {
|
||||
if ce, ok := internal.AsErrorType[*tls.CertificateVerificationError](err); ok {
|
||||
details = map[string]string{
|
||||
"code": "certificate_verification_error",
|
||||
"message": ce.Error(),
|
||||
}
|
||||
}
|
||||
var ne net.Error
|
||||
if details == nil && errors.As(err, &ne) {
|
||||
} else if ne, ok := internal.AsErrorType[net.Error](err); ok {
|
||||
details = map[string]string{
|
||||
"code": "network_error",
|
||||
"message": ne.Error(),
|
||||
}
|
||||
}
|
||||
if details == nil {
|
||||
var we websocket.HandshakeError
|
||||
if errors.Is(err, websocket.ErrBadHandshake) {
|
||||
details = map[string]string{
|
||||
"code": "network_error",
|
||||
"message": err.Error(),
|
||||
}
|
||||
} else if errors.As(err, &we) {
|
||||
details = map[string]string{
|
||||
"code": "network_error",
|
||||
"message": we.Error(),
|
||||
}
|
||||
} else if errors.Is(err, websocket.ErrBadHandshake) {
|
||||
details = map[string]string{
|
||||
"code": "network_error",
|
||||
"message": err.Error(),
|
||||
}
|
||||
} else if we, ok := internal.AsErrorType[websocket.HandshakeError](err); ok {
|
||||
details = map[string]string{
|
||||
"code": "network_error",
|
||||
"message": we.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,19 +22,20 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/internal"
|
||||
)
|
||||
|
||||
func IsErrorAddressAlreadyInUse(err error) bool {
|
||||
var eOsSyscall *os.SyscallError
|
||||
if !errors.As(err, &eOsSyscall) {
|
||||
eOsSyscall, ok := internal.AsErrorType[*os.SyscallError](err)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
var errErrno syscall.Errno // doesn't need a "*" (ptr) because it's already a ptr (uintptr)
|
||||
if !errors.As(eOsSyscall, &errErrno) {
|
||||
errErrno, ok := internal.AsErrorType[syscall.Errno](eOsSyscall)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if errErrno == syscall.EADDRINUSE {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue