From 002618eb785dc9636d102ffad8dce54a1fa15dc8 Mon Sep 17 00:00:00 2001 From: Dragan Milic Date: Mon, 2 Sep 2024 12:03:14 +0200 Subject: [PATCH 1/2] api: endpoints for WebRTC handshake --- api/apirouter/api_router.go | 87 +++++ api/end_to_end_test.go | 529 ++++++++++++++++++++++++++ api/go.mod | 89 ++++- api/go.sum | 282 ++++++++++++-- api/handlers/peer_to_peer_handlers.go | 272 +++++++++++++ api/main.go | 10 +- bringyour/router/router.go | 6 +- bringyour/router/router_test.go | 5 +- 8 files changed, 1224 insertions(+), 56 deletions(-) create mode 100644 api/apirouter/api_router.go create mode 100644 api/end_to_end_test.go create mode 100644 api/handlers/peer_to_peer_handlers.go diff --git a/api/apirouter/api_router.go b/api/apirouter/api_router.go new file mode 100644 index 00000000..41fe6016 --- /dev/null +++ b/api/apirouter/api_router.go @@ -0,0 +1,87 @@ +package apirouter + +import ( + "bringyour.com/bringyour/router" + "bringyour.com/service/api/handlers" +) + +func NewAPIRouter() *router.Router { + + routes := []*router.Route{ + router.NewRoute("GET", "/privacy.txt", router.Txt), + router.NewRoute("GET", "/terms.txt", router.Txt), + router.NewRoute("GET", "/vdp.txt", router.Txt), + router.NewRoute("GET", "/status", router.WarpStatus), + router.NewRoute("GET", "/stats/last-90", handlers.StatsLast90), + router.NewRoute("GET", "/stats/providers-overview-last-90", handlers.StatsProvidersOverviewLast90), + router.NewRoute("GET", "/stats/providers", handlers.StatsProviders), + router.NewRoute("POST", "/stats/provider-last-90", handlers.StatsProviderLast90), + router.NewRoute("POST", "/auth/login", handlers.AuthLogin), + router.NewRoute("POST", "/auth/login-with-password", handlers.AuthLoginWithPassword), + router.NewRoute("POST", "/auth/verify", handlers.AuthVerify), + router.NewRoute("POST", "/auth/verify-send", handlers.AuthVerifySend), + router.NewRoute("POST", "/auth/password-reset", handlers.AuthPasswordReset), + router.NewRoute("POST", "/auth/password-set", handlers.AuthPasswordSet), + router.NewRoute("POST", "/auth/network-check", handlers.NetworkCheck), + router.NewRoute("POST", "/auth/network-create", handlers.NetworkCreate), + router.NewRoute("POST", "/auth/code-create", handlers.AuthCodeCreate), + router.NewRoute("POST", "/auth/code-login", handlers.AuthCodeLogin), + router.NewRoute("POST", "/network/auth-client", handlers.AuthNetworkClient), + router.NewRoute("POST", "/network/remove-client", handlers.RemoveNetworkClient), + router.NewRoute("GET", "/network/clients", handlers.NetworkClients), + router.NewRoute("GET", "/network/provider-locations", handlers.NetworkGetProviderLocations), + router.NewRoute("POST", "/network/find-provider-locations", handlers.NetworkFindProviderLocations), + router.NewRoute("POST", "/network/find-locations", handlers.NetworkFindLocations), + router.NewRoute("POST", "/network/find-providers", handlers.NetworkFindProviders), + router.NewRoute("POST", "/network/find-providers2", handlers.NetworkFindProviders2), + router.NewRoute("POST", "/network/create-provider-spec", handlers.NetworkCreateProviderSpec), + router.NewRoute("GET", "/network/user", handlers.GetNetworkUser), + router.NewRoute("POST", "/preferences/set-preferences", handlers.PreferencesSet), + router.NewRoute("POST", "/feedback/send-feedback", handlers.FeedbackSend), + router.NewRoute("POST", "/pay/stripe", handlers.StripeWebhook), + router.NewRoute("POST", "/pay/coinbase", handlers.CoinbaseWebhook), + router.NewRoute("POST", "/pay/circle", handlers.CircleWebhook), + router.NewRoute("POST", "/pay/play", handlers.PlayWebhook), + router.NewRoute("GET", "/wallet/balance", handlers.WalletBalance), + router.NewRoute("POST", "/wallet/validate-address", handlers.WalletValidateAddress), + router.NewRoute("POST", "/wallet/circle-init", handlers.WalletCircleInit), + router.NewRoute("POST", "/wallet/circle-transfer-out", handlers.WalletCircleTransferOut), + router.NewRoute("GET", "/subscription/balance", handlers.SubscriptionBalance), + router.NewRoute("POST", "/subscription/check-balance-code", handlers.SubscriptionCheckBalanceCode), + router.NewRoute("POST", "/subscription/redeem-balance-code", handlers.SubscriptionRedeemBalanceCode), + router.NewRoute("POST", "/subscription/create-payment-id", handlers.SubscriptionCreatePaymentId), + router.NewRoute("POST", "/device/add", handlers.DeviceAdd), + router.NewRoute("POST", "/device/create-share-code", handlers.DeviceCreateShareCode), + router.NewRoute("GET", "/device/share-code/([^/]+)/qr.png", handlers.DeviceShareCodeQR), + router.NewRoute("POST", "/device/share-status", handlers.DeviceShareStatus), + router.NewRoute("POST", "/device/confirm-share", handlers.DeviceConfirmShare), + router.NewRoute("POST", "/device/create-adopt-code", handlers.DeviceCreateAdoptCode), + router.NewRoute("GET", "/device/adopt-code/([^/]+)/qr.png", handlers.DeviceAdoptCodeQR), + router.NewRoute("POST", "/device/adopt-status", handlers.DeviceAdoptStatus), + router.NewRoute("POST", "/device/confirm-adopt", handlers.DeviceConfirmAdopt), + router.NewRoute("POST", "/device/remove-adopt-code", handlers.DeviceRemoveAdoptCode), + router.NewRoute("GET", "/device/associations", handlers.DeviceAssociations), + router.NewRoute("POST", "/device/remove-association", handlers.DeviceRemoveAssociation), + router.NewRoute("POST", "/device/set-association-name", handlers.DeviceSetAssociationName), + router.NewRoute("POST", "/device/set-provide", handlers.DeviceSetProvide), + router.NewRoute("POST", "/connect/control", handlers.ConnectControl), + router.NewRoute("GET", "/hello", handlers.Hello), + router.NewRoute("POST", "/account/payout-wallet", handlers.SetPayoutWallet), + router.NewRoute("GET", "/account/payout-wallet", handlers.GetPayoutWallet), + router.NewRoute("POST", "/account/wallet", handlers.CreateAccountWallet), + router.NewRoute("GET", "/account/wallets", handlers.GetAccountWallets), + router.NewRoute("GET", "/account/referral-code", handlers.GetNetworkReferralCode), + + router.NewRoute("PUT", "/peer-to-peer/handshake/([^/]+)/offer/sdp", handlers.PeerToPeerHandshakeOfferSetSDP), + router.NewRoute("GET", "/peer-to-peer/handshake/([^/]+)/offer/sdp", handlers.PeerToPeerHandshakeLongPollOfferSDP), + router.NewRoute("POST", "/peer-to-peer/handshake/([^/]+)/offer/peer_candidates", handlers.PeerToPeerHandshakeOfferAddPeerCandidate), + router.NewRoute("GET", "/peer-to-peer/handshake/([^/]+)/offer/peer_candidates", handlers.PeerToPeerHandshakeOfferLongPollNewPeerCandidates), + router.NewRoute("PUT", "/peer-to-peer/handshake/([^/]+)/answer/sdp", handlers.PeerToPeerHandshakeAnswerSetSDP), + router.NewRoute("GET", "/peer-to-peer/handshake/([^/]+)/answer/sdp", handlers.PeerToPeerHandshakeLongPollAnswerSDP), + router.NewRoute("POST", "/peer-to-peer/handshake/([^/]+)/answer/peer_candidates", handlers.PeerToPeerHandshakeAnswerAddPeerCandidate), + router.NewRoute("GET", "/peer-to-peer/handshake/([^/]+)/answer/peer_candidates", handlers.PeerToPeerHandshakeAnswerLongPollNewPeerCandidates), + } + + return router.NewRouter(routes) + +} diff --git a/api/end_to_end_test.go b/api/end_to_end_test.go new file mode 100644 index 00000000..9e27d2b8 --- /dev/null +++ b/api/end_to_end_test.go @@ -0,0 +1,529 @@ +package main_test + +import ( + "context" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" + "crypto/x509" + "encoding/hex" + "encoding/json" + "encoding/pem" + "fmt" + "net/http/httptest" + "os" + "path/filepath" + "testing" + "time" + + "bringyour.com/bringyour" + "bringyour.com/bringyour/jwt" + "bringyour.com/bringyour/model" + "bringyour.com/bringyour/session" + "bringyour.com/connect" + "bringyour.com/service/api/apirouter" + webrtcconn "github.com/bringyour/webrtc-conn" + "github.com/pion/webrtc/v3" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/postgres" + "github.com/testcontainers/testcontainers-go/modules/redis" + "github.com/testcontainers/testcontainers-go/wait" + "golang.org/x/sync/errgroup" +) + +func setupPostgres(t *testing.T, tempDir string) { + + t.Helper() + + ctx := context.Background() + + dbName := "bringyour" + dbUser := "bringyour" + dbPassword := "thisisatest" + + postgresContainer, err := postgres.Run( + ctx, + "docker.io/postgres:16-alpine", + postgres.WithDatabase(dbName), + postgres.WithUsername(dbUser), + postgres.WithPassword(dbPassword), + testcontainers.WithWaitStrategy( + wait.ForLog("database system is ready to accept connections"). + WithOccurrence(2). + WithStartupTimeout(5*time.Second), + ), + ) + require.NoError(t, err) + + t.Cleanup(func() { + postgresContainer.Terminate(ctx) + }) + + ep, err := postgresContainer.Endpoint(ctx, "") + require.NoError(t, err) + + pgAuth := map[string]string{ + "authority": ep, + "user": dbUser, + "password": dbPassword, + "db": dbName, + } + + d, err := json.Marshal(pgAuth) + require.NoError(t, err) + + err = os.WriteFile(filepath.Join(tempDir, "pg.yml"), d, 0644) + require.NoError(t, err) + + bringyour.ApplyDbMigrations(ctx) + +} + +func setupRedis(t *testing.T, tempDir string) { + ctx := context.Background() + + redisContainer, err := redis.Run(ctx, "redis:7.4.0") + require.NoError(t, err) + + t.Cleanup(func() { + redisContainer.Terminate(ctx) + }) + + ep, err := redisContainer.Endpoint(ctx, "") + require.NoError(t, err) + + redisConfig := map[string]any{ + "authority": ep, + "password": "", + "db": 0, + } + + d, err := json.Marshal(redisConfig) + require.NoError(t, err) + + err = os.WriteFile(filepath.Join(tempDir, "redis.yml"), d, 0644) + require.NoError(t, err) + +} + +func setupPrivateKey(t *testing.T, tempDir string) { + + t.Helper() + + // Generate RSA private key + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + require.NoError(t, err) + + pksc8, err := x509.MarshalPKCS8PrivateKey(privateKey) + require.NoError(t, err) + + // Encode the private key to PEM format + privateKeyPEM := &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: pksc8, + } + + keyDir := filepath.Join(tempDir, "tls", "bringyour.com") + + err = os.MkdirAll(keyDir, 0755) + require.NoError(t, err) + + // // Create a file to save the PEM encoded private key + file, err := os.Create(filepath.Join(keyDir, "bringyour.com.key")) + require.NoError(t, err) + defer file.Close() + + // Write the PEM encoded private key to the file + err = pem.Encode(file, privateKeyPEM) + require.NoError(t, err) + +} + +func testID(t *testing.T) string { + t.Helper() + s := sha1.Sum([]byte(t.Name())) + return hex.EncodeToString(s[:]) +} + +func TestEndToEnd(t *testing.T) { + + td := t.TempDir() + + os.Setenv("WARP_VAULT_HOME", td) + + setupPrivateKey(t, td) + setupRedis(t, td) + setupPostgres(t, td) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + notJWTSession := session.NewLocalClientSession(ctx, "localhost:1234", nil) + + userName := "test" + userAuth := "test@bringyour.com" + userPassword := "aaksdfkasd634" + networkName := "thisisatest" + + result, err := model.NetworkCreate(model.NetworkCreateArgs{ + UserName: userName, + Password: &userPassword, + UserAuth: &userAuth, + NetworkName: networkName, + Terms: true, + }, notJWTSession) + require.NoError(t, err) + require.NotNil(t, result) + + require.NotNil(t, result.VerificationRequired) + + createCodeResult, err := model.AuthVerifyCreateCode( + model.AuthVerifyCreateCodeArgs{ + UserAuth: result.VerificationRequired.UserAuth, + }, + notJWTSession, + ) + require.NoError(t, err) + require.Nil(t, createCodeResult.Error) + + av, err := model.AuthVerify( + model.AuthVerifyArgs{ + UserAuth: result.VerificationRequired.UserAuth, + VerifyCode: *createCodeResult.VerifyCode, + }, + notJWTSession, + ) + + require.NoError(t, err) + require.NotNil(t, av) + + s := httptest.NewServer(apirouter.NewAPIRouter()) + defer s.Close() + + login, err := model.AuthLoginWithPassword(model.AuthLoginWithPasswordArgs{ + UserAuth: userAuth, + Password: userPassword, + }, notJWTSession) + + require.NoError(t, err) + require.NotNil(t, login) + + byJwt, err := jwt.ParseByJwt(*login.Network.ByJwt) + require.NoError(t, err) + + jwtSession := session.NewLocalClientSession(ctx, "localhost:1234", byJwt) + + cl, err := model.AuthNetworkClient(&model.AuthNetworkClientArgs{ + Description: "test", + DeviceSpec: "test", + }, jwtSession) + require.NoError(t, err) + + require.Nil(t, cl.Error) + + byApiClient := connect.NewBringYourApi(connect.DefaultClientStrategy(ctx), s.URL) + byApiClient.SetByJwt(*cl.ByClientJwt) + + t.Run("offer sdp", func(t *testing.T) { + + handshakeID := testID(t) + + err := byApiClient.PutPeerToPeerOfferSDPSync( + ctx, + handshakeID, + webrtc.SessionDescription{ + Type: webrtc.SDPTypeOffer, + SDP: "", + }, + ) + require.NoError(t, err) + + sdp, err := byApiClient.PollPeerToPeerOfferSDPSync( + ctx, + handshakeID, + ) + + require.NoError(t, err) + require.Equal( + t, + webrtc.SessionDescription{ + Type: webrtc.SDPTypeOffer, + SDP: "", + }, + sdp, + ) + }) + + t.Run("answer sdp", func(t *testing.T) { + + handshakeID := testID(t) + + err := byApiClient.PutPeerToPeerAnswerSDPSync( + ctx, + handshakeID, + webrtc.SessionDescription{ + Type: webrtc.SDPTypeAnswer, + SDP: "", + }, + ) + require.NoError(t, err) + + sdp, err := byApiClient.PollPeerToPeerAnswerSDPSync( + ctx, + handshakeID, + ) + require.NoError(t, err) + + require.Equal( + t, + webrtc.SessionDescription{ + Type: webrtc.SDPTypeAnswer, + SDP: "", + }, + sdp, + ) + }) + + t.Run("offer peer candidates", func(t *testing.T) { + + handshakeID := testID(t) + + require.NoError(t, err) + err := byApiClient.PostPeerToPeerOfferPeerCandidateSync( + ctx, + handshakeID, + webrtc.ICECandidate{ + Typ: webrtc.ICECandidateTypeHost, + Foundation: "test", + Priority: 1, + Protocol: webrtc.ICEProtocolTCP, + Address: "test1", + Port: 1, + }, + ) + require.NoError(t, err) + + candidates, err := byApiClient.PollPeerToPeerOfferCandidatesSync( + ctx, + handshakeID, + 0, + ) + require.NoError(t, err) + require.Equal( + t, + []webrtc.ICECandidate{ + { + Typ: webrtc.ICECandidateTypeHost, + Foundation: "test", + Priority: 1, + Protocol: webrtc.ICEProtocolTCP, + Address: "test1", + Port: 1, + }, + }, + candidates, + ) + + err = byApiClient.PostPeerToPeerOfferPeerCandidateSync( + ctx, + handshakeID, + webrtc.ICECandidate{ + Typ: webrtc.ICECandidateTypeHost, + + Foundation: "test", + Priority: 2, + Protocol: webrtc.ICEProtocolTCP, + Address: "test2", + Port: 2, + }, + ) + require.NoError(t, err) + + candidates, err = byApiClient.PollPeerToPeerOfferCandidatesSync( + ctx, + handshakeID, + 1, + ) + require.NoError(t, err) + require.Equal( + t, + []webrtc.ICECandidate{ + { + Typ: webrtc.ICECandidateTypeHost, + + Foundation: "test", + Priority: 2, + Protocol: webrtc.ICEProtocolTCP, + Address: "test2", + Port: 2, + }, + }, + candidates, + ) + + }) + + t.Run("answer peer candidates", func(t *testing.T) { + + handshakeID := testID(t) + + err := byApiClient.PostPeerToPeerAnswerPeerCandidateSync( + ctx, + handshakeID, + webrtc.ICECandidate{ + Typ: webrtc.ICECandidateTypeHost, + Foundation: "test", + Priority: 1, + Protocol: webrtc.ICEProtocolTCP, + Address: "test1", + Port: 1, + }, + ) + require.NoError(t, err) + + candidates, err := byApiClient.PollPeerToPeerAnswerCandidatesSync( + ctx, + handshakeID, + 0, + ) + require.NoError(t, err) + require.Equal( + t, + []webrtc.ICECandidate{ + { + Typ: webrtc.ICECandidateTypeHost, + Foundation: "test", + Priority: 1, + Protocol: webrtc.ICEProtocolTCP, + Address: "test1", + Port: 1, + }, + }, candidates, + ) + + err = byApiClient.PostPeerToPeerAnswerPeerCandidateSync( + ctx, + handshakeID, + webrtc.ICECandidate{ + Typ: webrtc.ICECandidateTypeHost, + + Foundation: "test", + Priority: 2, + Protocol: webrtc.ICEProtocolTCP, + Address: "test2", + Port: 2, + }, + ) + require.NoError(t, err) + + candidates, err = byApiClient.PollPeerToPeerAnswerCandidatesSync( + ctx, + handshakeID, + 1, + ) + require.NoError(t, err) + require.Equal( + t, + []webrtc.ICECandidate{ + { + Typ: webrtc.ICECandidateTypeHost, + + Foundation: "test", + Priority: 2, + Protocol: webrtc.ICEProtocolTCP, + Address: "test2", + Port: 2, + }, + }, + candidates, + ) + + }) + + t.Run("establish WebRTC conn using the backend", func(t *testing.T) { + + handshakeID := testID(t) + + tctx, cancel := context.WithTimeout(ctx, 2*time.Second) + defer cancel() + + eg, egCtx := errgroup.WithContext(tctx) + + var offerReceived string + + eg.Go(func() error { + + conn, err := webrtcconn.Offer( + egCtx, + webrtc.Configuration{}, + connect.NewWebRTCOfferHandshake(byApiClient, handshakeID), + true, + 3, + 5*time.Second, + ) + if err != nil { + return fmt.Errorf("offer: %w", err) + } + defer conn.Close() + + _, err = conn.Write([]byte("test offer body")) + if err != nil { + return fmt.Errorf("offer write: %w", err) + } + + buffer := make([]byte, 1024) + + n, err := conn.Read(buffer) + + if err != nil { + return fmt.Errorf("offer read: %w", err) + } + + offerReceived = string(buffer[:n]) + + return err + }) + + var answerReceived string + + eg.Go(func() error { + conn, err := webrtcconn.Answer( + egCtx, + webrtc.Configuration{}, + connect.NewWebRTCAnswerHandshake(byApiClient, handshakeID), + 5*time.Second, + ) + if err != nil { + return fmt.Errorf("answer: %w", err) + } + defer conn.Close() + + _, err = conn.Write([]byte("test answer body")) + + if err != nil { + return fmt.Errorf("answer write: %w", err) + } + + buffer := make([]byte, 1024) + + n, err := conn.Read(buffer) + if err != nil { + return fmt.Errorf("answer read: %w", err) + } + + answerReceived = string(buffer[:n]) + + return nil + }) + + err = eg.Wait() + require.NoError(t, err) + + require.Equal(t, "test answer body", offerReceived) + + require.Equal(t, "test offer body", answerReceived) + + }) + +} diff --git a/api/go.mod b/api/go.mod index 554f1b6b..af01fde2 100644 --- a/api/go.mod +++ b/api/go.mod @@ -1,49 +1,116 @@ module bringyour.com/service/api +go 1.22.5 + require ( bringyour.com/bringyour v0.0.0 + bringyour.com/connect v0.0.0 + github.com/bringyour/webrtc-conn v0.0.3 + github.com/cenkalti/backoff/v4 v4.3.0 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 + github.com/pion/webrtc/v3 v3.3.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go/modules/postgres v0.33.0 + github.com/testcontainers/testcontainers-go/modules/redis v0.33.0 + golang.org/x/sync v0.8.0 ) require ( - bringyour.com/connect v0.0.0 // indirect bringyour.com/protocol v0.0.0 // indirect + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/aws/aws-sdk-go v1.44.331 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/containerd/containerd v1.7.18 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-jose/go-jose/v3 v3.0.3 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect github.com/golang/glog v1.2.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.3.1 // indirect - github.com/jackc/puddle/v2 v2.2.0 // indirect + github.com/jackc/pgx/v5 v5.5.4 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/mozillazg/go-unidecode v0.2.0 // indirect github.com/nyaruka/phonenumbers v1.1.6 // indirect github.com/oklog/ulid/v2 v2.1.0 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pion/datachannel v1.5.8 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect + github.com/pion/ice/v2 v2.3.34 // indirect + github.com/pion/interceptor v0.1.30 // indirect + github.com/pion/logging v0.2.2 // indirect + github.com/pion/mdns v0.0.12 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.14 // indirect + github.com/pion/rtp v1.8.9 // indirect + github.com/pion/sctp v1.8.21 // indirect + github.com/pion/sdp/v3 v3.0.9 // indirect + github.com/pion/srtp/v2 v2.0.20 // indirect + github.com/pion/stun v0.6.1 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect + github.com/pion/turn/v2 v2.1.6 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/pquerna/cachecontrol v0.2.0 // indirect github.com/quic-go/quic-go v0.46.0 // indirect github.com/redis/go-redis/v9 v9.0.3 // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/stripe/stripe-go/v76 v76.16.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/wlynxg/anet v0.0.3 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/mock v0.4.0 // indirect - golang.org/x/crypto v0.25.0 // indirect + golang.org/x/crypto v0.26.0 // indirect golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -55,5 +122,3 @@ replace bringyour.com/bringyour v0.0.0 => ../bringyour replace bringyour.com/connect v0.0.0 => ../../connect/connect replace bringyour.com/protocol v0.0.0 => ../../connect/protocol/build/bringyour.com/protocol - -go 1.22.0 diff --git a/api/go.sum b/api/go.sum index 91536b00..5b9c4100 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,48 +1,93 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/aws/aws-sdk-go v1.44.331 h1:hEwdOTv6973uegCUY2EY8jyyq0OUg9INc0HOzcu2bjw= github.com/aws/aws-sdk-go v1.44.331/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/bringyour/webrtc-conn v0.0.3 h1:BSeLu9l31HGWpBvz1NmmuMfRgFiIrCvnopfZEuNoXGg= +github.com/bringyour/webrtc-conn v0.0.3/go.mod h1:iKpYIadSl8wpVF/Z3dPK7h1eBCcNxwgSxCLXPPYxMGI= github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= +github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw= github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= @@ -50,18 +95,43 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= -github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= -github.com/jackc/puddle/v2 v2.2.0 h1:RdcDk92EJBuBS55nQMMYFXTxwstHug4jkhT5pq8VxPk= -github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= +github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozillazg/go-unidecode v0.2.0 h1:vFGEzAH9KSwyWmXCOblazEWDh7fOkpmy/Z4ArmamSUc= github.com/mozillazg/go-unidecode v0.2.0/go.mod h1:zB48+/Z5toiRolOZy9ksLryJ976VIwmDmpQ2quyt1aA= github.com/nyaruka/phonenumbers v1.1.6 h1:DcueYq7QrOArAprAYNoQfDgp0KetO4LqtnBtQC6Wyes= @@ -72,102 +142,252 @@ github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/pion/datachannel v1.5.8 h1:ph1P1NsGkazkjrvyMfhRBUAWMxugJjq2HfQifaOoSNo= +github.com/pion/datachannel v1.5.8/go.mod h1:PgmdpoaNBLX9HNzNClmdki4DYW5JtI7Yibu8QzbL3tI= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/ice/v2 v2.3.34 h1:Ic1ppYCj4tUOcPAp76U6F3fVrlSw8A9JtRXLqw6BbUM= +github.com/pion/ice/v2 v2.3.34/go.mod h1:mBF7lnigdqgtB+YHkaY/Y6s6tsyRyo4u4rPGRuOjUBQ= +github.com/pion/interceptor v0.1.30 h1:au5rlVHsgmxNi+v/mjOPazbW1SHzfx7/hYOEYQnUcxA= +github.com/pion/interceptor v0.1.30/go.mod h1:RQuKT5HTdkP2Fi0cuOS5G5WNymTjzXaGF75J4k7z2nc= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8= +github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= +github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE= +github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= +github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/rtp v1.8.9 h1:E2HX740TZKaqdcPmf4pw6ZZuG8u5RlMMt+l3dxeu6Wk= +github.com/pion/rtp v1.8.9/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/sctp v1.8.21 h1:ZJUU4R1IZA0tdFnWsmnltvRz/6pQPSJqDtzLZ83dINs= +github.com/pion/sctp v1.8.21/go.mod h1:beTnqSzewI53KWoG3nqB282oDMGrhNxBdb+JZnkCwRM= +github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= +github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= +github.com/pion/srtp/v2 v2.0.20 h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk= +github.com/pion/srtp/v2 v2.0.20/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= +github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= +github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= +github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= +github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc= +github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= +github.com/pion/webrtc/v3 v3.3.0 h1:Rf4u6n6U5t5sUxhYPQk/samzU/oDv7jk6BA5hyO2F9I= +github.com/pion/webrtc/v3 v3.3.0/go.mod h1:hVmrDJvwhEertRWObeb1xzulzHGeVUoPlWvxdGzcfU0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k= github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y= github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI= github.com/redis/go-redis/v9 v9.0.3 h1:+7mmR26M0IvyLxGZUHxu4GiBkJkVDid0Un+j4ScYu4k= github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stripe/stripe-go/v76 v76.16.0 h1:XB+gA4QX532p1N98ZWez6wuI+5xcUbxR+jT5s7mmmug= github.com/stripe/stripe-go/v76 v76.16.0/go.mod h1:rw1MxjlAKKcZ+3FOXgTHgwiOa2ya6CPq6ykpJ0Q6Po4= +github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw= +github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8= +github.com/testcontainers/testcontainers-go/modules/postgres v0.33.0 h1:c+Gt+XLJjqFAejgX4hSpnHIpC9eAhvgI/TFWL/PbrFI= +github.com/testcontainers/testcontainers-go/modules/postgres v0.33.0/go.mod h1:I4DazHBoWDyf69ByOIyt3OdNjefiUx372459txOpQ3o= +github.com/testcontainers/testcontainers-go/modules/redis v0.33.0 h1:S/QvMOwpr00MM2aWH+krzP73Erlp/Ug0dr2rkgZYI5s= +github.com/testcontainers/testcontainers-go/modules/redis v0.33.0/go.mod h1:gudb3+6uZ9SsAysOVoLs7nazbjGlkHegBW8nqPXvDMI= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/wlynxg/anet v0.0.3 h1:PvR53psxFXstc12jelG6f1Lv4MWqE0tI76/hHGjh9rg= +github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13 h1:vlzZttNJGVqTsRFU9AmdnrcO1Znh8Ew9kCD//yjigk0= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= src.agwa.name/tlshacks v0.0.0-20231008131857-90d701ba3225 h1:KvJgNzDBgG6IawXLCenHhjvU7RXQ5UD1a18Nm2ZMyGg= src.agwa.name/tlshacks v0.0.0-20231008131857-90d701ba3225/go.mod h1:NT4HI59yJusF5Il4/DlC8F5+mfylE4CbRVwdoEi6MF8= diff --git a/api/handlers/peer_to_peer_handlers.go b/api/handlers/peer_to_peer_handlers.go new file mode 100644 index 00000000..58161bf1 --- /dev/null +++ b/api/handlers/peer_to_peer_handlers.go @@ -0,0 +1,272 @@ +package handlers + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "strconv" + "time" + + "bringyour.com/bringyour" + "bringyour.com/bringyour/router" + "bringyour.com/bringyour/session" + "github.com/cenkalti/backoff/v4" +) + +const peerToPeerRedisKeyPrefix = "peer_to_peer" +const peerToPeerObjectExpire = 60 * time.Second +const pollTimeout = 10 * time.Second + +func peerToPeerOfferRedisKey(id string) string { + return fmt.Sprintf("%s:%s:offer", peerToPeerRedisKeyPrefix, id) +} + +func peerToPeerAnswerRedisKey(id string) string { + return fmt.Sprintf("%s:%s:answer", peerToPeerRedisKeyPrefix, id) +} + +func peerToPeerHandshakeSetSDP(redisKeyFunc func(string) string, w http.ResponseWriter, r *http.Request) { + + pathValues := router.GetPathValues(r) + + sessionID := pathValues[0] + + router.WrapWithInputRequireClient( + func(sdp json.RawMessage, cs *session.ClientSession) (string, error) { + ctx := cs.Ctx + var err error + sdpKey := redisKeyFunc(sessionID) + bringyour.Redis(ctx, func(client bringyour.RedisClient) { + pipeline := client.Pipeline() + pipeline.Set(ctx, sdpKey, []byte(sdp), 0) + pipeline.Expire(ctx, sdpKey, peerToPeerObjectExpire) + _, err = pipeline.Exec(ctx) + }) + + return "", err + + }, + w, + r, + ) + +} + +func PeerToPeerHandshakeOfferSetSDP(w http.ResponseWriter, r *http.Request) { + peerToPeerHandshakeSetSDP(peerToPeerOfferRedisKey, w, r) +} + +func PeerToPeerHandshakeAnswerSetSDP(w http.ResponseWriter, r *http.Request) { + peerToPeerHandshakeSetSDP(peerToPeerAnswerRedisKey, w, r) +} + +func peerToPeerHandshakeLongPollSDP(redisKeyFunc func(string) string, w http.ResponseWriter, r *http.Request) { + + pathValues := router.GetPathValues(r) + + sessionID := pathValues[0] + + router.WrapRequireClient( + func(cs *session.ClientSession) (json.RawMessage, error) { + ctx := cs.Ctx + var err error + + sdpKey := redisKeyFunc(sessionID) + + var sdp json.RawMessage + + bringyour.Redis(ctx, func(client bringyour.RedisClient) { + ctx, cancel := context.WithTimeout(cs.Ctx, pollTimeout) + defer cancel() + + bo := backoff.NewExponentialBackOff() + bo.InitialInterval = 50 * time.Millisecond + bo.MaxInterval = 1 * time.Second + bo.MaxElapsedTime = pollTimeout + + boWithContext := backoff.WithContext(bo, ctx) + + sdp, err = backoff.RetryWithData( + func() ([]byte, error) { + res := client.Get(ctx, sdpKey) + return res.Bytes() + }, + boWithContext, + ) + + }) + + if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { + w.WriteHeader(http.StatusNoContent) + return nil, nil + } + + if err != nil { + return nil, err + } + + return sdp, err + + }, + w, + r, + ) + +} + +func PeerToPeerHandshakeLongPollOfferSDP(w http.ResponseWriter, r *http.Request) { + peerToPeerHandshakeLongPollSDP(peerToPeerOfferRedisKey, w, r) +} + +func PeerToPeerHandshakeLongPollAnswerSDP(w http.ResponseWriter, r *http.Request) { + peerToPeerHandshakeLongPollSDP(peerToPeerAnswerRedisKey, w, r) +} + +func peerToPeerOfferPeerCandidatesRedisKey(id string) string { + return fmt.Sprintf("%s:%s:offer:peer_candidates", peerToPeerRedisKeyPrefix, id) +} +func peerToPeerAnswerPeerCandidatesRedisKey(id string) string { + return fmt.Sprintf("%s:%s:answer:peer_candidates", peerToPeerRedisKeyPrefix, id) +} + +func peerToPeerHandshakeAddPeerCandidate(redisKeyFunc func(string) string, w http.ResponseWriter, r *http.Request) { + + pathValues := router.GetPathValues(r) + + sessionID := pathValues[0] + + router.WrapWithInputRequireClient( + func(peerCandidate json.RawMessage, cs *session.ClientSession) (string, error) { + ctx := cs.Ctx + + var err error + + bringyour.Redis(ctx, func(client bringyour.RedisClient) { + pl := client.Pipeline() + + candidatesKey := redisKeyFunc(sessionID) + + pl.RPush(ctx, candidatesKey, []byte(peerCandidate)) + pl.ExpireNX(ctx, candidatesKey, peerToPeerObjectExpire) + + _, err = pl.Exec(ctx) + if err != nil { + return + } + }) + + if err != nil { + return "", err + } + + return "", nil + + }, + w, + r, + ) + +} + +func PeerToPeerHandshakeOfferAddPeerCandidate(w http.ResponseWriter, r *http.Request) { + peerToPeerHandshakeAddPeerCandidate(peerToPeerOfferPeerCandidatesRedisKey, w, r) +} + +func PeerToPeerHandshakeAnswerAddPeerCandidate(w http.ResponseWriter, r *http.Request) { + peerToPeerHandshakeAddPeerCandidate(peerToPeerAnswerPeerCandidatesRedisKey, w, r) +} + +func peerToPeerHandshakeLongPollNewPeerCandidates(redisKeyFunc func(string) string, w http.ResponseWriter, r *http.Request) { + + fromString := r.URL.Query().Get("from") + + from := uint64(0) + if fromString != "" { + var err error + from, err = strconv.ParseUint(fromString, 10, 64) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + } + + pathValues := router.GetPathValues(r) + + sessionID := pathValues[0] + + router.WrapRequireClient( + func(cs *session.ClientSession) ([]json.RawMessage, error) { + + ctx, cancel := context.WithTimeout(cs.Ctx, pollTimeout) + defer cancel() + + var err error + + var vals []json.RawMessage + + bringyour.Redis(ctx, func(client bringyour.RedisClient) { + + candidatesKey := redisKeyFunc(sessionID) + + bo := backoff.NewExponentialBackOff() + bo.InitialInterval = 50 * time.Millisecond + bo.MaxInterval = 1 * time.Second + bo.MaxElapsedTime = pollTimeout + + boWithContext := backoff.WithContext(bo, ctx) + + vals, err = backoff.RetryWithData( + func() ([]json.RawMessage, error) { + + slCmd := client.LRange(ctx, candidatesKey, int64(from), -1) + err = slCmd.Err() + if err != nil { + return nil, err + } + + for _, v := range slCmd.Val() { + vals = append(vals, json.RawMessage(v)) + } + + if len(vals) == 0 { + return nil, fmt.Errorf("no candidates") + } + + return vals, nil + + }, + boWithContext, + ) + + }) + + if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { + w.WriteHeader(http.StatusNoContent) + return nil, nil + } + + if err != nil { + return nil, err + } + + json.NewEncoder(os.Stdout).Encode(vals) + + return vals, nil + + }, + w, + r, + ) + +} + +func PeerToPeerHandshakeOfferLongPollNewPeerCandidates(w http.ResponseWriter, r *http.Request) { + peerToPeerHandshakeLongPollNewPeerCandidates(peerToPeerOfferPeerCandidatesRedisKey, w, r) +} + +func PeerToPeerHandshakeAnswerLongPollNewPeerCandidates(w http.ResponseWriter, r *http.Request) { + peerToPeerHandshakeLongPollNewPeerCandidates(peerToPeerAnswerPeerCandidatesRedisKey, w, r) +} diff --git a/api/main.go b/api/main.go index 49ea2d3e..08e8db21 100644 --- a/api/main.go +++ b/api/main.go @@ -1,7 +1,6 @@ package main import ( - "context" "fmt" "net/http" "os" @@ -9,8 +8,7 @@ import ( "github.com/docopt/docopt-go" "bringyour.com/bringyour" - "bringyour.com/bringyour/router" - "bringyour.com/service/api/handlers" + "bringyour.com/service/api/apirouter" ) func main() { @@ -31,6 +29,7 @@ Options: panic(err) } +<<<<<<< HEAD // FIXME signal cancel cancelCtx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -101,6 +100,8 @@ Options: router.NewRoute("GET", "/account/referral-code", handlers.GetNetworkReferralCode), } +======= +>>>>>>> 71a9e24 (api: endpoints for WebRTC handshake) // bringyour.Logger().Printf("%s\n", opts) port, _ := opts.Int("--port") @@ -112,8 +113,7 @@ Options: port, ) - routerHandler := router.NewRouter(cancelCtx, routes) - err = http.ListenAndServe(fmt.Sprintf(":%d", port), routerHandler) + err = http.ListenAndServe(fmt.Sprintf(":%d", port), apirouter.NewAPIRouter()) bringyour.Logger().Fatal(err) } diff --git a/bringyour/router/router.go b/bringyour/router/router.go index 46c993fc..bb30ec41 100644 --- a/bringyour/router/router.go +++ b/bringyour/router/router.go @@ -34,13 +34,11 @@ func (self *Route) String() string { type pathValuesKey struct{} type Router struct { - ctx context.Context routes []*Route } -func NewRouter(ctx context.Context, routes []*Route) *Router { +func NewRouter(routes []*Route) *Router { return &Router{ - ctx: ctx, routes: routes, } } @@ -55,7 +53,7 @@ func (self *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) { allow = append(allow, route.method) continue } - ctx := context.WithValue(self.ctx, pathValuesKey{}, matches[1:]) + ctx := context.WithValue(r.Context(), pathValuesKey{}, matches[1:]) func() { defer func() { if r := recover(); r != nil { diff --git a/bringyour/router/router_test.go b/bringyour/router/router_test.go index 3bea7df8..3ca6845e 100644 --- a/bringyour/router/router_test.go +++ b/bringyour/router/router_test.go @@ -1,7 +1,6 @@ package router import ( - "context" "errors" "fmt" "net/http" @@ -17,8 +16,6 @@ import ( func TestRouterBasic(t *testing.T) { bringyour.DefaultTestEnv().Run(func() { - cancelCtx, cancel := context.WithCancel(context.Background()) - defer cancel() NoAuth := func(w http.ResponseWriter, r *http.Request) { impl := func(clientSession *session.ClientSession) (map[string]any, error) { @@ -125,7 +122,7 @@ func TestRouterBasic(t *testing.T) { port := 8080 - routerHandler := NewRouter(cancelCtx, routes) + routerHandler := NewRouter(routes) go http.ListenAndServe(fmt.Sprintf(":%d", port), routerHandler) select { From 7b9fb115ef39172016938db0e4298f5585b31c4d Mon Sep 17 00:00:00 2001 From: Dragan Milic Date: Tue, 3 Sep 2024 16:37:47 +0200 Subject: [PATCH 2/2] fix the end-to-end test race condition --- api/end_to_end_test.go | 6 ++++ api/main.go | 73 ------------------------------------------ 2 files changed, 6 insertions(+), 73 deletions(-) diff --git a/api/end_to_end_test.go b/api/end_to_end_test.go index 9e27d2b8..a6a1b5eb 100644 --- a/api/end_to_end_test.go +++ b/api/end_to_end_test.go @@ -467,6 +467,12 @@ func TestEndToEnd(t *testing.T) { } defer conn.Close() + // There is a race condition in this test: `Offer` side of the WebRTC will close the data channel + // This sleep makes sure that the data channel is kept open long enough for the `Answer` side to read + // the sent data. + + defer time.Sleep(200 * time.Millisecond) + _, err = conn.Write([]byte("test offer body")) if err != nil { return fmt.Errorf("offer write: %w", err) diff --git a/api/main.go b/api/main.go index 08e8db21..5d957528 100644 --- a/api/main.go +++ b/api/main.go @@ -29,79 +29,6 @@ Options: panic(err) } -<<<<<<< HEAD - // FIXME signal cancel - cancelCtx, cancel := context.WithCancel(context.Background()) - defer cancel() - - routes := []*router.Route{ - router.NewRoute("GET", "/privacy.txt", router.Txt), - router.NewRoute("GET", "/terms.txt", router.Txt), - router.NewRoute("GET", "/vdp.txt", router.Txt), - router.NewRoute("GET", "/status", router.WarpStatus), - router.NewRoute("GET", "/stats/last-90", handlers.StatsLast90), - router.NewRoute("GET", "/stats/providers-overview-last-90", handlers.StatsProvidersOverviewLast90), - router.NewRoute("GET", "/stats/providers", handlers.StatsProviders), - router.NewRoute("POST", "/stats/provider-last-90", handlers.StatsProviderLast90), - router.NewRoute("POST", "/auth/login", handlers.AuthLogin), - router.NewRoute("POST", "/auth/login-with-password", handlers.AuthLoginWithPassword), - router.NewRoute("POST", "/auth/verify", handlers.AuthVerify), - router.NewRoute("POST", "/auth/verify-send", handlers.AuthVerifySend), - router.NewRoute("POST", "/auth/password-reset", handlers.AuthPasswordReset), - router.NewRoute("POST", "/auth/password-set", handlers.AuthPasswordSet), - router.NewRoute("POST", "/auth/network-check", handlers.NetworkCheck), - router.NewRoute("POST", "/auth/network-create", handlers.NetworkCreate), - router.NewRoute("POST", "/auth/code-create", handlers.AuthCodeCreate), - router.NewRoute("POST", "/auth/code-login", handlers.AuthCodeLogin), - router.NewRoute("POST", "/network/auth-client", handlers.AuthNetworkClient), - router.NewRoute("POST", "/network/remove-client", handlers.RemoveNetworkClient), - router.NewRoute("GET", "/network/clients", handlers.NetworkClients), - router.NewRoute("GET", "/network/provider-locations", handlers.NetworkGetProviderLocations), - router.NewRoute("POST", "/network/find-provider-locations", handlers.NetworkFindProviderLocations), - router.NewRoute("POST", "/network/find-locations", handlers.NetworkFindLocations), - router.NewRoute("POST", "/network/find-providers", handlers.NetworkFindProviders), - router.NewRoute("POST", "/network/find-providers2", handlers.NetworkFindProviders2), - router.NewRoute("POST", "/network/create-provider-spec", handlers.NetworkCreateProviderSpec), - router.NewRoute("GET", "/network/user", handlers.GetNetworkUser), - router.NewRoute("POST", "/preferences/set-preferences", handlers.PreferencesSet), - router.NewRoute("POST", "/feedback/send-feedback", handlers.FeedbackSend), - router.NewRoute("POST", "/pay/stripe", handlers.StripeWebhook), - router.NewRoute("POST", "/pay/coinbase", handlers.CoinbaseWebhook), - router.NewRoute("POST", "/pay/circle", handlers.CircleWebhook), - router.NewRoute("POST", "/pay/play", handlers.PlayWebhook), - router.NewRoute("GET", "/wallet/balance", handlers.WalletBalance), - router.NewRoute("POST", "/wallet/validate-address", handlers.WalletValidateAddress), - router.NewRoute("POST", "/wallet/circle-init", handlers.WalletCircleInit), - router.NewRoute("POST", "/wallet/circle-transfer-out", handlers.WalletCircleTransferOut), - router.NewRoute("GET", "/subscription/balance", handlers.SubscriptionBalance), - router.NewRoute("POST", "/subscription/check-balance-code", handlers.SubscriptionCheckBalanceCode), - router.NewRoute("POST", "/subscription/redeem-balance-code", handlers.SubscriptionRedeemBalanceCode), - router.NewRoute("POST", "/subscription/create-payment-id", handlers.SubscriptionCreatePaymentId), - router.NewRoute("POST", "/device/add", handlers.DeviceAdd), - router.NewRoute("POST", "/device/create-share-code", handlers.DeviceCreateShareCode), - router.NewRoute("GET", "/device/share-code/([^/]+)/qr.png", handlers.DeviceShareCodeQR), - router.NewRoute("POST", "/device/share-status", handlers.DeviceShareStatus), - router.NewRoute("POST", "/device/confirm-share", handlers.DeviceConfirmShare), - router.NewRoute("POST", "/device/create-adopt-code", handlers.DeviceCreateAdoptCode), - router.NewRoute("GET", "/device/adopt-code/([^/]+)/qr.png", handlers.DeviceAdoptCodeQR), - router.NewRoute("POST", "/device/adopt-status", handlers.DeviceAdoptStatus), - router.NewRoute("POST", "/device/confirm-adopt", handlers.DeviceConfirmAdopt), - router.NewRoute("POST", "/device/remove-adopt-code", handlers.DeviceRemoveAdoptCode), - router.NewRoute("GET", "/device/associations", handlers.DeviceAssociations), - router.NewRoute("POST", "/device/remove-association", handlers.DeviceRemoveAssociation), - router.NewRoute("POST", "/device/set-association-name", handlers.DeviceSetAssociationName), - router.NewRoute("POST", "/device/set-provide", handlers.DeviceSetProvide), - router.NewRoute("POST", "/connect/control", handlers.ConnectControl), - router.NewRoute("GET", "/hello", handlers.Hello), - router.NewRoute("POST", "/account/payout-wallet", handlers.SetPayoutWallet), - router.NewRoute("GET", "/account/payout-wallet", handlers.GetPayoutWallet), - router.NewRoute("POST", "/account/wallet", handlers.CreateAccountWallet), - router.NewRoute("GET", "/account/wallets", handlers.GetAccountWallets), - router.NewRoute("GET", "/account/referral-code", handlers.GetNetworkReferralCode), - } - -======= ->>>>>>> 71a9e24 (api: endpoints for WebRTC handshake) // bringyour.Logger().Printf("%s\n", opts) port, _ := opts.Int("--port")