common errors as variable.

This commit is contained in:
Miroslav Šedivý 2021-08-29 17:09:13 +02:00
parent 530cc04805
commit 343b0c562a
17 changed files with 108 additions and 77 deletions

View File

@ -2,6 +2,7 @@ package members
import ( import (
"context" "context"
"errors"
"net/http" "net/http"
"github.com/go-chi/chi" "github.com/go-chi/chi"
@ -68,14 +69,21 @@ func GetMember(r *http.Request) MemberData {
func (h *MembersHandler) ExtractMember(next http.Handler) http.Handler { func (h *MembersHandler) ExtractMember(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
memberId := chi.URLParam(r, "memberId") memberId := chi.URLParam(r, "memberId")
profile, err := h.members.Select(memberId) profile, err := h.members.Select(memberId)
if err != nil { if err != nil {
if errors.Is(err, types.ErrMemberDoesNotExist) {
utils.HttpNotFound(w, err) utils.HttpNotFound(w, err)
} else { } else {
utils.HttpInternalServerError(w, err)
}
return
}
next.ServeHTTP(w, SetMember(r, MemberData{ next.ServeHTTP(w, SetMember(r, MemberData{
ID: memberId, ID: memberId,
Profile: profile, Profile: profile,
})) }))
}
}) })
} }

View File

@ -1,7 +1,6 @@
package capture package capture
import ( import (
"fmt"
"strings" "strings"
"sync" "sync"
@ -9,6 +8,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"demodesk/neko/internal/capture/gst" "demodesk/neko/internal/capture/gst"
"demodesk/neko/internal/types"
) )
type BroacastManagerCtx struct { type BroacastManagerCtx struct {
@ -67,7 +67,7 @@ func (manager *BroacastManagerCtx) Url() string {
func (manager *BroacastManagerCtx) createPipeline() error { func (manager *BroacastManagerCtx) createPipeline() error {
if manager.pipeline != nil { if manager.pipeline != nil {
return fmt.Errorf("pipeline already exists") return types.ErrCapturePipelineAlreadyExists
} }
var err error var err error

View File

@ -1,7 +1,7 @@
package capture package capture
import ( import (
"fmt" "errors"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -93,12 +93,12 @@ func (manager *ScreencastManagerCtx) Image() ([]byte, error) {
case sample := <-manager.sample: case sample := <-manager.sample:
return sample.Data, nil return sample.Data, nil
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
return nil, fmt.Errorf("timeouted") return nil, errors.New("timeouted")
} }
} }
if manager.image.Data == nil { if manager.image.Data == nil {
return nil, fmt.Errorf("image sample not found") return nil, errors.New("image sample not found")
} }
return manager.image.Data, nil return manager.image.Data, nil
@ -109,7 +109,7 @@ func (manager *ScreencastManagerCtx) start() error {
defer manager.mu.Unlock() defer manager.mu.Unlock()
if !manager.enabled { if !manager.enabled {
return fmt.Errorf("screenshot pipeline not enabled") return errors.New("screenshot pipeline not enabled")
} }
err := manager.createPipeline() err := manager.createPipeline()
@ -131,7 +131,7 @@ func (manager *ScreencastManagerCtx) stop() {
func (manager *ScreencastManagerCtx) createPipeline() error { func (manager *ScreencastManagerCtx) createPipeline() error {
if manager.pipeline != nil { if manager.pipeline != nil {
return fmt.Errorf("pipeline already exists") return types.ErrCapturePipelineAlreadyExists
} }
var err error var err error

View File

@ -1,7 +1,6 @@
package capture package capture
import ( import (
"fmt"
"reflect" "reflect"
"sync" "sync"
@ -141,7 +140,7 @@ func (manager *StreamManagerCtx) Started() bool {
func (manager *StreamManagerCtx) createPipeline() error { func (manager *StreamManagerCtx) createPipeline() error {
if manager.pipeline != nil { if manager.pipeline != nil {
return fmt.Errorf("pipeline already exists") return types.ErrCapturePipelineAlreadyExists
} }
var err error var err error

View File

@ -1,7 +1,7 @@
package desktop package desktop
import ( import (
"fmt" "errors"
"os/exec" "os/exec"
"time" "time"
) )
@ -46,7 +46,7 @@ func (manager *DesktopManagerCtx) HandleFileChooserDialog(uri string) error {
// if last command didn't return error, consider dialog as still open // if last command didn't return error, consider dialog as still open
if err2 == nil { if err2 == nil {
return fmt.Errorf("unable to select files in dialog") return errors.New("unable to select files in dialog")
} }
return nil return nil

View File

@ -1,7 +1,7 @@
package dummy package dummy
import ( import (
"fmt" "errors"
"demodesk/neko/internal/types" "demodesk/neko/internal/types"
) )
@ -37,7 +37,7 @@ func (provider *MemberProviderCtx) Authenticate(username string, password string
} }
func (provider *MemberProviderCtx) Insert(username string, password string, profile types.MemberProfile) (string, error) { func (provider *MemberProviderCtx) Insert(username string, password string, profile types.MemberProfile) (string, error) {
return "", fmt.Errorf("not implemented") return "", errors.New("not implemented")
} }
func (provider *MemberProviderCtx) Select(id string) (types.MemberProfile, error) { func (provider *MemberProviderCtx) Select(id string) (types.MemberProfile, error) {
@ -54,7 +54,7 @@ func (provider *MemberProviderCtx) UpdateProfile(id string, profile types.Member
} }
func (provider *MemberProviderCtx) UpdatePassword(id string, password string) error { func (provider *MemberProviderCtx) UpdatePassword(id string, password string) error {
return fmt.Errorf("not implemented") return errors.New("not implemented")
} }
func (provider *MemberProviderCtx) Delete(id string) error { func (provider *MemberProviderCtx) Delete(id string) error {

View File

@ -2,7 +2,6 @@ package file
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -38,7 +37,7 @@ func (provider *MemberProviderCtx) Authenticate(username string, password string
// TODO: Use hash function. // TODO: Use hash function.
if entry.Password != password { if entry.Password != password {
return "", types.MemberProfile{}, fmt.Errorf("invalid password") return "", types.MemberProfile{}, types.ErrMemberInvalidPassword
} }
return id, entry.Profile, nil return id, entry.Profile, nil
@ -55,7 +54,7 @@ func (provider *MemberProviderCtx) Insert(username string, password string, prof
_, ok := entries[id] _, ok := entries[id]
if ok { if ok {
return "", fmt.Errorf("member ID already exists") return "", types.ErrMemberAlreadyExists
} }
entries[id] = MemberEntry{ entries[id] = MemberEntry{
@ -75,7 +74,7 @@ func (provider *MemberProviderCtx) UpdateProfile(id string, profile types.Member
entry, ok := entries[id] entry, ok := entries[id]
if !ok { if !ok {
return fmt.Errorf("member ID does not exist") return types.ErrMemberDoesNotExist
} }
entry.Profile = profile entry.Profile = profile
@ -92,7 +91,7 @@ func (provider *MemberProviderCtx) UpdatePassword(id string, password string) er
entry, ok := entries[id] entry, ok := entries[id]
if !ok { if !ok {
return fmt.Errorf("member ID does not exist") return types.ErrMemberDoesNotExist
} }
// TODO: Use hash function. // TODO: Use hash function.
@ -139,7 +138,7 @@ func (provider *MemberProviderCtx) Delete(id string) error {
_, ok := entries[id] _, ok := entries[id]
if !ok { if !ok {
return fmt.Errorf("member ID does not exist") return types.ErrMemberDoesNotExist
} }
delete(entries, id) delete(entries, id)
@ -178,7 +177,7 @@ func (provider *MemberProviderCtx) getEntry(id string) (MemberEntry, error) {
entry, ok := entries[id] entry, ok := entries[id]
if !ok { if !ok {
return MemberEntry{}, fmt.Errorf("member ID does not exist") return MemberEntry{}, types.ErrMemberDoesNotExist
} }
return entry, nil return entry, nil

View File

@ -1,7 +1,7 @@
package member package member
import ( import (
"fmt" "errors"
"sync" "sync"
"github.com/rs/zerolog" "github.com/rs/zerolog"
@ -41,7 +41,7 @@ type MemberManagerCtx struct {
config *config.Member config *config.Member
providerMu sync.Mutex providerMu sync.Mutex
provider types.MemberProvider provider types.MemberProvider
sessionMu sync.Mutex loginMu sync.Mutex
} }
func (manager *MemberManagerCtx) Connect() error { func (manager *MemberManagerCtx) Connect() error {
@ -91,13 +91,10 @@ func (manager *MemberManagerCtx) UpdateProfile(id string, profile types.MemberPr
defer manager.providerMu.Unlock() defer manager.providerMu.Unlock()
// update corresponding session, if exists // update corresponding session, if exists
manager.sessionMu.Lock() err := manager.sessions.Update(id, profile)
if _, ok := manager.sessions.Get(id); ok { if err != nil && !errors.Is(err, types.ErrSessionNotFound) {
if err := manager.sessions.Update(id, profile); err != nil {
manager.logger.Err(err).Msg("error while updating session") manager.logger.Err(err).Msg("error while updating session")
} }
}
manager.sessionMu.Unlock()
return manager.provider.UpdateProfile(id, profile) return manager.provider.UpdateProfile(id, profile)
} }
@ -114,13 +111,10 @@ func (manager *MemberManagerCtx) Delete(id string) error {
defer manager.providerMu.Unlock() defer manager.providerMu.Unlock()
// destroy corresponding session, if exists // destroy corresponding session, if exists
manager.sessionMu.Lock() err := manager.sessions.Delete(id)
if _, ok := manager.sessions.Get(id); ok { if err != nil && !errors.Is(err, types.ErrSessionNotFound) {
if err := manager.sessions.Delete(id); err != nil {
manager.logger.Err(err).Msg("error while deleting session") manager.logger.Err(err).Msg("error while deleting session")
} }
}
manager.sessionMu.Unlock()
return manager.provider.Delete(id) return manager.provider.Delete(id)
} }
@ -130,8 +124,8 @@ func (manager *MemberManagerCtx) Delete(id string) error {
// //
func (manager *MemberManagerCtx) Login(username string, password string) (types.Session, string, error) { func (manager *MemberManagerCtx) Login(username string, password string) (types.Session, string, error) {
manager.sessionMu.Lock() manager.loginMu.Lock()
defer manager.sessionMu.Unlock() defer manager.loginMu.Unlock()
id, profile, err := manager.provider.Authenticate(username, password) id, profile, err := manager.provider.Authenticate(username, password)
if err != nil { if err != nil {
@ -141,7 +135,7 @@ func (manager *MemberManagerCtx) Login(username string, password string) (types.
session, ok := manager.sessions.Get(id) session, ok := manager.sessions.Get(id)
if ok { if ok {
if session.State().IsConnected { if session.State().IsConnected {
return nil, "", fmt.Errorf("session is already connected") return nil, "", types.ErrSessionAlreadyConnected
} }
// TODO: Replace session. // TODO: Replace session.
@ -154,12 +148,8 @@ func (manager *MemberManagerCtx) Login(username string, password string) (types.
} }
func (manager *MemberManagerCtx) Logout(id string) error { func (manager *MemberManagerCtx) Logout(id string) error {
manager.sessionMu.Lock() manager.loginMu.Lock()
defer manager.sessionMu.Unlock() defer manager.loginMu.Unlock()
if _, ok := manager.sessions.Get(id); !ok {
return fmt.Errorf("session not found")
}
return manager.sessions.Delete(id) return manager.sessions.Delete(id)
} }

View File

@ -1,8 +1,6 @@
package object package object
import ( import (
"fmt"
"demodesk/neko/internal/types" "demodesk/neko/internal/types"
) )
@ -60,12 +58,12 @@ func (provider *MemberProviderCtx) Authenticate(username string, password string
entry, ok := provider.entries[id] entry, ok := provider.entries[id]
if !ok { if !ok {
return "", types.MemberProfile{}, fmt.Errorf("member ID does not exist") return "", types.MemberProfile{}, types.ErrMemberDoesNotExist
} }
// TODO: Use hash function. // TODO: Use hash function.
if entry.Password != password { if entry.Password != password {
return "", types.MemberProfile{}, fmt.Errorf("invalid password") return "", types.MemberProfile{}, types.ErrMemberInvalidPassword
} }
return id, entry.Profile, nil return id, entry.Profile, nil
@ -77,7 +75,7 @@ func (provider *MemberProviderCtx) Insert(username string, password string, prof
_, ok := provider.entries[id] _, ok := provider.entries[id]
if ok { if ok {
return "", fmt.Errorf("member ID already exists") return "", types.ErrMemberAlreadyExists
} }
provider.entries[id] = &MemberEntry{ provider.entries[id] = &MemberEntry{
@ -92,7 +90,7 @@ func (provider *MemberProviderCtx) Insert(username string, password string, prof
func (provider *MemberProviderCtx) UpdateProfile(id string, profile types.MemberProfile) error { func (provider *MemberProviderCtx) UpdateProfile(id string, profile types.MemberProfile) error {
entry, ok := provider.entries[id] entry, ok := provider.entries[id]
if !ok { if !ok {
return fmt.Errorf("member ID does not exist") return types.ErrMemberDoesNotExist
} }
entry.Profile = profile entry.Profile = profile
@ -103,7 +101,7 @@ func (provider *MemberProviderCtx) UpdateProfile(id string, profile types.Member
func (provider *MemberProviderCtx) UpdatePassword(id string, password string) error { func (provider *MemberProviderCtx) UpdatePassword(id string, password string) error {
entry, ok := provider.entries[id] entry, ok := provider.entries[id]
if !ok { if !ok {
return fmt.Errorf("member ID does not exist") return types.ErrMemberDoesNotExist
} }
// TODO: Use hash function. // TODO: Use hash function.
@ -115,7 +113,7 @@ func (provider *MemberProviderCtx) UpdatePassword(id string, password string) er
func (provider *MemberProviderCtx) Select(id string) (types.MemberProfile, error) { func (provider *MemberProviderCtx) Select(id string) (types.MemberProfile, error) {
entry, ok := provider.entries[id] entry, ok := provider.entries[id]
if !ok { if !ok {
return types.MemberProfile{}, fmt.Errorf("member ID does not exist") return types.MemberProfile{}, types.ErrMemberDoesNotExist
} }
return entry.Profile, nil return entry.Profile, nil
@ -139,7 +137,7 @@ func (provider *MemberProviderCtx) SelectAll(limit int, offset int) (map[string]
func (provider *MemberProviderCtx) Delete(id string) error { func (provider *MemberProviderCtx) Delete(id string) error {
_, ok := provider.entries[id] _, ok := provider.entries[id]
if !ok { if !ok {
return fmt.Errorf("member ID does not exist") return types.ErrMemberDoesNotExist
} }
delete(provider.entries, id) delete(provider.entries, id)

View File

@ -1,7 +1,7 @@
package session package session
import ( import (
"fmt" "errors"
"net/http" "net/http"
"strings" "strings"
"time" "time"
@ -39,16 +39,16 @@ func (manager *SessionManagerCtx) CookieClearToken(w http.ResponseWriter, r *htt
func (manager *SessionManagerCtx) Authenticate(r *http.Request) (types.Session, error) { func (manager *SessionManagerCtx) Authenticate(r *http.Request) (types.Session, error) {
token, ok := manager.getToken(r) token, ok := manager.getToken(r)
if !ok { if !ok {
return nil, fmt.Errorf("no authentication provided") return nil, errors.New("no authentication provided")
} }
session, ok := manager.GetByToken(token) session, ok := manager.GetByToken(token)
if !ok { if !ok {
return nil, fmt.Errorf("session not found") return nil, types.ErrSessionNotFound
} }
if !session.Profile().CanLogin { if !session.Profile().CanLogin {
return nil, fmt.Errorf("login disabled") return nil, types.ErrSessionLoginDisabled
} }
return session, nil return session, nil

View File

@ -1,7 +1,7 @@
package session package session
import ( import (
"fmt" "errors"
"sync" "sync"
"github.com/kataras/go-events" "github.com/kataras/go-events"
@ -68,12 +68,12 @@ func (manager *SessionManagerCtx) Create(id string, profile types.MemberProfile)
manager.sessionsMu.Lock() manager.sessionsMu.Lock()
if _, ok := manager.sessions[id]; ok { if _, ok := manager.sessions[id]; ok {
manager.sessionsMu.Unlock() manager.sessionsMu.Unlock()
return nil, "", fmt.Errorf("session id already exists") return nil, "", types.ErrSessionAlreadyExists
} }
if _, ok := manager.tokens[token]; ok { if _, ok := manager.tokens[token]; ok {
manager.sessionsMu.Unlock() manager.sessionsMu.Unlock()
return nil, "", fmt.Errorf("session token already exists") return nil, "", errors.New("session token already exists")
} }
session := &SessionCtx{ session := &SessionCtx{
@ -98,7 +98,7 @@ func (manager *SessionManagerCtx) Update(id string, profile types.MemberProfile)
session, ok := manager.sessions[id] session, ok := manager.sessions[id]
if !ok { if !ok {
manager.sessionsMu.Unlock() manager.sessionsMu.Unlock()
return fmt.Errorf("session id not found") return types.ErrSessionNotFound
} }
session.profile = profile session.profile = profile
@ -114,7 +114,7 @@ func (manager *SessionManagerCtx) Delete(id string) error {
session, ok := manager.sessions[id] session, ok := manager.sessions[id]
if !ok { if !ok {
manager.sessionsMu.Unlock() manager.sessionsMu.Unlock()
return fmt.Errorf("session id not found") return types.ErrSessionNotFound
} }
delete(manager.tokens, session.token) delete(manager.tokens, session.token)

View File

@ -2,6 +2,7 @@ package types
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"math" "math"
"strings" "strings"
@ -12,6 +13,10 @@ import (
"demodesk/neko/internal/types/codec" "demodesk/neko/internal/types/codec"
) )
var (
ErrCapturePipelineAlreadyExists = errors.New("capture pipeline already exists")
)
type Sample media.Sample type Sample media.Sample
type BroadcastManager interface { type BroadcastManager interface {

View File

@ -1,5 +1,13 @@
package types package types
import "errors"
var (
ErrMemberAlreadyExists = errors.New("member already exists")
ErrMemberDoesNotExist = errors.New("member does not exist")
ErrMemberInvalidPassword = errors.New("invalid password")
)
type MemberProfile struct { type MemberProfile struct {
Name string `json:"name"` Name string `json:"name"`
IsAdmin bool `json:"is_admin"` IsAdmin bool `json:"is_admin"`

View File

@ -1,6 +1,16 @@
package types package types
import "net/http" import (
"errors"
"net/http"
)
var (
ErrSessionNotFound = errors.New("session not found")
ErrSessionAlreadyExists = errors.New("session already exists")
ErrSessionAlreadyConnected = errors.New("session is already connected")
ErrSessionLoginDisabled = errors.New("session login disabled")
)
type SessionState struct { type SessionState struct {
IsConnected bool `json:"is_connected"` IsConnected bool `json:"is_connected"`

View File

@ -1,6 +1,15 @@
package types package types
import "github.com/pion/webrtc/v3" import (
"errors"
"github.com/pion/webrtc/v3"
)
var (
ErrWebRTCVideoNotFound = errors.New("webrtc video not found")
ErrWebRTCDataChannelNotFound = errors.New("webrtc data channel not found")
)
type ICEServer struct { type ICEServer struct {
URLs []string `mapstructure:"urls" json:"urls"` URLs []string `mapstructure:"urls" json:"urls"`

View File

@ -66,7 +66,7 @@ func (manager *WebRTCManagerCtx) Start() {
} }
audioListener := func(sample types.Sample) { audioListener := func(sample types.Sample) {
if err := manager.audioTrack.WriteSample(media.Sample(sample)); err != nil && err != io.ErrClosedPipe { if err := manager.audioTrack.WriteSample(media.Sample(sample)); err != nil {
if errors.Is(err, io.ErrClosedPipe) { if errors.Is(err, io.ErrClosedPipe) {
// The peerConnection has been closed. // The peerConnection has been closed.
return return
@ -166,7 +166,7 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, videoID strin
} }
videoListener := func(sample types.Sample) { videoListener := func(sample types.Sample) {
if err := videoTrack.WriteSample(media.Sample(sample)); err != nil && err != io.ErrClosedPipe { if err := videoTrack.WriteSample(media.Sample(sample)); err != nil {
if errors.Is(err, io.ErrClosedPipe) { if errors.Is(err, io.ErrClosedPipe) {
// The peerConnection has been closed. // The peerConnection has been closed.
return return
@ -200,7 +200,7 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, videoID strin
changeVideo := func(videoID string) error { changeVideo := func(videoID string) error {
newVideoStream, ok := manager.capture.Video(videoID) newVideoStream, ok := manager.capture.Video(videoID)
if !ok { if !ok {
return fmt.Errorf("video stream not found") return types.ErrWebRTCVideoNotFound
} }
// should be new stream started // should be new stream started
@ -357,7 +357,7 @@ func (manager *WebRTCManagerCtx) mediaEngine(videoID string) (*webrtc.MediaEngin
// all videos must have the same codec // all videos must have the same codec
video, ok := manager.capture.Video(videoID) video, ok := manager.capture.Video(videoID)
if !ok { if !ok {
return nil, fmt.Errorf("selected video track not found") return nil, types.ErrWebRTCVideoNotFound
} }
videoCodec := video.Codec() videoCodec := video.Codec()

View File

@ -3,7 +3,6 @@ package webrtc
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"fmt"
"demodesk/neko/internal/types" "demodesk/neko/internal/types"
) )
@ -28,8 +27,11 @@ type PayloadCursorImage struct {
} }
func (peer *WebRTCPeerCtx) SendCursorPosition(x, y int) error { func (peer *WebRTCPeerCtx) SendCursorPosition(x, y int) error {
peer.mu.Lock()
defer peer.mu.Unlock()
if peer.dataChannel == nil { if peer.dataChannel == nil {
return fmt.Errorf("no data channel") return types.ErrWebRTCDataChannelNotFound
} }
data := PayloadCursorPosition{ data := PayloadCursorPosition{
@ -50,8 +52,11 @@ func (peer *WebRTCPeerCtx) SendCursorPosition(x, y int) error {
} }
func (peer *WebRTCPeerCtx) SendCursorImage(cur *types.CursorImage, img []byte) error { func (peer *WebRTCPeerCtx) SendCursorImage(cur *types.CursorImage, img []byte) error {
peer.mu.Lock()
defer peer.mu.Unlock()
if peer.dataChannel == nil { if peer.dataChannel == nil {
return fmt.Errorf("no data channel") return types.ErrWebRTCDataChannelNotFound
} }
data := PayloadCursorImage{ data := PayloadCursorImage{