mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-29 13:46:41 +00:00
Compare commits
20 Commits
debug-user
...
feature/bu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43176fb96c | ||
|
|
2f34e984b0 | ||
|
|
d5b52e86b6 | ||
|
|
cad2fe1f39 | ||
|
|
fcd2c15a37 | ||
|
|
ebda0fc538 | ||
|
|
ac135ab11d | ||
|
|
25faf9283d | ||
|
|
59faaa99f6 | ||
|
|
9762b39f29 | ||
|
|
ffdd115ded | ||
|
|
055df9854c | ||
|
|
12f883badf | ||
|
|
2abb92b0d4 | ||
|
|
01c3719c5d | ||
|
|
7b64953eed | ||
|
|
9bc7d788f0 | ||
|
|
b5419ef11a | ||
|
|
d1e4bb0fa3 | ||
|
|
12b0c13511 |
7
buf.gen.yaml
Normal file
7
buf.gen.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# For details on buf.gen.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-gen-yaml/
|
||||||
|
version: v2
|
||||||
|
plugins:
|
||||||
|
- remote: buf.build/protocolbuffers/go:v1.35.1
|
||||||
|
out: .
|
||||||
|
- remote: buf.build/grpc/go:v1.5.1
|
||||||
|
out: .
|
||||||
10
buf.yaml
Normal file
10
buf.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml
|
||||||
|
version: v2
|
||||||
|
modules:
|
||||||
|
- path: proto
|
||||||
|
lint:
|
||||||
|
use:
|
||||||
|
- BASIC
|
||||||
|
breaking:
|
||||||
|
use:
|
||||||
|
- FILE
|
||||||
@@ -235,13 +235,6 @@ func runForDuration(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("failed to bundle debug: %v", status.Convert(err).Message())
|
return fmt.Errorf("failed to bundle debug: %v", status.Convert(err).Message())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable network map persistence after creating the debug bundle
|
|
||||||
if _, err := client.SetNetworkMapPersistence(cmd.Context(), &proto.SetNetworkMapPersistenceRequest{
|
|
||||||
Enabled: false,
|
|
||||||
}); err != nil {
|
|
||||||
return fmt.Errorf("failed to disable network map persistence: %v", status.Convert(err).Message())
|
|
||||||
}
|
|
||||||
|
|
||||||
if stateWasDown {
|
if stateWasDown {
|
||||||
if _, err := client.Down(cmd.Context(), &proto.DownRequest{}); err != nil {
|
if _, err := client.Down(cmd.Context(), &proto.DownRequest{}); err != nil {
|
||||||
return fmt.Errorf("failed to down: %v", status.Convert(err).Message())
|
return fmt.Errorf("failed to down: %v", status.Convert(err).Message())
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ const (
|
|||||||
blockLANAccessFlag = "block-lan-access"
|
blockLANAccessFlag = "block-lan-access"
|
||||||
uploadBundle = "upload-bundle"
|
uploadBundle = "upload-bundle"
|
||||||
uploadBundleURL = "upload-bundle-url"
|
uploadBundleURL = "upload-bundle-url"
|
||||||
defaultBundleURL = "https://upload.debug.netbird.io" + types.GetURLPath
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -188,7 +187,7 @@ func init() {
|
|||||||
|
|
||||||
debugCmd.PersistentFlags().BoolVarP(&debugSystemInfoFlag, systemInfoFlag, "S", true, "Adds system information to the debug bundle")
|
debugCmd.PersistentFlags().BoolVarP(&debugSystemInfoFlag, systemInfoFlag, "S", true, "Adds system information to the debug bundle")
|
||||||
debugCmd.PersistentFlags().BoolVarP(&debugUploadBundle, uploadBundle, "U", false, fmt.Sprintf("Uploads the debug bundle to a server from URL defined by %s", uploadBundleURL))
|
debugCmd.PersistentFlags().BoolVarP(&debugUploadBundle, uploadBundle, "U", false, fmt.Sprintf("Uploads the debug bundle to a server from URL defined by %s", uploadBundleURL))
|
||||||
debugCmd.PersistentFlags().StringVar(&debugUploadBundleURL, uploadBundleURL, defaultBundleURL, "Service URL to get an URL to upload the debug bundle")
|
debugCmd.PersistentFlags().StringVar(&debugUploadBundleURL, uploadBundleURL, types.DefaultBundleURL, "Service URL to get an URL to upload the debug bundle")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupCloseHandler handles SIGTERM signal and exits with success
|
// SetupCloseHandler handles SIGTERM signal and exits with success
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package dns_test
|
package dns_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
@@ -9,6 +8,7 @@ import (
|
|||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/client/internal/dns"
|
nbdns "github.com/netbirdio/netbird/client/internal/dns"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestHandlerChain_ServeDNS_Priorities tests that handlers are executed in priority order
|
// TestHandlerChain_ServeDNS_Priorities tests that handlers are executed in priority order
|
||||||
@@ -30,7 +30,7 @@ func TestHandlerChain_ServeDNS_Priorities(t *testing.T) {
|
|||||||
r.SetQuestion("example.com.", dns.TypeA)
|
r.SetQuestion("example.com.", dns.TypeA)
|
||||||
|
|
||||||
// Create test writer
|
// Create test writer
|
||||||
w := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
|
|
||||||
// Setup expectations - only highest priority handler should be called
|
// Setup expectations - only highest priority handler should be called
|
||||||
dnsRouteHandler.On("ServeDNS", mock.Anything, r).Once()
|
dnsRouteHandler.On("ServeDNS", mock.Anything, r).Once()
|
||||||
@@ -142,7 +142,7 @@ func TestHandlerChain_ServeDNS_DomainMatching(t *testing.T) {
|
|||||||
|
|
||||||
r := new(dns.Msg)
|
r := new(dns.Msg)
|
||||||
r.SetQuestion(tt.queryDomain, dns.TypeA)
|
r.SetQuestion(tt.queryDomain, dns.TypeA)
|
||||||
w := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
|
|
||||||
chain.ServeDNS(w, r)
|
chain.ServeDNS(w, r)
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ func TestHandlerChain_ServeDNS_OverlappingDomains(t *testing.T) {
|
|||||||
// Create and execute request
|
// Create and execute request
|
||||||
r := new(dns.Msg)
|
r := new(dns.Msg)
|
||||||
r.SetQuestion(tt.queryDomain, dns.TypeA)
|
r.SetQuestion(tt.queryDomain, dns.TypeA)
|
||||||
w := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
chain.ServeDNS(w, r)
|
chain.ServeDNS(w, r)
|
||||||
|
|
||||||
// Verify expectations
|
// Verify expectations
|
||||||
@@ -316,7 +316,7 @@ func TestHandlerChain_ServeDNS_ChainContinuation(t *testing.T) {
|
|||||||
}).Once()
|
}).Once()
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
w := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
chain.ServeDNS(w, r)
|
chain.ServeDNS(w, r)
|
||||||
|
|
||||||
// Verify all handlers were called in order
|
// Verify all handlers were called in order
|
||||||
@@ -325,20 +325,6 @@ func TestHandlerChain_ServeDNS_ChainContinuation(t *testing.T) {
|
|||||||
handler3.AssertExpectations(t)
|
handler3.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// mockResponseWriter implements dns.ResponseWriter for testing
|
|
||||||
type mockResponseWriter struct {
|
|
||||||
mock.Mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockResponseWriter) LocalAddr() net.Addr { return nil }
|
|
||||||
func (m *mockResponseWriter) RemoteAddr() net.Addr { return nil }
|
|
||||||
func (m *mockResponseWriter) WriteMsg(*dns.Msg) error { return nil }
|
|
||||||
func (m *mockResponseWriter) Write([]byte) (int, error) { return 0, nil }
|
|
||||||
func (m *mockResponseWriter) Close() error { return nil }
|
|
||||||
func (m *mockResponseWriter) TsigStatus() error { return nil }
|
|
||||||
func (m *mockResponseWriter) TsigTimersOnly(bool) {}
|
|
||||||
func (m *mockResponseWriter) Hijack() {}
|
|
||||||
|
|
||||||
func TestHandlerChain_PriorityDeregistration(t *testing.T) {
|
func TestHandlerChain_PriorityDeregistration(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -425,7 +411,7 @@ func TestHandlerChain_PriorityDeregistration(t *testing.T) {
|
|||||||
// Create test request
|
// Create test request
|
||||||
r := new(dns.Msg)
|
r := new(dns.Msg)
|
||||||
r.SetQuestion(tt.query, dns.TypeA)
|
r.SetQuestion(tt.query, dns.TypeA)
|
||||||
w := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
|
|
||||||
// Setup expectations
|
// Setup expectations
|
||||||
for priority, handler := range handlers {
|
for priority, handler := range handlers {
|
||||||
@@ -471,7 +457,7 @@ func TestHandlerChain_MultiPriorityHandling(t *testing.T) {
|
|||||||
chain.AddHandler(testDomain, matchHandler, nbdns.PriorityMatchDomain)
|
chain.AddHandler(testDomain, matchHandler, nbdns.PriorityMatchDomain)
|
||||||
|
|
||||||
// Test 1: Initial state
|
// Test 1: Initial state
|
||||||
w1 := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w1 := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
// Highest priority handler (routeHandler) should be called
|
// Highest priority handler (routeHandler) should be called
|
||||||
routeHandler.On("ServeDNS", mock.Anything, r).Return().Once()
|
routeHandler.On("ServeDNS", mock.Anything, r).Return().Once()
|
||||||
matchHandler.On("ServeDNS", mock.Anything, r).Maybe() // Ensure others are not expected yet
|
matchHandler.On("ServeDNS", mock.Anything, r).Maybe() // Ensure others are not expected yet
|
||||||
@@ -490,7 +476,7 @@ func TestHandlerChain_MultiPriorityHandling(t *testing.T) {
|
|||||||
// Test 2: Remove highest priority handler
|
// Test 2: Remove highest priority handler
|
||||||
chain.RemoveHandler(testDomain, nbdns.PriorityDNSRoute)
|
chain.RemoveHandler(testDomain, nbdns.PriorityDNSRoute)
|
||||||
|
|
||||||
w2 := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w2 := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
// Now middle priority handler (matchHandler) should be called
|
// Now middle priority handler (matchHandler) should be called
|
||||||
matchHandler.On("ServeDNS", mock.Anything, r).Return().Once()
|
matchHandler.On("ServeDNS", mock.Anything, r).Return().Once()
|
||||||
defaultHandler.On("ServeDNS", mock.Anything, r).Maybe() // Ensure default is not expected yet
|
defaultHandler.On("ServeDNS", mock.Anything, r).Maybe() // Ensure default is not expected yet
|
||||||
@@ -506,7 +492,7 @@ func TestHandlerChain_MultiPriorityHandling(t *testing.T) {
|
|||||||
// Test 3: Remove middle priority handler
|
// Test 3: Remove middle priority handler
|
||||||
chain.RemoveHandler(testDomain, nbdns.PriorityMatchDomain)
|
chain.RemoveHandler(testDomain, nbdns.PriorityMatchDomain)
|
||||||
|
|
||||||
w3 := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w3 := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
// Now lowest priority handler (defaultHandler) should be called
|
// Now lowest priority handler (defaultHandler) should be called
|
||||||
defaultHandler.On("ServeDNS", mock.Anything, r).Return().Once()
|
defaultHandler.On("ServeDNS", mock.Anything, r).Return().Once()
|
||||||
|
|
||||||
@@ -519,7 +505,7 @@ func TestHandlerChain_MultiPriorityHandling(t *testing.T) {
|
|||||||
// Test 4: Remove last handler
|
// Test 4: Remove last handler
|
||||||
chain.RemoveHandler(testDomain, nbdns.PriorityDefault)
|
chain.RemoveHandler(testDomain, nbdns.PriorityDefault)
|
||||||
|
|
||||||
w4 := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w4 := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
chain.ServeDNS(w4, r) // Call ServeDNS on the now empty chain for this domain
|
chain.ServeDNS(w4, r) // Call ServeDNS on the now empty chain for this domain
|
||||||
|
|
||||||
for _, m := range mocks {
|
for _, m := range mocks {
|
||||||
@@ -675,7 +661,7 @@ func TestHandlerChain_CaseSensitivity(t *testing.T) {
|
|||||||
// Execute request
|
// Execute request
|
||||||
r := new(dns.Msg)
|
r := new(dns.Msg)
|
||||||
r.SetQuestion(tt.query, dns.TypeA)
|
r.SetQuestion(tt.query, dns.TypeA)
|
||||||
chain.ServeDNS(&mockResponseWriter{}, r)
|
chain.ServeDNS(&test.MockResponseWriter{}, r)
|
||||||
|
|
||||||
// Verify each handler was called exactly as expected
|
// Verify each handler was called exactly as expected
|
||||||
for _, h := range tt.addHandlers {
|
for _, h := range tt.addHandlers {
|
||||||
@@ -819,7 +805,7 @@ func TestHandlerChain_DomainSpecificityOrdering(t *testing.T) {
|
|||||||
|
|
||||||
r := new(dns.Msg)
|
r := new(dns.Msg)
|
||||||
r.SetQuestion(tt.query, dns.TypeA)
|
r.SetQuestion(tt.query, dns.TypeA)
|
||||||
w := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
|
|
||||||
// Setup handler expectations
|
// Setup handler expectations
|
||||||
for pattern, handler := range handlers {
|
for pattern, handler := range handlers {
|
||||||
@@ -969,7 +955,7 @@ func TestHandlerChain_AddRemoveRoundtrip(t *testing.T) {
|
|||||||
handler := &nbdns.MockHandler{}
|
handler := &nbdns.MockHandler{}
|
||||||
r := new(dns.Msg)
|
r := new(dns.Msg)
|
||||||
r.SetQuestion(tt.queryPattern, dns.TypeA)
|
r.SetQuestion(tt.queryPattern, dns.TypeA)
|
||||||
w := &nbdns.ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w := &nbdns.ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
|
|
||||||
// First verify no handler is called before adding any
|
// First verify no handler is called before adding any
|
||||||
chain.ServeDNS(w, r)
|
chain.ServeDNS(w, r)
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
type registrationMap map[string]struct{}
|
|
||||||
|
|
||||||
type localResolver struct {
|
|
||||||
registeredMap registrationMap
|
|
||||||
records sync.Map // key: string (domain_class_type), value: []dns.RR
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *localResolver) MatchSubdomains() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *localResolver) stop() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a string representation of the local resolver
|
|
||||||
func (d *localResolver) String() string {
|
|
||||||
return fmt.Sprintf("local resolver [%d records]", len(d.registeredMap))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ID returns the unique handler ID
|
|
||||||
func (d *localResolver) id() handlerID {
|
|
||||||
return "local-resolver"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServeDNS handles a DNS request
|
|
||||||
func (d *localResolver) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
if len(r.Question) > 0 {
|
|
||||||
log.Tracef("received local question: domain=%s type=%v class=%v", r.Question[0].Name, r.Question[0].Qtype, r.Question[0].Qclass)
|
|
||||||
}
|
|
||||||
|
|
||||||
replyMessage := &dns.Msg{}
|
|
||||||
replyMessage.SetReply(r)
|
|
||||||
replyMessage.RecursionAvailable = true
|
|
||||||
|
|
||||||
// lookup all records matching the question
|
|
||||||
records := d.lookupRecords(r)
|
|
||||||
if len(records) > 0 {
|
|
||||||
replyMessage.Rcode = dns.RcodeSuccess
|
|
||||||
replyMessage.Answer = append(replyMessage.Answer, records...)
|
|
||||||
} else {
|
|
||||||
replyMessage.Rcode = dns.RcodeNameError
|
|
||||||
}
|
|
||||||
|
|
||||||
err := w.WriteMsg(replyMessage)
|
|
||||||
if err != nil {
|
|
||||||
log.Debugf("got an error while writing the local resolver response, error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// lookupRecords fetches *all* DNS records matching the first question in r.
|
|
||||||
func (d *localResolver) lookupRecords(r *dns.Msg) []dns.RR {
|
|
||||||
if len(r.Question) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
question := r.Question[0]
|
|
||||||
question.Name = strings.ToLower(question.Name)
|
|
||||||
key := buildRecordKey(question.Name, question.Qclass, question.Qtype)
|
|
||||||
|
|
||||||
value, found := d.records.Load(key)
|
|
||||||
if !found {
|
|
||||||
// alternatively check if we have a cname
|
|
||||||
if question.Qtype != dns.TypeCNAME {
|
|
||||||
r.Question[0].Qtype = dns.TypeCNAME
|
|
||||||
return d.lookupRecords(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
records, ok := value.([]dns.RR)
|
|
||||||
if !ok {
|
|
||||||
log.Errorf("failed to cast records to []dns.RR, records: %v", value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there's more than one record, rotate them (round-robin)
|
|
||||||
if len(records) > 1 {
|
|
||||||
first := records[0]
|
|
||||||
records = append(records[1:], first)
|
|
||||||
d.records.Store(key, records)
|
|
||||||
}
|
|
||||||
|
|
||||||
return records
|
|
||||||
}
|
|
||||||
|
|
||||||
// registerRecord stores a new record by appending it to any existing list
|
|
||||||
func (d *localResolver) registerRecord(record nbdns.SimpleRecord) (string, error) {
|
|
||||||
rr, err := dns.NewRR(record.String())
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("register record: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rr.Header().Rdlength = record.Len()
|
|
||||||
header := rr.Header()
|
|
||||||
key := buildRecordKey(header.Name, header.Class, header.Rrtype)
|
|
||||||
|
|
||||||
// load any existing slice of records, then append
|
|
||||||
existing, _ := d.records.LoadOrStore(key, []dns.RR{})
|
|
||||||
records := existing.([]dns.RR)
|
|
||||||
records = append(records, rr)
|
|
||||||
|
|
||||||
// store updated slice
|
|
||||||
d.records.Store(key, records)
|
|
||||||
return key, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteRecord removes *all* records under the recordKey.
|
|
||||||
func (d *localResolver) deleteRecord(recordKey string) {
|
|
||||||
d.records.Delete(dns.Fqdn(recordKey))
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildRecordKey consistently generates a key: name_class_type
|
|
||||||
func buildRecordKey(name string, class, qType uint16) string {
|
|
||||||
return fmt.Sprintf("%s_%d_%d", dns.Fqdn(name), class, qType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *localResolver) probeAvailability() {}
|
|
||||||
149
client/internal/dns/local/local.go
Normal file
149
client/internal/dns/local/local.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
package local
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/types"
|
||||||
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Resolver struct {
|
||||||
|
mu sync.RWMutex
|
||||||
|
records map[dns.Question][]dns.RR
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResolver() *Resolver {
|
||||||
|
return &Resolver{
|
||||||
|
records: make(map[dns.Question][]dns.RR),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Resolver) MatchSubdomains() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the local resolver
|
||||||
|
func (d *Resolver) String() string {
|
||||||
|
return fmt.Sprintf("local resolver [%d records]", len(d.records))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Resolver) Stop() {}
|
||||||
|
|
||||||
|
// ID returns the unique handler ID
|
||||||
|
func (d *Resolver) ID() types.HandlerID {
|
||||||
|
return "local-resolver"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Resolver) ProbeAvailability() {}
|
||||||
|
|
||||||
|
// ServeDNS handles a DNS request
|
||||||
|
func (d *Resolver) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
|
if len(r.Question) == 0 {
|
||||||
|
log.Debugf("received local resolver request with no question")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
question := r.Question[0]
|
||||||
|
question.Name = strings.ToLower(dns.Fqdn(question.Name))
|
||||||
|
|
||||||
|
log.Tracef("received local question: domain=%s type=%v class=%v", r.Question[0].Name, question.Qtype, question.Qclass)
|
||||||
|
|
||||||
|
replyMessage := &dns.Msg{}
|
||||||
|
replyMessage.SetReply(r)
|
||||||
|
replyMessage.RecursionAvailable = true
|
||||||
|
|
||||||
|
// lookup all records matching the question
|
||||||
|
records := d.lookupRecords(question)
|
||||||
|
if len(records) > 0 {
|
||||||
|
replyMessage.Rcode = dns.RcodeSuccess
|
||||||
|
replyMessage.Answer = append(replyMessage.Answer, records...)
|
||||||
|
} else {
|
||||||
|
// TODO: return success if we have a different record type for the same name, relevant for search domains
|
||||||
|
replyMessage.Rcode = dns.RcodeNameError
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.WriteMsg(replyMessage); err != nil {
|
||||||
|
log.Warnf("failed to write the local resolver response: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupRecords fetches *all* DNS records matching the first question in r.
|
||||||
|
func (d *Resolver) lookupRecords(question dns.Question) []dns.RR {
|
||||||
|
d.mu.RLock()
|
||||||
|
records, found := d.records[question]
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
d.mu.RUnlock()
|
||||||
|
// alternatively check if we have a cname
|
||||||
|
if question.Qtype != dns.TypeCNAME {
|
||||||
|
question.Qtype = dns.TypeCNAME
|
||||||
|
return d.lookupRecords(question)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
recordsCopy := slices.Clone(records)
|
||||||
|
d.mu.RUnlock()
|
||||||
|
|
||||||
|
// if there's more than one record, rotate them (round-robin)
|
||||||
|
if len(recordsCopy) > 1 {
|
||||||
|
d.mu.Lock()
|
||||||
|
records = d.records[question]
|
||||||
|
if len(records) > 1 {
|
||||||
|
first := records[0]
|
||||||
|
records = append(records[1:], first)
|
||||||
|
d.records[question] = records
|
||||||
|
}
|
||||||
|
d.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return recordsCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Resolver) Update(update []nbdns.SimpleRecord) {
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
|
maps.Clear(d.records)
|
||||||
|
|
||||||
|
for _, rec := range update {
|
||||||
|
if err := d.registerRecord(rec); err != nil {
|
||||||
|
log.Warnf("failed to register the record (%s): %v", rec, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterRecord stores a new record by appending it to any existing list
|
||||||
|
func (d *Resolver) RegisterRecord(record nbdns.SimpleRecord) error {
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
|
return d.registerRecord(record)
|
||||||
|
}
|
||||||
|
|
||||||
|
// registerRecord performs the registration with the lock already held
|
||||||
|
func (d *Resolver) registerRecord(record nbdns.SimpleRecord) error {
|
||||||
|
rr, err := dns.NewRR(record.String())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("register record: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rr.Header().Rdlength = record.Len()
|
||||||
|
header := rr.Header()
|
||||||
|
q := dns.Question{
|
||||||
|
Name: strings.ToLower(dns.Fqdn(header.Name)),
|
||||||
|
Qtype: header.Rrtype,
|
||||||
|
Qclass: header.Class,
|
||||||
|
}
|
||||||
|
|
||||||
|
d.records[q] = append(d.records[q], rr)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
472
client/internal/dns/local/local_test.go
Normal file
472
client/internal/dns/local/local_test.go
Normal file
@@ -0,0 +1,472 @@
|
|||||||
|
package local
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/test"
|
||||||
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLocalResolver_ServeDNS(t *testing.T) {
|
||||||
|
recordA := nbdns.SimpleRecord{
|
||||||
|
Name: "peera.netbird.cloud.",
|
||||||
|
Type: 1,
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: 300,
|
||||||
|
RData: "1.2.3.4",
|
||||||
|
}
|
||||||
|
|
||||||
|
recordCNAME := nbdns.SimpleRecord{
|
||||||
|
Name: "peerb.netbird.cloud.",
|
||||||
|
Type: 5,
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: 300,
|
||||||
|
RData: "www.netbird.io",
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
inputRecord nbdns.SimpleRecord
|
||||||
|
inputMSG *dns.Msg
|
||||||
|
responseShouldBeNil bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Should Resolve A Record",
|
||||||
|
inputRecord: recordA,
|
||||||
|
inputMSG: new(dns.Msg).SetQuestion(recordA.Name, dns.TypeA),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should Resolve CNAME Record",
|
||||||
|
inputRecord: recordCNAME,
|
||||||
|
inputMSG: new(dns.Msg).SetQuestion(recordCNAME.Name, dns.TypeCNAME),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Should Not Write When Not Found A Record",
|
||||||
|
inputRecord: recordA,
|
||||||
|
inputMSG: new(dns.Msg).SetQuestion("not.found.com", dns.TypeA),
|
||||||
|
responseShouldBeNil: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
resolver := NewResolver()
|
||||||
|
_ = resolver.RegisterRecord(testCase.inputRecord)
|
||||||
|
var responseMSG *dns.Msg
|
||||||
|
responseWriter := &test.MockResponseWriter{
|
||||||
|
WriteMsgFunc: func(m *dns.Msg) error {
|
||||||
|
responseMSG = m
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
resolver.ServeDNS(responseWriter, testCase.inputMSG)
|
||||||
|
|
||||||
|
if responseMSG == nil || len(responseMSG.Answer) == 0 {
|
||||||
|
if testCase.responseShouldBeNil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Fatalf("should write a response message")
|
||||||
|
}
|
||||||
|
|
||||||
|
answerString := responseMSG.Answer[0].String()
|
||||||
|
if !strings.Contains(answerString, testCase.inputRecord.Name) {
|
||||||
|
t.Fatalf("answer doesn't contain the same domain name: \nWant: %s\nGot:%s", testCase.name, answerString)
|
||||||
|
}
|
||||||
|
if !strings.Contains(answerString, dns.Type(testCase.inputRecord.Type).String()) {
|
||||||
|
t.Fatalf("answer doesn't contain the correct type: \nWant: %s\nGot:%s", dns.Type(testCase.inputRecord.Type).String(), answerString)
|
||||||
|
}
|
||||||
|
if !strings.Contains(answerString, testCase.inputRecord.RData) {
|
||||||
|
t.Fatalf("answer doesn't contain the same address: \nWant: %s\nGot:%s", testCase.inputRecord.RData, answerString)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLocalResolver_Update_StaleRecord verifies that updating
|
||||||
|
// a record correctly replaces the old one, preventing stale entries.
|
||||||
|
func TestLocalResolver_Update_StaleRecord(t *testing.T) {
|
||||||
|
recordName := "host.example.com."
|
||||||
|
recordType := dns.TypeA
|
||||||
|
recordClass := dns.ClassINET
|
||||||
|
|
||||||
|
record1 := nbdns.SimpleRecord{
|
||||||
|
Name: recordName, Type: int(recordType), Class: nbdns.DefaultClass, TTL: 300, RData: "1.1.1.1",
|
||||||
|
}
|
||||||
|
record2 := nbdns.SimpleRecord{
|
||||||
|
Name: recordName, Type: int(recordType), Class: nbdns.DefaultClass, TTL: 300, RData: "2.2.2.2",
|
||||||
|
}
|
||||||
|
|
||||||
|
recordKey := dns.Question{Name: recordName, Qtype: uint16(recordClass), Qclass: recordType}
|
||||||
|
|
||||||
|
resolver := NewResolver()
|
||||||
|
|
||||||
|
update1 := []nbdns.SimpleRecord{record1}
|
||||||
|
update2 := []nbdns.SimpleRecord{record2}
|
||||||
|
|
||||||
|
// Apply first update
|
||||||
|
resolver.Update(update1)
|
||||||
|
|
||||||
|
// Verify first update
|
||||||
|
resolver.mu.RLock()
|
||||||
|
rrSlice1, found1 := resolver.records[recordKey]
|
||||||
|
resolver.mu.RUnlock()
|
||||||
|
|
||||||
|
require.True(t, found1, "Record key %s not found after first update", recordKey)
|
||||||
|
require.Len(t, rrSlice1, 1, "Should have exactly 1 record after first update")
|
||||||
|
assert.Contains(t, rrSlice1[0].String(), record1.RData, "Record after first update should be %s", record1.RData)
|
||||||
|
|
||||||
|
// Apply second update
|
||||||
|
resolver.Update(update2)
|
||||||
|
|
||||||
|
// Verify second update
|
||||||
|
resolver.mu.RLock()
|
||||||
|
rrSlice2, found2 := resolver.records[recordKey]
|
||||||
|
resolver.mu.RUnlock()
|
||||||
|
|
||||||
|
require.True(t, found2, "Record key %s not found after second update", recordKey)
|
||||||
|
require.Len(t, rrSlice2, 1, "Should have exactly 1 record after update overwriting the key")
|
||||||
|
assert.Contains(t, rrSlice2[0].String(), record2.RData, "The single record should be the updated one (%s)", record2.RData)
|
||||||
|
assert.NotContains(t, rrSlice2[0].String(), record1.RData, "The stale record (%s) should not be present", record1.RData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLocalResolver_MultipleRecords_SameQuestion verifies that multiple records
|
||||||
|
// with the same question are stored properly
|
||||||
|
func TestLocalResolver_MultipleRecords_SameQuestion(t *testing.T) {
|
||||||
|
resolver := NewResolver()
|
||||||
|
|
||||||
|
recordName := "multi.example.com."
|
||||||
|
recordType := dns.TypeA
|
||||||
|
|
||||||
|
// Create two records with the same name and type but different IPs
|
||||||
|
record1 := nbdns.SimpleRecord{
|
||||||
|
Name: recordName, Type: int(recordType), Class: nbdns.DefaultClass, TTL: 300, RData: "10.0.0.1",
|
||||||
|
}
|
||||||
|
record2 := nbdns.SimpleRecord{
|
||||||
|
Name: recordName, Type: int(recordType), Class: nbdns.DefaultClass, TTL: 300, RData: "10.0.0.2",
|
||||||
|
}
|
||||||
|
|
||||||
|
update := []nbdns.SimpleRecord{record1, record2}
|
||||||
|
|
||||||
|
// Apply update with both records
|
||||||
|
resolver.Update(update)
|
||||||
|
|
||||||
|
// Create question that matches both records
|
||||||
|
question := dns.Question{
|
||||||
|
Name: recordName,
|
||||||
|
Qtype: recordType,
|
||||||
|
Qclass: dns.ClassINET,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify both records are stored
|
||||||
|
resolver.mu.RLock()
|
||||||
|
records, found := resolver.records[question]
|
||||||
|
resolver.mu.RUnlock()
|
||||||
|
|
||||||
|
require.True(t, found, "Records for question %v not found", question)
|
||||||
|
require.Len(t, records, 2, "Should have exactly 2 records for the same question")
|
||||||
|
|
||||||
|
// Verify both record data values are present
|
||||||
|
recordStrings := []string{records[0].String(), records[1].String()}
|
||||||
|
assert.Contains(t, recordStrings[0]+recordStrings[1], record1.RData, "First record data should be present")
|
||||||
|
assert.Contains(t, recordStrings[0]+recordStrings[1], record2.RData, "Second record data should be present")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLocalResolver_RecordRotation verifies that records are rotated in a round-robin fashion
|
||||||
|
func TestLocalResolver_RecordRotation(t *testing.T) {
|
||||||
|
resolver := NewResolver()
|
||||||
|
|
||||||
|
recordName := "rotation.example.com."
|
||||||
|
recordType := dns.TypeA
|
||||||
|
|
||||||
|
// Create three records with the same name and type but different IPs
|
||||||
|
record1 := nbdns.SimpleRecord{
|
||||||
|
Name: recordName, Type: int(recordType), Class: nbdns.DefaultClass, TTL: 300, RData: "192.168.1.1",
|
||||||
|
}
|
||||||
|
record2 := nbdns.SimpleRecord{
|
||||||
|
Name: recordName, Type: int(recordType), Class: nbdns.DefaultClass, TTL: 300, RData: "192.168.1.2",
|
||||||
|
}
|
||||||
|
record3 := nbdns.SimpleRecord{
|
||||||
|
Name: recordName, Type: int(recordType), Class: nbdns.DefaultClass, TTL: 300, RData: "192.168.1.3",
|
||||||
|
}
|
||||||
|
|
||||||
|
update := []nbdns.SimpleRecord{record1, record2, record3}
|
||||||
|
|
||||||
|
// Apply update with all three records
|
||||||
|
resolver.Update(update)
|
||||||
|
|
||||||
|
msg := new(dns.Msg).SetQuestion(recordName, recordType)
|
||||||
|
|
||||||
|
// First lookup - should return the records in original order
|
||||||
|
var responses [3]*dns.Msg
|
||||||
|
|
||||||
|
// Perform three lookups to verify rotation
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
responseWriter := &test.MockResponseWriter{
|
||||||
|
WriteMsgFunc: func(m *dns.Msg) error {
|
||||||
|
responses[i] = m
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
resolver.ServeDNS(responseWriter, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify all three responses contain answers
|
||||||
|
for i, resp := range responses {
|
||||||
|
require.NotNil(t, resp, "Response %d should not be nil", i)
|
||||||
|
require.Len(t, resp.Answer, 3, "Response %d should have 3 answers", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the first record in each response is different due to rotation
|
||||||
|
firstRecordIPs := []string{
|
||||||
|
responses[0].Answer[0].String(),
|
||||||
|
responses[1].Answer[0].String(),
|
||||||
|
responses[2].Answer[0].String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each record should be different (rotated)
|
||||||
|
assert.NotEqual(t, firstRecordIPs[0], firstRecordIPs[1], "First lookup should differ from second lookup due to rotation")
|
||||||
|
assert.NotEqual(t, firstRecordIPs[1], firstRecordIPs[2], "Second lookup should differ from third lookup due to rotation")
|
||||||
|
assert.NotEqual(t, firstRecordIPs[0], firstRecordIPs[2], "First lookup should differ from third lookup due to rotation")
|
||||||
|
|
||||||
|
// After three rotations, we should have cycled through all records
|
||||||
|
assert.Contains(t, firstRecordIPs[0]+firstRecordIPs[1]+firstRecordIPs[2], record1.RData)
|
||||||
|
assert.Contains(t, firstRecordIPs[0]+firstRecordIPs[1]+firstRecordIPs[2], record2.RData)
|
||||||
|
assert.Contains(t, firstRecordIPs[0]+firstRecordIPs[1]+firstRecordIPs[2], record3.RData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLocalResolver_CaseInsensitiveMatching verifies that DNS record lookups are case-insensitive
|
||||||
|
func TestLocalResolver_CaseInsensitiveMatching(t *testing.T) {
|
||||||
|
resolver := NewResolver()
|
||||||
|
|
||||||
|
// Create record with lowercase name
|
||||||
|
lowerCaseRecord := nbdns.SimpleRecord{
|
||||||
|
Name: "lower.example.com.",
|
||||||
|
Type: int(dns.TypeA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: 300,
|
||||||
|
RData: "10.10.10.10",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create record with mixed case name
|
||||||
|
mixedCaseRecord := nbdns.SimpleRecord{
|
||||||
|
Name: "MiXeD.ExAmPlE.CoM.",
|
||||||
|
Type: int(dns.TypeA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: 300,
|
||||||
|
RData: "20.20.20.20",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update resolver with the records
|
||||||
|
resolver.Update([]nbdns.SimpleRecord{lowerCaseRecord, mixedCaseRecord})
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
queryName string
|
||||||
|
expectedRData string
|
||||||
|
shouldResolve bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Query lowercase with lowercase record",
|
||||||
|
queryName: "lower.example.com.",
|
||||||
|
expectedRData: "10.10.10.10",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query uppercase with lowercase record",
|
||||||
|
queryName: "LOWER.EXAMPLE.COM.",
|
||||||
|
expectedRData: "10.10.10.10",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query mixed case with lowercase record",
|
||||||
|
queryName: "LoWeR.eXaMpLe.CoM.",
|
||||||
|
expectedRData: "10.10.10.10",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query lowercase with mixed case record",
|
||||||
|
queryName: "mixed.example.com.",
|
||||||
|
expectedRData: "20.20.20.20",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query uppercase with mixed case record",
|
||||||
|
queryName: "MIXED.EXAMPLE.COM.",
|
||||||
|
expectedRData: "20.20.20.20",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query with different casing pattern",
|
||||||
|
queryName: "mIxEd.ExaMpLe.cOm.",
|
||||||
|
expectedRData: "20.20.20.20",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query non-existent domain",
|
||||||
|
queryName: "nonexistent.example.com.",
|
||||||
|
shouldResolve: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
var responseMSG *dns.Msg
|
||||||
|
|
||||||
|
// Create DNS query with the test case name
|
||||||
|
msg := new(dns.Msg).SetQuestion(tc.queryName, dns.TypeA)
|
||||||
|
|
||||||
|
// Create mock response writer to capture the response
|
||||||
|
responseWriter := &test.MockResponseWriter{
|
||||||
|
WriteMsgFunc: func(m *dns.Msg) error {
|
||||||
|
responseMSG = m
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform DNS query
|
||||||
|
resolver.ServeDNS(responseWriter, msg)
|
||||||
|
|
||||||
|
// Check if we expect a successful resolution
|
||||||
|
if !tc.shouldResolve {
|
||||||
|
if responseMSG == nil || len(responseMSG.Answer) == 0 {
|
||||||
|
// Expected no answer, test passes
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Fatalf("Expected no resolution for %s, but got answer: %v", tc.queryName, responseMSG.Answer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify we got a response
|
||||||
|
require.NotNil(t, responseMSG, "Should have received a response message")
|
||||||
|
require.Greater(t, len(responseMSG.Answer), 0, "Response should contain at least one answer")
|
||||||
|
|
||||||
|
// Verify the response contains the expected data
|
||||||
|
answerString := responseMSG.Answer[0].String()
|
||||||
|
assert.Contains(t, answerString, tc.expectedRData,
|
||||||
|
"Answer should contain the expected IP address %s, got: %s",
|
||||||
|
tc.expectedRData, answerString)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestLocalResolver_CNAMEFallback verifies that the resolver correctly falls back
|
||||||
|
// to checking for CNAME records when the requested record type isn't found
|
||||||
|
func TestLocalResolver_CNAMEFallback(t *testing.T) {
|
||||||
|
resolver := NewResolver()
|
||||||
|
|
||||||
|
// Create a CNAME record (but no A record for this name)
|
||||||
|
cnameRecord := nbdns.SimpleRecord{
|
||||||
|
Name: "alias.example.com.",
|
||||||
|
Type: int(dns.TypeCNAME),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: 300,
|
||||||
|
RData: "target.example.com.",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an A record for the CNAME target
|
||||||
|
targetRecord := nbdns.SimpleRecord{
|
||||||
|
Name: "target.example.com.",
|
||||||
|
Type: int(dns.TypeA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: 300,
|
||||||
|
RData: "192.168.100.100",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update resolver with both records
|
||||||
|
resolver.Update([]nbdns.SimpleRecord{cnameRecord, targetRecord})
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
queryName string
|
||||||
|
queryType uint16
|
||||||
|
expectedType string
|
||||||
|
expectedRData string
|
||||||
|
shouldResolve bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Directly query CNAME record",
|
||||||
|
queryName: "alias.example.com.",
|
||||||
|
queryType: dns.TypeCNAME,
|
||||||
|
expectedType: "CNAME",
|
||||||
|
expectedRData: "target.example.com.",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query A record but get CNAME fallback",
|
||||||
|
queryName: "alias.example.com.",
|
||||||
|
queryType: dns.TypeA,
|
||||||
|
expectedType: "CNAME",
|
||||||
|
expectedRData: "target.example.com.",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query AAAA record but get CNAME fallback",
|
||||||
|
queryName: "alias.example.com.",
|
||||||
|
queryType: dns.TypeAAAA,
|
||||||
|
expectedType: "CNAME",
|
||||||
|
expectedRData: "target.example.com.",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query direct A record",
|
||||||
|
queryName: "target.example.com.",
|
||||||
|
queryType: dns.TypeA,
|
||||||
|
expectedType: "A",
|
||||||
|
expectedRData: "192.168.100.100",
|
||||||
|
shouldResolve: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Query non-existent name",
|
||||||
|
queryName: "nonexistent.example.com.",
|
||||||
|
queryType: dns.TypeA,
|
||||||
|
shouldResolve: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
var responseMSG *dns.Msg
|
||||||
|
|
||||||
|
// Create DNS query with the test case parameters
|
||||||
|
msg := new(dns.Msg).SetQuestion(tc.queryName, tc.queryType)
|
||||||
|
|
||||||
|
// Create mock response writer to capture the response
|
||||||
|
responseWriter := &test.MockResponseWriter{
|
||||||
|
WriteMsgFunc: func(m *dns.Msg) error {
|
||||||
|
responseMSG = m
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform DNS query
|
||||||
|
resolver.ServeDNS(responseWriter, msg)
|
||||||
|
|
||||||
|
// Check if we expect a successful resolution
|
||||||
|
if !tc.shouldResolve {
|
||||||
|
if responseMSG == nil || len(responseMSG.Answer) == 0 || responseMSG.Rcode != dns.RcodeSuccess {
|
||||||
|
// Expected no resolution, test passes
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Fatalf("Expected no resolution for %s, but got answer: %v", tc.queryName, responseMSG.Answer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify we got a successful response
|
||||||
|
require.NotNil(t, responseMSG, "Should have received a response message")
|
||||||
|
require.Equal(t, dns.RcodeSuccess, responseMSG.Rcode, "Response should have success status code")
|
||||||
|
require.Greater(t, len(responseMSG.Answer), 0, "Response should contain at least one answer")
|
||||||
|
|
||||||
|
// Verify the response contains the expected data
|
||||||
|
answerString := responseMSG.Answer[0].String()
|
||||||
|
assert.Contains(t, answerString, tc.expectedType,
|
||||||
|
"Answer should be of type %s, got: %s", tc.expectedType, answerString)
|
||||||
|
assert.Contains(t, answerString, tc.expectedRData,
|
||||||
|
"Answer should contain the expected data %s, got: %s", tc.expectedRData, answerString)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLocalResolver_ServeDNS(t *testing.T) {
|
|
||||||
recordA := nbdns.SimpleRecord{
|
|
||||||
Name: "peera.netbird.cloud.",
|
|
||||||
Type: 1,
|
|
||||||
Class: nbdns.DefaultClass,
|
|
||||||
TTL: 300,
|
|
||||||
RData: "1.2.3.4",
|
|
||||||
}
|
|
||||||
|
|
||||||
recordCNAME := nbdns.SimpleRecord{
|
|
||||||
Name: "peerb.netbird.cloud.",
|
|
||||||
Type: 5,
|
|
||||||
Class: nbdns.DefaultClass,
|
|
||||||
TTL: 300,
|
|
||||||
RData: "www.netbird.io",
|
|
||||||
}
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
inputRecord nbdns.SimpleRecord
|
|
||||||
inputMSG *dns.Msg
|
|
||||||
responseShouldBeNil bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Should Resolve A Record",
|
|
||||||
inputRecord: recordA,
|
|
||||||
inputMSG: new(dns.Msg).SetQuestion(recordA.Name, dns.TypeA),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Should Resolve CNAME Record",
|
|
||||||
inputRecord: recordCNAME,
|
|
||||||
inputMSG: new(dns.Msg).SetQuestion(recordCNAME.Name, dns.TypeCNAME),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Should Not Write When Not Found A Record",
|
|
||||||
inputRecord: recordA,
|
|
||||||
inputMSG: new(dns.Msg).SetQuestion("not.found.com", dns.TypeA),
|
|
||||||
responseShouldBeNil: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
|
||||||
resolver := &localResolver{
|
|
||||||
registeredMap: make(registrationMap),
|
|
||||||
}
|
|
||||||
_, _ = resolver.registerRecord(testCase.inputRecord)
|
|
||||||
var responseMSG *dns.Msg
|
|
||||||
responseWriter := &mockResponseWriter{
|
|
||||||
WriteMsgFunc: func(m *dns.Msg) error {
|
|
||||||
responseMSG = m
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
resolver.ServeDNS(responseWriter, testCase.inputMSG)
|
|
||||||
|
|
||||||
if responseMSG == nil || len(responseMSG.Answer) == 0 {
|
|
||||||
if testCase.responseShouldBeNil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t.Fatalf("should write a response message")
|
|
||||||
}
|
|
||||||
|
|
||||||
answerString := responseMSG.Answer[0].String()
|
|
||||||
if !strings.Contains(answerString, testCase.inputRecord.Name) {
|
|
||||||
t.Fatalf("answer doesn't contain the same domain name: \nWant: %s\nGot:%s", testCase.name, answerString)
|
|
||||||
}
|
|
||||||
if !strings.Contains(answerString, dns.Type(testCase.inputRecord.Type).String()) {
|
|
||||||
t.Fatalf("answer doesn't contain the correct type: \nWant: %s\nGot:%s", dns.Type(testCase.inputRecord.Type).String(), answerString)
|
|
||||||
}
|
|
||||||
if !strings.Contains(answerString, testCase.inputRecord.RData) {
|
|
||||||
t.Fatalf("answer doesn't contain the same address: \nWant: %s\nGot:%s", testCase.inputRecord.RData, answerString)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mockResponseWriter struct {
|
|
||||||
WriteMsgFunc func(m *dns.Msg) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rw *mockResponseWriter) WriteMsg(m *dns.Msg) error {
|
|
||||||
if rw.WriteMsgFunc != nil {
|
|
||||||
return rw.WriteMsgFunc(m)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rw *mockResponseWriter) LocalAddr() net.Addr { return nil }
|
|
||||||
func (rw *mockResponseWriter) RemoteAddr() net.Addr { return nil }
|
|
||||||
func (rw *mockResponseWriter) Write([]byte) (int, error) { return 0, nil }
|
|
||||||
func (rw *mockResponseWriter) Close() error { return nil }
|
|
||||||
func (rw *mockResponseWriter) TsigStatus() error { return nil }
|
|
||||||
func (rw *mockResponseWriter) TsigTimersOnly(bool) {}
|
|
||||||
func (rw *mockResponseWriter) Hijack() {}
|
|
||||||
@@ -15,6 +15,8 @@ import (
|
|||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/netstack"
|
"github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/local"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/types"
|
||||||
"github.com/netbirdio/netbird/client/internal/listener"
|
"github.com/netbirdio/netbird/client/internal/listener"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||||
@@ -46,8 +48,6 @@ type Server interface {
|
|||||||
ProbeAvailability()
|
ProbeAvailability()
|
||||||
}
|
}
|
||||||
|
|
||||||
type handlerID string
|
|
||||||
|
|
||||||
type nsGroupsByDomain struct {
|
type nsGroupsByDomain struct {
|
||||||
domain string
|
domain string
|
||||||
groups []*nbdns.NameServerGroup
|
groups []*nbdns.NameServerGroup
|
||||||
@@ -61,7 +61,7 @@ type DefaultServer struct {
|
|||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
service service
|
service service
|
||||||
dnsMuxMap registeredHandlerMap
|
dnsMuxMap registeredHandlerMap
|
||||||
localResolver *localResolver
|
localResolver *local.Resolver
|
||||||
wgInterface WGIface
|
wgInterface WGIface
|
||||||
hostManager hostManager
|
hostManager hostManager
|
||||||
updateSerial uint64
|
updateSerial uint64
|
||||||
@@ -84,9 +84,9 @@ type DefaultServer struct {
|
|||||||
|
|
||||||
type handlerWithStop interface {
|
type handlerWithStop interface {
|
||||||
dns.Handler
|
dns.Handler
|
||||||
stop()
|
Stop()
|
||||||
probeAvailability()
|
ProbeAvailability()
|
||||||
id() handlerID
|
ID() types.HandlerID
|
||||||
}
|
}
|
||||||
|
|
||||||
type handlerWrapper struct {
|
type handlerWrapper struct {
|
||||||
@@ -95,7 +95,7 @@ type handlerWrapper struct {
|
|||||||
priority int
|
priority int
|
||||||
}
|
}
|
||||||
|
|
||||||
type registeredHandlerMap map[handlerID]handlerWrapper
|
type registeredHandlerMap map[types.HandlerID]handlerWrapper
|
||||||
|
|
||||||
// NewDefaultServer returns a new dns server
|
// NewDefaultServer returns a new dns server
|
||||||
func NewDefaultServer(
|
func NewDefaultServer(
|
||||||
@@ -171,16 +171,14 @@ func newDefaultServer(
|
|||||||
handlerChain := NewHandlerChain()
|
handlerChain := NewHandlerChain()
|
||||||
ctx, stop := context.WithCancel(ctx)
|
ctx, stop := context.WithCancel(ctx)
|
||||||
defaultServer := &DefaultServer{
|
defaultServer := &DefaultServer{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
ctxCancel: stop,
|
ctxCancel: stop,
|
||||||
disableSys: disableSys,
|
disableSys: disableSys,
|
||||||
service: dnsService,
|
service: dnsService,
|
||||||
handlerChain: handlerChain,
|
handlerChain: handlerChain,
|
||||||
extraDomains: make(map[domain.Domain]int),
|
extraDomains: make(map[domain.Domain]int),
|
||||||
dnsMuxMap: make(registeredHandlerMap),
|
dnsMuxMap: make(registeredHandlerMap),
|
||||||
localResolver: &localResolver{
|
localResolver: local.NewResolver(),
|
||||||
registeredMap: make(registrationMap),
|
|
||||||
},
|
|
||||||
wgInterface: wgInterface,
|
wgInterface: wgInterface,
|
||||||
statusRecorder: statusRecorder,
|
statusRecorder: statusRecorder,
|
||||||
stateManager: stateManager,
|
stateManager: stateManager,
|
||||||
@@ -403,7 +401,7 @@ func (s *DefaultServer) ProbeAvailability() {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(mux handlerWithStop) {
|
go func(mux handlerWithStop) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
mux.probeAvailability()
|
mux.ProbeAvailability()
|
||||||
}(mux.handler)
|
}(mux.handler)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@@ -420,7 +418,7 @@ func (s *DefaultServer) applyConfiguration(update nbdns.Config) error {
|
|||||||
s.service.Stop()
|
s.service.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
localMuxUpdates, localRecordsByDomain, err := s.buildLocalHandlerUpdate(update.CustomZones)
|
localMuxUpdates, localRecords, err := s.buildLocalHandlerUpdate(update.CustomZones)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("local handler updater: %w", err)
|
return fmt.Errorf("local handler updater: %w", err)
|
||||||
}
|
}
|
||||||
@@ -434,7 +432,7 @@ func (s *DefaultServer) applyConfiguration(update nbdns.Config) error {
|
|||||||
s.updateMux(muxUpdates)
|
s.updateMux(muxUpdates)
|
||||||
|
|
||||||
// register local records
|
// register local records
|
||||||
s.updateLocalResolver(localRecordsByDomain)
|
s.localResolver.Update(localRecords)
|
||||||
|
|
||||||
s.currentConfig = dnsConfigToHostDNSConfig(update, s.service.RuntimeIP(), s.service.RuntimePort())
|
s.currentConfig = dnsConfigToHostDNSConfig(update, s.service.RuntimeIP(), s.service.RuntimePort())
|
||||||
|
|
||||||
@@ -516,11 +514,9 @@ func (s *DefaultServer) handleErrNoGroupaAll(err error) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DefaultServer) buildLocalHandlerUpdate(
|
func (s *DefaultServer) buildLocalHandlerUpdate(customZones []nbdns.CustomZone) ([]handlerWrapper, []nbdns.SimpleRecord, error) {
|
||||||
customZones []nbdns.CustomZone,
|
|
||||||
) ([]handlerWrapper, map[string][]nbdns.SimpleRecord, error) {
|
|
||||||
var muxUpdates []handlerWrapper
|
var muxUpdates []handlerWrapper
|
||||||
localRecords := make(map[string][]nbdns.SimpleRecord)
|
var localRecords []nbdns.SimpleRecord
|
||||||
|
|
||||||
for _, customZone := range customZones {
|
for _, customZone := range customZones {
|
||||||
if len(customZone.Records) == 0 {
|
if len(customZone.Records) == 0 {
|
||||||
@@ -534,17 +530,13 @@ func (s *DefaultServer) buildLocalHandlerUpdate(
|
|||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
})
|
})
|
||||||
|
|
||||||
// group all records under this domain
|
|
||||||
for _, record := range customZone.Records {
|
for _, record := range customZone.Records {
|
||||||
var class uint16 = dns.ClassINET
|
|
||||||
if record.Class != nbdns.DefaultClass {
|
if record.Class != nbdns.DefaultClass {
|
||||||
log.Warnf("received an invalid class type: %s", record.Class)
|
log.Warnf("received an invalid class type: %s", record.Class)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// zone records contain the fqdn, so we can just flatten them
|
||||||
key := buildRecordKey(record.Name, class, uint16(record.Type))
|
localRecords = append(localRecords, record)
|
||||||
|
|
||||||
localRecords[key] = append(localRecords[key], record)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,7 +619,7 @@ func (s *DefaultServer) createHandlersForDomainGroup(domainGroup nsGroupsByDomai
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(handler.upstreamServers) == 0 {
|
if len(handler.upstreamServers) == 0 {
|
||||||
handler.stop()
|
handler.Stop()
|
||||||
log.Errorf("received a nameserver group with an invalid nameserver list")
|
log.Errorf("received a nameserver group with an invalid nameserver list")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -656,7 +648,7 @@ func (s *DefaultServer) updateMux(muxUpdates []handlerWrapper) {
|
|||||||
// this will introduce a short period of time when the server is not able to handle DNS requests
|
// this will introduce a short period of time when the server is not able to handle DNS requests
|
||||||
for _, existing := range s.dnsMuxMap {
|
for _, existing := range s.dnsMuxMap {
|
||||||
s.deregisterHandler([]string{existing.domain}, existing.priority)
|
s.deregisterHandler([]string{existing.domain}, existing.priority)
|
||||||
existing.handler.stop()
|
existing.handler.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
muxUpdateMap := make(registeredHandlerMap)
|
muxUpdateMap := make(registeredHandlerMap)
|
||||||
@@ -667,7 +659,7 @@ func (s *DefaultServer) updateMux(muxUpdates []handlerWrapper) {
|
|||||||
containsRootUpdate = true
|
containsRootUpdate = true
|
||||||
}
|
}
|
||||||
s.registerHandler([]string{update.domain}, update.handler, update.priority)
|
s.registerHandler([]string{update.domain}, update.handler, update.priority)
|
||||||
muxUpdateMap[update.handler.id()] = update
|
muxUpdateMap[update.handler.ID()] = update
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no root update and we had a root handler, restore it
|
// If there's no root update and we had a root handler, restore it
|
||||||
@@ -683,33 +675,6 @@ func (s *DefaultServer) updateMux(muxUpdates []handlerWrapper) {
|
|||||||
s.dnsMuxMap = muxUpdateMap
|
s.dnsMuxMap = muxUpdateMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DefaultServer) updateLocalResolver(update map[string][]nbdns.SimpleRecord) {
|
|
||||||
// remove old records that are no longer present
|
|
||||||
for key := range s.localResolver.registeredMap {
|
|
||||||
_, found := update[key]
|
|
||||||
if !found {
|
|
||||||
s.localResolver.deleteRecord(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedMap := make(registrationMap)
|
|
||||||
for _, recs := range update {
|
|
||||||
for _, rec := range recs {
|
|
||||||
// convert the record to a dns.RR and register
|
|
||||||
key, err := s.localResolver.registerRecord(rec)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("got an error while registering the record (%s), error: %v",
|
|
||||||
rec.String(), err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedMap[key] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.localResolver.registeredMap = updatedMap
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNSHostPort(ns nbdns.NameServer) string {
|
func getNSHostPort(ns nbdns.NameServer) string {
|
||||||
return fmt.Sprintf("%s:%d", ns.IP.String(), ns.Port)
|
return fmt.Sprintf("%s:%d", ns.IP.String(), ns.Port)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
pfmock "github.com/netbirdio/netbird/client/iface/mocks"
|
pfmock "github.com/netbirdio/netbird/client/iface/mocks"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/local"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/test"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/types"
|
||||||
"github.com/netbirdio/netbird/client/internal/netflow"
|
"github.com/netbirdio/netbird/client/internal/netflow"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||||
@@ -107,6 +110,7 @@ func generateDummyHandler(domain string, servers []nbdns.NameServer) *upstreamRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateDNSServer(t *testing.T) {
|
func TestUpdateDNSServer(t *testing.T) {
|
||||||
|
|
||||||
nameServers := []nbdns.NameServer{
|
nameServers := []nbdns.NameServer{
|
||||||
{
|
{
|
||||||
IP: netip.MustParseAddr("8.8.8.8"),
|
IP: netip.MustParseAddr("8.8.8.8"),
|
||||||
@@ -120,22 +124,21 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
dummyHandler := &localResolver{}
|
dummyHandler := local.NewResolver()
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
initUpstreamMap registeredHandlerMap
|
initUpstreamMap registeredHandlerMap
|
||||||
initLocalMap registrationMap
|
initLocalRecords []nbdns.SimpleRecord
|
||||||
initSerial uint64
|
initSerial uint64
|
||||||
inputSerial uint64
|
inputSerial uint64
|
||||||
inputUpdate nbdns.Config
|
inputUpdate nbdns.Config
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
expectedUpstreamMap registeredHandlerMap
|
expectedUpstreamMap registeredHandlerMap
|
||||||
expectedLocalMap registrationMap
|
expectedLocalQs []dns.Question
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Initial Config Should Succeed",
|
name: "Initial Config Should Succeed",
|
||||||
initLocalMap: make(registrationMap),
|
|
||||||
initUpstreamMap: make(registeredHandlerMap),
|
initUpstreamMap: make(registeredHandlerMap),
|
||||||
initSerial: 0,
|
initSerial: 0,
|
||||||
inputSerial: 1,
|
inputSerial: 1,
|
||||||
@@ -159,30 +162,30 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedUpstreamMap: registeredHandlerMap{
|
expectedUpstreamMap: registeredHandlerMap{
|
||||||
generateDummyHandler("netbird.io", nameServers).id(): handlerWrapper{
|
generateDummyHandler("netbird.io", nameServers).ID(): handlerWrapper{
|
||||||
domain: "netbird.io",
|
domain: "netbird.io",
|
||||||
handler: dummyHandler,
|
handler: dummyHandler,
|
||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
},
|
},
|
||||||
dummyHandler.id(): handlerWrapper{
|
dummyHandler.ID(): handlerWrapper{
|
||||||
domain: "netbird.cloud",
|
domain: "netbird.cloud",
|
||||||
handler: dummyHandler,
|
handler: dummyHandler,
|
||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
},
|
},
|
||||||
generateDummyHandler(".", nameServers).id(): handlerWrapper{
|
generateDummyHandler(".", nameServers).ID(): handlerWrapper{
|
||||||
domain: nbdns.RootZone,
|
domain: nbdns.RootZone,
|
||||||
handler: dummyHandler,
|
handler: dummyHandler,
|
||||||
priority: PriorityDefault,
|
priority: PriorityDefault,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedLocalMap: registrationMap{buildRecordKey(zoneRecords[0].Name, 1, 1): struct{}{}},
|
expectedLocalQs: []dns.Question{{Name: "peera.netbird.cloud.", Qtype: dns.TypeA, Qclass: dns.ClassINET}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "New Config Should Succeed",
|
name: "New Config Should Succeed",
|
||||||
initLocalMap: registrationMap{"netbird.cloud": struct{}{}},
|
initLocalRecords: []nbdns.SimpleRecord{{Name: "netbird.cloud", Type: 1, Class: nbdns.DefaultClass, TTL: 300, RData: "10.0.0.1"}},
|
||||||
initUpstreamMap: registeredHandlerMap{
|
initUpstreamMap: registeredHandlerMap{
|
||||||
generateDummyHandler(zoneRecords[0].Name, nameServers).id(): handlerWrapper{
|
generateDummyHandler(zoneRecords[0].Name, nameServers).ID(): handlerWrapper{
|
||||||
domain: buildRecordKey(zoneRecords[0].Name, 1, 1),
|
domain: "netbird.cloud",
|
||||||
handler: dummyHandler,
|
handler: dummyHandler,
|
||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
},
|
},
|
||||||
@@ -205,7 +208,7 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedUpstreamMap: registeredHandlerMap{
|
expectedUpstreamMap: registeredHandlerMap{
|
||||||
generateDummyHandler("netbird.io", nameServers).id(): handlerWrapper{
|
generateDummyHandler("netbird.io", nameServers).ID(): handlerWrapper{
|
||||||
domain: "netbird.io",
|
domain: "netbird.io",
|
||||||
handler: dummyHandler,
|
handler: dummyHandler,
|
||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
@@ -216,22 +219,22 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedLocalMap: registrationMap{buildRecordKey(zoneRecords[0].Name, 1, 1): struct{}{}},
|
expectedLocalQs: []dns.Question{{Name: zoneRecords[0].Name, Qtype: 1, Qclass: 1}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Smaller Config Serial Should Be Skipped",
|
name: "Smaller Config Serial Should Be Skipped",
|
||||||
initLocalMap: make(registrationMap),
|
initLocalRecords: []nbdns.SimpleRecord{},
|
||||||
initUpstreamMap: make(registeredHandlerMap),
|
initUpstreamMap: make(registeredHandlerMap),
|
||||||
initSerial: 2,
|
initSerial: 2,
|
||||||
inputSerial: 1,
|
inputSerial: 1,
|
||||||
shouldFail: true,
|
shouldFail: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Empty NS Group Domain Or Not Primary Element Should Fail",
|
name: "Empty NS Group Domain Or Not Primary Element Should Fail",
|
||||||
initLocalMap: make(registrationMap),
|
initLocalRecords: []nbdns.SimpleRecord{},
|
||||||
initUpstreamMap: make(registeredHandlerMap),
|
initUpstreamMap: make(registeredHandlerMap),
|
||||||
initSerial: 0,
|
initSerial: 0,
|
||||||
inputSerial: 1,
|
inputSerial: 1,
|
||||||
inputUpdate: nbdns.Config{
|
inputUpdate: nbdns.Config{
|
||||||
ServiceEnable: true,
|
ServiceEnable: true,
|
||||||
CustomZones: []nbdns.CustomZone{
|
CustomZones: []nbdns.CustomZone{
|
||||||
@@ -249,11 +252,11 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
shouldFail: true,
|
shouldFail: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid NS Group Nameservers list Should Fail",
|
name: "Invalid NS Group Nameservers list Should Fail",
|
||||||
initLocalMap: make(registrationMap),
|
initLocalRecords: []nbdns.SimpleRecord{},
|
||||||
initUpstreamMap: make(registeredHandlerMap),
|
initUpstreamMap: make(registeredHandlerMap),
|
||||||
initSerial: 0,
|
initSerial: 0,
|
||||||
inputSerial: 1,
|
inputSerial: 1,
|
||||||
inputUpdate: nbdns.Config{
|
inputUpdate: nbdns.Config{
|
||||||
ServiceEnable: true,
|
ServiceEnable: true,
|
||||||
CustomZones: []nbdns.CustomZone{
|
CustomZones: []nbdns.CustomZone{
|
||||||
@@ -271,11 +274,11 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
shouldFail: true,
|
shouldFail: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid Custom Zone Records list Should Skip",
|
name: "Invalid Custom Zone Records list Should Skip",
|
||||||
initLocalMap: make(registrationMap),
|
initLocalRecords: []nbdns.SimpleRecord{},
|
||||||
initUpstreamMap: make(registeredHandlerMap),
|
initUpstreamMap: make(registeredHandlerMap),
|
||||||
initSerial: 0,
|
initSerial: 0,
|
||||||
inputSerial: 1,
|
inputSerial: 1,
|
||||||
inputUpdate: nbdns.Config{
|
inputUpdate: nbdns.Config{
|
||||||
ServiceEnable: true,
|
ServiceEnable: true,
|
||||||
CustomZones: []nbdns.CustomZone{
|
CustomZones: []nbdns.CustomZone{
|
||||||
@@ -290,17 +293,17 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedUpstreamMap: registeredHandlerMap{generateDummyHandler(".", nameServers).id(): handlerWrapper{
|
expectedUpstreamMap: registeredHandlerMap{generateDummyHandler(".", nameServers).ID(): handlerWrapper{
|
||||||
domain: ".",
|
domain: ".",
|
||||||
handler: dummyHandler,
|
handler: dummyHandler,
|
||||||
priority: PriorityDefault,
|
priority: PriorityDefault,
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Empty Config Should Succeed and Clean Maps",
|
name: "Empty Config Should Succeed and Clean Maps",
|
||||||
initLocalMap: registrationMap{"netbird.cloud": struct{}{}},
|
initLocalRecords: []nbdns.SimpleRecord{{Name: "netbird.cloud", Type: int(dns.TypeA), Class: nbdns.DefaultClass, TTL: 300, RData: "10.0.0.1"}},
|
||||||
initUpstreamMap: registeredHandlerMap{
|
initUpstreamMap: registeredHandlerMap{
|
||||||
generateDummyHandler(zoneRecords[0].Name, nameServers).id(): handlerWrapper{
|
generateDummyHandler(zoneRecords[0].Name, nameServers).ID(): handlerWrapper{
|
||||||
domain: zoneRecords[0].Name,
|
domain: zoneRecords[0].Name,
|
||||||
handler: dummyHandler,
|
handler: dummyHandler,
|
||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
@@ -310,13 +313,13 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
inputSerial: 1,
|
inputSerial: 1,
|
||||||
inputUpdate: nbdns.Config{ServiceEnable: true},
|
inputUpdate: nbdns.Config{ServiceEnable: true},
|
||||||
expectedUpstreamMap: make(registeredHandlerMap),
|
expectedUpstreamMap: make(registeredHandlerMap),
|
||||||
expectedLocalMap: make(registrationMap),
|
expectedLocalQs: []dns.Question{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Disabled Service Should clean map",
|
name: "Disabled Service Should clean map",
|
||||||
initLocalMap: registrationMap{"netbird.cloud": struct{}{}},
|
initLocalRecords: []nbdns.SimpleRecord{{Name: "netbird.cloud", Type: int(dns.TypeA), Class: nbdns.DefaultClass, TTL: 300, RData: "10.0.0.1"}},
|
||||||
initUpstreamMap: registeredHandlerMap{
|
initUpstreamMap: registeredHandlerMap{
|
||||||
generateDummyHandler(zoneRecords[0].Name, nameServers).id(): handlerWrapper{
|
generateDummyHandler(zoneRecords[0].Name, nameServers).ID(): handlerWrapper{
|
||||||
domain: zoneRecords[0].Name,
|
domain: zoneRecords[0].Name,
|
||||||
handler: dummyHandler,
|
handler: dummyHandler,
|
||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
@@ -326,7 +329,7 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
inputSerial: 1,
|
inputSerial: 1,
|
||||||
inputUpdate: nbdns.Config{ServiceEnable: false},
|
inputUpdate: nbdns.Config{ServiceEnable: false},
|
||||||
expectedUpstreamMap: make(registeredHandlerMap),
|
expectedUpstreamMap: make(registeredHandlerMap),
|
||||||
expectedLocalMap: make(registrationMap),
|
expectedLocalQs: []dns.Question{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +380,7 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
dnsServer.dnsMuxMap = testCase.initUpstreamMap
|
dnsServer.dnsMuxMap = testCase.initUpstreamMap
|
||||||
dnsServer.localResolver.registeredMap = testCase.initLocalMap
|
dnsServer.localResolver.Update(testCase.initLocalRecords)
|
||||||
dnsServer.updateSerial = testCase.initSerial
|
dnsServer.updateSerial = testCase.initSerial
|
||||||
|
|
||||||
err = dnsServer.UpdateDNSServer(testCase.inputSerial, testCase.inputUpdate)
|
err = dnsServer.UpdateDNSServer(testCase.inputSerial, testCase.inputUpdate)
|
||||||
@@ -399,15 +402,23 @@ func TestUpdateDNSServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dnsServer.localResolver.registeredMap) != len(testCase.expectedLocalMap) {
|
var responseMSG *dns.Msg
|
||||||
t.Fatalf("update local failed, registered map size is different than expected, want %d, got %d", len(testCase.expectedLocalMap), len(dnsServer.localResolver.registeredMap))
|
responseWriter := &test.MockResponseWriter{
|
||||||
|
WriteMsgFunc: func(m *dns.Msg) error {
|
||||||
|
responseMSG = m
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, q := range testCase.expectedLocalQs {
|
||||||
|
dnsServer.localResolver.ServeDNS(responseWriter, &dns.Msg{
|
||||||
|
Question: []dns.Question{q},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for key := range testCase.expectedLocalMap {
|
if len(testCase.expectedLocalQs) > 0 {
|
||||||
_, found := dnsServer.localResolver.registeredMap[key]
|
assert.NotNil(t, responseMSG, "response message should not be nil")
|
||||||
if !found {
|
assert.Equal(t, dns.RcodeSuccess, responseMSG.Rcode, "response code should be success")
|
||||||
t.Fatalf("update local failed, key %s was not found in the localResolver.registeredMap: %#v", key, dnsServer.localResolver.registeredMap)
|
assert.NotEmpty(t, responseMSG.Answer, "response message should have answers")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -491,11 +502,12 @@ func TestDNSFakeResolverHandleUpdates(t *testing.T) {
|
|||||||
dnsServer.dnsMuxMap = registeredHandlerMap{
|
dnsServer.dnsMuxMap = registeredHandlerMap{
|
||||||
"id1": handlerWrapper{
|
"id1": handlerWrapper{
|
||||||
domain: zoneRecords[0].Name,
|
domain: zoneRecords[0].Name,
|
||||||
handler: &localResolver{},
|
handler: &local.Resolver{},
|
||||||
priority: PriorityMatchDomain,
|
priority: PriorityMatchDomain,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dnsServer.localResolver.registeredMap = registrationMap{"netbird.cloud": struct{}{}}
|
//dnsServer.localResolver.RegisteredMap = local.RegistrationMap{local.BuildRecordKey("netbird.cloud", dns.ClassINET, dns.TypeA): struct{}{}}
|
||||||
|
dnsServer.localResolver.Update([]nbdns.SimpleRecord{{Name: "netbird.cloud", Type: int(dns.TypeA), Class: nbdns.DefaultClass, TTL: 300, RData: "10.0.0.1"}})
|
||||||
dnsServer.updateSerial = 0
|
dnsServer.updateSerial = 0
|
||||||
|
|
||||||
nameServers := []nbdns.NameServer{
|
nameServers := []nbdns.NameServer{
|
||||||
@@ -582,7 +594,7 @@ func TestDNSServerStartStop(t *testing.T) {
|
|||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
defer dnsServer.Stop()
|
defer dnsServer.Stop()
|
||||||
_, err = dnsServer.localResolver.registerRecord(zoneRecords[0])
|
err = dnsServer.localResolver.RegisterRecord(zoneRecords[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@@ -630,13 +642,11 @@ func TestDNSServerStartStop(t *testing.T) {
|
|||||||
func TestDNSServerUpstreamDeactivateCallback(t *testing.T) {
|
func TestDNSServerUpstreamDeactivateCallback(t *testing.T) {
|
||||||
hostManager := &mockHostConfigurator{}
|
hostManager := &mockHostConfigurator{}
|
||||||
server := DefaultServer{
|
server := DefaultServer{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
service: NewServiceViaMemory(&mocWGIface{}),
|
service: NewServiceViaMemory(&mocWGIface{}),
|
||||||
localResolver: &localResolver{
|
localResolver: local.NewResolver(),
|
||||||
registeredMap: make(registrationMap),
|
handlerChain: NewHandlerChain(),
|
||||||
},
|
hostManager: hostManager,
|
||||||
handlerChain: NewHandlerChain(),
|
|
||||||
hostManager: hostManager,
|
|
||||||
currentConfig: HostDNSConfig{
|
currentConfig: HostDNSConfig{
|
||||||
Domains: []DomainConfig{
|
Domains: []DomainConfig{
|
||||||
{false, "domain0", false},
|
{false, "domain0", false},
|
||||||
@@ -1004,7 +1014,7 @@ func TestHandlerChain_DomainPriorities(t *testing.T) {
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
r := new(dns.Msg)
|
r := new(dns.Msg)
|
||||||
r.SetQuestion(tc.query, dns.TypeA)
|
r.SetQuestion(tc.query, dns.TypeA)
|
||||||
w := &ResponseWriterChain{ResponseWriter: &mockResponseWriter{}}
|
w := &ResponseWriterChain{ResponseWriter: &test.MockResponseWriter{}}
|
||||||
|
|
||||||
if mh, ok := tc.expectedHandler.(*MockHandler); ok {
|
if mh, ok := tc.expectedHandler.(*MockHandler); ok {
|
||||||
mh.On("ServeDNS", mock.Anything, r).Once()
|
mh.On("ServeDNS", mock.Anything, r).Once()
|
||||||
@@ -1037,9 +1047,9 @@ type mockHandler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockHandler) ServeDNS(dns.ResponseWriter, *dns.Msg) {}
|
func (m *mockHandler) ServeDNS(dns.ResponseWriter, *dns.Msg) {}
|
||||||
func (m *mockHandler) stop() {}
|
func (m *mockHandler) Stop() {}
|
||||||
func (m *mockHandler) probeAvailability() {}
|
func (m *mockHandler) ProbeAvailability() {}
|
||||||
func (m *mockHandler) id() handlerID { return handlerID(m.Id) }
|
func (m *mockHandler) ID() types.HandlerID { return types.HandlerID(m.Id) }
|
||||||
|
|
||||||
type mockService struct{}
|
type mockService struct{}
|
||||||
|
|
||||||
@@ -1113,7 +1123,7 @@ func TestDefaultServer_UpdateMux(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
initialHandlers registeredHandlerMap
|
initialHandlers registeredHandlerMap
|
||||||
updates []handlerWrapper
|
updates []handlerWrapper
|
||||||
expectedHandlers map[string]string // map[handlerID]domain
|
expectedHandlers map[string]string // map[HandlerID]domain
|
||||||
description string
|
description string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -1409,7 +1419,7 @@ func TestDefaultServer_UpdateMux(t *testing.T) {
|
|||||||
|
|
||||||
// Check each expected handler
|
// Check each expected handler
|
||||||
for id, expectedDomain := range tt.expectedHandlers {
|
for id, expectedDomain := range tt.expectedHandlers {
|
||||||
handler, exists := server.dnsMuxMap[handlerID(id)]
|
handler, exists := server.dnsMuxMap[types.HandlerID(id)]
|
||||||
assert.True(t, exists, "Expected handler %s not found", id)
|
assert.True(t, exists, "Expected handler %s not found", id)
|
||||||
if exists {
|
if exists {
|
||||||
assert.Equal(t, expectedDomain, handler.domain,
|
assert.Equal(t, expectedDomain, handler.domain,
|
||||||
@@ -1418,9 +1428,9 @@ func TestDefaultServer_UpdateMux(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify no unexpected handlers exist
|
// Verify no unexpected handlers exist
|
||||||
for handlerID := range server.dnsMuxMap {
|
for HandlerID := range server.dnsMuxMap {
|
||||||
_, expected := tt.expectedHandlers[string(handlerID)]
|
_, expected := tt.expectedHandlers[string(HandlerID)]
|
||||||
assert.True(t, expected, "Unexpected handler found: %s", handlerID)
|
assert.True(t, expected, "Unexpected handler found: %s", HandlerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the handlerChain state and order
|
// Verify the handlerChain state and order
|
||||||
@@ -1696,7 +1706,7 @@ func TestExtraDomains(t *testing.T) {
|
|||||||
handlerChain: NewHandlerChain(),
|
handlerChain: NewHandlerChain(),
|
||||||
wgInterface: &mocWGIface{},
|
wgInterface: &mocWGIface{},
|
||||||
hostManager: mockHostConfig,
|
hostManager: mockHostConfig,
|
||||||
localResolver: &localResolver{},
|
localResolver: &local.Resolver{},
|
||||||
service: mockSvc,
|
service: mockSvc,
|
||||||
statusRecorder: peer.NewRecorder("test"),
|
statusRecorder: peer.NewRecorder("test"),
|
||||||
extraDomains: make(map[domain.Domain]int),
|
extraDomains: make(map[domain.Domain]int),
|
||||||
@@ -1781,7 +1791,7 @@ func TestExtraDomainsRefCounting(t *testing.T) {
|
|||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
handlerChain: NewHandlerChain(),
|
handlerChain: NewHandlerChain(),
|
||||||
hostManager: mockHostConfig,
|
hostManager: mockHostConfig,
|
||||||
localResolver: &localResolver{},
|
localResolver: &local.Resolver{},
|
||||||
service: mockSvc,
|
service: mockSvc,
|
||||||
statusRecorder: peer.NewRecorder("test"),
|
statusRecorder: peer.NewRecorder("test"),
|
||||||
extraDomains: make(map[domain.Domain]int),
|
extraDomains: make(map[domain.Domain]int),
|
||||||
@@ -1833,7 +1843,7 @@ func TestUpdateConfigWithExistingExtraDomains(t *testing.T) {
|
|||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
handlerChain: NewHandlerChain(),
|
handlerChain: NewHandlerChain(),
|
||||||
hostManager: mockHostConfig,
|
hostManager: mockHostConfig,
|
||||||
localResolver: &localResolver{},
|
localResolver: &local.Resolver{},
|
||||||
service: mockSvc,
|
service: mockSvc,
|
||||||
statusRecorder: peer.NewRecorder("test"),
|
statusRecorder: peer.NewRecorder("test"),
|
||||||
extraDomains: make(map[domain.Domain]int),
|
extraDomains: make(map[domain.Domain]int),
|
||||||
@@ -1916,7 +1926,7 @@ func TestDomainCaseHandling(t *testing.T) {
|
|||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
handlerChain: NewHandlerChain(),
|
handlerChain: NewHandlerChain(),
|
||||||
hostManager: mockHostConfig,
|
hostManager: mockHostConfig,
|
||||||
localResolver: &localResolver{},
|
localResolver: &local.Resolver{},
|
||||||
service: mockSvc,
|
service: mockSvc,
|
||||||
statusRecorder: peer.NewRecorder("test"),
|
statusRecorder: peer.NewRecorder("test"),
|
||||||
extraDomains: make(map[domain.Domain]int),
|
extraDomains: make(map[domain.Domain]int),
|
||||||
|
|||||||
26
client/internal/dns/test/mock.go
Normal file
26
client/internal/dns/test/mock.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockResponseWriter struct {
|
||||||
|
WriteMsgFunc func(m *dns.Msg) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *MockResponseWriter) WriteMsg(m *dns.Msg) error {
|
||||||
|
if rw.WriteMsgFunc != nil {
|
||||||
|
return rw.WriteMsgFunc(m)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *MockResponseWriter) LocalAddr() net.Addr { return nil }
|
||||||
|
func (rw *MockResponseWriter) RemoteAddr() net.Addr { return nil }
|
||||||
|
func (rw *MockResponseWriter) Write([]byte) (int, error) { return 0, nil }
|
||||||
|
func (rw *MockResponseWriter) Close() error { return nil }
|
||||||
|
func (rw *MockResponseWriter) TsigStatus() error { return nil }
|
||||||
|
func (rw *MockResponseWriter) TsigTimersOnly(bool) {}
|
||||||
|
func (rw *MockResponseWriter) Hijack() {}
|
||||||
3
client/internal/dns/types/types.go
Normal file
3
client/internal/dns/types/types.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
type HandlerID string
|
||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/types"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/client/proto"
|
"github.com/netbirdio/netbird/client/proto"
|
||||||
)
|
)
|
||||||
@@ -81,21 +82,21 @@ func (u *upstreamResolverBase) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ID returns the unique handler ID
|
// ID returns the unique handler ID
|
||||||
func (u *upstreamResolverBase) id() handlerID {
|
func (u *upstreamResolverBase) ID() types.HandlerID {
|
||||||
servers := slices.Clone(u.upstreamServers)
|
servers := slices.Clone(u.upstreamServers)
|
||||||
slices.Sort(servers)
|
slices.Sort(servers)
|
||||||
|
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
hash.Write([]byte(u.domain + ":"))
|
hash.Write([]byte(u.domain + ":"))
|
||||||
hash.Write([]byte(strings.Join(servers, ",")))
|
hash.Write([]byte(strings.Join(servers, ",")))
|
||||||
return handlerID("upstream-" + hex.EncodeToString(hash.Sum(nil)[:8]))
|
return types.HandlerID("upstream-" + hex.EncodeToString(hash.Sum(nil)[:8]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *upstreamResolverBase) MatchSubdomains() bool {
|
func (u *upstreamResolverBase) MatchSubdomains() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *upstreamResolverBase) stop() {
|
func (u *upstreamResolverBase) Stop() {
|
||||||
log.Debugf("stopping serving DNS for upstreams %s", u.upstreamServers)
|
log.Debugf("stopping serving DNS for upstreams %s", u.upstreamServers)
|
||||||
u.cancel()
|
u.cancel()
|
||||||
}
|
}
|
||||||
@@ -198,9 +199,9 @@ func (u *upstreamResolverBase) checkUpstreamFails(err error) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// probeAvailability tests all upstream servers simultaneously and
|
// ProbeAvailability tests all upstream servers simultaneously and
|
||||||
// disables the resolver if none work
|
// disables the resolver if none work
|
||||||
func (u *upstreamResolverBase) probeAvailability() {
|
func (u *upstreamResolverBase) ProbeAvailability() {
|
||||||
u.mutex.Lock()
|
u.mutex.Lock()
|
||||||
defer u.mutex.Unlock()
|
defer u.mutex.Unlock()
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/dns/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUpstreamResolver_ServeDNS(t *testing.T) {
|
func TestUpstreamResolver_ServeDNS(t *testing.T) {
|
||||||
@@ -66,7 +68,7 @@ func TestUpstreamResolver_ServeDNS(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var responseMSG *dns.Msg
|
var responseMSG *dns.Msg
|
||||||
responseWriter := &mockResponseWriter{
|
responseWriter := &test.MockResponseWriter{
|
||||||
WriteMsgFunc: func(m *dns.Msg) error {
|
WriteMsgFunc: func(m *dns.Msg) error {
|
||||||
responseMSG = m
|
responseMSG = m
|
||||||
return nil
|
return nil
|
||||||
@@ -130,7 +132,7 @@ func TestUpstreamResolver_DeactivationReactivation(t *testing.T) {
|
|||||||
resolver.failsTillDeact = 0
|
resolver.failsTillDeact = 0
|
||||||
resolver.reactivatePeriod = time.Microsecond * 100
|
resolver.reactivatePeriod = time.Microsecond * 100
|
||||||
|
|
||||||
responseWriter := &mockResponseWriter{
|
responseWriter := &test.MockResponseWriter{
|
||||||
WriteMsgFunc: func(m *dns.Msg) error { return nil },
|
WriteMsgFunc: func(m *dns.Msg) error { return nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ type DNSForwarder struct {
|
|||||||
|
|
||||||
dnsServer *dns.Server
|
dnsServer *dns.Server
|
||||||
mux *dns.ServeMux
|
mux *dns.ServeMux
|
||||||
|
tcpServer *dns.Server
|
||||||
|
tcpMux *dns.ServeMux
|
||||||
|
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
fwdEntries []*ForwarderEntry
|
fwdEntries []*ForwarderEntry
|
||||||
@@ -50,22 +52,41 @@ func NewDNSForwarder(listenAddress string, ttl uint32, firewall firewall.Manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *DNSForwarder) Listen(entries []*ForwarderEntry) error {
|
func (f *DNSForwarder) Listen(entries []*ForwarderEntry) error {
|
||||||
log.Infof("listen DNS forwarder on address=%s", f.listenAddress)
|
log.Infof("starting DNS forwarder on address=%s", f.listenAddress)
|
||||||
mux := dns.NewServeMux()
|
|
||||||
|
|
||||||
dnsServer := &dns.Server{
|
// UDP server
|
||||||
|
mux := dns.NewServeMux()
|
||||||
|
f.mux = mux
|
||||||
|
f.dnsServer = &dns.Server{
|
||||||
Addr: f.listenAddress,
|
Addr: f.listenAddress,
|
||||||
Net: "udp",
|
Net: "udp",
|
||||||
Handler: mux,
|
Handler: mux,
|
||||||
}
|
}
|
||||||
f.dnsServer = dnsServer
|
// TCP server
|
||||||
f.mux = mux
|
tcpMux := dns.NewServeMux()
|
||||||
|
f.tcpMux = tcpMux
|
||||||
|
f.tcpServer = &dns.Server{
|
||||||
|
Addr: f.listenAddress,
|
||||||
|
Net: "tcp",
|
||||||
|
Handler: tcpMux,
|
||||||
|
}
|
||||||
|
|
||||||
f.UpdateDomains(entries)
|
f.UpdateDomains(entries)
|
||||||
|
|
||||||
return dnsServer.ListenAndServe()
|
errCh := make(chan error, 2)
|
||||||
}
|
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
log.Infof("DNS UDP listener running on %s", f.listenAddress)
|
||||||
|
errCh <- f.dnsServer.ListenAndServe()
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
log.Infof("DNS TCP listener running on %s", f.listenAddress)
|
||||||
|
errCh <- f.tcpServer.ListenAndServe()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// return the first error we get (e.g. bind failure or shutdown)
|
||||||
|
return <-errCh
|
||||||
|
}
|
||||||
func (f *DNSForwarder) UpdateDomains(entries []*ForwarderEntry) {
|
func (f *DNSForwarder) UpdateDomains(entries []*ForwarderEntry) {
|
||||||
f.mutex.Lock()
|
f.mutex.Lock()
|
||||||
defer f.mutex.Unlock()
|
defer f.mutex.Unlock()
|
||||||
@@ -77,31 +98,41 @@ func (f *DNSForwarder) UpdateDomains(entries []*ForwarderEntry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oldDomains := filterDomains(f.fwdEntries)
|
oldDomains := filterDomains(f.fwdEntries)
|
||||||
|
|
||||||
for _, d := range oldDomains {
|
for _, d := range oldDomains {
|
||||||
f.mux.HandleRemove(d.PunycodeString())
|
f.mux.HandleRemove(d.PunycodeString())
|
||||||
|
f.tcpMux.HandleRemove(d.PunycodeString())
|
||||||
}
|
}
|
||||||
|
|
||||||
newDomains := filterDomains(entries)
|
newDomains := filterDomains(entries)
|
||||||
for _, d := range newDomains {
|
for _, d := range newDomains {
|
||||||
f.mux.HandleFunc(d.PunycodeString(), f.handleDNSQuery)
|
f.mux.HandleFunc(d.PunycodeString(), f.handleDNSQueryUDP)
|
||||||
|
f.tcpMux.HandleFunc(d.PunycodeString(), f.handleDNSQueryTCP)
|
||||||
}
|
}
|
||||||
|
|
||||||
f.fwdEntries = entries
|
f.fwdEntries = entries
|
||||||
|
|
||||||
log.Debugf("Updated domains from %v to %v", oldDomains, newDomains)
|
log.Debugf("Updated domains from %v to %v", oldDomains, newDomains)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *DNSForwarder) Close(ctx context.Context) error {
|
func (f *DNSForwarder) Close(ctx context.Context) error {
|
||||||
if f.dnsServer == nil {
|
var result *multierror.Error
|
||||||
return nil
|
|
||||||
|
if f.dnsServer != nil {
|
||||||
|
if err := f.dnsServer.ShutdownContext(ctx); err != nil {
|
||||||
|
result = multierror.Append(result, fmt.Errorf("UDP shutdown: %w", err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return f.dnsServer.ShutdownContext(ctx)
|
if f.tcpServer != nil {
|
||||||
|
if err := f.tcpServer.ShutdownContext(ctx); err != nil {
|
||||||
|
result = multierror.Append(result, fmt.Errorf("TCP shutdown: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nberrors.FormatErrorOrNil(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *DNSForwarder) handleDNSQuery(w dns.ResponseWriter, query *dns.Msg) {
|
func (f *DNSForwarder) handleDNSQuery(w dns.ResponseWriter, query *dns.Msg) *dns.Msg {
|
||||||
if len(query.Question) == 0 {
|
if len(query.Question) == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
question := query.Question[0]
|
question := query.Question[0]
|
||||||
log.Tracef("received DNS request for DNS forwarder: domain=%v type=%v class=%v",
|
log.Tracef("received DNS request for DNS forwarder: domain=%v type=%v class=%v",
|
||||||
@@ -123,20 +154,53 @@ func (f *DNSForwarder) handleDNSQuery(w dns.ResponseWriter, query *dns.Msg) {
|
|||||||
if err := w.WriteMsg(resp); err != nil {
|
if err := w.WriteMsg(resp); err != nil {
|
||||||
log.Errorf("failed to write DNS response: %v", err)
|
log.Errorf("failed to write DNS response: %v", err)
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), upstreamTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), upstreamTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
ips, err := net.DefaultResolver.LookupNetIP(ctx, network, domain)
|
ips, err := net.DefaultResolver.LookupNetIP(ctx, network, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.handleDNSError(w, resp, domain, err)
|
f.handleDNSError(w, query, resp, domain, err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
f.updateInternalState(domain, ips)
|
f.updateInternalState(domain, ips)
|
||||||
f.addIPsToResponse(resp, domain, ips)
|
f.addIPsToResponse(resp, domain, ips)
|
||||||
|
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *DNSForwarder) handleDNSQueryUDP(w dns.ResponseWriter, query *dns.Msg) {
|
||||||
|
|
||||||
|
resp := f.handleDNSQuery(w, query)
|
||||||
|
if resp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
opt := query.IsEdns0()
|
||||||
|
maxSize := dns.MinMsgSize
|
||||||
|
if opt != nil {
|
||||||
|
// client advertised a larger EDNS0 buffer
|
||||||
|
maxSize = int(opt.UDPSize())
|
||||||
|
}
|
||||||
|
|
||||||
|
// if our response is too big, truncate and set the TC bit
|
||||||
|
if resp.Len() > maxSize {
|
||||||
|
resp.Truncate(maxSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.WriteMsg(resp); err != nil {
|
||||||
|
log.Errorf("failed to write DNS response: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *DNSForwarder) handleDNSQueryTCP(w dns.ResponseWriter, query *dns.Msg) {
|
||||||
|
resp := f.handleDNSQuery(w, query)
|
||||||
|
if resp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := w.WriteMsg(resp); err != nil {
|
if err := w.WriteMsg(resp); err != nil {
|
||||||
log.Errorf("failed to write DNS response: %v", err)
|
log.Errorf("failed to write DNS response: %v", err)
|
||||||
}
|
}
|
||||||
@@ -179,7 +243,7 @@ func (f *DNSForwarder) updateFirewall(matchingEntries []*ForwarderEntry, prefixe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handleDNSError processes DNS lookup errors and sends an appropriate error response
|
// handleDNSError processes DNS lookup errors and sends an appropriate error response
|
||||||
func (f *DNSForwarder) handleDNSError(w dns.ResponseWriter, resp *dns.Msg, domain string, err error) {
|
func (f *DNSForwarder) handleDNSError(w dns.ResponseWriter, query, resp *dns.Msg, domain string, err error) {
|
||||||
var dnsErr *net.DNSError
|
var dnsErr *net.DNSError
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@@ -191,7 +255,7 @@ func (f *DNSForwarder) handleDNSError(w dns.ResponseWriter, resp *dns.Msg, domai
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dnsErr.Server != "" {
|
if dnsErr.Server != "" {
|
||||||
log.Warnf("failed to resolve query for domain=%s server=%s: %v", domain, dnsErr.Server, err)
|
log.Warnf("failed to resolve query for type=%s domain=%s server=%s: %v", dns.TypeToString[query.Question[0].Qtype], domain, dnsErr.Server, err)
|
||||||
} else {
|
} else {
|
||||||
log.Warnf(errResolveFailed, domain, err)
|
log.Warnf(errResolveFailed, domain, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Manager struct {
|
|||||||
statusRecorder *peer.Status
|
statusRecorder *peer.Status
|
||||||
|
|
||||||
fwRules []firewall.Rule
|
fwRules []firewall.Rule
|
||||||
|
tcpRules []firewall.Rule
|
||||||
dnsForwarder *DNSForwarder
|
dnsForwarder *DNSForwarder
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +108,13 @@ func (m *Manager) allowDNSFirewall() error {
|
|||||||
}
|
}
|
||||||
m.fwRules = dnsRules
|
m.fwRules = dnsRules
|
||||||
|
|
||||||
|
tcpRules, err := m.firewall.AddPeerFiltering(nil, net.IP{0, 0, 0, 0}, firewall.ProtocolTCP, nil, dport, firewall.ActionAccept, "")
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to add allow DNS router rules, err: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.tcpRules = tcpRules
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +125,13 @@ func (m *Manager) dropDNSFirewall() error {
|
|||||||
mErr = multierror.Append(mErr, fmt.Errorf("failed to delete DNS router rules, err: %v", err))
|
mErr = multierror.Append(mErr, fmt.Errorf("failed to delete DNS router rules, err: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, rule := range m.tcpRules {
|
||||||
|
if err := m.firewall.DeletePeerRule(rule); err != nil {
|
||||||
|
mErr = multierror.Append(mErr, fmt.Errorf("failed to delete DNS router rules, err: %v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m.fwRules = nil
|
m.fwRules = nil
|
||||||
|
m.tcpRules = nil
|
||||||
return nberrors.FormatErrorOrNil(mErr)
|
return nberrors.FormatErrorOrNil(mErr)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop) error {
|
func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop) error {
|
||||||
fd, err := unix.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC)
|
fd, err := unix.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open routing socket: %v", err)
|
return fmt.Errorf("open routing socket: %v", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
err := unix.Close(fd)
|
err := unix.Close(fd)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop) error {
|
func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop) error {
|
||||||
routeMonitor, err := systemops.NewRouteMonitor(ctx)
|
routeMonitor, err := systemops.NewRouteMonitor(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create route monitor: %w", err)
|
return fmt.Errorf("create route monitor: %w", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := routeMonitor.Stop(); err != nil {
|
if err := routeMonitor.Stop(); err != nil {
|
||||||
@@ -38,35 +38,49 @@ func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func routeChanged(route systemops.RouteUpdate, nexthopv4, nexthopv6 systemops.Nexthop) bool {
|
func routeChanged(route systemops.RouteUpdate, nexthopv4, nexthopv6 systemops.Nexthop) bool {
|
||||||
intf := "<nil>"
|
if intf := route.NextHop.Intf; intf != nil && isSoftInterface(intf.Name) {
|
||||||
if route.Interface != nil {
|
log.Debugf("Network monitor: ignoring default route change for next hop with soft interface %s", route.NextHop)
|
||||||
intf = route.Interface.Name
|
return false
|
||||||
if isSoftInterface(intf) {
|
}
|
||||||
log.Debugf("Network monitor: ignoring default route change for soft interface %s", intf)
|
|
||||||
return false
|
// TODO: for the empty nexthop ip (on-link), determine the family differently
|
||||||
}
|
nexthop := nexthopv4
|
||||||
|
if route.NextHop.IP.Is6() {
|
||||||
|
nexthop = nexthopv6
|
||||||
}
|
}
|
||||||
|
|
||||||
switch route.Type {
|
switch route.Type {
|
||||||
case systemops.RouteModified:
|
case systemops.RouteModified, systemops.RouteAdded:
|
||||||
// TODO: get routing table to figure out if our route is affected for modified routes
|
return handleRouteAddedOrModified(route, nexthop)
|
||||||
log.Infof("Network monitor: default route changed: via %s, interface %s", route.NextHop, intf)
|
|
||||||
return true
|
|
||||||
case systemops.RouteAdded:
|
|
||||||
if route.NextHop.Is4() && route.NextHop != nexthopv4.IP || route.NextHop.Is6() && route.NextHop != nexthopv6.IP {
|
|
||||||
log.Infof("Network monitor: default route added: via %s, interface %s", route.NextHop, intf)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case systemops.RouteDeleted:
|
case systemops.RouteDeleted:
|
||||||
if nexthopv4.Intf != nil && route.NextHop == nexthopv4.IP || nexthopv6.Intf != nil && route.NextHop == nexthopv6.IP {
|
return handleRouteDeleted(route, nexthop)
|
||||||
log.Infof("Network monitor: default route removed: via %s, interface %s", route.NextHop, intf)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleRouteAddedOrModified(route systemops.RouteUpdate, nexthop systemops.Nexthop) bool {
|
||||||
|
// For added/modified routes, we care about different next hops
|
||||||
|
if !nexthop.Equal(route.NextHop) {
|
||||||
|
action := "changed"
|
||||||
|
if route.Type == systemops.RouteAdded {
|
||||||
|
action = "added"
|
||||||
|
}
|
||||||
|
log.Infof("Network monitor: default route %s: via %s", action, route.NextHop)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleRouteDeleted(route systemops.RouteUpdate, nexthop systemops.Nexthop) bool {
|
||||||
|
// For deleted routes, we care about our tracked next hop being deleted
|
||||||
|
if nexthop.Equal(route.NextHop) {
|
||||||
|
log.Infof("Network monitor: default route removed: via %s", route.NextHop)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func isSoftInterface(name string) bool {
|
func isSoftInterface(name string) bool {
|
||||||
return strings.Contains(strings.ToLower(name), "isatap") || strings.Contains(strings.ToLower(name), "teredo")
|
return strings.Contains(strings.ToLower(name), "isatap") || strings.Contains(strings.ToLower(name), "teredo")
|
||||||
}
|
}
|
||||||
|
|||||||
404
client/internal/networkmonitor/check_change_windows_test.go
Normal file
404
client/internal/networkmonitor/check_change_windows_test.go
Normal file
@@ -0,0 +1,404 @@
|
|||||||
|
package networkmonitor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/routemanager/systemops"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRouteChanged(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
route systemops.RouteUpdate
|
||||||
|
nexthopv4 systemops.Nexthop
|
||||||
|
nexthopv6 systemops.Nexthop
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "soft interface should be ignored",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteModified,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Name: "ISATAP-Interface", // isSoftInterface checks name
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.2"),
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modified route with different v4 nexthop IP should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteModified,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.2"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modified route with same v4 nexthop (IP and Intf Index) should return false",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteModified,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "added route with different v6 nexthop IP should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteAdded,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv6Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::2"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "added route with same v6 nexthop (IP and Intf Index) should return false",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteAdded,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv6Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deleted route matching tracked v4 nexthop (IP and Intf Index) should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteDeleted,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deleted route not matching tracked v4 nexthop (different IP) should return false",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteDeleted,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.3"), // Different IP
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{
|
||||||
|
Index: 1, Name: "eth0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modified v4 route with same IP, different Intf Index should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteModified,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{Index: 2, Name: "eth1"}, // Different Intf Index
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modified v4 route with same IP, one Intf nil, other non-nil should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteModified,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: nil, // Intf is nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"}, // Tracked Intf is not nil
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "added v4 route with same IP, different Intf Index should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteAdded,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{Index: 2, Name: "eth1"}, // Different Intf Index
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deleted v4 route with same IP, different Intf Index should return false",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteDeleted,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{ // This is the route being deleted
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{ // This is our tracked nexthop
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{Index: 2, Name: "eth1"}, // Different Intf Index
|
||||||
|
},
|
||||||
|
expected: false, // Because nexthopv4.Equal(route.NextHop) will be false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modified v6 route with different IP, same Intf Index should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteModified,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv6Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::3"), // Different IP
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modified v6 route with same IP, different Intf Index should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteModified,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv6Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 2, Name: "eth1"}, // Different Intf Index
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modified v6 route with same IP, same Intf Index should return false",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteModified,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv6Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deleted v6 route matching tracked nexthop (IP and Intf Index) should return true",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteDeleted,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv6Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deleted v6 route not matching tracked nexthop (different IP) should return false",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteDeleted,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv6Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::3"), // Different IP
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deleted v6 route not matching tracked nexthop (same IP, different Intf Index) should return false",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteDeleted,
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv6Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{ // This is the route being deleted
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv6: systemops.Nexthop{ // This is our tracked nexthop
|
||||||
|
IP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
Intf: &net.Interface{Index: 2, Name: "eth1"}, // Different Intf Index
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unknown route type should return false",
|
||||||
|
route: systemops.RouteUpdate{
|
||||||
|
Type: systemops.RouteUpdateType(99), // Unknown type
|
||||||
|
Destination: netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||||
|
NextHop: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.1"),
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nexthopv4: systemops.Nexthop{
|
||||||
|
IP: netip.MustParseAddr("192.168.1.2"), // Different from route.NextHop
|
||||||
|
Intf: &net.Interface{Index: 1, Name: "eth0"},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := routeChanged(tt.route, tt.nexthopv4, tt.nexthopv6)
|
||||||
|
assert.Equal(t, tt.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsSoftInterface(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
ifname string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "ISATAP interface should be detected",
|
||||||
|
ifname: "ISATAP tunnel adapter",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "lowercase soft interface should be detected",
|
||||||
|
ifname: "isatap.{14A5CF17-CA72-43EC-B4EA-B4B093641B7D}",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Teredo interface should be detected",
|
||||||
|
ifname: "Teredo Tunneling Pseudo-Interface",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "regular interface should not be detected as soft",
|
||||||
|
ifname: "eth0",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "another regular interface should not be detected as soft",
|
||||||
|
ifname: "wlan0",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := isSoftInterface(tt.ifname)
|
||||||
|
assert.Equal(t, tt.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,9 +118,12 @@ func (nw *NetworkMonitor) Stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (nw *NetworkMonitor) checkChanges(ctx context.Context, event chan struct{}, nexthop4 systemops.Nexthop, nexthop6 systemops.Nexthop) {
|
func (nw *NetworkMonitor) checkChanges(ctx context.Context, event chan struct{}, nexthop4 systemops.Nexthop, nexthop6 systemops.Nexthop) {
|
||||||
|
defer close(event)
|
||||||
for {
|
for {
|
||||||
if err := checkChangeFn(ctx, nexthop4, nexthop6); err != nil {
|
if err := checkChangeFn(ctx, nexthop4, nexthop6); err != nil {
|
||||||
close(event)
|
if !errors.Is(err, context.Canceled) {
|
||||||
|
log.Errorf("Network monitor: failed to check for changes: %v", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// prevent blocking
|
// prevent blocking
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package systemops
|
package systemops
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -15,6 +16,20 @@ type Nexthop struct {
|
|||||||
Intf *net.Interface
|
Intf *net.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equal checks if two nexthops are equal.
|
||||||
|
func (n Nexthop) Equal(other Nexthop) bool {
|
||||||
|
return n.IP == other.IP && (n.Intf == nil && other.Intf == nil ||
|
||||||
|
n.Intf != nil && other.Intf != nil && n.Intf.Index == other.Intf.Index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the nexthop.
|
||||||
|
func (n Nexthop) String() string {
|
||||||
|
if n.Intf == nil {
|
||||||
|
return n.IP.String()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s @ %d (%s)", n.IP.String(), n.Intf.Index, n.Intf.Name)
|
||||||
|
}
|
||||||
|
|
||||||
type ExclusionCounter = refcounter.Counter[netip.Prefix, struct{}, Nexthop]
|
type ExclusionCounter = refcounter.Counter[netip.Prefix, struct{}, Nexthop]
|
||||||
|
|
||||||
type SysOps struct {
|
type SysOps struct {
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ type RouteUpdateType int
|
|||||||
type RouteUpdate struct {
|
type RouteUpdate struct {
|
||||||
Type RouteUpdateType
|
Type RouteUpdateType
|
||||||
Destination netip.Prefix
|
Destination netip.Prefix
|
||||||
NextHop netip.Addr
|
NextHop Nexthop
|
||||||
Interface *net.Interface
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RouteMonitor provides a way to monitor changes in the routing table.
|
// RouteMonitor provides a way to monitor changes in the routing table.
|
||||||
@@ -231,15 +230,15 @@ func (rm *RouteMonitor) parseUpdate(row *MIB_IPFORWARD_ROW2, notificationType MI
|
|||||||
intf, err := net.InterfaceByIndex(idx)
|
intf, err := net.InterfaceByIndex(idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to get interface name for index %d: %v", idx, err)
|
log.Warnf("failed to get interface name for index %d: %v", idx, err)
|
||||||
update.Interface = &net.Interface{
|
update.NextHop.Intf = &net.Interface{
|
||||||
Index: idx,
|
Index: idx,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
update.Interface = intf
|
update.NextHop.Intf = intf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Tracef("Received route update with destination %v, next hop %v, interface %v", row.DestinationPrefix, row.NextHop, update.Interface)
|
log.Tracef("Received route update with destination %v, next hop %v, interface %v", row.DestinationPrefix, row.NextHop, update.NextHop.Intf)
|
||||||
dest := parseIPPrefix(row.DestinationPrefix, idx)
|
dest := parseIPPrefix(row.DestinationPrefix, idx)
|
||||||
if !dest.Addr().IsValid() {
|
if !dest.Addr().IsValid() {
|
||||||
return RouteUpdate{}, fmt.Errorf("invalid destination: %v", row)
|
return RouteUpdate{}, fmt.Errorf("invalid destination: %v", row)
|
||||||
@@ -262,7 +261,7 @@ func (rm *RouteMonitor) parseUpdate(row *MIB_IPFORWARD_ROW2, notificationType MI
|
|||||||
|
|
||||||
update.Type = updateType
|
update.Type = updateType
|
||||||
update.Destination = dest
|
update.Destination = dest
|
||||||
update.NextHop = nexthop
|
update.NextHop.IP = nexthop
|
||||||
|
|
||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
|
// - protoc (unknown)
|
||||||
|
// source: daemon/daemon.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
@@ -11,8 +15,31 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.64.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
|
const (
|
||||||
|
DaemonService_Login_FullMethodName = "/daemon.DaemonService/Login"
|
||||||
|
DaemonService_WaitSSOLogin_FullMethodName = "/daemon.DaemonService/WaitSSOLogin"
|
||||||
|
DaemonService_Up_FullMethodName = "/daemon.DaemonService/Up"
|
||||||
|
DaemonService_Status_FullMethodName = "/daemon.DaemonService/Status"
|
||||||
|
DaemonService_Down_FullMethodName = "/daemon.DaemonService/Down"
|
||||||
|
DaemonService_GetConfig_FullMethodName = "/daemon.DaemonService/GetConfig"
|
||||||
|
DaemonService_ListNetworks_FullMethodName = "/daemon.DaemonService/ListNetworks"
|
||||||
|
DaemonService_SelectNetworks_FullMethodName = "/daemon.DaemonService/SelectNetworks"
|
||||||
|
DaemonService_DeselectNetworks_FullMethodName = "/daemon.DaemonService/DeselectNetworks"
|
||||||
|
DaemonService_ForwardingRules_FullMethodName = "/daemon.DaemonService/ForwardingRules"
|
||||||
|
DaemonService_DebugBundle_FullMethodName = "/daemon.DaemonService/DebugBundle"
|
||||||
|
DaemonService_GetLogLevel_FullMethodName = "/daemon.DaemonService/GetLogLevel"
|
||||||
|
DaemonService_SetLogLevel_FullMethodName = "/daemon.DaemonService/SetLogLevel"
|
||||||
|
DaemonService_ListStates_FullMethodName = "/daemon.DaemonService/ListStates"
|
||||||
|
DaemonService_CleanState_FullMethodName = "/daemon.DaemonService/CleanState"
|
||||||
|
DaemonService_DeleteState_FullMethodName = "/daemon.DaemonService/DeleteState"
|
||||||
|
DaemonService_SetNetworkMapPersistence_FullMethodName = "/daemon.DaemonService/SetNetworkMapPersistence"
|
||||||
|
DaemonService_TracePacket_FullMethodName = "/daemon.DaemonService/TracePacket"
|
||||||
|
DaemonService_SubscribeEvents_FullMethodName = "/daemon.DaemonService/SubscribeEvents"
|
||||||
|
DaemonService_GetEvents_FullMethodName = "/daemon.DaemonService/GetEvents"
|
||||||
|
)
|
||||||
|
|
||||||
// DaemonServiceClient is the client API for DaemonService service.
|
// DaemonServiceClient is the client API for DaemonService service.
|
||||||
//
|
//
|
||||||
@@ -53,7 +80,7 @@ type DaemonServiceClient interface {
|
|||||||
// SetNetworkMapPersistence enables or disables network map persistence
|
// SetNetworkMapPersistence enables or disables network map persistence
|
||||||
SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error)
|
SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error)
|
||||||
TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error)
|
TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error)
|
||||||
SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error)
|
SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SystemEvent], error)
|
||||||
GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error)
|
GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,8 +93,9 @@ func NewDaemonServiceClient(cc grpc.ClientConnInterface) DaemonServiceClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
|
func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(LoginResponse)
|
out := new(LoginResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Login", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_Login_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -75,8 +103,9 @@ func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) WaitSSOLogin(ctx context.Context, in *WaitSSOLoginRequest, opts ...grpc.CallOption) (*WaitSSOLoginResponse, error) {
|
func (c *daemonServiceClient) WaitSSOLogin(ctx context.Context, in *WaitSSOLoginRequest, opts ...grpc.CallOption) (*WaitSSOLoginResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(WaitSSOLoginResponse)
|
out := new(WaitSSOLoginResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/WaitSSOLogin", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_WaitSSOLogin_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -84,8 +113,9 @@ func (c *daemonServiceClient) WaitSSOLogin(ctx context.Context, in *WaitSSOLogin
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grpc.CallOption) (*UpResponse, error) {
|
func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grpc.CallOption) (*UpResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(UpResponse)
|
out := new(UpResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Up", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_Up_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -93,8 +123,9 @@ func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grp
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
|
func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(StatusResponse)
|
out := new(StatusResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Status", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_Status_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -102,8 +133,9 @@ func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts ...grpc.CallOption) (*DownResponse, error) {
|
func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts ...grpc.CallOption) (*DownResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(DownResponse)
|
out := new(DownResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/Down", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_Down_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -111,8 +143,9 @@ func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts ..
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error) {
|
func (c *daemonServiceClient) GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(GetConfigResponse)
|
out := new(GetConfigResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetConfig", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_GetConfig_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -120,8 +153,9 @@ func (c *daemonServiceClient) GetConfig(ctx context.Context, in *GetConfigReques
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) ListNetworks(ctx context.Context, in *ListNetworksRequest, opts ...grpc.CallOption) (*ListNetworksResponse, error) {
|
func (c *daemonServiceClient) ListNetworks(ctx context.Context, in *ListNetworksRequest, opts ...grpc.CallOption) (*ListNetworksResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListNetworksResponse)
|
out := new(ListNetworksResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/ListNetworks", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_ListNetworks_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -129,8 +163,9 @@ func (c *daemonServiceClient) ListNetworks(ctx context.Context, in *ListNetworks
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) SelectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) {
|
func (c *daemonServiceClient) SelectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(SelectNetworksResponse)
|
out := new(SelectNetworksResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/SelectNetworks", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_SelectNetworks_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -138,8 +173,9 @@ func (c *daemonServiceClient) SelectNetworks(ctx context.Context, in *SelectNetw
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) {
|
func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(SelectNetworksResponse)
|
out := new(SelectNetworksResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/DeselectNetworks", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_DeselectNetworks_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -147,8 +183,9 @@ func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*ForwardingRulesResponse, error) {
|
func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*ForwardingRulesResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ForwardingRulesResponse)
|
out := new(ForwardingRulesResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/ForwardingRules", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_ForwardingRules_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -156,8 +193,9 @@ func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) DebugBundle(ctx context.Context, in *DebugBundleRequest, opts ...grpc.CallOption) (*DebugBundleResponse, error) {
|
func (c *daemonServiceClient) DebugBundle(ctx context.Context, in *DebugBundleRequest, opts ...grpc.CallOption) (*DebugBundleResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(DebugBundleResponse)
|
out := new(DebugBundleResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/DebugBundle", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_DebugBundle_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -165,8 +203,9 @@ func (c *daemonServiceClient) DebugBundle(ctx context.Context, in *DebugBundleRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) GetLogLevel(ctx context.Context, in *GetLogLevelRequest, opts ...grpc.CallOption) (*GetLogLevelResponse, error) {
|
func (c *daemonServiceClient) GetLogLevel(ctx context.Context, in *GetLogLevelRequest, opts ...grpc.CallOption) (*GetLogLevelResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(GetLogLevelResponse)
|
out := new(GetLogLevelResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetLogLevel", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_GetLogLevel_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -174,8 +213,9 @@ func (c *daemonServiceClient) GetLogLevel(ctx context.Context, in *GetLogLevelRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) SetLogLevel(ctx context.Context, in *SetLogLevelRequest, opts ...grpc.CallOption) (*SetLogLevelResponse, error) {
|
func (c *daemonServiceClient) SetLogLevel(ctx context.Context, in *SetLogLevelRequest, opts ...grpc.CallOption) (*SetLogLevelResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(SetLogLevelResponse)
|
out := new(SetLogLevelResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/SetLogLevel", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_SetLogLevel_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -183,8 +223,9 @@ func (c *daemonServiceClient) SetLogLevel(ctx context.Context, in *SetLogLevelRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) ListStates(ctx context.Context, in *ListStatesRequest, opts ...grpc.CallOption) (*ListStatesResponse, error) {
|
func (c *daemonServiceClient) ListStates(ctx context.Context, in *ListStatesRequest, opts ...grpc.CallOption) (*ListStatesResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListStatesResponse)
|
out := new(ListStatesResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/ListStates", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_ListStates_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -192,8 +233,9 @@ func (c *daemonServiceClient) ListStates(ctx context.Context, in *ListStatesRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) CleanState(ctx context.Context, in *CleanStateRequest, opts ...grpc.CallOption) (*CleanStateResponse, error) {
|
func (c *daemonServiceClient) CleanState(ctx context.Context, in *CleanStateRequest, opts ...grpc.CallOption) (*CleanStateResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(CleanStateResponse)
|
out := new(CleanStateResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/CleanState", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_CleanState_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -201,8 +243,9 @@ func (c *daemonServiceClient) CleanState(ctx context.Context, in *CleanStateRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) DeleteState(ctx context.Context, in *DeleteStateRequest, opts ...grpc.CallOption) (*DeleteStateResponse, error) {
|
func (c *daemonServiceClient) DeleteState(ctx context.Context, in *DeleteStateRequest, opts ...grpc.CallOption) (*DeleteStateResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(DeleteStateResponse)
|
out := new(DeleteStateResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/DeleteState", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_DeleteState_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -210,8 +253,9 @@ func (c *daemonServiceClient) DeleteState(ctx context.Context, in *DeleteStateRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error) {
|
func (c *daemonServiceClient) SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(SetNetworkMapPersistenceResponse)
|
out := new(SetNetworkMapPersistenceResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/SetNetworkMapPersistence", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_SetNetworkMapPersistence_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -219,20 +263,22 @@ func (c *daemonServiceClient) SetNetworkMapPersistence(ctx context.Context, in *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error) {
|
func (c *daemonServiceClient) TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(TracePacketResponse)
|
out := new(TracePacketResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/TracePacket", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_TracePacket_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error) {
|
func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SystemEvent], error) {
|
||||||
stream, err := c.cc.NewStream(ctx, &DaemonService_ServiceDesc.Streams[0], "/daemon.DaemonService/SubscribeEvents", opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
stream, err := c.cc.NewStream(ctx, &DaemonService_ServiceDesc.Streams[0], DaemonService_SubscribeEvents_FullMethodName, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
x := &daemonServiceSubscribeEventsClient{stream}
|
x := &grpc.GenericClientStream[SubscribeRequest, SystemEvent]{ClientStream: stream}
|
||||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -242,26 +288,13 @@ func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *Subscribe
|
|||||||
return x, nil
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type DaemonService_SubscribeEventsClient interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Recv() (*SystemEvent, error)
|
type DaemonService_SubscribeEventsClient = grpc.ServerStreamingClient[SystemEvent]
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type daemonServiceSubscribeEventsClient struct {
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *daemonServiceSubscribeEventsClient) Recv() (*SystemEvent, error) {
|
|
||||||
m := new(SystemEvent)
|
|
||||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) {
|
func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(GetEventsResponse)
|
out := new(GetEventsResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetEvents", in, out, opts...)
|
err := c.cc.Invoke(ctx, DaemonService_GetEvents_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -270,7 +303,7 @@ func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsReques
|
|||||||
|
|
||||||
// DaemonServiceServer is the server API for DaemonService service.
|
// DaemonServiceServer is the server API for DaemonService service.
|
||||||
// All implementations must embed UnimplementedDaemonServiceServer
|
// All implementations must embed UnimplementedDaemonServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility.
|
||||||
type DaemonServiceServer interface {
|
type DaemonServiceServer interface {
|
||||||
// Login uses setup key to prepare configuration for the daemon.
|
// Login uses setup key to prepare configuration for the daemon.
|
||||||
Login(context.Context, *LoginRequest) (*LoginResponse, error)
|
Login(context.Context, *LoginRequest) (*LoginResponse, error)
|
||||||
@@ -307,14 +340,17 @@ type DaemonServiceServer interface {
|
|||||||
// SetNetworkMapPersistence enables or disables network map persistence
|
// SetNetworkMapPersistence enables or disables network map persistence
|
||||||
SetNetworkMapPersistence(context.Context, *SetNetworkMapPersistenceRequest) (*SetNetworkMapPersistenceResponse, error)
|
SetNetworkMapPersistence(context.Context, *SetNetworkMapPersistenceRequest) (*SetNetworkMapPersistenceResponse, error)
|
||||||
TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error)
|
TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error)
|
||||||
SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error
|
SubscribeEvents(*SubscribeRequest, grpc.ServerStreamingServer[SystemEvent]) error
|
||||||
GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error)
|
GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error)
|
||||||
mustEmbedUnimplementedDaemonServiceServer()
|
mustEmbedUnimplementedDaemonServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnimplementedDaemonServiceServer must be embedded to have forward compatible implementations.
|
// UnimplementedDaemonServiceServer must be embedded to have
|
||||||
type UnimplementedDaemonServiceServer struct {
|
// forward compatible implementations.
|
||||||
}
|
//
|
||||||
|
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||||
|
// pointer dereference when methods are called.
|
||||||
|
type UnimplementedDaemonServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedDaemonServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
|
func (UnimplementedDaemonServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
|
||||||
@@ -370,13 +406,14 @@ func (UnimplementedDaemonServiceServer) SetNetworkMapPersistence(context.Context
|
|||||||
func (UnimplementedDaemonServiceServer) TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error) {
|
func (UnimplementedDaemonServiceServer) TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method TracePacket not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method TracePacket not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error {
|
func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, grpc.ServerStreamingServer[SystemEvent]) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method SubscribeEvents not implemented")
|
return status.Errorf(codes.Unimplemented, "method SubscribeEvents not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) {
|
func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedDaemonServiceServer) mustEmbedUnimplementedDaemonServiceServer() {}
|
func (UnimplementedDaemonServiceServer) mustEmbedUnimplementedDaemonServiceServer() {}
|
||||||
|
func (UnimplementedDaemonServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
// UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
// Use of this interface is not recommended, as added methods to DaemonServiceServer will
|
// Use of this interface is not recommended, as added methods to DaemonServiceServer will
|
||||||
@@ -386,6 +423,13 @@ type UnsafeDaemonServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterDaemonServiceServer(s grpc.ServiceRegistrar, srv DaemonServiceServer) {
|
func RegisterDaemonServiceServer(s grpc.ServiceRegistrar, srv DaemonServiceServer) {
|
||||||
|
// If the following call pancis, it indicates UnimplementedDaemonServiceServer was
|
||||||
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||||
|
t.testEmbeddedByValue()
|
||||||
|
}
|
||||||
s.RegisterService(&DaemonService_ServiceDesc, srv)
|
s.RegisterService(&DaemonService_ServiceDesc, srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +443,7 @@ func _DaemonService_Login_Handler(srv interface{}, ctx context.Context, dec func
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/Login",
|
FullMethod: DaemonService_Login_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).Login(ctx, req.(*LoginRequest))
|
return srv.(DaemonServiceServer).Login(ctx, req.(*LoginRequest))
|
||||||
@@ -417,7 +461,7 @@ func _DaemonService_WaitSSOLogin_Handler(srv interface{}, ctx context.Context, d
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/WaitSSOLogin",
|
FullMethod: DaemonService_WaitSSOLogin_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).WaitSSOLogin(ctx, req.(*WaitSSOLoginRequest))
|
return srv.(DaemonServiceServer).WaitSSOLogin(ctx, req.(*WaitSSOLoginRequest))
|
||||||
@@ -435,7 +479,7 @@ func _DaemonService_Up_Handler(srv interface{}, ctx context.Context, dec func(in
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/Up",
|
FullMethod: DaemonService_Up_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).Up(ctx, req.(*UpRequest))
|
return srv.(DaemonServiceServer).Up(ctx, req.(*UpRequest))
|
||||||
@@ -453,7 +497,7 @@ func _DaemonService_Status_Handler(srv interface{}, ctx context.Context, dec fun
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/Status",
|
FullMethod: DaemonService_Status_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).Status(ctx, req.(*StatusRequest))
|
return srv.(DaemonServiceServer).Status(ctx, req.(*StatusRequest))
|
||||||
@@ -471,7 +515,7 @@ func _DaemonService_Down_Handler(srv interface{}, ctx context.Context, dec func(
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/Down",
|
FullMethod: DaemonService_Down_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).Down(ctx, req.(*DownRequest))
|
return srv.(DaemonServiceServer).Down(ctx, req.(*DownRequest))
|
||||||
@@ -489,7 +533,7 @@ func _DaemonService_GetConfig_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/GetConfig",
|
FullMethod: DaemonService_GetConfig_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).GetConfig(ctx, req.(*GetConfigRequest))
|
return srv.(DaemonServiceServer).GetConfig(ctx, req.(*GetConfigRequest))
|
||||||
@@ -507,7 +551,7 @@ func _DaemonService_ListNetworks_Handler(srv interface{}, ctx context.Context, d
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/ListNetworks",
|
FullMethod: DaemonService_ListNetworks_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).ListNetworks(ctx, req.(*ListNetworksRequest))
|
return srv.(DaemonServiceServer).ListNetworks(ctx, req.(*ListNetworksRequest))
|
||||||
@@ -525,7 +569,7 @@ func _DaemonService_SelectNetworks_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/SelectNetworks",
|
FullMethod: DaemonService_SelectNetworks_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).SelectNetworks(ctx, req.(*SelectNetworksRequest))
|
return srv.(DaemonServiceServer).SelectNetworks(ctx, req.(*SelectNetworksRequest))
|
||||||
@@ -543,7 +587,7 @@ func _DaemonService_DeselectNetworks_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/DeselectNetworks",
|
FullMethod: DaemonService_DeselectNetworks_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).DeselectNetworks(ctx, req.(*SelectNetworksRequest))
|
return srv.(DaemonServiceServer).DeselectNetworks(ctx, req.(*SelectNetworksRequest))
|
||||||
@@ -561,7 +605,7 @@ func _DaemonService_ForwardingRules_Handler(srv interface{}, ctx context.Context
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/ForwardingRules",
|
FullMethod: DaemonService_ForwardingRules_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).ForwardingRules(ctx, req.(*EmptyRequest))
|
return srv.(DaemonServiceServer).ForwardingRules(ctx, req.(*EmptyRequest))
|
||||||
@@ -579,7 +623,7 @@ func _DaemonService_DebugBundle_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/DebugBundle",
|
FullMethod: DaemonService_DebugBundle_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).DebugBundle(ctx, req.(*DebugBundleRequest))
|
return srv.(DaemonServiceServer).DebugBundle(ctx, req.(*DebugBundleRequest))
|
||||||
@@ -597,7 +641,7 @@ func _DaemonService_GetLogLevel_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/GetLogLevel",
|
FullMethod: DaemonService_GetLogLevel_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).GetLogLevel(ctx, req.(*GetLogLevelRequest))
|
return srv.(DaemonServiceServer).GetLogLevel(ctx, req.(*GetLogLevelRequest))
|
||||||
@@ -615,7 +659,7 @@ func _DaemonService_SetLogLevel_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/SetLogLevel",
|
FullMethod: DaemonService_SetLogLevel_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).SetLogLevel(ctx, req.(*SetLogLevelRequest))
|
return srv.(DaemonServiceServer).SetLogLevel(ctx, req.(*SetLogLevelRequest))
|
||||||
@@ -633,7 +677,7 @@ func _DaemonService_ListStates_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/ListStates",
|
FullMethod: DaemonService_ListStates_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).ListStates(ctx, req.(*ListStatesRequest))
|
return srv.(DaemonServiceServer).ListStates(ctx, req.(*ListStatesRequest))
|
||||||
@@ -651,7 +695,7 @@ func _DaemonService_CleanState_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/CleanState",
|
FullMethod: DaemonService_CleanState_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).CleanState(ctx, req.(*CleanStateRequest))
|
return srv.(DaemonServiceServer).CleanState(ctx, req.(*CleanStateRequest))
|
||||||
@@ -669,7 +713,7 @@ func _DaemonService_DeleteState_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/DeleteState",
|
FullMethod: DaemonService_DeleteState_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).DeleteState(ctx, req.(*DeleteStateRequest))
|
return srv.(DaemonServiceServer).DeleteState(ctx, req.(*DeleteStateRequest))
|
||||||
@@ -687,7 +731,7 @@ func _DaemonService_SetNetworkMapPersistence_Handler(srv interface{}, ctx contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/SetNetworkMapPersistence",
|
FullMethod: DaemonService_SetNetworkMapPersistence_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).SetNetworkMapPersistence(ctx, req.(*SetNetworkMapPersistenceRequest))
|
return srv.(DaemonServiceServer).SetNetworkMapPersistence(ctx, req.(*SetNetworkMapPersistenceRequest))
|
||||||
@@ -705,7 +749,7 @@ func _DaemonService_TracePacket_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/TracePacket",
|
FullMethod: DaemonService_TracePacket_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).TracePacket(ctx, req.(*TracePacketRequest))
|
return srv.(DaemonServiceServer).TracePacket(ctx, req.(*TracePacketRequest))
|
||||||
@@ -718,21 +762,11 @@ func _DaemonService_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerS
|
|||||||
if err := stream.RecvMsg(m); err != nil {
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return srv.(DaemonServiceServer).SubscribeEvents(m, &daemonServiceSubscribeEventsServer{stream})
|
return srv.(DaemonServiceServer).SubscribeEvents(m, &grpc.GenericServerStream[SubscribeRequest, SystemEvent]{ServerStream: stream})
|
||||||
}
|
}
|
||||||
|
|
||||||
type DaemonService_SubscribeEventsServer interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Send(*SystemEvent) error
|
type DaemonService_SubscribeEventsServer = grpc.ServerStreamingServer[SystemEvent]
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type daemonServiceSubscribeEventsServer struct {
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *daemonServiceSubscribeEventsServer) Send(m *SystemEvent) error {
|
|
||||||
return x.ServerStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(GetEventsRequest)
|
in := new(GetEventsRequest)
|
||||||
@@ -744,7 +778,7 @@ func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/daemon.DaemonService/GetEvents",
|
FullMethod: DaemonService_GetEvents_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(DaemonServiceServer).GetEvents(ctx, req.(*GetEventsRequest))
|
return srv.(DaemonServiceServer).GetEvents(ctx, req.(*GetEventsRequest))
|
||||||
@@ -843,5 +877,5 @@ var DaemonService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
ServerStreams: true,
|
ServerStreams: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Metadata: "daemon.proto",
|
Metadata: "daemon/daemon.proto",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if ! which realpath > /dev/null 2>&1
|
|
||||||
then
|
|
||||||
echo realpath is not installed
|
|
||||||
echo run: brew install coreutils
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
old_pwd=$(pwd)
|
|
||||||
script_path=$(dirname $(realpath "$0"))
|
|
||||||
cd "$script_path"
|
|
||||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
|
||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
|
||||||
protoc -I ./ ./daemon.proto --go_out=../ --go-grpc_out=../ --experimental_allow_proto3_optional
|
|
||||||
cd "$old_pwd"
|
|
||||||
@@ -51,14 +51,16 @@ func (s *Server) DebugBundle(_ context.Context, req *proto.DebugBundleRequest) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if req.GetUploadURL() == "" {
|
if req.GetUploadURL() == "" {
|
||||||
|
|
||||||
return &proto.DebugBundleResponse{Path: path}, nil
|
return &proto.DebugBundleResponse{Path: path}, nil
|
||||||
}
|
}
|
||||||
key, err := uploadDebugBundle(context.Background(), req.GetUploadURL(), s.config.ManagementURL.String(), path)
|
key, err := uploadDebugBundle(context.Background(), req.GetUploadURL(), s.config.ManagementURL.String(), path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Errorf("failed to upload debug bundle to %s: %v", req.GetUploadURL(), err)
|
||||||
return &proto.DebugBundleResponse{Path: path, UploadFailureReason: err.Error()}, nil
|
return &proto.DebugBundleResponse{Path: path, UploadFailureReason: err.Error()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("debug bundle uploaded to %s with key %s", req.GetUploadURL(), key)
|
||||||
|
|
||||||
return &proto.DebugBundleResponse{Path: path, UploadedKey: key}, nil
|
return &proto.DebugBundleResponse{Path: path, UploadedKey: key}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,14 +51,17 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
daemonAddr, showSettings, showNetworks, errorMsg, saveLogsInFile := parseFlags()
|
daemonAddr, showSettings, showNetworks, showDebug, errorMsg, saveLogsInFile := parseFlags()
|
||||||
|
|
||||||
// Initialize file logging if needed.
|
// Initialize file logging if needed.
|
||||||
|
var logFile string
|
||||||
if saveLogsInFile {
|
if saveLogsInFile {
|
||||||
if err := initLogFile(); err != nil {
|
file, err := initLogFile()
|
||||||
|
if err != nil {
|
||||||
log.Errorf("error while initializing log: %v", err)
|
log.Errorf("error while initializing log: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
logFile = file
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the Fyne application.
|
// Create the Fyne application.
|
||||||
@@ -72,13 +75,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the service client (this also builds the settings or networks UI if requested).
|
// Create the service client (this also builds the settings or networks UI if requested).
|
||||||
client := newServiceClient(daemonAddr, a, showSettings, showNetworks)
|
client := newServiceClient(daemonAddr, logFile, a, showSettings, showNetworks, showDebug)
|
||||||
|
|
||||||
// Watch for theme/settings changes to update the icon.
|
// Watch for theme/settings changes to update the icon.
|
||||||
go watchSettingsChanges(a, client)
|
go watchSettingsChanges(a, client)
|
||||||
|
|
||||||
// Run in window mode if any UI flag was set.
|
// Run in window mode if any UI flag was set.
|
||||||
if showSettings || showNetworks {
|
if showSettings || showNetworks || showDebug {
|
||||||
a.Run()
|
a.Run()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -99,7 +102,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseFlags reads and returns all needed command-line flags.
|
// parseFlags reads and returns all needed command-line flags.
|
||||||
func parseFlags() (daemonAddr string, showSettings, showNetworks bool, errorMsg string, saveLogsInFile bool) {
|
func parseFlags() (daemonAddr string, showSettings, showNetworks, showDebug bool, errorMsg string, saveLogsInFile bool) {
|
||||||
defaultDaemonAddr := "unix:///var/run/netbird.sock"
|
defaultDaemonAddr := "unix:///var/run/netbird.sock"
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
defaultDaemonAddr = "tcp://127.0.0.1:41731"
|
defaultDaemonAddr = "tcp://127.0.0.1:41731"
|
||||||
@@ -107,25 +110,17 @@ func parseFlags() (daemonAddr string, showSettings, showNetworks bool, errorMsg
|
|||||||
flag.StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]")
|
flag.StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]")
|
||||||
flag.BoolVar(&showSettings, "settings", false, "run settings window")
|
flag.BoolVar(&showSettings, "settings", false, "run settings window")
|
||||||
flag.BoolVar(&showNetworks, "networks", false, "run networks window")
|
flag.BoolVar(&showNetworks, "networks", false, "run networks window")
|
||||||
|
flag.BoolVar(&showDebug, "debug", false, "run debug window")
|
||||||
flag.StringVar(&errorMsg, "error-msg", "", "displays an error message window")
|
flag.StringVar(&errorMsg, "error-msg", "", "displays an error message window")
|
||||||
|
flag.BoolVar(&saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", os.TempDir()))
|
||||||
tmpDir := "/tmp"
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
tmpDir = os.TempDir()
|
|
||||||
}
|
|
||||||
flag.BoolVar(&saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", tmpDir))
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// initLogFile initializes logging into a file.
|
// initLogFile initializes logging into a file.
|
||||||
func initLogFile() error {
|
func initLogFile() (string, error) {
|
||||||
tmpDir := "/tmp"
|
logFile := path.Join(os.TempDir(), fmt.Sprintf("netbird-ui-%d.log", os.Getpid()))
|
||||||
if runtime.GOOS == "windows" {
|
return logFile, util.InitLog("trace", logFile)
|
||||||
tmpDir = os.TempDir()
|
|
||||||
}
|
|
||||||
logFile := path.Join(tmpDir, fmt.Sprintf("netbird-ui-%d.log", os.Getpid()))
|
|
||||||
return util.InitLog("trace", logFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// watchSettingsChanges listens for Fyne theme/settings changes and updates the client icon.
|
// watchSettingsChanges listens for Fyne theme/settings changes and updates the client icon.
|
||||||
@@ -168,9 +163,10 @@ var iconConnectingMacOS []byte
|
|||||||
var iconErrorMacOS []byte
|
var iconErrorMacOS []byte
|
||||||
|
|
||||||
type serviceClient struct {
|
type serviceClient struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
addr string
|
cancel context.CancelFunc
|
||||||
conn proto.DaemonServiceClient
|
addr string
|
||||||
|
conn proto.DaemonServiceClient
|
||||||
|
|
||||||
icAbout []byte
|
icAbout []byte
|
||||||
icConnected []byte
|
icConnected []byte
|
||||||
@@ -231,13 +227,14 @@ type serviceClient struct {
|
|||||||
daemonVersion string
|
daemonVersion string
|
||||||
updateIndicationLock sync.Mutex
|
updateIndicationLock sync.Mutex
|
||||||
isUpdateIconActive bool
|
isUpdateIconActive bool
|
||||||
showRoutes bool
|
showNetworks bool
|
||||||
wRoutes fyne.Window
|
wNetworks fyne.Window
|
||||||
|
|
||||||
eventManager *event.Manager
|
eventManager *event.Manager
|
||||||
|
|
||||||
exitNodeMu sync.Mutex
|
exitNodeMu sync.Mutex
|
||||||
mExitNodeItems []menuHandler
|
mExitNodeItems []menuHandler
|
||||||
|
logFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
type menuHandler struct {
|
type menuHandler struct {
|
||||||
@@ -248,25 +245,30 @@ type menuHandler struct {
|
|||||||
// newServiceClient instance constructor
|
// newServiceClient instance constructor
|
||||||
//
|
//
|
||||||
// This constructor also builds the UI elements for the settings window.
|
// This constructor also builds the UI elements for the settings window.
|
||||||
func newServiceClient(addr string, a fyne.App, showSettings bool, showRoutes bool) *serviceClient {
|
func newServiceClient(addr string, logFile string, a fyne.App, showSettings bool, showNetworks bool, showDebug bool) *serviceClient {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
s := &serviceClient{
|
s := &serviceClient{
|
||||||
ctx: context.Background(),
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
app: a,
|
app: a,
|
||||||
|
logFile: logFile,
|
||||||
sendNotification: false,
|
sendNotification: false,
|
||||||
|
|
||||||
showAdvancedSettings: showSettings,
|
showAdvancedSettings: showSettings,
|
||||||
showRoutes: showRoutes,
|
showNetworks: showNetworks,
|
||||||
update: version.NewUpdate(),
|
update: version.NewUpdate(),
|
||||||
}
|
}
|
||||||
|
|
||||||
s.setNewIcons()
|
s.setNewIcons()
|
||||||
|
|
||||||
if showSettings {
|
switch {
|
||||||
|
case showSettings:
|
||||||
s.showSettingsUI()
|
s.showSettingsUI()
|
||||||
return s
|
case showNetworks:
|
||||||
} else if showRoutes {
|
|
||||||
s.showNetworksUI()
|
s.showNetworksUI()
|
||||||
|
case showDebug:
|
||||||
|
s.showDebugUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
@@ -313,6 +315,8 @@ func (s *serviceClient) updateIcon() {
|
|||||||
func (s *serviceClient) showSettingsUI() {
|
func (s *serviceClient) showSettingsUI() {
|
||||||
// add settings window UI elements.
|
// add settings window UI elements.
|
||||||
s.wSettings = s.app.NewWindow("NetBird Settings")
|
s.wSettings = s.app.NewWindow("NetBird Settings")
|
||||||
|
s.wSettings.SetOnClosed(s.cancel)
|
||||||
|
|
||||||
s.iMngURL = widget.NewEntry()
|
s.iMngURL = widget.NewEntry()
|
||||||
s.iAdminURL = widget.NewEntry()
|
s.iAdminURL = widget.NewEntry()
|
||||||
s.iConfigFile = widget.NewEntry()
|
s.iConfigFile = widget.NewEntry()
|
||||||
@@ -743,11 +747,10 @@ func (s *serviceClient) onTrayReady() {
|
|||||||
s.runSelfCommand("settings", "true")
|
s.runSelfCommand("settings", "true")
|
||||||
}()
|
}()
|
||||||
case <-s.mCreateDebugBundle.ClickedCh:
|
case <-s.mCreateDebugBundle.ClickedCh:
|
||||||
|
s.mCreateDebugBundle.Disable()
|
||||||
go func() {
|
go func() {
|
||||||
if err := s.createAndOpenDebugBundle(); err != nil {
|
defer s.mCreateDebugBundle.Enable()
|
||||||
log.Errorf("Failed to create debug bundle: %v", err)
|
s.runSelfCommand("debug", "true")
|
||||||
s.app.SendNotification(fyne.NewNotification("Error", "Failed to create debug bundle"))
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
case <-s.mQuit.ClickedCh:
|
case <-s.mQuit.ClickedCh:
|
||||||
systray.Quit()
|
systray.Quit()
|
||||||
@@ -789,7 +792,7 @@ func (s *serviceClient) onTrayReady() {
|
|||||||
func (s *serviceClient) runSelfCommand(command, arg string) {
|
func (s *serviceClient) runSelfCommand(command, arg string) {
|
||||||
proc, err := os.Executable()
|
proc, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("show %s failed with error: %v", command, err)
|
log.Errorf("Error getting executable path: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,14 +801,48 @@ func (s *serviceClient) runSelfCommand(command, arg string) {
|
|||||||
fmt.Sprintf("--daemon-addr=%s", s.addr),
|
fmt.Sprintf("--daemon-addr=%s", s.addr),
|
||||||
)
|
)
|
||||||
|
|
||||||
out, err := cmd.CombinedOutput()
|
if out := s.attachOutput(cmd); out != nil {
|
||||||
if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
|
defer func() {
|
||||||
log.Errorf("start %s UI: %v, %s", command, err, string(out))
|
if err := out.Close(); err != nil {
|
||||||
|
log.Errorf("Error closing log file %s: %v", s.logFile, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Running command: %s --%s=%s --daemon-addr=%s", proc, command, arg, s.addr)
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
var exitErr *exec.ExitError
|
||||||
|
if errors.As(err, &exitErr) {
|
||||||
|
log.Printf("Command '%s %s' failed with exit code %d", command, arg, exitErr.ExitCode())
|
||||||
|
} else {
|
||||||
|
log.Printf("Failed to start/run command '%s %s': %v", command, arg, err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(out) != 0 {
|
|
||||||
log.Infof("command %s executed: %s", command, string(out))
|
log.Printf("Command '%s %s' completed successfully.", command, arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) attachOutput(cmd *exec.Cmd) *os.File {
|
||||||
|
if s.logFile == "" {
|
||||||
|
// attach child's streams to parent's streams
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out, err := os.OpenFile(s.logFile, os.O_WRONLY|os.O_APPEND, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to open log file %s: %v", s.logFile, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cmd.Stdout = out
|
||||||
|
cmd.Stderr = out
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizedVersion(version string) string {
|
func normalizedVersion(version string) string {
|
||||||
@@ -818,9 +855,7 @@ func normalizedVersion(version string) string {
|
|||||||
|
|
||||||
// onTrayExit is called when the tray icon is closed.
|
// onTrayExit is called when the tray icon is closed.
|
||||||
func (s *serviceClient) onTrayExit() {
|
func (s *serviceClient) onTrayExit() {
|
||||||
for _, item := range s.mExitNodeItems {
|
s.cancel()
|
||||||
item.cancel()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSrvClient connection to the service.
|
// getSrvClient connection to the service.
|
||||||
@@ -829,7 +864,7 @@ func (s *serviceClient) getSrvClient(timeout time.Duration) (proto.DaemonService
|
|||||||
return s.conn, nil
|
return s.conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
ctx, cancel := context.WithTimeout(s.ctx, timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
conn, err := grpc.DialContext(
|
conn, err := grpc.DialContext(
|
||||||
|
|||||||
@@ -3,48 +3,721 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/dialog"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/skratchdot/open-golang/open"
|
"github.com/skratchdot/open-golang/open"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal"
|
||||||
"github.com/netbirdio/netbird/client/proto"
|
"github.com/netbirdio/netbird/client/proto"
|
||||||
nbstatus "github.com/netbirdio/netbird/client/status"
|
nbstatus "github.com/netbirdio/netbird/client/status"
|
||||||
|
uptypes "github.com/netbirdio/netbird/upload-server/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *serviceClient) createAndOpenDebugBundle() error {
|
// Initial state for the debug collection
|
||||||
|
type debugInitialState struct {
|
||||||
|
wasDown bool
|
||||||
|
logLevel proto.LogLevel
|
||||||
|
isLevelTrace bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug collection parameters
|
||||||
|
type debugCollectionParams struct {
|
||||||
|
duration time.Duration
|
||||||
|
anonymize bool
|
||||||
|
systemInfo bool
|
||||||
|
upload bool
|
||||||
|
uploadURL string
|
||||||
|
enablePersistence bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// UI components for progress tracking
|
||||||
|
type progressUI struct {
|
||||||
|
statusLabel *widget.Label
|
||||||
|
progressBar *widget.ProgressBar
|
||||||
|
uiControls []fyne.Disableable
|
||||||
|
window fyne.Window
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) showDebugUI() {
|
||||||
|
w := s.app.NewWindow("NetBird Debug")
|
||||||
|
w.SetOnClosed(s.cancel)
|
||||||
|
|
||||||
|
w.Resize(fyne.NewSize(600, 500))
|
||||||
|
w.SetFixedSize(true)
|
||||||
|
|
||||||
|
anonymizeCheck := widget.NewCheck("Anonymize sensitive information (public IPs, domains, ...)", nil)
|
||||||
|
systemInfoCheck := widget.NewCheck("Include system information (routes, interfaces, ...)", nil)
|
||||||
|
systemInfoCheck.SetChecked(true)
|
||||||
|
uploadCheck := widget.NewCheck("Upload bundle automatically after creation", nil)
|
||||||
|
uploadCheck.SetChecked(true)
|
||||||
|
|
||||||
|
uploadURLLabel := widget.NewLabel("Debug upload URL:")
|
||||||
|
uploadURL := widget.NewEntry()
|
||||||
|
uploadURL.SetText(uptypes.DefaultBundleURL)
|
||||||
|
uploadURL.SetPlaceHolder("Enter upload URL")
|
||||||
|
|
||||||
|
uploadURLContainer := container.NewVBox(
|
||||||
|
uploadURLLabel,
|
||||||
|
uploadURL,
|
||||||
|
)
|
||||||
|
|
||||||
|
uploadCheck.OnChanged = func(checked bool) {
|
||||||
|
if checked {
|
||||||
|
uploadURLContainer.Show()
|
||||||
|
} else {
|
||||||
|
uploadURLContainer.Hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debugModeContainer := container.NewHBox()
|
||||||
|
runForDurationCheck := widget.NewCheck("Run with trace logs before creating bundle", nil)
|
||||||
|
runForDurationCheck.SetChecked(true)
|
||||||
|
|
||||||
|
forLabel := widget.NewLabel("for")
|
||||||
|
|
||||||
|
durationInput := widget.NewEntry()
|
||||||
|
durationInput.SetText("1")
|
||||||
|
minutesLabel := widget.NewLabel("minute")
|
||||||
|
durationInput.Validator = func(s string) error {
|
||||||
|
return validateMinute(s, minutesLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
noteLabel := widget.NewLabel("Note: NetBird will be brought up and down during collection")
|
||||||
|
|
||||||
|
runForDurationCheck.OnChanged = func(checked bool) {
|
||||||
|
if checked {
|
||||||
|
forLabel.Show()
|
||||||
|
durationInput.Show()
|
||||||
|
minutesLabel.Show()
|
||||||
|
noteLabel.Show()
|
||||||
|
} else {
|
||||||
|
forLabel.Hide()
|
||||||
|
durationInput.Hide()
|
||||||
|
minutesLabel.Hide()
|
||||||
|
noteLabel.Hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debugModeContainer.Add(runForDurationCheck)
|
||||||
|
debugModeContainer.Add(forLabel)
|
||||||
|
debugModeContainer.Add(durationInput)
|
||||||
|
debugModeContainer.Add(minutesLabel)
|
||||||
|
|
||||||
|
statusLabel := widget.NewLabel("")
|
||||||
|
statusLabel.Hide()
|
||||||
|
|
||||||
|
progressBar := widget.NewProgressBar()
|
||||||
|
progressBar.Hide()
|
||||||
|
|
||||||
|
createButton := widget.NewButton("Create Debug Bundle", nil)
|
||||||
|
|
||||||
|
// UI controls that should be disabled during debug collection
|
||||||
|
uiControls := []fyne.Disableable{
|
||||||
|
anonymizeCheck,
|
||||||
|
systemInfoCheck,
|
||||||
|
uploadCheck,
|
||||||
|
uploadURL,
|
||||||
|
runForDurationCheck,
|
||||||
|
durationInput,
|
||||||
|
createButton,
|
||||||
|
}
|
||||||
|
|
||||||
|
createButton.OnTapped = s.getCreateHandler(
|
||||||
|
statusLabel,
|
||||||
|
progressBar,
|
||||||
|
uploadCheck,
|
||||||
|
uploadURL,
|
||||||
|
anonymizeCheck,
|
||||||
|
systemInfoCheck,
|
||||||
|
runForDurationCheck,
|
||||||
|
durationInput,
|
||||||
|
uiControls,
|
||||||
|
w,
|
||||||
|
)
|
||||||
|
|
||||||
|
content := container.NewVBox(
|
||||||
|
widget.NewLabel("Create a debug bundle to help troubleshoot issues with NetBird"),
|
||||||
|
widget.NewLabel(""),
|
||||||
|
anonymizeCheck,
|
||||||
|
systemInfoCheck,
|
||||||
|
uploadCheck,
|
||||||
|
uploadURLContainer,
|
||||||
|
widget.NewLabel(""),
|
||||||
|
debugModeContainer,
|
||||||
|
noteLabel,
|
||||||
|
widget.NewLabel(""),
|
||||||
|
statusLabel,
|
||||||
|
progressBar,
|
||||||
|
createButton,
|
||||||
|
)
|
||||||
|
|
||||||
|
paddedContent := container.NewPadded(content)
|
||||||
|
w.SetContent(paddedContent)
|
||||||
|
|
||||||
|
w.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateMinute(s string, minutesLabel *widget.Label) error {
|
||||||
|
if val, err := strconv.Atoi(s); err != nil || val < 1 {
|
||||||
|
return fmt.Errorf("must be a number ≥ 1")
|
||||||
|
}
|
||||||
|
if s == "1" {
|
||||||
|
minutesLabel.SetText("minute")
|
||||||
|
} else {
|
||||||
|
minutesLabel.SetText("minutes")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// disableUIControls disables the provided UI controls
|
||||||
|
func disableUIControls(controls []fyne.Disableable) {
|
||||||
|
for _, control := range controls {
|
||||||
|
control.Disable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// enableUIControls enables the provided UI controls
|
||||||
|
func enableUIControls(controls []fyne.Disableable) {
|
||||||
|
for _, control := range controls {
|
||||||
|
control.Enable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) getCreateHandler(
|
||||||
|
statusLabel *widget.Label,
|
||||||
|
progressBar *widget.ProgressBar,
|
||||||
|
uploadCheck *widget.Check,
|
||||||
|
uploadURL *widget.Entry,
|
||||||
|
anonymizeCheck *widget.Check,
|
||||||
|
systemInfoCheck *widget.Check,
|
||||||
|
runForDurationCheck *widget.Check,
|
||||||
|
duration *widget.Entry,
|
||||||
|
uiControls []fyne.Disableable,
|
||||||
|
w fyne.Window,
|
||||||
|
) func() {
|
||||||
|
return func() {
|
||||||
|
disableUIControls(uiControls)
|
||||||
|
statusLabel.Show()
|
||||||
|
|
||||||
|
var url string
|
||||||
|
if uploadCheck.Checked {
|
||||||
|
url = uploadURL.Text
|
||||||
|
if url == "" {
|
||||||
|
statusLabel.SetText("Error: Upload URL is required when upload is enabled")
|
||||||
|
enableUIControls(uiControls)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
params := &debugCollectionParams{
|
||||||
|
anonymize: anonymizeCheck.Checked,
|
||||||
|
systemInfo: systemInfoCheck.Checked,
|
||||||
|
upload: uploadCheck.Checked,
|
||||||
|
uploadURL: url,
|
||||||
|
enablePersistence: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
runForDuration := runForDurationCheck.Checked
|
||||||
|
if runForDuration {
|
||||||
|
minutes, err := time.ParseDuration(duration.Text + "m")
|
||||||
|
if err != nil {
|
||||||
|
statusLabel.SetText(fmt.Sprintf("Error: Invalid duration: %v", err))
|
||||||
|
enableUIControls(uiControls)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
params.duration = minutes
|
||||||
|
|
||||||
|
statusLabel.SetText(fmt.Sprintf("Running in debug mode for %d minutes...", int(minutes.Minutes())))
|
||||||
|
progressBar.Show()
|
||||||
|
progressBar.SetValue(0)
|
||||||
|
|
||||||
|
go s.handleRunForDuration(
|
||||||
|
statusLabel,
|
||||||
|
progressBar,
|
||||||
|
uiControls,
|
||||||
|
w,
|
||||||
|
params,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
statusLabel.SetText("Creating debug bundle...")
|
||||||
|
go s.handleDebugCreation(
|
||||||
|
anonymizeCheck.Checked,
|
||||||
|
systemInfoCheck.Checked,
|
||||||
|
uploadCheck.Checked,
|
||||||
|
url,
|
||||||
|
statusLabel,
|
||||||
|
uiControls,
|
||||||
|
w,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) handleRunForDuration(
|
||||||
|
statusLabel *widget.Label,
|
||||||
|
progressBar *widget.ProgressBar,
|
||||||
|
uiControls []fyne.Disableable,
|
||||||
|
w fyne.Window,
|
||||||
|
params *debugCollectionParams,
|
||||||
|
) {
|
||||||
|
progressUI := &progressUI{
|
||||||
|
statusLabel: statusLabel,
|
||||||
|
progressBar: progressBar,
|
||||||
|
uiControls: uiControls,
|
||||||
|
window: w,
|
||||||
|
}
|
||||||
|
|
||||||
conn, err := s.getSrvClient(failFastTimeout)
|
conn, err := s.getSrvClient(failFastTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get client: %v", err)
|
handleError(progressUI, fmt.Sprintf("Failed to get client for debug: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
initialState, err := s.getInitialState(conn)
|
||||||
|
if err != nil {
|
||||||
|
handleError(progressUI, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
statusOutput, err := s.collectDebugData(conn, initialState, params, progressUI)
|
||||||
|
if err != nil {
|
||||||
|
handleError(progressUI, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.createDebugBundleFromCollection(conn, params, statusOutput, progressUI); err != nil {
|
||||||
|
handleError(progressUI, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.restoreServiceState(conn, initialState)
|
||||||
|
|
||||||
|
progressUI.statusLabel.SetText("Bundle created successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get initial state of the service
|
||||||
|
func (s *serviceClient) getInitialState(conn proto.DaemonServiceClient) (*debugInitialState, error) {
|
||||||
|
statusResp, err := conn.Status(s.ctx, &proto.StatusRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(" get status: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logLevelResp, err := conn.GetLogLevel(s.ctx, &proto.GetLogLevelRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get log level: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wasDown := statusResp.Status != string(internal.StatusConnected) &&
|
||||||
|
statusResp.Status != string(internal.StatusConnecting)
|
||||||
|
|
||||||
|
initialLogLevel := logLevelResp.GetLevel()
|
||||||
|
initialLevelTrace := initialLogLevel >= proto.LogLevel_TRACE
|
||||||
|
|
||||||
|
return &debugInitialState{
|
||||||
|
wasDown: wasDown,
|
||||||
|
logLevel: initialLogLevel,
|
||||||
|
isLevelTrace: initialLevelTrace,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle progress tracking during collection
|
||||||
|
func startProgressTracker(ctx context.Context, wg *sync.WaitGroup, duration time.Duration, progress *progressUI) {
|
||||||
|
progress.progressBar.Show()
|
||||||
|
progress.progressBar.SetValue(0)
|
||||||
|
|
||||||
|
startTime := time.Now()
|
||||||
|
endTime := startTime.Add(duration)
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
ticker := time.NewTicker(500 * time.Millisecond)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
remaining := time.Until(endTime)
|
||||||
|
if remaining <= 0 {
|
||||||
|
remaining = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsed := time.Since(startTime)
|
||||||
|
progressVal := float64(elapsed) / float64(duration)
|
||||||
|
if progressVal > 1.0 {
|
||||||
|
progressVal = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
progress.progressBar.SetValue(progressVal)
|
||||||
|
progress.statusLabel.SetText(fmt.Sprintf("Running with trace logs... %s remaining", formatDuration(remaining)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) configureServiceForDebug(
|
||||||
|
conn proto.DaemonServiceClient,
|
||||||
|
state *debugInitialState,
|
||||||
|
enablePersistence bool,
|
||||||
|
) error {
|
||||||
|
if state.wasDown {
|
||||||
|
if _, err := conn.Up(s.ctx, &proto.UpRequest{}); err != nil {
|
||||||
|
return fmt.Errorf("bring service up: %v", err)
|
||||||
|
}
|
||||||
|
log.Info("Service brought up for debug")
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !state.isLevelTrace {
|
||||||
|
if _, err := conn.SetLogLevel(s.ctx, &proto.SetLogLevelRequest{Level: proto.LogLevel_TRACE}); err != nil {
|
||||||
|
return fmt.Errorf("set log level to TRACE: %v", err)
|
||||||
|
}
|
||||||
|
log.Info("Log level set to TRACE for debug")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := conn.Down(s.ctx, &proto.DownRequest{}); err != nil {
|
||||||
|
return fmt.Errorf("bring service down: %v", err)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
if enablePersistence {
|
||||||
|
if _, err := conn.SetNetworkMapPersistence(s.ctx, &proto.SetNetworkMapPersistenceRequest{
|
||||||
|
Enabled: true,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("enable network map persistence: %v", err)
|
||||||
|
}
|
||||||
|
log.Info("Network map persistence enabled for debug")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := conn.Up(s.ctx, &proto.UpRequest{}); err != nil {
|
||||||
|
return fmt.Errorf("bring service back up: %v", err)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) collectDebugData(
|
||||||
|
conn proto.DaemonServiceClient,
|
||||||
|
state *debugInitialState,
|
||||||
|
params *debugCollectionParams,
|
||||||
|
progress *progressUI,
|
||||||
|
) (string, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(s.ctx, params.duration)
|
||||||
|
defer cancel()
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
startProgressTracker(ctx, &wg, params.duration, progress)
|
||||||
|
|
||||||
|
if err := s.configureServiceForDebug(conn, state, params.enablePersistence); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
postUpStatus, err := conn.Status(s.ctx, &proto.StatusRequest{GetFullPeerStatus: true})
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to get post-up status: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var postUpStatusOutput string
|
||||||
|
if postUpStatus != nil {
|
||||||
|
overview := nbstatus.ConvertToStatusOutputOverview(postUpStatus, params.anonymize, "", nil, nil, nil)
|
||||||
|
postUpStatusOutput = nbstatus.ParseToFullDetailSummary(overview)
|
||||||
|
}
|
||||||
|
headerPostUp := fmt.Sprintf("----- NetBird post-up - Timestamp: %s", time.Now().Format(time.RFC3339))
|
||||||
|
statusOutput := fmt.Sprintf("%s\n%s", headerPostUp, postUpStatusOutput)
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
progress.progressBar.Hide()
|
||||||
|
progress.statusLabel.SetText("Collecting debug data...")
|
||||||
|
|
||||||
|
preDownStatus, err := conn.Status(s.ctx, &proto.StatusRequest{GetFullPeerStatus: true})
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to get pre-down status: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var preDownStatusOutput string
|
||||||
|
if preDownStatus != nil {
|
||||||
|
overview := nbstatus.ConvertToStatusOutputOverview(preDownStatus, params.anonymize, "", nil, nil, nil)
|
||||||
|
preDownStatusOutput = nbstatus.ParseToFullDetailSummary(overview)
|
||||||
|
}
|
||||||
|
headerPreDown := fmt.Sprintf("----- NetBird pre-down - Timestamp: %s - Duration: %s",
|
||||||
|
time.Now().Format(time.RFC3339), params.duration)
|
||||||
|
statusOutput = fmt.Sprintf("%s\n%s\n%s", statusOutput, headerPreDown, preDownStatusOutput)
|
||||||
|
|
||||||
|
return statusOutput, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the debug bundle with collected data
|
||||||
|
func (s *serviceClient) createDebugBundleFromCollection(
|
||||||
|
conn proto.DaemonServiceClient,
|
||||||
|
params *debugCollectionParams,
|
||||||
|
statusOutput string,
|
||||||
|
progress *progressUI,
|
||||||
|
) error {
|
||||||
|
progress.statusLabel.SetText("Creating debug bundle with collected logs...")
|
||||||
|
|
||||||
|
request := &proto.DebugBundleRequest{
|
||||||
|
Anonymize: params.anonymize,
|
||||||
|
Status: statusOutput,
|
||||||
|
SystemInfo: params.systemInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.upload {
|
||||||
|
request.UploadURL = params.uploadURL
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := conn.DebugBundle(s.ctx, request)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create debug bundle: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show appropriate dialog based on upload status
|
||||||
|
localPath := resp.GetPath()
|
||||||
|
uploadFailureReason := resp.GetUploadFailureReason()
|
||||||
|
uploadedKey := resp.GetUploadedKey()
|
||||||
|
|
||||||
|
if params.upload {
|
||||||
|
if uploadFailureReason != "" {
|
||||||
|
showUploadFailedDialog(progress.window, localPath, uploadFailureReason)
|
||||||
|
} else {
|
||||||
|
showUploadSuccessDialog(progress.window, localPath, uploadedKey)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showBundleCreatedDialog(progress.window, localPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
enableUIControls(progress.uiControls)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore service to original state
|
||||||
|
func (s *serviceClient) restoreServiceState(conn proto.DaemonServiceClient, state *debugInitialState) {
|
||||||
|
if state.wasDown {
|
||||||
|
if _, err := conn.Down(s.ctx, &proto.DownRequest{}); err != nil {
|
||||||
|
log.Errorf("Failed to restore down state: %v", err)
|
||||||
|
} else {
|
||||||
|
log.Info("Service state restored to down")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !state.isLevelTrace {
|
||||||
|
if _, err := conn.SetLogLevel(s.ctx, &proto.SetLogLevelRequest{Level: state.logLevel}); err != nil {
|
||||||
|
log.Errorf("Failed to restore log level: %v", err)
|
||||||
|
} else {
|
||||||
|
log.Info("Log level restored to original setting")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle errors during debug collection
|
||||||
|
func handleError(progress *progressUI, errMsg string) {
|
||||||
|
log.Errorf("%s", errMsg)
|
||||||
|
progress.statusLabel.SetText(errMsg)
|
||||||
|
progress.progressBar.Hide()
|
||||||
|
enableUIControls(progress.uiControls)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) handleDebugCreation(
|
||||||
|
anonymize bool,
|
||||||
|
systemInfo bool,
|
||||||
|
upload bool,
|
||||||
|
uploadURL string,
|
||||||
|
statusLabel *widget.Label,
|
||||||
|
uiControls []fyne.Disableable,
|
||||||
|
w fyne.Window,
|
||||||
|
) {
|
||||||
|
log.Infof("Creating debug bundle (Anonymized: %v, System Info: %v, Upload Attempt: %v)...",
|
||||||
|
anonymize, systemInfo, upload)
|
||||||
|
|
||||||
|
resp, err := s.createDebugBundle(anonymize, systemInfo, uploadURL)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to create debug bundle: %v", err)
|
||||||
|
statusLabel.SetText(fmt.Sprintf("Error creating bundle: %v", err))
|
||||||
|
enableUIControls(uiControls)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
localPath := resp.GetPath()
|
||||||
|
uploadFailureReason := resp.GetUploadFailureReason()
|
||||||
|
uploadedKey := resp.GetUploadedKey()
|
||||||
|
|
||||||
|
if upload {
|
||||||
|
if uploadFailureReason != "" {
|
||||||
|
showUploadFailedDialog(w, localPath, uploadFailureReason)
|
||||||
|
} else {
|
||||||
|
showUploadSuccessDialog(w, localPath, uploadedKey)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showBundleCreatedDialog(w, localPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
enableUIControls(uiControls)
|
||||||
|
statusLabel.SetText("Bundle created successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceClient) createDebugBundle(anonymize bool, systemInfo bool, uploadURL string) (*proto.DebugBundleResponse, error) {
|
||||||
|
conn, err := s.getSrvClient(failFastTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
statusResp, err := conn.Status(s.ctx, &proto.StatusRequest{GetFullPeerStatus: true})
|
statusResp, err := conn.Status(s.ctx, &proto.StatusRequest{GetFullPeerStatus: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get status: %v", err)
|
log.Warnf("failed to get status for debug bundle: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
overview := nbstatus.ConvertToStatusOutputOverview(statusResp, true, "", nil, nil, nil)
|
var statusOutput string
|
||||||
statusOutput := nbstatus.ParseToFullDetailSummary(overview)
|
if statusResp != nil {
|
||||||
|
overview := nbstatus.ConvertToStatusOutputOverview(statusResp, anonymize, "", nil, nil, nil)
|
||||||
|
statusOutput = nbstatus.ParseToFullDetailSummary(overview)
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := conn.DebugBundle(s.ctx, &proto.DebugBundleRequest{
|
request := &proto.DebugBundleRequest{
|
||||||
Anonymize: true,
|
Anonymize: anonymize,
|
||||||
Status: statusOutput,
|
Status: statusOutput,
|
||||||
SystemInfo: true,
|
SystemInfo: systemInfo,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if uploadURL != "" {
|
||||||
|
request.UploadURL = uploadURL
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := conn.DebugBundle(s.ctx, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create debug bundle: %v", err)
|
return nil, fmt.Errorf("failed to create debug bundle via daemon: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bundleDir := filepath.Dir(resp.GetPath())
|
return resp, nil
|
||||||
if err := open.Start(bundleDir); err != nil {
|
}
|
||||||
return fmt.Errorf("failed to open debug bundle directory: %v", err)
|
|
||||||
}
|
// formatDuration formats a duration in HH:MM:SS format
|
||||||
|
func formatDuration(d time.Duration) string {
|
||||||
s.app.SendNotification(fyne.NewNotification(
|
d = d.Round(time.Second)
|
||||||
"Debug Bundle",
|
h := d / time.Hour
|
||||||
fmt.Sprintf("Debug bundle created at %s. Administrator privileges are required to access it.", resp.GetPath()),
|
d %= time.Hour
|
||||||
))
|
m := d / time.Minute
|
||||||
|
d %= time.Minute
|
||||||
return nil
|
s := d / time.Second
|
||||||
|
return fmt.Sprintf("%02d:%02d:%02d", h, m, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// createButtonWithAction creates a button with the given label and action
|
||||||
|
func createButtonWithAction(label string, action func()) *widget.Button {
|
||||||
|
button := widget.NewButton(label, action)
|
||||||
|
return button
|
||||||
|
}
|
||||||
|
|
||||||
|
// showUploadFailedDialog displays a dialog when upload fails
|
||||||
|
func showUploadFailedDialog(w fyne.Window, localPath, failureReason string) {
|
||||||
|
content := container.NewVBox(
|
||||||
|
widget.NewLabel(fmt.Sprintf("Bundle upload failed:\n%s\n\n"+
|
||||||
|
"A local copy was saved at:\n%s", failureReason, localPath)),
|
||||||
|
)
|
||||||
|
|
||||||
|
customDialog := dialog.NewCustom("Upload Failed", "Cancel", content, w)
|
||||||
|
|
||||||
|
buttonBox := container.NewHBox(
|
||||||
|
createButtonWithAction("Open file", func() {
|
||||||
|
log.Infof("Attempting to open local file: %s", localPath)
|
||||||
|
if openErr := open.Start(localPath); openErr != nil {
|
||||||
|
log.Errorf("Failed to open local file '%s': %v", localPath, openErr)
|
||||||
|
dialog.ShowError(fmt.Errorf("open the local file:\n%s\n\nError: %v", localPath, openErr), w)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
createButtonWithAction("Open folder", func() {
|
||||||
|
folderPath := filepath.Dir(localPath)
|
||||||
|
log.Infof("Attempting to open local folder: %s", folderPath)
|
||||||
|
if openErr := open.Start(folderPath); openErr != nil {
|
||||||
|
log.Errorf("Failed to open local folder '%s': %v", folderPath, openErr)
|
||||||
|
dialog.ShowError(fmt.Errorf("open the local folder:\n%s\n\nError: %v", folderPath, openErr), w)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
content.Add(buttonBox)
|
||||||
|
customDialog.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// showUploadSuccessDialog displays a dialog when upload succeeds
|
||||||
|
func showUploadSuccessDialog(w fyne.Window, localPath, uploadedKey string) {
|
||||||
|
log.Infof("Upload key: %s", uploadedKey)
|
||||||
|
keyEntry := widget.NewEntry()
|
||||||
|
keyEntry.SetText(uploadedKey)
|
||||||
|
keyEntry.Disable()
|
||||||
|
|
||||||
|
content := container.NewVBox(
|
||||||
|
widget.NewLabel("Bundle uploaded successfully!"),
|
||||||
|
widget.NewLabel(""),
|
||||||
|
widget.NewLabel("Upload key:"),
|
||||||
|
keyEntry,
|
||||||
|
widget.NewLabel(""),
|
||||||
|
widget.NewLabel(fmt.Sprintf("Local copy saved at:\n%s", localPath)),
|
||||||
|
)
|
||||||
|
|
||||||
|
customDialog := dialog.NewCustom("Upload Successful", "OK", content, w)
|
||||||
|
|
||||||
|
copyBtn := createButtonWithAction("Copy key", func() {
|
||||||
|
w.Clipboard().SetContent(uploadedKey)
|
||||||
|
log.Info("Upload key copied to clipboard")
|
||||||
|
})
|
||||||
|
|
||||||
|
buttonBox := createButtonBox(localPath, w, copyBtn)
|
||||||
|
content.Add(buttonBox)
|
||||||
|
customDialog.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// showBundleCreatedDialog displays a dialog when bundle is created without upload
|
||||||
|
func showBundleCreatedDialog(w fyne.Window, localPath string) {
|
||||||
|
content := container.NewVBox(
|
||||||
|
widget.NewLabel(fmt.Sprintf("Bundle created locally at:\n%s\n\n"+
|
||||||
|
"Administrator privileges may be required to access the file.", localPath)),
|
||||||
|
)
|
||||||
|
|
||||||
|
customDialog := dialog.NewCustom("Debug Bundle Created", "Cancel", content, w)
|
||||||
|
|
||||||
|
buttonBox := createButtonBox(localPath, w, nil)
|
||||||
|
content.Add(buttonBox)
|
||||||
|
customDialog.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func createButtonBox(localPath string, w fyne.Window, elems ...fyne.Widget) *fyne.Container {
|
||||||
|
box := container.NewHBox()
|
||||||
|
for _, elem := range elems {
|
||||||
|
box.Add(elem)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileBtn := createButtonWithAction("Open file", func() {
|
||||||
|
log.Infof("Attempting to open local file: %s", localPath)
|
||||||
|
if openErr := open.Start(localPath); openErr != nil {
|
||||||
|
log.Errorf("Failed to open local file '%s': %v", localPath, openErr)
|
||||||
|
dialog.ShowError(fmt.Errorf("open the local file:\n%s\n\nError: %v", localPath, openErr), w)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
folderBtn := createButtonWithAction("Open folder", func() {
|
||||||
|
folderPath := filepath.Dir(localPath)
|
||||||
|
log.Infof("Attempting to open local folder: %s", folderPath)
|
||||||
|
if openErr := open.Start(folderPath); openErr != nil {
|
||||||
|
log.Errorf("Failed to open local folder '%s': %v", folderPath, openErr)
|
||||||
|
dialog.ShowError(fmt.Errorf("open the local folder:\n%s\n\nError: %v", folderPath, openErr), w)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
box.Add(fileBtn)
|
||||||
|
box.Add(folderBtn)
|
||||||
|
|
||||||
|
return box
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ const (
|
|||||||
type filter string
|
type filter string
|
||||||
|
|
||||||
func (s *serviceClient) showNetworksUI() {
|
func (s *serviceClient) showNetworksUI() {
|
||||||
s.wRoutes = s.app.NewWindow("Networks")
|
s.wNetworks = s.app.NewWindow("Networks")
|
||||||
|
s.wNetworks.SetOnClosed(s.cancel)
|
||||||
|
|
||||||
allGrid := container.New(layout.NewGridLayout(3))
|
allGrid := container.New(layout.NewGridLayout(3))
|
||||||
go s.updateNetworks(allGrid, allNetworks)
|
go s.updateNetworks(allGrid, allNetworks)
|
||||||
@@ -78,8 +79,8 @@ func (s *serviceClient) showNetworksUI() {
|
|||||||
|
|
||||||
content := container.NewBorder(nil, buttonBox, nil, nil, scrollContainer)
|
content := container.NewBorder(nil, buttonBox, nil, nil, scrollContainer)
|
||||||
|
|
||||||
s.wRoutes.SetContent(content)
|
s.wNetworks.SetContent(content)
|
||||||
s.wRoutes.Show()
|
s.wNetworks.Show()
|
||||||
|
|
||||||
s.startAutoRefresh(10*time.Second, tabs, allGrid, overlappingGrid, exitNodeGrid)
|
s.startAutoRefresh(10*time.Second, tabs, allGrid, overlappingGrid, exitNodeGrid)
|
||||||
}
|
}
|
||||||
@@ -148,7 +149,7 @@ func (s *serviceClient) updateNetworks(grid *fyne.Container, f filter) {
|
|||||||
grid.Add(resolvedIPsSelector)
|
grid.Add(resolvedIPsSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.wRoutes.Content().Refresh()
|
s.wNetworks.Content().Refresh()
|
||||||
grid.Refresh()
|
grid.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +306,7 @@ func (s *serviceClient) getNetworksRequest(f filter, appendRoute bool) *proto.Se
|
|||||||
func (s *serviceClient) showError(err error) {
|
func (s *serviceClient) showError(err error) {
|
||||||
wrappedMessage := wrapText(err.Error(), 50)
|
wrappedMessage := wrapText(err.Error(), 50)
|
||||||
|
|
||||||
dialog.ShowError(fmt.Errorf("%s", wrappedMessage), s.wRoutes)
|
dialog.ShowError(fmt.Errorf("%s", wrappedMessage), s.wNetworks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *serviceClient) startAutoRefresh(interval time.Duration, tabs *container.AppTabs, allGrid, overlappingGrid, exitNodesGrid *fyne.Container) {
|
func (s *serviceClient) startAutoRefresh(interval time.Duration, tabs *container.AppTabs, allGrid, overlappingGrid, exitNodesGrid *fyne.Container) {
|
||||||
@@ -316,14 +317,15 @@ func (s *serviceClient) startAutoRefresh(interval time.Duration, tabs *container
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
s.wRoutes.SetOnClosed(func() {
|
s.wNetworks.SetOnClosed(func() {
|
||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
|
s.cancel()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *serviceClient) updateNetworksBasedOnDisplayTab(tabs *container.AppTabs, allGrid, overlappingGrid, exitNodesGrid *fyne.Container) {
|
func (s *serviceClient) updateNetworksBasedOnDisplayTab(tabs *container.AppTabs, allGrid, overlappingGrid, exitNodesGrid *fyne.Container) {
|
||||||
grid, f := getGridAndFilterFromTab(tabs, allGrid, overlappingGrid, exitNodesGrid)
|
grid, f := getGridAndFilterFromTab(tabs, allGrid, overlappingGrid, exitNodesGrid)
|
||||||
s.wRoutes.Content().Refresh()
|
s.wNetworks.Content().Refresh()
|
||||||
s.updateNetworks(grid, f)
|
s.updateNetworks(grid, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +375,7 @@ func (s *serviceClient) recreateExitNodeMenu(exitNodes []*proto.Network) {
|
|||||||
node.Selected,
|
node.Selected,
|
||||||
)
|
)
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(s.ctx)
|
||||||
s.mExitNodeItems = append(s.mExitNodeItems, menuHandler{
|
s.mExitNodeItems = append(s.mExitNodeItems, menuHandler{
|
||||||
MenuItem: menuItem,
|
MenuItem: menuItem,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
|
|||||||
@@ -66,17 +66,17 @@ func (s SimpleRecord) String() string {
|
|||||||
func (s SimpleRecord) Len() uint16 {
|
func (s SimpleRecord) Len() uint16 {
|
||||||
emptyString := s.RData == ""
|
emptyString := s.RData == ""
|
||||||
switch s.Type {
|
switch s.Type {
|
||||||
case 1:
|
case int(dns.TypeA):
|
||||||
if emptyString {
|
if emptyString {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return net.IPv4len
|
return net.IPv4len
|
||||||
case 5:
|
case int(dns.TypeCNAME):
|
||||||
if emptyString || s.RData == "." {
|
if emptyString || s.RData == "." {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
return uint16(len(s.RData) + 1)
|
return uint16(len(s.RData) + 1)
|
||||||
case 28:
|
case int(dns.TypeAAAA):
|
||||||
if emptyString {
|
if emptyString {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
protoc -I testprotos/ testprotos/testproto.proto --go_out=.
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.35.1
|
||||||
// protoc v3.12.4
|
// protoc (unknown)
|
||||||
// source: testproto.proto
|
// source: testprotos/testproto.proto
|
||||||
|
|
||||||
package testprotos
|
package testprotos
|
||||||
|
|
||||||
@@ -30,11 +30,9 @@ type TestMessage struct {
|
|||||||
|
|
||||||
func (x *TestMessage) Reset() {
|
func (x *TestMessage) Reset() {
|
||||||
*x = TestMessage{}
|
*x = TestMessage{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_testprotos_testproto_proto_msgTypes[0]
|
||||||
mi := &file_testproto_proto_msgTypes[0]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TestMessage) String() string {
|
func (x *TestMessage) String() string {
|
||||||
@@ -44,8 +42,8 @@ func (x *TestMessage) String() string {
|
|||||||
func (*TestMessage) ProtoMessage() {}
|
func (*TestMessage) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *TestMessage) ProtoReflect() protoreflect.Message {
|
func (x *TestMessage) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_testproto_proto_msgTypes[0]
|
mi := &file_testprotos_testproto_proto_msgTypes[0]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -57,7 +55,7 @@ func (x *TestMessage) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use TestMessage.ProtoReflect.Descriptor instead.
|
// Deprecated: Use TestMessage.ProtoReflect.Descriptor instead.
|
||||||
func (*TestMessage) Descriptor() ([]byte, []int) {
|
func (*TestMessage) Descriptor() ([]byte, []int) {
|
||||||
return file_testproto_proto_rawDescGZIP(), []int{0}
|
return file_testprotos_testproto_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TestMessage) GetBody() string {
|
func (x *TestMessage) GetBody() string {
|
||||||
@@ -67,34 +65,35 @@ func (x *TestMessage) GetBody() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_testproto_proto protoreflect.FileDescriptor
|
var File_testprotos_testproto_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_testproto_proto_rawDesc = []byte{
|
var file_testprotos_testproto_proto_rawDesc = []byte{
|
||||||
0x0a, 0x0f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
0x0a, 0x1a, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x65, 0x73,
|
||||||
0x6f, 0x12, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x21, 0x0a,
|
0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x74, 0x65,
|
||||||
0x0b, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x21, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74,
|
||||||
0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79,
|
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
|
||||||
0x42, 0x0d, 0x5a, 0x0b, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x42, 0x17, 0x5a, 0x15, 0x65,
|
||||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_testproto_proto_rawDescOnce sync.Once
|
file_testprotos_testproto_proto_rawDescOnce sync.Once
|
||||||
file_testproto_proto_rawDescData = file_testproto_proto_rawDesc
|
file_testprotos_testproto_proto_rawDescData = file_testprotos_testproto_proto_rawDesc
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_testproto_proto_rawDescGZIP() []byte {
|
func file_testprotos_testproto_proto_rawDescGZIP() []byte {
|
||||||
file_testproto_proto_rawDescOnce.Do(func() {
|
file_testprotos_testproto_proto_rawDescOnce.Do(func() {
|
||||||
file_testproto_proto_rawDescData = protoimpl.X.CompressGZIP(file_testproto_proto_rawDescData)
|
file_testprotos_testproto_proto_rawDescData = protoimpl.X.CompressGZIP(file_testprotos_testproto_proto_rawDescData)
|
||||||
})
|
})
|
||||||
return file_testproto_proto_rawDescData
|
return file_testprotos_testproto_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_testproto_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
var file_testprotos_testproto_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
var file_testproto_proto_goTypes = []interface{}{
|
var file_testprotos_testproto_proto_goTypes = []any{
|
||||||
(*TestMessage)(nil), // 0: testprotos.TestMessage
|
(*TestMessage)(nil), // 0: testprotos.TestMessage
|
||||||
}
|
}
|
||||||
var file_testproto_proto_depIdxs = []int32{
|
var file_testprotos_testproto_proto_depIdxs = []int32{
|
||||||
0, // [0:0] is the sub-list for method output_type
|
0, // [0:0] is the sub-list for method output_type
|
||||||
0, // [0:0] is the sub-list for method input_type
|
0, // [0:0] is the sub-list for method input_type
|
||||||
0, // [0:0] is the sub-list for extension type_name
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
@@ -102,41 +101,27 @@ var file_testproto_proto_depIdxs = []int32{
|
|||||||
0, // [0:0] is the sub-list for field type_name
|
0, // [0:0] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_testproto_proto_init() }
|
func init() { file_testprotos_testproto_proto_init() }
|
||||||
func file_testproto_proto_init() {
|
func file_testprotos_testproto_proto_init() {
|
||||||
if File_testproto_proto != nil {
|
if File_testprotos_testproto_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_testproto_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*TestMessage); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_testproto_proto_rawDesc,
|
RawDescriptor: file_testprotos_testproto_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 1,
|
NumMessages: 1,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
GoTypes: file_testproto_proto_goTypes,
|
GoTypes: file_testprotos_testproto_proto_goTypes,
|
||||||
DependencyIndexes: file_testproto_proto_depIdxs,
|
DependencyIndexes: file_testprotos_testproto_proto_depIdxs,
|
||||||
MessageInfos: file_testproto_proto_msgTypes,
|
MessageInfos: file_testprotos_testproto_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_testproto_proto = out.File
|
File_testprotos_testproto_proto = out.File
|
||||||
file_testproto_proto_rawDesc = nil
|
file_testprotos_testproto_proto_rawDesc = nil
|
||||||
file_testproto_proto_goTypes = nil
|
file_testprotos_testproto_proto_goTypes = nil
|
||||||
file_testproto_proto_depIdxs = nil
|
file_testprotos_testproto_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.35.1
|
||||||
// protoc v3.21.9
|
// protoc (unknown)
|
||||||
// source: flow.proto
|
// source: flow/flow.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
@@ -58,11 +58,11 @@ func (x Type) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (Type) Descriptor() protoreflect.EnumDescriptor {
|
func (Type) Descriptor() protoreflect.EnumDescriptor {
|
||||||
return file_flow_proto_enumTypes[0].Descriptor()
|
return file_flow_flow_proto_enumTypes[0].Descriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Type) Type() protoreflect.EnumType {
|
func (Type) Type() protoreflect.EnumType {
|
||||||
return &file_flow_proto_enumTypes[0]
|
return &file_flow_flow_proto_enumTypes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x Type) Number() protoreflect.EnumNumber {
|
func (x Type) Number() protoreflect.EnumNumber {
|
||||||
@@ -71,7 +71,7 @@ func (x Type) Number() protoreflect.EnumNumber {
|
|||||||
|
|
||||||
// Deprecated: Use Type.Descriptor instead.
|
// Deprecated: Use Type.Descriptor instead.
|
||||||
func (Type) EnumDescriptor() ([]byte, []int) {
|
func (Type) EnumDescriptor() ([]byte, []int) {
|
||||||
return file_flow_proto_rawDescGZIP(), []int{0}
|
return file_flow_flow_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flow direction
|
// Flow direction
|
||||||
@@ -108,11 +108,11 @@ func (x Direction) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (Direction) Descriptor() protoreflect.EnumDescriptor {
|
func (Direction) Descriptor() protoreflect.EnumDescriptor {
|
||||||
return file_flow_proto_enumTypes[1].Descriptor()
|
return file_flow_flow_proto_enumTypes[1].Descriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Direction) Type() protoreflect.EnumType {
|
func (Direction) Type() protoreflect.EnumType {
|
||||||
return &file_flow_proto_enumTypes[1]
|
return &file_flow_flow_proto_enumTypes[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x Direction) Number() protoreflect.EnumNumber {
|
func (x Direction) Number() protoreflect.EnumNumber {
|
||||||
@@ -121,7 +121,7 @@ func (x Direction) Number() protoreflect.EnumNumber {
|
|||||||
|
|
||||||
// Deprecated: Use Direction.Descriptor instead.
|
// Deprecated: Use Direction.Descriptor instead.
|
||||||
func (Direction) EnumDescriptor() ([]byte, []int) {
|
func (Direction) EnumDescriptor() ([]byte, []int) {
|
||||||
return file_flow_proto_rawDescGZIP(), []int{1}
|
return file_flow_flow_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FlowEvent struct {
|
type FlowEvent struct {
|
||||||
@@ -141,11 +141,9 @@ type FlowEvent struct {
|
|||||||
|
|
||||||
func (x *FlowEvent) Reset() {
|
func (x *FlowEvent) Reset() {
|
||||||
*x = FlowEvent{}
|
*x = FlowEvent{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_flow_flow_proto_msgTypes[0]
|
||||||
mi := &file_flow_proto_msgTypes[0]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FlowEvent) String() string {
|
func (x *FlowEvent) String() string {
|
||||||
@@ -155,8 +153,8 @@ func (x *FlowEvent) String() string {
|
|||||||
func (*FlowEvent) ProtoMessage() {}
|
func (*FlowEvent) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *FlowEvent) ProtoReflect() protoreflect.Message {
|
func (x *FlowEvent) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_flow_proto_msgTypes[0]
|
mi := &file_flow_flow_proto_msgTypes[0]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -168,7 +166,7 @@ func (x *FlowEvent) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use FlowEvent.ProtoReflect.Descriptor instead.
|
// Deprecated: Use FlowEvent.ProtoReflect.Descriptor instead.
|
||||||
func (*FlowEvent) Descriptor() ([]byte, []int) {
|
func (*FlowEvent) Descriptor() ([]byte, []int) {
|
||||||
return file_flow_proto_rawDescGZIP(), []int{0}
|
return file_flow_flow_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FlowEvent) GetEventId() []byte {
|
func (x *FlowEvent) GetEventId() []byte {
|
||||||
@@ -218,11 +216,9 @@ type FlowEventAck struct {
|
|||||||
|
|
||||||
func (x *FlowEventAck) Reset() {
|
func (x *FlowEventAck) Reset() {
|
||||||
*x = FlowEventAck{}
|
*x = FlowEventAck{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_flow_flow_proto_msgTypes[1]
|
||||||
mi := &file_flow_proto_msgTypes[1]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FlowEventAck) String() string {
|
func (x *FlowEventAck) String() string {
|
||||||
@@ -232,8 +228,8 @@ func (x *FlowEventAck) String() string {
|
|||||||
func (*FlowEventAck) ProtoMessage() {}
|
func (*FlowEventAck) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *FlowEventAck) ProtoReflect() protoreflect.Message {
|
func (x *FlowEventAck) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_flow_proto_msgTypes[1]
|
mi := &file_flow_flow_proto_msgTypes[1]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -245,7 +241,7 @@ func (x *FlowEventAck) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use FlowEventAck.ProtoReflect.Descriptor instead.
|
// Deprecated: Use FlowEventAck.ProtoReflect.Descriptor instead.
|
||||||
func (*FlowEventAck) Descriptor() ([]byte, []int) {
|
func (*FlowEventAck) Descriptor() ([]byte, []int) {
|
||||||
return file_flow_proto_rawDescGZIP(), []int{1}
|
return file_flow_flow_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FlowEventAck) GetEventId() []byte {
|
func (x *FlowEventAck) GetEventId() []byte {
|
||||||
@@ -301,11 +297,9 @@ type FlowFields struct {
|
|||||||
|
|
||||||
func (x *FlowFields) Reset() {
|
func (x *FlowFields) Reset() {
|
||||||
*x = FlowFields{}
|
*x = FlowFields{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_flow_flow_proto_msgTypes[2]
|
||||||
mi := &file_flow_proto_msgTypes[2]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FlowFields) String() string {
|
func (x *FlowFields) String() string {
|
||||||
@@ -315,8 +309,8 @@ func (x *FlowFields) String() string {
|
|||||||
func (*FlowFields) ProtoMessage() {}
|
func (*FlowFields) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *FlowFields) ProtoReflect() protoreflect.Message {
|
func (x *FlowFields) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_flow_proto_msgTypes[2]
|
mi := &file_flow_flow_proto_msgTypes[2]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -328,7 +322,7 @@ func (x *FlowFields) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use FlowFields.ProtoReflect.Descriptor instead.
|
// Deprecated: Use FlowFields.ProtoReflect.Descriptor instead.
|
||||||
func (*FlowFields) Descriptor() ([]byte, []int) {
|
func (*FlowFields) Descriptor() ([]byte, []int) {
|
||||||
return file_flow_proto_rawDescGZIP(), []int{2}
|
return file_flow_flow_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FlowFields) GetFlowId() []byte {
|
func (x *FlowFields) GetFlowId() []byte {
|
||||||
@@ -473,11 +467,9 @@ type PortInfo struct {
|
|||||||
|
|
||||||
func (x *PortInfo) Reset() {
|
func (x *PortInfo) Reset() {
|
||||||
*x = PortInfo{}
|
*x = PortInfo{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_flow_flow_proto_msgTypes[3]
|
||||||
mi := &file_flow_proto_msgTypes[3]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PortInfo) String() string {
|
func (x *PortInfo) String() string {
|
||||||
@@ -487,8 +479,8 @@ func (x *PortInfo) String() string {
|
|||||||
func (*PortInfo) ProtoMessage() {}
|
func (*PortInfo) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *PortInfo) ProtoReflect() protoreflect.Message {
|
func (x *PortInfo) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_flow_proto_msgTypes[3]
|
mi := &file_flow_flow_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -500,7 +492,7 @@ func (x *PortInfo) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use PortInfo.ProtoReflect.Descriptor instead.
|
// Deprecated: Use PortInfo.ProtoReflect.Descriptor instead.
|
||||||
func (*PortInfo) Descriptor() ([]byte, []int) {
|
func (*PortInfo) Descriptor() ([]byte, []int) {
|
||||||
return file_flow_proto_rawDescGZIP(), []int{3}
|
return file_flow_flow_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PortInfo) GetSourcePort() uint32 {
|
func (x *PortInfo) GetSourcePort() uint32 {
|
||||||
@@ -529,11 +521,9 @@ type ICMPInfo struct {
|
|||||||
|
|
||||||
func (x *ICMPInfo) Reset() {
|
func (x *ICMPInfo) Reset() {
|
||||||
*x = ICMPInfo{}
|
*x = ICMPInfo{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_flow_flow_proto_msgTypes[4]
|
||||||
mi := &file_flow_proto_msgTypes[4]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ICMPInfo) String() string {
|
func (x *ICMPInfo) String() string {
|
||||||
@@ -543,8 +533,8 @@ func (x *ICMPInfo) String() string {
|
|||||||
func (*ICMPInfo) ProtoMessage() {}
|
func (*ICMPInfo) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ICMPInfo) ProtoReflect() protoreflect.Message {
|
func (x *ICMPInfo) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_flow_proto_msgTypes[4]
|
mi := &file_flow_flow_proto_msgTypes[4]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -556,7 +546,7 @@ func (x *ICMPInfo) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use ICMPInfo.ProtoReflect.Descriptor instead.
|
// Deprecated: Use ICMPInfo.ProtoReflect.Descriptor instead.
|
||||||
func (*ICMPInfo) Descriptor() ([]byte, []int) {
|
func (*ICMPInfo) Descriptor() ([]byte, []int) {
|
||||||
return file_flow_proto_rawDescGZIP(), []int{4}
|
return file_flow_flow_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ICMPInfo) GetIcmpType() uint32 {
|
func (x *ICMPInfo) GetIcmpType() uint32 {
|
||||||
@@ -573,104 +563,105 @@ func (x *ICMPInfo) GetIcmpCode() uint32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_flow_proto protoreflect.FileDescriptor
|
var File_flow_flow_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_flow_proto_rawDesc = []byte{
|
var file_flow_flow_proto_rawDesc = []byte{
|
||||||
0x0a, 0x0a, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x66, 0x6c,
|
0x0a, 0x0f, 0x66, 0x6c, 0x6f, 0x77, 0x2f, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x6f, 0x77, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x6f, 0x12, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
|
||||||
0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
|
||||||
0x6f, 0x74, 0x6f, 0x22, 0xd4, 0x01, 0x0a, 0x09, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e,
|
0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd4, 0x01, 0x0a, 0x09, 0x46, 0x6c, 0x6f,
|
||||||
0x74, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
|
0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f,
|
||||||
0x01, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x09,
|
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49,
|
||||||
0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02,
|
||||||
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||||
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d,
|
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x70,
|
||||||
0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c,
|
0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||||
0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x0b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x66, 0x69,
|
0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x0b, 0x66, 0x6c,
|
||||||
0x65, 0x6c, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x66, 0x6c, 0x6f,
|
0x6f, 0x77, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x77, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x0a, 0x66, 0x6c,
|
0x10, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
||||||
0x6f, 0x77, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x49, 0x6e,
|
0x73, 0x52, 0x0a, 0x66, 0x6c, 0x6f, 0x77, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x20, 0x0a,
|
||||||
0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69,
|
0x0b, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01,
|
||||||
0x73, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x4b, 0x0a, 0x0c, 0x46, 0x6c,
|
0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x22,
|
||||||
0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x6b, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76,
|
0x4b, 0x0a, 0x0c, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x6b, 0x12,
|
||||||
0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x76,
|
0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x69,
|
0x0c, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73,
|
||||||
0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x49, 0x6e,
|
0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x9c, 0x04, 0x0a, 0x0a, 0x46, 0x6c, 0x6f, 0x77,
|
0x0b, 0x69, 0x73, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x9c, 0x04, 0x0a,
|
||||||
0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69,
|
0x0a, 0x46, 0x6c, 0x6f, 0x77, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x66,
|
||||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12,
|
0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x66, 0x6c,
|
||||||
0x1e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0a, 0x2e,
|
0x6f, 0x77, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
|
0x28, 0x0e, 0x32, 0x0a, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
|
||||||
0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
0x74, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18,
|
||||||
0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65,
|
0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a,
|
||||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x66, 0x6c,
|
0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e,
|
||||||
0x6f, 0x77, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69,
|
0x32, 0x0f, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f,
|
||||||
0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08,
|
||||||
0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08,
|
||||||
0x63, 0x6f, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x70,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72,
|
||||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x70,
|
0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x6f, 0x75,
|
||||||
0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28,
|
0x72, 0x63, 0x65, 0x49, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x70,
|
||||||
0x0c, 0x52, 0x06, 0x64, 0x65, 0x73, 0x74, 0x49, 0x70, 0x12, 0x2d, 0x0a, 0x09, 0x70, 0x6f, 0x72,
|
0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x64, 0x65, 0x73, 0x74, 0x49, 0x70, 0x12, 0x2d,
|
||||||
0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x66,
|
0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28,
|
||||||
0x6c, 0x6f, 0x77, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x08,
|
0x0b, 0x32, 0x0e, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66,
|
||||||
0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2d, 0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70,
|
0x6f, 0x48, 0x00, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2d, 0x0a,
|
||||||
0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x66, 0x6c,
|
0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x6f, 0x77, 0x2e, 0x49, 0x43, 0x4d, 0x50, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x08, 0x69,
|
0x32, 0x0e, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x43, 0x4d, 0x50, 0x49, 0x6e, 0x66, 0x6f,
|
||||||
0x63, 0x6d, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x78, 0x5f, 0x70, 0x61,
|
0x48, 0x00, 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a,
|
||||||
0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x78, 0x50,
|
0x72, 0x78, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04,
|
||||||
0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x78, 0x5f, 0x70, 0x61, 0x63,
|
0x52, 0x09, 0x72, 0x78, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74,
|
||||||
0x6b, 0x65, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x78, 0x50, 0x61,
|
0x78, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||||
0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65,
|
0x09, 0x74, 0x78, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x78,
|
||||||
0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x72, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73,
|
0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x72, 0x78,
|
||||||
0x12, 0x19, 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x01,
|
0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x62, 0x79, 0x74, 0x65,
|
||||||
0x28, 0x04, 0x52, 0x07, 0x74, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73,
|
0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x74, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73,
|
||||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69,
|
0x12, 0x2c, 0x0a, 0x12, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75,
|
||||||
0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52,
|
0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x73, 0x6f,
|
||||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x65, 0x73,
|
0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x28,
|
||||||
0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0f, 0x20,
|
0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
|
||||||
0x01, 0x28, 0x0c, 0x52, 0x0e, 0x64, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
0x69, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x64, 0x65, 0x73, 0x74, 0x52, 0x65,
|
||||||
0x65, 0x49, 0x64, 0x42, 0x11, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
|
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x42, 0x11, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e,
|
||||||
0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x48, 0x0a, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e,
|
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x48, 0x0a, 0x08, 0x50,
|
||||||
0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x72,
|
0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||||
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50,
|
0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x6f,
|
||||||
0x6f, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74,
|
0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x73, 0x74,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, 0x65, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74,
|
0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, 0x65, 0x73,
|
||||||
0x22, 0x44, 0x0a, 0x08, 0x49, 0x43, 0x4d, 0x50, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09,
|
0x74, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x44, 0x0a, 0x08, 0x49, 0x43, 0x4d, 0x50, 0x49, 0x6e, 0x66,
|
||||||
0x69, 0x63, 0x6d, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
|
||||||
0x08, 0x69, 0x63, 0x6d, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x63, 0x6d,
|
0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b,
|
||||||
0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, 0x63,
|
0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x6d, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x2a, 0x45, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10,
|
0x0d, 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x2a, 0x45, 0x0a, 0x04, 0x54,
|
||||||
0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00,
|
0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e,
|
||||||
0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01,
|
0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54,
|
||||||
0x12, 0x0c, 0x0a, 0x08, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x0d,
|
0x41, 0x52, 0x54, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e,
|
||||||
0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x03, 0x2a, 0x3b, 0x0a,
|
0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x52, 0x4f, 0x50,
|
||||||
0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x49,
|
0x10, 0x03, 0x2a, 0x3b, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12,
|
||||||
0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
|
0x15, 0x0a, 0x11, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b,
|
||||||
0x00, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x0a,
|
0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53,
|
||||||
0x0a, 0x06, 0x45, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x02, 0x32, 0x42, 0x0a, 0x0b, 0x46, 0x6c,
|
0x53, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x02, 0x32,
|
||||||
0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x45, 0x76, 0x65,
|
0x42, 0x0a, 0x0b, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x33,
|
||||||
0x6e, 0x74, 0x73, 0x12, 0x0f, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x45,
|
0x0a, 0x06, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x0f, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e,
|
||||||
0x76, 0x65, 0x6e, 0x74, 0x1a, 0x12, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x46, 0x6c, 0x6f, 0x77,
|
0x46, 0x6c, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0x12, 0x2e, 0x66, 0x6c, 0x6f, 0x77,
|
||||||
0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x08,
|
0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x28,
|
||||||
0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x01, 0x30, 0x01, 0x42, 0x0c, 0x5a, 0x0a, 0x66, 0x6c, 0x6f, 0x77, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||||
|
0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_flow_proto_rawDescOnce sync.Once
|
file_flow_flow_proto_rawDescOnce sync.Once
|
||||||
file_flow_proto_rawDescData = file_flow_proto_rawDesc
|
file_flow_flow_proto_rawDescData = file_flow_flow_proto_rawDesc
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_flow_proto_rawDescGZIP() []byte {
|
func file_flow_flow_proto_rawDescGZIP() []byte {
|
||||||
file_flow_proto_rawDescOnce.Do(func() {
|
file_flow_flow_proto_rawDescOnce.Do(func() {
|
||||||
file_flow_proto_rawDescData = protoimpl.X.CompressGZIP(file_flow_proto_rawDescData)
|
file_flow_flow_proto_rawDescData = protoimpl.X.CompressGZIP(file_flow_flow_proto_rawDescData)
|
||||||
})
|
})
|
||||||
return file_flow_proto_rawDescData
|
return file_flow_flow_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_flow_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_flow_flow_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||||
var file_flow_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
var file_flow_flow_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
var file_flow_proto_goTypes = []interface{}{
|
var file_flow_flow_proto_goTypes = []any{
|
||||||
(Type)(0), // 0: flow.Type
|
(Type)(0), // 0: flow.Type
|
||||||
(Direction)(0), // 1: flow.Direction
|
(Direction)(0), // 1: flow.Direction
|
||||||
(*FlowEvent)(nil), // 2: flow.FlowEvent
|
(*FlowEvent)(nil), // 2: flow.FlowEvent
|
||||||
@@ -680,7 +671,7 @@ var file_flow_proto_goTypes = []interface{}{
|
|||||||
(*ICMPInfo)(nil), // 6: flow.ICMPInfo
|
(*ICMPInfo)(nil), // 6: flow.ICMPInfo
|
||||||
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
|
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
|
||||||
}
|
}
|
||||||
var file_flow_proto_depIdxs = []int32{
|
var file_flow_flow_proto_depIdxs = []int32{
|
||||||
7, // 0: flow.FlowEvent.timestamp:type_name -> google.protobuf.Timestamp
|
7, // 0: flow.FlowEvent.timestamp:type_name -> google.protobuf.Timestamp
|
||||||
4, // 1: flow.FlowEvent.flow_fields:type_name -> flow.FlowFields
|
4, // 1: flow.FlowEvent.flow_fields:type_name -> flow.FlowFields
|
||||||
0, // 2: flow.FlowFields.type:type_name -> flow.Type
|
0, // 2: flow.FlowFields.type:type_name -> flow.Type
|
||||||
@@ -696,74 +687,12 @@ var file_flow_proto_depIdxs = []int32{
|
|||||||
0, // [0:6] is the sub-list for field type_name
|
0, // [0:6] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_flow_proto_init() }
|
func init() { file_flow_flow_proto_init() }
|
||||||
func file_flow_proto_init() {
|
func file_flow_flow_proto_init() {
|
||||||
if File_flow_proto != nil {
|
if File_flow_flow_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !protoimpl.UnsafeEnabled {
|
file_flow_flow_proto_msgTypes[2].OneofWrappers = []any{
|
||||||
file_flow_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*FlowEvent); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_flow_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*FlowEventAck); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_flow_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*FlowFields); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_flow_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*PortInfo); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_flow_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*ICMPInfo); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_flow_proto_msgTypes[2].OneofWrappers = []interface{}{
|
|
||||||
(*FlowFields_PortInfo)(nil),
|
(*FlowFields_PortInfo)(nil),
|
||||||
(*FlowFields_IcmpInfo)(nil),
|
(*FlowFields_IcmpInfo)(nil),
|
||||||
}
|
}
|
||||||
@@ -771,19 +700,19 @@ func file_flow_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_flow_proto_rawDesc,
|
RawDescriptor: file_flow_flow_proto_rawDesc,
|
||||||
NumEnums: 2,
|
NumEnums: 2,
|
||||||
NumMessages: 5,
|
NumMessages: 5,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
GoTypes: file_flow_proto_goTypes,
|
GoTypes: file_flow_flow_proto_goTypes,
|
||||||
DependencyIndexes: file_flow_proto_depIdxs,
|
DependencyIndexes: file_flow_flow_proto_depIdxs,
|
||||||
EnumInfos: file_flow_proto_enumTypes,
|
EnumInfos: file_flow_flow_proto_enumTypes,
|
||||||
MessageInfos: file_flow_proto_msgTypes,
|
MessageInfos: file_flow_flow_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_flow_proto = out.File
|
File_flow_flow_proto = out.File
|
||||||
file_flow_proto_rawDesc = nil
|
file_flow_flow_proto_rawDesc = nil
|
||||||
file_flow_proto_goTypes = nil
|
file_flow_flow_proto_goTypes = nil
|
||||||
file_flow_proto_depIdxs = nil
|
file_flow_flow_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
|
// - protoc (unknown)
|
||||||
|
// source: flow/flow.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
@@ -11,15 +15,19 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.64.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
|
const (
|
||||||
|
FlowService_Events_FullMethodName = "/flow.FlowService/Events"
|
||||||
|
)
|
||||||
|
|
||||||
// FlowServiceClient is the client API for FlowService service.
|
// FlowServiceClient is the client API for FlowService service.
|
||||||
//
|
//
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
type FlowServiceClient interface {
|
type FlowServiceClient interface {
|
||||||
// Client to receiver streams of events and acknowledgements
|
// Client to receiver streams of events and acknowledgements
|
||||||
Events(ctx context.Context, opts ...grpc.CallOption) (FlowService_EventsClient, error)
|
Events(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[FlowEvent, FlowEventAck], error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type flowServiceClient struct {
|
type flowServiceClient struct {
|
||||||
@@ -30,54 +38,40 @@ func NewFlowServiceClient(cc grpc.ClientConnInterface) FlowServiceClient {
|
|||||||
return &flowServiceClient{cc}
|
return &flowServiceClient{cc}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *flowServiceClient) Events(ctx context.Context, opts ...grpc.CallOption) (FlowService_EventsClient, error) {
|
func (c *flowServiceClient) Events(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[FlowEvent, FlowEventAck], error) {
|
||||||
stream, err := c.cc.NewStream(ctx, &FlowService_ServiceDesc.Streams[0], "/flow.FlowService/Events", opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
stream, err := c.cc.NewStream(ctx, &FlowService_ServiceDesc.Streams[0], FlowService_Events_FullMethodName, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
x := &flowServiceEventsClient{stream}
|
x := &grpc.GenericClientStream[FlowEvent, FlowEventAck]{ClientStream: stream}
|
||||||
return x, nil
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type FlowService_EventsClient interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Send(*FlowEvent) error
|
type FlowService_EventsClient = grpc.BidiStreamingClient[FlowEvent, FlowEventAck]
|
||||||
Recv() (*FlowEventAck, error)
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type flowServiceEventsClient struct {
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *flowServiceEventsClient) Send(m *FlowEvent) error {
|
|
||||||
return x.ClientStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *flowServiceEventsClient) Recv() (*FlowEventAck, error) {
|
|
||||||
m := new(FlowEventAck)
|
|
||||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlowServiceServer is the server API for FlowService service.
|
// FlowServiceServer is the server API for FlowService service.
|
||||||
// All implementations must embed UnimplementedFlowServiceServer
|
// All implementations must embed UnimplementedFlowServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility.
|
||||||
type FlowServiceServer interface {
|
type FlowServiceServer interface {
|
||||||
// Client to receiver streams of events and acknowledgements
|
// Client to receiver streams of events and acknowledgements
|
||||||
Events(FlowService_EventsServer) error
|
Events(grpc.BidiStreamingServer[FlowEvent, FlowEventAck]) error
|
||||||
mustEmbedUnimplementedFlowServiceServer()
|
mustEmbedUnimplementedFlowServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnimplementedFlowServiceServer must be embedded to have forward compatible implementations.
|
// UnimplementedFlowServiceServer must be embedded to have
|
||||||
type UnimplementedFlowServiceServer struct {
|
// forward compatible implementations.
|
||||||
}
|
//
|
||||||
|
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||||
|
// pointer dereference when methods are called.
|
||||||
|
type UnimplementedFlowServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedFlowServiceServer) Events(FlowService_EventsServer) error {
|
func (UnimplementedFlowServiceServer) Events(grpc.BidiStreamingServer[FlowEvent, FlowEventAck]) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method Events not implemented")
|
return status.Errorf(codes.Unimplemented, "method Events not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedFlowServiceServer) mustEmbedUnimplementedFlowServiceServer() {}
|
func (UnimplementedFlowServiceServer) mustEmbedUnimplementedFlowServiceServer() {}
|
||||||
|
func (UnimplementedFlowServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
// UnsafeFlowServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeFlowServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
// Use of this interface is not recommended, as added methods to FlowServiceServer will
|
// Use of this interface is not recommended, as added methods to FlowServiceServer will
|
||||||
@@ -87,34 +81,22 @@ type UnsafeFlowServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterFlowServiceServer(s grpc.ServiceRegistrar, srv FlowServiceServer) {
|
func RegisterFlowServiceServer(s grpc.ServiceRegistrar, srv FlowServiceServer) {
|
||||||
|
// If the following call pancis, it indicates UnimplementedFlowServiceServer was
|
||||||
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||||
|
t.testEmbeddedByValue()
|
||||||
|
}
|
||||||
s.RegisterService(&FlowService_ServiceDesc, srv)
|
s.RegisterService(&FlowService_ServiceDesc, srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _FlowService_Events_Handler(srv interface{}, stream grpc.ServerStream) error {
|
func _FlowService_Events_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
return srv.(FlowServiceServer).Events(&flowServiceEventsServer{stream})
|
return srv.(FlowServiceServer).Events(&grpc.GenericServerStream[FlowEvent, FlowEventAck]{ServerStream: stream})
|
||||||
}
|
}
|
||||||
|
|
||||||
type FlowService_EventsServer interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Send(*FlowEventAck) error
|
type FlowService_EventsServer = grpc.BidiStreamingServer[FlowEvent, FlowEventAck]
|
||||||
Recv() (*FlowEvent, error)
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type flowServiceEventsServer struct {
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *flowServiceEventsServer) Send(m *FlowEventAck) error {
|
|
||||||
return x.ServerStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *flowServiceEventsServer) Recv() (*FlowEvent, error) {
|
|
||||||
m := new(FlowEvent)
|
|
||||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlowService_ServiceDesc is the grpc.ServiceDesc for FlowService service.
|
// FlowService_ServiceDesc is the grpc.ServiceDesc for FlowService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
@@ -131,5 +113,5 @@ var FlowService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
ClientStreams: true,
|
ClientStreams: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Metadata: "flow.proto",
|
Metadata: "flow/flow.proto",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if ! which realpath > /dev/null 2>&1
|
|
||||||
then
|
|
||||||
echo realpath is not installed
|
|
||||||
echo run: brew install coreutils
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
old_pwd=$(pwd)
|
|
||||||
script_path=$(dirname $(realpath "$0"))
|
|
||||||
cd "$script_path"
|
|
||||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
|
||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
|
||||||
protoc -I ./ ./flow.proto --go_out=../ --go-grpc_out=../
|
|
||||||
cd "$old_pwd"
|
|
||||||
@@ -20,7 +20,9 @@ func (a *AccountsAPI) List(ctx context.Context) ([]api.Account, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Account](resp)
|
ret, err := parseResponse[[]api.Account](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -36,7 +38,9 @@ func (a *AccountsAPI) Update(ctx context.Context, accountID string, request api.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Account](resp)
|
ret, err := parseResponse[api.Account](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *AccountsAPI) Delete(ctx context.Context, accountID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *DNSAPI) ListNameserverGroups(ctx context.Context) ([]api.NameserverGrou
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.NameserverGroup](resp)
|
ret, err := parseResponse[[]api.NameserverGroup](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *DNSAPI) GetNameserverGroup(ctx context.Context, nameserverGroupID strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NameserverGroup](resp)
|
ret, err := parseResponse[api.NameserverGroup](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *DNSAPI) CreateNameserverGroup(ctx context.Context, request api.PostApiD
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NameserverGroup](resp)
|
ret, err := parseResponse[api.NameserverGroup](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,9 @@ func (a *DNSAPI) UpdateNameserverGroup(ctx context.Context, nameserverGroupID st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NameserverGroup](resp)
|
ret, err := parseResponse[api.NameserverGroup](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,9 @@ func (a *DNSAPI) DeleteNameserverGroup(ctx context.Context, nameserverGroupID st
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -88,7 +98,9 @@ func (a *DNSAPI) GetSettings(ctx context.Context) (*api.DNSSettings, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.DNSSettings](resp)
|
ret, err := parseResponse[api.DNSSettings](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -104,7 +116,9 @@ func (a *DNSAPI) UpdateSettings(ctx context.Context, request api.PutApiDnsSettin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.DNSSettings](resp)
|
ret, err := parseResponse[api.DNSSettings](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ func (a *EventsAPI) List(ctx context.Context) ([]api.Event, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Event](resp)
|
ret, err := parseResponse[[]api.Event](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ func (a *GeoLocationAPI) ListCountries(ctx context.Context) ([]api.Country, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Country](resp)
|
ret, err := parseResponse[[]api.Country](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -30,7 +32,9 @@ func (a *GeoLocationAPI) ListCountryCities(ctx context.Context, countryCode stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.City](resp)
|
ret, err := parseResponse[[]api.City](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *GroupsAPI) List(ctx context.Context) ([]api.Group, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Group](resp)
|
ret, err := parseResponse[[]api.Group](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *GroupsAPI) Get(ctx context.Context, groupID string) (*api.Group, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Group](resp)
|
ret, err := parseResponse[api.Group](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *GroupsAPI) Create(ctx context.Context, request api.PostApiGroupsJSONReq
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Group](resp)
|
ret, err := parseResponse[api.Group](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,9 @@ func (a *GroupsAPI) Update(ctx context.Context, groupID string, request api.PutA
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Group](resp)
|
ret, err := parseResponse[api.Group](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,9 @@ func (a *GroupsAPI) Delete(ctx context.Context, groupID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *NetworksAPI) List(ctx context.Context) ([]api.Network, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Network](resp)
|
ret, err := parseResponse[[]api.Network](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *NetworksAPI) Get(ctx context.Context, networkID string) (*api.Network,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Network](resp)
|
ret, err := parseResponse[api.Network](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *NetworksAPI) Create(ctx context.Context, request api.PostApiNetworksJSO
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Network](resp)
|
ret, err := parseResponse[api.Network](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,9 @@ func (a *NetworksAPI) Update(ctx context.Context, networkID string, request api.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Network](resp)
|
ret, err := parseResponse[api.Network](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,9 @@ func (a *NetworksAPI) Delete(ctx context.Context, networkID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -102,7 +112,9 @@ func (a *NetworkResourcesAPI) List(ctx context.Context) ([]api.NetworkResource,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.NetworkResource](resp)
|
ret, err := parseResponse[[]api.NetworkResource](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -114,7 +126,9 @@ func (a *NetworkResourcesAPI) Get(ctx context.Context, networkResourceID string)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NetworkResource](resp)
|
ret, err := parseResponse[api.NetworkResource](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -130,7 +144,9 @@ func (a *NetworkResourcesAPI) Create(ctx context.Context, request api.PostApiNet
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NetworkResource](resp)
|
ret, err := parseResponse[api.NetworkResource](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -146,7 +162,9 @@ func (a *NetworkResourcesAPI) Update(ctx context.Context, networkResourceID stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NetworkResource](resp)
|
ret, err := parseResponse[api.NetworkResource](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -158,7 +176,9 @@ func (a *NetworkResourcesAPI) Delete(ctx context.Context, networkResourceID stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -184,7 +204,9 @@ func (a *NetworkRoutersAPI) List(ctx context.Context) ([]api.NetworkRouter, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.NetworkRouter](resp)
|
ret, err := parseResponse[[]api.NetworkRouter](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -196,7 +218,9 @@ func (a *NetworkRoutersAPI) Get(ctx context.Context, networkRouterID string) (*a
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NetworkRouter](resp)
|
ret, err := parseResponse[api.NetworkRouter](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -212,7 +236,9 @@ func (a *NetworkRoutersAPI) Create(ctx context.Context, request api.PostApiNetwo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NetworkRouter](resp)
|
ret, err := parseResponse[api.NetworkRouter](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -228,7 +254,9 @@ func (a *NetworkRoutersAPI) Update(ctx context.Context, networkRouterID string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.NetworkRouter](resp)
|
ret, err := parseResponse[api.NetworkRouter](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -240,7 +268,9 @@ func (a *NetworkRoutersAPI) Delete(ctx context.Context, networkRouterID string)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *PeersAPI) List(ctx context.Context) ([]api.Peer, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Peer](resp)
|
ret, err := parseResponse[[]api.Peer](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *PeersAPI) Get(ctx context.Context, peerID string) (*api.Peer, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Peer](resp)
|
ret, err := parseResponse[api.Peer](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *PeersAPI) Update(ctx context.Context, peerID string, request api.PutApi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Peer](resp)
|
ret, err := parseResponse[api.Peer](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -60,7 +66,9 @@ func (a *PeersAPI) Delete(ctx context.Context, peerID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -72,7 +80,9 @@ func (a *PeersAPI) ListAccessiblePeers(ctx context.Context, peerID string) ([]ap
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Peer](resp)
|
ret, err := parseResponse[[]api.Peer](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *PoliciesAPI) List(ctx context.Context) ([]api.Policy, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Policy](resp)
|
ret, err := parseResponse[[]api.Policy](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *PoliciesAPI) Get(ctx context.Context, policyID string) (*api.Policy, er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Policy](resp)
|
ret, err := parseResponse[api.Policy](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *PoliciesAPI) Create(ctx context.Context, request api.PostApiPoliciesJSO
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Policy](resp)
|
ret, err := parseResponse[api.Policy](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,9 @@ func (a *PoliciesAPI) Update(ctx context.Context, policyID string, request api.P
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Policy](resp)
|
ret, err := parseResponse[api.Policy](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,9 @@ func (a *PoliciesAPI) Delete(ctx context.Context, policyID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *PostureChecksAPI) List(ctx context.Context) ([]api.PostureCheck, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.PostureCheck](resp)
|
ret, err := parseResponse[[]api.PostureCheck](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *PostureChecksAPI) Get(ctx context.Context, postureCheckID string) (*api
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.PostureCheck](resp)
|
ret, err := parseResponse[api.PostureCheck](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *PostureChecksAPI) Create(ctx context.Context, request api.PostApiPostur
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.PostureCheck](resp)
|
ret, err := parseResponse[api.PostureCheck](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,9 @@ func (a *PostureChecksAPI) Update(ctx context.Context, postureCheckID string, re
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.PostureCheck](resp)
|
ret, err := parseResponse[api.PostureCheck](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,9 @@ func (a *PostureChecksAPI) Delete(ctx context.Context, postureCheckID string) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *RoutesAPI) List(ctx context.Context) ([]api.Route, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.Route](resp)
|
ret, err := parseResponse[[]api.Route](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *RoutesAPI) Get(ctx context.Context, routeID string) (*api.Route, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Route](resp)
|
ret, err := parseResponse[api.Route](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *RoutesAPI) Create(ctx context.Context, request api.PostApiRoutesJSONReq
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Route](resp)
|
ret, err := parseResponse[api.Route](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,9 @@ func (a *RoutesAPI) Update(ctx context.Context, routeID string, request api.PutA
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.Route](resp)
|
ret, err := parseResponse[api.Route](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,9 @@ func (a *RoutesAPI) Delete(ctx context.Context, routeID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *SetupKeysAPI) List(ctx context.Context) ([]api.SetupKey, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.SetupKey](resp)
|
ret, err := parseResponse[[]api.SetupKey](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *SetupKeysAPI) Get(ctx context.Context, setupKeyID string) (*api.SetupKe
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.SetupKey](resp)
|
ret, err := parseResponse[api.SetupKey](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *SetupKeysAPI) Create(ctx context.Context, request api.PostApiSetupKeysJ
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.SetupKeyClear](resp)
|
ret, err := parseResponse[api.SetupKeyClear](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,9 @@ func (a *SetupKeysAPI) Update(ctx context.Context, setupKeyID string, request ap
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.SetupKey](resp)
|
ret, err := parseResponse[api.SetupKey](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,9 @@ func (a *SetupKeysAPI) Delete(ctx context.Context, setupKeyID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *TokensAPI) List(ctx context.Context, userID string) ([]api.PersonalAcce
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.PersonalAccessToken](resp)
|
ret, err := parseResponse[[]api.PersonalAccessToken](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -32,7 +34,9 @@ func (a *TokensAPI) Get(ctx context.Context, userID, tokenID string) (*api.Perso
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.PersonalAccessToken](resp)
|
ret, err := parseResponse[api.PersonalAccessToken](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,9 @@ func (a *TokensAPI) Create(ctx context.Context, userID string, request api.PostA
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.PersonalAccessTokenGenerated](resp)
|
ret, err := parseResponse[api.PersonalAccessTokenGenerated](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -60,7 +66,9 @@ func (a *TokensAPI) Delete(ctx context.Context, userID, tokenID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ func (a *UsersAPI) List(ctx context.Context) ([]api.User, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[[]api.User](resp)
|
ret, err := parseResponse[[]api.User](resp)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
@@ -36,7 +38,9 @@ func (a *UsersAPI) Create(ctx context.Context, request api.PostApiUsersJSONReque
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.User](resp)
|
ret, err := parseResponse[api.User](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -52,7 +56,9 @@ func (a *UsersAPI) Update(ctx context.Context, userID string, request api.PutApi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
ret, err := parseResponse[api.User](resp)
|
ret, err := parseResponse[api.User](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,9 @@ func (a *UsersAPI) Delete(ctx context.Context, userID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,9 @@ func (a *UsersAPI) ResendInvitation(ctx context.Context, userID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -88,7 +98,9 @@ func (a *UsersAPI) Current(ctx context.Context) (*api.User, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
if resp.Body != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
ret, err := parseResponse[api.User](resp)
|
ret, err := parseResponse[api.User](resp)
|
||||||
return &ret, err
|
return &ret, err
|
||||||
|
|||||||
@@ -30,11 +30,8 @@ var (
|
|||||||
Issued: ptr("api"),
|
Issued: ptr("api"),
|
||||||
LastLogin: &time.Time{},
|
LastLogin: &time.Time{},
|
||||||
Name: "M. Essam",
|
Name: "M. Essam",
|
||||||
Permissions: &api.UserPermissions{
|
Role: "user",
|
||||||
DashboardView: ptr(api.UserPermissionsDashboardViewFull),
|
Status: api.UserStatusActive,
|
||||||
},
|
|
||||||
Role: "user",
|
|
||||||
Status: api.UserStatusActive,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if ! which realpath > /dev/null 2>&1
|
|
||||||
then
|
|
||||||
echo realpath is not installed
|
|
||||||
echo run: brew install coreutils
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
old_pwd=$(pwd)
|
|
||||||
script_path=$(dirname $(realpath "$0"))
|
|
||||||
cd "$script_path"
|
|
||||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
|
||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
|
||||||
protoc -I ./ ./management.proto --go_out=../ --go-grpc_out=../
|
|
||||||
cd "$old_pwd"
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
|
// - protoc (unknown)
|
||||||
|
// source: management/management.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
@@ -11,8 +15,18 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.64.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
|
const (
|
||||||
|
ManagementService_Login_FullMethodName = "/management.ManagementService/Login"
|
||||||
|
ManagementService_Sync_FullMethodName = "/management.ManagementService/Sync"
|
||||||
|
ManagementService_GetServerKey_FullMethodName = "/management.ManagementService/GetServerKey"
|
||||||
|
ManagementService_IsHealthy_FullMethodName = "/management.ManagementService/isHealthy"
|
||||||
|
ManagementService_GetDeviceAuthorizationFlow_FullMethodName = "/management.ManagementService/GetDeviceAuthorizationFlow"
|
||||||
|
ManagementService_GetPKCEAuthorizationFlow_FullMethodName = "/management.ManagementService/GetPKCEAuthorizationFlow"
|
||||||
|
ManagementService_SyncMeta_FullMethodName = "/management.ManagementService/SyncMeta"
|
||||||
|
)
|
||||||
|
|
||||||
// ManagementServiceClient is the client API for ManagementService service.
|
// ManagementServiceClient is the client API for ManagementService service.
|
||||||
//
|
//
|
||||||
@@ -25,7 +39,7 @@ type ManagementServiceClient interface {
|
|||||||
// For example, if a new peer has been added to an account all other connected peers will receive this peer's Wireguard public key as an update
|
// For example, if a new peer has been added to an account all other connected peers will receive this peer's Wireguard public key as an update
|
||||||
// The initial SyncResponse contains all of the available peers so the local state can be refreshed
|
// The initial SyncResponse contains all of the available peers so the local state can be refreshed
|
||||||
// Returns encrypted SyncResponse in EncryptedMessage.Body
|
// Returns encrypted SyncResponse in EncryptedMessage.Body
|
||||||
Sync(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (ManagementService_SyncClient, error)
|
Sync(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (grpc.ServerStreamingClient[EncryptedMessage], error)
|
||||||
// Exposes a Wireguard public key of the Management service.
|
// Exposes a Wireguard public key of the Management service.
|
||||||
// This key is used to support message encryption between client and server
|
// This key is used to support message encryption between client and server
|
||||||
GetServerKey(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ServerKeyResponse, error)
|
GetServerKey(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ServerKeyResponse, error)
|
||||||
@@ -59,20 +73,22 @@ func NewManagementServiceClient(cc grpc.ClientConnInterface) ManagementServiceCl
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *managementServiceClient) Login(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
func (c *managementServiceClient) Login(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(EncryptedMessage)
|
out := new(EncryptedMessage)
|
||||||
err := c.cc.Invoke(ctx, "/management.ManagementService/Login", in, out, opts...)
|
err := c.cc.Invoke(ctx, ManagementService_Login_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *managementServiceClient) Sync(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (ManagementService_SyncClient, error) {
|
func (c *managementServiceClient) Sync(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (grpc.ServerStreamingClient[EncryptedMessage], error) {
|
||||||
stream, err := c.cc.NewStream(ctx, &ManagementService_ServiceDesc.Streams[0], "/management.ManagementService/Sync", opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
stream, err := c.cc.NewStream(ctx, &ManagementService_ServiceDesc.Streams[0], ManagementService_Sync_FullMethodName, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
x := &managementServiceSyncClient{stream}
|
x := &grpc.GenericClientStream[EncryptedMessage, EncryptedMessage]{ClientStream: stream}
|
||||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -82,26 +98,13 @@ func (c *managementServiceClient) Sync(ctx context.Context, in *EncryptedMessage
|
|||||||
return x, nil
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ManagementService_SyncClient interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Recv() (*EncryptedMessage, error)
|
type ManagementService_SyncClient = grpc.ServerStreamingClient[EncryptedMessage]
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type managementServiceSyncClient struct {
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *managementServiceSyncClient) Recv() (*EncryptedMessage, error) {
|
|
||||||
m := new(EncryptedMessage)
|
|
||||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *managementServiceClient) GetServerKey(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ServerKeyResponse, error) {
|
func (c *managementServiceClient) GetServerKey(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ServerKeyResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ServerKeyResponse)
|
out := new(ServerKeyResponse)
|
||||||
err := c.cc.Invoke(ctx, "/management.ManagementService/GetServerKey", in, out, opts...)
|
err := c.cc.Invoke(ctx, ManagementService_GetServerKey_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -109,8 +112,9 @@ func (c *managementServiceClient) GetServerKey(ctx context.Context, in *Empty, o
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *managementServiceClient) IsHealthy(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
|
func (c *managementServiceClient) IsHealthy(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(Empty)
|
out := new(Empty)
|
||||||
err := c.cc.Invoke(ctx, "/management.ManagementService/isHealthy", in, out, opts...)
|
err := c.cc.Invoke(ctx, ManagementService_IsHealthy_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -118,8 +122,9 @@ func (c *managementServiceClient) IsHealthy(ctx context.Context, in *Empty, opts
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *managementServiceClient) GetDeviceAuthorizationFlow(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
func (c *managementServiceClient) GetDeviceAuthorizationFlow(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(EncryptedMessage)
|
out := new(EncryptedMessage)
|
||||||
err := c.cc.Invoke(ctx, "/management.ManagementService/GetDeviceAuthorizationFlow", in, out, opts...)
|
err := c.cc.Invoke(ctx, ManagementService_GetDeviceAuthorizationFlow_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -127,8 +132,9 @@ func (c *managementServiceClient) GetDeviceAuthorizationFlow(ctx context.Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *managementServiceClient) GetPKCEAuthorizationFlow(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
func (c *managementServiceClient) GetPKCEAuthorizationFlow(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(EncryptedMessage)
|
out := new(EncryptedMessage)
|
||||||
err := c.cc.Invoke(ctx, "/management.ManagementService/GetPKCEAuthorizationFlow", in, out, opts...)
|
err := c.cc.Invoke(ctx, ManagementService_GetPKCEAuthorizationFlow_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -136,8 +142,9 @@ func (c *managementServiceClient) GetPKCEAuthorizationFlow(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *managementServiceClient) SyncMeta(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*Empty, error) {
|
func (c *managementServiceClient) SyncMeta(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(Empty)
|
out := new(Empty)
|
||||||
err := c.cc.Invoke(ctx, "/management.ManagementService/SyncMeta", in, out, opts...)
|
err := c.cc.Invoke(ctx, ManagementService_SyncMeta_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -146,7 +153,7 @@ func (c *managementServiceClient) SyncMeta(ctx context.Context, in *EncryptedMes
|
|||||||
|
|
||||||
// ManagementServiceServer is the server API for ManagementService service.
|
// ManagementServiceServer is the server API for ManagementService service.
|
||||||
// All implementations must embed UnimplementedManagementServiceServer
|
// All implementations must embed UnimplementedManagementServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility.
|
||||||
type ManagementServiceServer interface {
|
type ManagementServiceServer interface {
|
||||||
// Login logs in peer. In case server returns codes.PermissionDenied this endpoint can be used to register Peer providing LoginRequest.setupKey
|
// Login logs in peer. In case server returns codes.PermissionDenied this endpoint can be used to register Peer providing LoginRequest.setupKey
|
||||||
// Returns encrypted LoginResponse in EncryptedMessage.Body
|
// Returns encrypted LoginResponse in EncryptedMessage.Body
|
||||||
@@ -155,7 +162,7 @@ type ManagementServiceServer interface {
|
|||||||
// For example, if a new peer has been added to an account all other connected peers will receive this peer's Wireguard public key as an update
|
// For example, if a new peer has been added to an account all other connected peers will receive this peer's Wireguard public key as an update
|
||||||
// The initial SyncResponse contains all of the available peers so the local state can be refreshed
|
// The initial SyncResponse contains all of the available peers so the local state can be refreshed
|
||||||
// Returns encrypted SyncResponse in EncryptedMessage.Body
|
// Returns encrypted SyncResponse in EncryptedMessage.Body
|
||||||
Sync(*EncryptedMessage, ManagementService_SyncServer) error
|
Sync(*EncryptedMessage, grpc.ServerStreamingServer[EncryptedMessage]) error
|
||||||
// Exposes a Wireguard public key of the Management service.
|
// Exposes a Wireguard public key of the Management service.
|
||||||
// This key is used to support message encryption between client and server
|
// This key is used to support message encryption between client and server
|
||||||
GetServerKey(context.Context, *Empty) (*ServerKeyResponse, error)
|
GetServerKey(context.Context, *Empty) (*ServerKeyResponse, error)
|
||||||
@@ -181,14 +188,17 @@ type ManagementServiceServer interface {
|
|||||||
mustEmbedUnimplementedManagementServiceServer()
|
mustEmbedUnimplementedManagementServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnimplementedManagementServiceServer must be embedded to have forward compatible implementations.
|
// UnimplementedManagementServiceServer must be embedded to have
|
||||||
type UnimplementedManagementServiceServer struct {
|
// forward compatible implementations.
|
||||||
}
|
//
|
||||||
|
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||||
|
// pointer dereference when methods are called.
|
||||||
|
type UnimplementedManagementServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedManagementServiceServer) Login(context.Context, *EncryptedMessage) (*EncryptedMessage, error) {
|
func (UnimplementedManagementServiceServer) Login(context.Context, *EncryptedMessage) (*EncryptedMessage, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedManagementServiceServer) Sync(*EncryptedMessage, ManagementService_SyncServer) error {
|
func (UnimplementedManagementServiceServer) Sync(*EncryptedMessage, grpc.ServerStreamingServer[EncryptedMessage]) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method Sync not implemented")
|
return status.Errorf(codes.Unimplemented, "method Sync not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedManagementServiceServer) GetServerKey(context.Context, *Empty) (*ServerKeyResponse, error) {
|
func (UnimplementedManagementServiceServer) GetServerKey(context.Context, *Empty) (*ServerKeyResponse, error) {
|
||||||
@@ -207,6 +217,7 @@ func (UnimplementedManagementServiceServer) SyncMeta(context.Context, *Encrypted
|
|||||||
return nil, status.Errorf(codes.Unimplemented, "method SyncMeta not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method SyncMeta not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedManagementServiceServer) mustEmbedUnimplementedManagementServiceServer() {}
|
func (UnimplementedManagementServiceServer) mustEmbedUnimplementedManagementServiceServer() {}
|
||||||
|
func (UnimplementedManagementServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
// UnsafeManagementServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeManagementServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
// Use of this interface is not recommended, as added methods to ManagementServiceServer will
|
// Use of this interface is not recommended, as added methods to ManagementServiceServer will
|
||||||
@@ -216,6 +227,13 @@ type UnsafeManagementServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterManagementServiceServer(s grpc.ServiceRegistrar, srv ManagementServiceServer) {
|
func RegisterManagementServiceServer(s grpc.ServiceRegistrar, srv ManagementServiceServer) {
|
||||||
|
// If the following call pancis, it indicates UnimplementedManagementServiceServer was
|
||||||
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||||
|
t.testEmbeddedByValue()
|
||||||
|
}
|
||||||
s.RegisterService(&ManagementService_ServiceDesc, srv)
|
s.RegisterService(&ManagementService_ServiceDesc, srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +247,7 @@ func _ManagementService_Login_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/management.ManagementService/Login",
|
FullMethod: ManagementService_Login_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(ManagementServiceServer).Login(ctx, req.(*EncryptedMessage))
|
return srv.(ManagementServiceServer).Login(ctx, req.(*EncryptedMessage))
|
||||||
@@ -242,21 +260,11 @@ func _ManagementService_Sync_Handler(srv interface{}, stream grpc.ServerStream)
|
|||||||
if err := stream.RecvMsg(m); err != nil {
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return srv.(ManagementServiceServer).Sync(m, &managementServiceSyncServer{stream})
|
return srv.(ManagementServiceServer).Sync(m, &grpc.GenericServerStream[EncryptedMessage, EncryptedMessage]{ServerStream: stream})
|
||||||
}
|
}
|
||||||
|
|
||||||
type ManagementService_SyncServer interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Send(*EncryptedMessage) error
|
type ManagementService_SyncServer = grpc.ServerStreamingServer[EncryptedMessage]
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type managementServiceSyncServer struct {
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *managementServiceSyncServer) Send(m *EncryptedMessage) error {
|
|
||||||
return x.ServerStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _ManagementService_GetServerKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _ManagementService_GetServerKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(Empty)
|
in := new(Empty)
|
||||||
@@ -268,7 +276,7 @@ func _ManagementService_GetServerKey_Handler(srv interface{}, ctx context.Contex
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/management.ManagementService/GetServerKey",
|
FullMethod: ManagementService_GetServerKey_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(ManagementServiceServer).GetServerKey(ctx, req.(*Empty))
|
return srv.(ManagementServiceServer).GetServerKey(ctx, req.(*Empty))
|
||||||
@@ -286,7 +294,7 @@ func _ManagementService_IsHealthy_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/management.ManagementService/isHealthy",
|
FullMethod: ManagementService_IsHealthy_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(ManagementServiceServer).IsHealthy(ctx, req.(*Empty))
|
return srv.(ManagementServiceServer).IsHealthy(ctx, req.(*Empty))
|
||||||
@@ -304,7 +312,7 @@ func _ManagementService_GetDeviceAuthorizationFlow_Handler(srv interface{}, ctx
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/management.ManagementService/GetDeviceAuthorizationFlow",
|
FullMethod: ManagementService_GetDeviceAuthorizationFlow_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(ManagementServiceServer).GetDeviceAuthorizationFlow(ctx, req.(*EncryptedMessage))
|
return srv.(ManagementServiceServer).GetDeviceAuthorizationFlow(ctx, req.(*EncryptedMessage))
|
||||||
@@ -322,7 +330,7 @@ func _ManagementService_GetPKCEAuthorizationFlow_Handler(srv interface{}, ctx co
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/management.ManagementService/GetPKCEAuthorizationFlow",
|
FullMethod: ManagementService_GetPKCEAuthorizationFlow_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(ManagementServiceServer).GetPKCEAuthorizationFlow(ctx, req.(*EncryptedMessage))
|
return srv.(ManagementServiceServer).GetPKCEAuthorizationFlow(ctx, req.(*EncryptedMessage))
|
||||||
@@ -340,7 +348,7 @@ func _ManagementService_SyncMeta_Handler(srv interface{}, ctx context.Context, d
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/management.ManagementService/SyncMeta",
|
FullMethod: ManagementService_SyncMeta_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(ManagementServiceServer).SyncMeta(ctx, req.(*EncryptedMessage))
|
return srv.(ManagementServiceServer).SyncMeta(ctx, req.(*EncryptedMessage))
|
||||||
@@ -387,5 +395,5 @@ var ManagementService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
ServerStreams: true,
|
ServerStreams: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Metadata: "management.proto",
|
Metadata: "management/management.proto",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -603,11 +603,15 @@ func (am *DefaultAccountManager) DeleteAccount(ctx context.Context, accountID, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, otherUser := range account.Users {
|
for _, otherUser := range account.Users {
|
||||||
if otherUser.IsServiceUser {
|
if otherUser.Id == userID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if otherUser.Id == userID {
|
if otherUser.IsServiceUser {
|
||||||
|
err = am.deleteServiceUser(ctx, accountID, userID, otherUser)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,7 +716,7 @@ func (am *DefaultAccountManager) loadAccount(ctx context.Context, accountID any)
|
|||||||
log.WithContext(ctx).Debugf("account %s not found in cache, reloading", accountID)
|
log.WithContext(ctx).Debugf("account %s not found in cache, reloading", accountID)
|
||||||
accountIDString := fmt.Sprintf("%v", accountID)
|
accountIDString := fmt.Sprintf("%v", accountID)
|
||||||
|
|
||||||
account, err := am.Store.GetAccount(ctx, accountIDString)
|
accountUsers, err := am.Store.GetAccountUsers(ctx, store.LockingStrengthShare, accountIDString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -721,7 +725,7 @@ func (am *DefaultAccountManager) loadAccount(ctx context.Context, accountID any)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
log.WithContext(ctx).Debugf("%d entries received from IdP management", len(userData))
|
log.WithContext(ctx).Debugf("%d entries received from IdP management for account %s", len(userData), accountIDString)
|
||||||
|
|
||||||
dataMap := make(map[string]*idp.UserData, len(userData))
|
dataMap := make(map[string]*idp.UserData, len(userData))
|
||||||
for _, datum := range userData {
|
for _, datum := range userData {
|
||||||
@@ -729,7 +733,7 @@ func (am *DefaultAccountManager) loadAccount(ctx context.Context, accountID any)
|
|||||||
}
|
}
|
||||||
|
|
||||||
matchedUserData := make([]*idp.UserData, 0)
|
matchedUserData := make([]*idp.UserData, 0)
|
||||||
for _, user := range account.Users {
|
for _, user := range accountUsers {
|
||||||
if user.IsServiceUser {
|
if user.IsServiceUser {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/server/posture"
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
"github.com/netbirdio/netbird/management/server/users"
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -115,5 +116,5 @@ type Manager interface {
|
|||||||
CreateAccountByPrivateDomain(ctx context.Context, initiatorId, domain string) (*types.Account, error)
|
CreateAccountByPrivateDomain(ctx context.Context, initiatorId, domain string) (*types.Account, error)
|
||||||
UpdateToPrimaryAccount(ctx context.Context, accountId string) (*types.Account, error)
|
UpdateToPrimaryAccount(ctx context.Context, accountId string) (*types.Account, error)
|
||||||
GetOwnerInfo(ctx context.Context, accountId string) (*types.UserInfo, error)
|
GetOwnerInfo(ctx context.Context, accountId string) (*types.UserInfo, error)
|
||||||
GetCurrentUserInfo(ctx context.Context, accountID, userID string) (*types.UserInfo, error)
|
GetCurrentUserInfo(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -853,6 +853,42 @@ func TestAccountManager_DeleteAccount(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
account.Users["service-user-1"] = &types.User{
|
||||||
|
Id: "service-user-1",
|
||||||
|
Role: types.UserRoleAdmin,
|
||||||
|
IsServiceUser: true,
|
||||||
|
Issued: types.UserIssuedAPI,
|
||||||
|
PATs: map[string]*types.PersonalAccessToken{
|
||||||
|
"pat-1": {
|
||||||
|
ID: "pat-1",
|
||||||
|
UserID: "service-user-1",
|
||||||
|
Name: "service-user-1",
|
||||||
|
HashedToken: "hashedToken",
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
account.Users[userId] = &types.User{
|
||||||
|
Id: "service-user-2",
|
||||||
|
Role: types.UserRoleUser,
|
||||||
|
IsServiceUser: true,
|
||||||
|
Issued: types.UserIssuedAPI,
|
||||||
|
PATs: map[string]*types.PersonalAccessToken{
|
||||||
|
"pat-2": {
|
||||||
|
ID: "pat-2",
|
||||||
|
UserID: userId,
|
||||||
|
Name: userId,
|
||||||
|
HashedToken: "hashedToken",
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = manager.Store.SaveAccount(context.Background(), account)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
err = manager.DeleteAccount(context.Background(), account.Id, userId)
|
err = manager.DeleteAccount(context.Background(), account.Id, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -862,6 +898,14 @@ func TestAccountManager_DeleteAccount(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal(fmt.Errorf("expected to get an error when trying to get deleted account, got %v", getAccount))
|
t.Fatal(fmt.Errorf("expected to get an error when trying to get deleted account, got %v", getAccount))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pats, err := manager.Store.GetUserPATs(context.Background(), store.LockingStrengthShare, "service-user-1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, pats, 0)
|
||||||
|
|
||||||
|
pats, err = manager.Store.GetUserPATs(context.Background(), store.LockingStrengthShare, userId)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, pats, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkTest_GetAccountWithclaims(b *testing.B) {
|
func BenchmarkTest_GetAccountWithclaims(b *testing.B) {
|
||||||
|
|||||||
@@ -216,11 +216,25 @@ components:
|
|||||||
UserPermissions:
|
UserPermissions:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
dashboard_view:
|
is_restricted:
|
||||||
description: User's permission to view the dashboard
|
type: boolean
|
||||||
type: string
|
description: Indicates whether this User's Peers view is restricted
|
||||||
enum: [ "limited", "blocked", "full" ]
|
modules:
|
||||||
example: limited
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: boolean
|
||||||
|
propertyNames:
|
||||||
|
type: string
|
||||||
|
description: The operation type
|
||||||
|
propertyNames:
|
||||||
|
type: string
|
||||||
|
description: The module name
|
||||||
|
example: {"networks": { "read": true, "create": false, "update": false, "delete": false}, "peers": { "read": false, "create": false, "update": false, "delete": false} }
|
||||||
|
required:
|
||||||
|
- modules
|
||||||
|
- is_restricted
|
||||||
UserRequest:
|
UserRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|||||||
@@ -178,13 +178,6 @@ const (
|
|||||||
UserStatusInvited UserStatus = "invited"
|
UserStatusInvited UserStatus = "invited"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines values for UserPermissionsDashboardView.
|
|
||||||
const (
|
|
||||||
UserPermissionsDashboardViewBlocked UserPermissionsDashboardView = "blocked"
|
|
||||||
UserPermissionsDashboardViewFull UserPermissionsDashboardView = "full"
|
|
||||||
UserPermissionsDashboardViewLimited UserPermissionsDashboardView = "limited"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Defines values for GetApiEventsNetworkTrafficParamsType.
|
// Defines values for GetApiEventsNetworkTrafficParamsType.
|
||||||
const (
|
const (
|
||||||
GetApiEventsNetworkTrafficParamsTypeTYPEDROP GetApiEventsNetworkTrafficParamsType = "TYPE_DROP"
|
GetApiEventsNetworkTrafficParamsTypeTYPEDROP GetApiEventsNetworkTrafficParamsType = "TYPE_DROP"
|
||||||
@@ -1757,13 +1750,11 @@ type UserCreateRequest struct {
|
|||||||
|
|
||||||
// UserPermissions defines model for UserPermissions.
|
// UserPermissions defines model for UserPermissions.
|
||||||
type UserPermissions struct {
|
type UserPermissions struct {
|
||||||
// DashboardView User's permission to view the dashboard
|
// IsRestricted Indicates whether this User's Peers view is restricted
|
||||||
DashboardView *UserPermissionsDashboardView `json:"dashboard_view,omitempty"`
|
IsRestricted bool `json:"is_restricted"`
|
||||||
|
Modules map[string]map[string]bool `json:"modules"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserPermissionsDashboardView User's permission to view the dashboard
|
|
||||||
type UserPermissionsDashboardView string
|
|
||||||
|
|
||||||
// UserRequest defines model for UserRequest.
|
// UserRequest defines model for UserRequest.
|
||||||
type UserRequest struct {
|
type UserRequest struct {
|
||||||
// AutoGroups Group IDs to auto-assign to peers registered by this user
|
// AutoGroups Group IDs to auto-assign to peers registered by this user
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
"github.com/netbirdio/netbird/management/server/users"
|
||||||
|
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
)
|
)
|
||||||
@@ -272,15 +273,33 @@ func (h *handler) getCurrentUser(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accountID, userID := userAuth.AccountId, userAuth.UserId
|
user, err := h.accountManager.GetCurrentUserInfo(ctx, userAuth)
|
||||||
|
|
||||||
user, err := h.accountManager.GetCurrentUserInfo(ctx, accountID, userID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.WriteError(r.Context(), err, w)
|
util.WriteError(r.Context(), err, w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
util.WriteJSONObject(r.Context(), w, toUserResponse(user, userID))
|
util.WriteJSONObject(r.Context(), w, toUserWithPermissionsResponse(user, userAuth.UserId))
|
||||||
|
}
|
||||||
|
|
||||||
|
func toUserWithPermissionsResponse(user *users.UserInfoWithPermissions, userID string) *api.User {
|
||||||
|
response := toUserResponse(user.UserInfo, userID)
|
||||||
|
|
||||||
|
// stringify modules and operations keys
|
||||||
|
modules := make(map[string]map[string]bool)
|
||||||
|
for module, operations := range user.Permissions {
|
||||||
|
modules[string(module)] = make(map[string]bool)
|
||||||
|
for op, val := range operations {
|
||||||
|
modules[string(module)][string(op)] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Permissions = &api.UserPermissions{
|
||||||
|
IsRestricted: user.Restricted,
|
||||||
|
Modules: modules,
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
func toUserResponse(user *types.UserInfo, currenUserID string) *api.User {
|
func toUserResponse(user *types.UserInfo, currenUserID string) *api.User {
|
||||||
@@ -316,8 +335,5 @@ func toUserResponse(user *types.UserInfo, currenUserID string) *api.User {
|
|||||||
IsBlocked: user.IsBlocked,
|
IsBlocked: user.IsBlocked,
|
||||||
LastLogin: &user.LastLogin,
|
LastLogin: &user.LastLogin,
|
||||||
Issued: &user.Issued,
|
Issued: &user.Issued,
|
||||||
Permissions: &api.UserPermissions{
|
|
||||||
DashboardView: (*api.UserPermissionsDashboardView)(&user.Permissions.DashboardView),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,16 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||||
|
"github.com/netbirdio/netbird/management/server/permissions/modules"
|
||||||
|
"github.com/netbirdio/netbird/management/server/permissions/roles"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
"github.com/netbirdio/netbird/management/server/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -107,7 +111,7 @@ func initUsersTestData() *handler {
|
|||||||
return nil, status.Errorf(status.NotFound, "user with ID %s does not exists", userID)
|
return nil, status.Errorf(status.NotFound, "user with ID %s does not exists", userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := update.Copy().ToUserInfo(nil, &types.Settings{RegularUsersViewBlocked: false})
|
info, err := update.Copy().ToUserInfo(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -124,8 +128,8 @@ func initUsersTestData() *handler {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
GetCurrentUserInfoFunc: func(ctx context.Context, accountID, userID string) (*types.UserInfo, error) {
|
GetCurrentUserInfoFunc: func(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||||
switch userID {
|
switch userAuth.UserId {
|
||||||
case "not-found":
|
case "not-found":
|
||||||
return nil, status.NewUserNotFoundError("not-found")
|
return nil, status.NewUserNotFoundError("not-found")
|
||||||
case "not-of-account":
|
case "not-of-account":
|
||||||
@@ -135,52 +139,68 @@ func initUsersTestData() *handler {
|
|||||||
case "service-user":
|
case "service-user":
|
||||||
return nil, status.NewPermissionDeniedError()
|
return nil, status.NewPermissionDeniedError()
|
||||||
case "owner":
|
case "owner":
|
||||||
return &types.UserInfo{
|
return &users.UserInfoWithPermissions{
|
||||||
ID: "owner",
|
UserInfo: &types.UserInfo{
|
||||||
Name: "",
|
ID: "owner",
|
||||||
Role: "owner",
|
Name: "",
|
||||||
Status: "active",
|
Role: "owner",
|
||||||
IsServiceUser: false,
|
Status: "active",
|
||||||
IsBlocked: false,
|
IsServiceUser: false,
|
||||||
NonDeletable: false,
|
IsBlocked: false,
|
||||||
Issued: "api",
|
NonDeletable: false,
|
||||||
Permissions: types.UserPermissions{
|
Issued: "api",
|
||||||
DashboardView: "full",
|
|
||||||
},
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.Owner),
|
||||||
}, nil
|
}, nil
|
||||||
case "regular-user":
|
case "regular-user":
|
||||||
return &types.UserInfo{
|
return &users.UserInfoWithPermissions{
|
||||||
ID: "regular-user",
|
UserInfo: &types.UserInfo{
|
||||||
Name: "",
|
ID: "regular-user",
|
||||||
Role: "user",
|
Name: "",
|
||||||
Status: "active",
|
Role: "user",
|
||||||
IsServiceUser: false,
|
Status: "active",
|
||||||
IsBlocked: false,
|
IsServiceUser: false,
|
||||||
NonDeletable: false,
|
IsBlocked: false,
|
||||||
Issued: "api",
|
NonDeletable: false,
|
||||||
Permissions: types.UserPermissions{
|
Issued: "api",
|
||||||
DashboardView: "limited",
|
|
||||||
},
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.User),
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
case "admin-user":
|
case "admin-user":
|
||||||
return &types.UserInfo{
|
return &users.UserInfoWithPermissions{
|
||||||
ID: "admin-user",
|
UserInfo: &types.UserInfo{
|
||||||
Name: "",
|
ID: "admin-user",
|
||||||
Role: "admin",
|
Name: "",
|
||||||
Status: "active",
|
Role: "admin",
|
||||||
IsServiceUser: false,
|
Status: "active",
|
||||||
IsBlocked: false,
|
IsServiceUser: false,
|
||||||
NonDeletable: false,
|
IsBlocked: false,
|
||||||
LastLogin: time.Time{},
|
NonDeletable: false,
|
||||||
Issued: "api",
|
LastLogin: time.Time{},
|
||||||
Permissions: types.UserPermissions{
|
Issued: "api",
|
||||||
DashboardView: "full",
|
|
||||||
},
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.Admin),
|
||||||
|
}, nil
|
||||||
|
case "restricted-user":
|
||||||
|
return &users.UserInfoWithPermissions{
|
||||||
|
UserInfo: &types.UserInfo{
|
||||||
|
ID: "restricted-user",
|
||||||
|
Name: "",
|
||||||
|
Role: "user",
|
||||||
|
Status: "active",
|
||||||
|
IsServiceUser: false,
|
||||||
|
IsBlocked: false,
|
||||||
|
NonDeletable: false,
|
||||||
|
LastLogin: time.Time{},
|
||||||
|
Issued: "api",
|
||||||
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.User),
|
||||||
|
Restricted: true,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("user id %s not handled", userID)
|
return nil, fmt.Errorf("user id %s not handled", userAuth.UserId)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -546,6 +566,7 @@ func TestCurrentUser(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
expectedStatus int
|
expectedStatus int
|
||||||
requestAuth nbcontext.UserAuth
|
requestAuth nbcontext.UserAuth
|
||||||
|
expectedResult *api.User
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "without auth",
|
name: "without auth",
|
||||||
@@ -575,16 +596,78 @@ func TestCurrentUser(t *testing.T) {
|
|||||||
name: "owner",
|
name: "owner",
|
||||||
requestAuth: nbcontext.UserAuth{UserId: "owner"},
|
requestAuth: nbcontext.UserAuth{UserId: "owner"},
|
||||||
expectedStatus: http.StatusOK,
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedResult: &api.User{
|
||||||
|
Id: "owner",
|
||||||
|
Role: "owner",
|
||||||
|
Status: "active",
|
||||||
|
IsBlocked: false,
|
||||||
|
IsCurrent: ptr(true),
|
||||||
|
IsServiceUser: ptr(false),
|
||||||
|
AutoGroups: []string{},
|
||||||
|
Issued: ptr("api"),
|
||||||
|
LastLogin: ptr(time.Time{}),
|
||||||
|
Permissions: &api.UserPermissions{
|
||||||
|
Modules: stringifyPermissionsKeys(mergeRolePermissions(roles.Owner)),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "regular user",
|
name: "regular user",
|
||||||
requestAuth: nbcontext.UserAuth{UserId: "regular-user"},
|
requestAuth: nbcontext.UserAuth{UserId: "regular-user"},
|
||||||
expectedStatus: http.StatusOK,
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedResult: &api.User{
|
||||||
|
Id: "regular-user",
|
||||||
|
Role: "user",
|
||||||
|
Status: "active",
|
||||||
|
IsBlocked: false,
|
||||||
|
IsCurrent: ptr(true),
|
||||||
|
IsServiceUser: ptr(false),
|
||||||
|
AutoGroups: []string{},
|
||||||
|
Issued: ptr("api"),
|
||||||
|
LastLogin: ptr(time.Time{}),
|
||||||
|
Permissions: &api.UserPermissions{
|
||||||
|
Modules: stringifyPermissionsKeys(mergeRolePermissions(roles.User)),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "admin user",
|
name: "admin user",
|
||||||
requestAuth: nbcontext.UserAuth{UserId: "admin-user"},
|
requestAuth: nbcontext.UserAuth{UserId: "admin-user"},
|
||||||
expectedStatus: http.StatusOK,
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedResult: &api.User{
|
||||||
|
Id: "admin-user",
|
||||||
|
Role: "admin",
|
||||||
|
Status: "active",
|
||||||
|
IsBlocked: false,
|
||||||
|
IsCurrent: ptr(true),
|
||||||
|
IsServiceUser: ptr(false),
|
||||||
|
AutoGroups: []string{},
|
||||||
|
Issued: ptr("api"),
|
||||||
|
LastLogin: ptr(time.Time{}),
|
||||||
|
Permissions: &api.UserPermissions{
|
||||||
|
Modules: stringifyPermissionsKeys(mergeRolePermissions(roles.Admin)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "restricted user",
|
||||||
|
requestAuth: nbcontext.UserAuth{UserId: "restricted-user"},
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedResult: &api.User{
|
||||||
|
Id: "restricted-user",
|
||||||
|
Role: "user",
|
||||||
|
Status: "active",
|
||||||
|
IsBlocked: false,
|
||||||
|
IsCurrent: ptr(true),
|
||||||
|
IsServiceUser: ptr(false),
|
||||||
|
AutoGroups: []string{},
|
||||||
|
Issued: ptr("api"),
|
||||||
|
LastLogin: ptr(time.Time{}),
|
||||||
|
Permissions: &api.UserPermissions{
|
||||||
|
IsRestricted: true,
|
||||||
|
Modules: stringifyPermissionsKeys(mergeRolePermissions(roles.User)),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,10 +686,42 @@ func TestCurrentUser(t *testing.T) {
|
|||||||
res := rr.Result()
|
res := rr.Result()
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
if status := rr.Code; status != tc.expectedStatus {
|
assert.Equal(t, tc.expectedStatus, rr.Code, "handler returned wrong status code")
|
||||||
t.Fatalf("handler returned wrong status code: got %v want %v",
|
|
||||||
status, tc.expectedStatus)
|
if tc.expectedResult != nil {
|
||||||
|
var result api.User
|
||||||
|
require.NoError(t, json.NewDecoder(res.Body).Decode(&result))
|
||||||
|
assert.EqualValues(t, *tc.expectedResult, result)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ptr[T any, PT *T](x T) PT {
|
||||||
|
return &x
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeRolePermissions(role roles.RolePermissions) roles.Permissions {
|
||||||
|
permissions := roles.Permissions{}
|
||||||
|
|
||||||
|
for k := range modules.All {
|
||||||
|
if rolePermissions, ok := role.Permissions[k]; ok {
|
||||||
|
permissions[k] = rolePermissions
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
permissions[k] = role.AutoAllowNew
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringifyPermissionsKeys(permissions roles.Permissions) map[string]map[string]bool {
|
||||||
|
modules := make(map[string]map[string]bool)
|
||||||
|
for module, operations := range permissions {
|
||||||
|
modules[string(module)] = make(map[string]bool)
|
||||||
|
for op, val := range operations {
|
||||||
|
modules[string(module)][string(op)] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modules
|
||||||
|
}
|
||||||
|
|||||||
@@ -352,3 +352,24 @@ func MigrateNewField[T any](ctx context.Context, db *gorm.DB, columnName string,
|
|||||||
log.WithContext(ctx).Infof("Migration of empty %s to default value in table %s completed", columnName, tableName)
|
log.WithContext(ctx).Infof("Migration of empty %s to default value in table %s completed", columnName, tableName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DropIndex[T any](ctx context.Context, db *gorm.DB, indexName string) error {
|
||||||
|
var model T
|
||||||
|
|
||||||
|
if !db.Migrator().HasTable(&model) {
|
||||||
|
log.WithContext(ctx).Debugf("table for %T does not exist, no migration needed", model)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !db.Migrator().HasIndex(&model, indexName) {
|
||||||
|
log.WithContext(ctx).Debugf("index %s does not exist in table %T, no migration needed", indexName, model)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Migrator().DropIndex(&model, indexName); err != nil {
|
||||||
|
return fmt.Errorf("failed to drop index %s: %w", indexName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.WithContext(ctx).Infof("dropped index %s from table %T", indexName, model)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -227,3 +227,25 @@ func TestMigrateSetupKeyToHashedSetupKey_ForAlreadyMigratedKey_Case2(t *testing.
|
|||||||
|
|
||||||
assert.Equal(t, "9+FQcmNd2GCxIK+SvHmtp6PPGV4MKEicDS+xuSQmvlE=", key.Key, "Key should be hashed")
|
assert.Equal(t, "9+FQcmNd2GCxIK+SvHmtp6PPGV4MKEicDS+xuSQmvlE=", key.Key, "Key should be hashed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDropIndex(t *testing.T) {
|
||||||
|
db := setupDatabase(t)
|
||||||
|
|
||||||
|
err := db.AutoMigrate(&types.SetupKey{})
|
||||||
|
require.NoError(t, err, "Failed to auto-migrate tables")
|
||||||
|
|
||||||
|
err = db.Save(&types.SetupKey{
|
||||||
|
Id: "1",
|
||||||
|
Key: "9+FQcmNd2GCxIK+SvHmtp6PPGV4MKEicDS+xuSQmvlE=",
|
||||||
|
}).Error
|
||||||
|
require.NoError(t, err, "Failed to insert setup key")
|
||||||
|
|
||||||
|
exist := db.Migrator().HasIndex(&types.SetupKey{}, "idx_setup_keys_account_id")
|
||||||
|
assert.True(t, exist, "Should have the index")
|
||||||
|
|
||||||
|
err = migration.DropIndex[types.SetupKey](context.Background(), db, "idx_setup_keys_account_id")
|
||||||
|
require.NoError(t, err, "Migration should not fail to remove index")
|
||||||
|
|
||||||
|
exist = db.Migrator().HasIndex(&types.SetupKey{}, "idx_setup_keys_account_id")
|
||||||
|
assert.False(t, exist, "Should not have the index")
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/server/posture"
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
"github.com/netbirdio/netbird/management/server/users"
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ type MockAccountManager struct {
|
|||||||
CreateAccountByPrivateDomainFunc func(ctx context.Context, initiatorId, domain string) (*types.Account, error)
|
CreateAccountByPrivateDomainFunc func(ctx context.Context, initiatorId, domain string) (*types.Account, error)
|
||||||
UpdateToPrimaryAccountFunc func(ctx context.Context, accountId string) (*types.Account, error)
|
UpdateToPrimaryAccountFunc func(ctx context.Context, accountId string) (*types.Account, error)
|
||||||
GetOwnerInfoFunc func(ctx context.Context, accountID string) (*types.UserInfo, error)
|
GetOwnerInfoFunc func(ctx context.Context, accountID string) (*types.UserInfo, error)
|
||||||
GetCurrentUserInfoFunc func(ctx context.Context, accountID, userID string) (*types.UserInfo, error)
|
GetCurrentUserInfoFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error)
|
||||||
GetAccountMetaFunc func(ctx context.Context, accountID, userID string) (*types.AccountMeta, error)
|
GetAccountMetaFunc func(ctx context.Context, accountID, userID string) (*types.AccountMeta, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,9 +883,9 @@ func (am *MockAccountManager) GetOwnerInfo(ctx context.Context, accountId string
|
|||||||
return nil, status.Errorf(codes.Unimplemented, "method GetOwnerInfo is not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetOwnerInfo is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *MockAccountManager) GetCurrentUserInfo(ctx context.Context, accountID, userID string) (*types.UserInfo, error) {
|
func (am *MockAccountManager) GetCurrentUserInfo(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||||
if am.GetCurrentUserInfoFunc != nil {
|
if am.GetCurrentUserInfoFunc != nil {
|
||||||
return am.GetCurrentUserInfoFunc(ctx, accountID, userID)
|
return am.GetCurrentUserInfoFunc(ctx, userAuth)
|
||||||
}
|
}
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetCurrentUserInfo is not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetCurrentUserInfo is not implemented")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func (p NetworkResourceType) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NetworkResource struct {
|
type NetworkResource struct {
|
||||||
ID string `gorm:"index"`
|
ID string `gorm:"primaryKey"`
|
||||||
NetworkID string `gorm:"index"`
|
NetworkID string `gorm:"index"`
|
||||||
AccountID string `gorm:"index"`
|
AccountID string `gorm:"index"`
|
||||||
Name string
|
Name string
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type NetworkRouter struct {
|
type NetworkRouter struct {
|
||||||
ID string `gorm:"index"`
|
ID string `gorm:"primaryKey"`
|
||||||
NetworkID string `gorm:"index"`
|
NetworkID string `gorm:"index"`
|
||||||
AccountID string `gorm:"index"`
|
AccountID string `gorm:"index"`
|
||||||
Peer string
|
Peer string
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Network struct {
|
type Network struct {
|
||||||
ID string `gorm:"index"`
|
ID string `gorm:"primaryKey"`
|
||||||
AccountID string `gorm:"index"`
|
AccountID string `gorm:"index"`
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
|
|||||||
@@ -49,20 +49,9 @@ func (am *DefaultAccountManager) GetPeers(ctx context.Context, accountID, userID
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
peers := make([]*nbpeer.Peer, 0)
|
// @note if the user has permission to read peers it shows all account peers
|
||||||
peersMap := make(map[string]*nbpeer.Peer)
|
|
||||||
|
|
||||||
for _, peer := range accountPeers {
|
|
||||||
if user.IsRegularUser() && user.Id != peer.UserID {
|
|
||||||
// only display peers that belong to the current user if the current user is not an admin
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
peers = append(peers, peer)
|
|
||||||
peersMap[peer.ID] = peer
|
|
||||||
}
|
|
||||||
|
|
||||||
if allowed {
|
if allowed {
|
||||||
return peers, nil
|
return accountPeers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID)
|
settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID)
|
||||||
@@ -70,10 +59,22 @@ func (am *DefaultAccountManager) GetPeers(ctx context.Context, accountID, userID
|
|||||||
return nil, fmt.Errorf("failed to get account settings: %w", err)
|
return nil, fmt.Errorf("failed to get account settings: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if settings.RegularUsersViewBlocked {
|
if user.IsRestrictable() && settings.RegularUsersViewBlocked {
|
||||||
return []*nbpeer.Peer{}, nil
|
return []*nbpeer.Peer{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @note if it does not have permission read peers then only display it's own peers
|
||||||
|
peers := make([]*nbpeer.Peer, 0)
|
||||||
|
peersMap := make(map[string]*nbpeer.Peer)
|
||||||
|
|
||||||
|
for _, peer := range accountPeers {
|
||||||
|
if user.Id != peer.UserID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
peers = append(peers, peer)
|
||||||
|
peersMap[peer.ID] = peer
|
||||||
|
}
|
||||||
|
|
||||||
return am.getUserAccessiblePeers(ctx, accountID, peersMap, peers)
|
return am.getUserAccessiblePeers(ctx, accountID, peersMap, peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ type Manager interface {
|
|||||||
ValidateUserPermissions(ctx context.Context, accountID, userID string, module modules.Module, operation operations.Operation) (bool, error)
|
ValidateUserPermissions(ctx context.Context, accountID, userID string, module modules.Module, operation operations.Operation) (bool, error)
|
||||||
ValidateRoleModuleAccess(ctx context.Context, accountID string, role roles.RolePermissions, module modules.Module, operation operations.Operation) bool
|
ValidateRoleModuleAccess(ctx context.Context, accountID string, role roles.RolePermissions, module modules.Module, operation operations.Operation) bool
|
||||||
ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error
|
ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error
|
||||||
|
|
||||||
|
GetPermissionsByRole(ctx context.Context, role types.UserRole) (roles.Permissions, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type managerImpl struct {
|
type managerImpl struct {
|
||||||
@@ -96,3 +98,22 @@ func (m *managerImpl) ValidateAccountAccess(ctx context.Context, accountID strin
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *managerImpl) GetPermissionsByRole(ctx context.Context, role types.UserRole) (roles.Permissions, error) {
|
||||||
|
roleMap, ok := roles.RolesMap[role]
|
||||||
|
if !ok {
|
||||||
|
return roles.Permissions{}, status.NewUserRoleNotFoundError(string(role))
|
||||||
|
}
|
||||||
|
|
||||||
|
permissions := roles.Permissions{}
|
||||||
|
|
||||||
|
for k := range modules.All {
|
||||||
|
if rolePermissions, ok := roleMap.Permissions[k]; ok {
|
||||||
|
permissions[k] = rolePermissions
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
permissions[k] = roleMap.AutoAllowNew
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,6 +38,21 @@ func (m *MockManager) EXPECT() *MockManagerMockRecorder {
|
|||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPermissionsByRole mocks base method.
|
||||||
|
func (m *MockManager) GetPermissionsByRole(ctx context.Context, role types.UserRole) (roles.Permissions, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetPermissionsByRole", ctx, role)
|
||||||
|
ret0, _ := ret[0].(roles.Permissions)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPermissionsByRole indicates an expected call of GetPermissionsByRole.
|
||||||
|
func (mr *MockManagerMockRecorder) GetPermissionsByRole(ctx, role interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPermissionsByRole", reflect.TypeOf((*MockManager)(nil).GetPermissionsByRole), ctx, role)
|
||||||
|
}
|
||||||
|
|
||||||
// ValidateAccountAccess mocks base method.
|
// ValidateAccountAccess mocks base method.
|
||||||
func (m *MockManager) ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error {
|
func (m *MockManager) ValidateAccountAccess(ctx context.Context, accountID string, user *types.User, allowOwnerAndAdmin bool) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|||||||
@@ -17,3 +17,19 @@ const (
|
|||||||
SetupKeys Module = "setup_keys"
|
SetupKeys Module = "setup_keys"
|
||||||
Pats Module = "pats"
|
Pats Module = "pats"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var All = map[Module]struct{}{
|
||||||
|
Networks: {},
|
||||||
|
Peers: {},
|
||||||
|
Groups: {},
|
||||||
|
Settings: {},
|
||||||
|
Accounts: {},
|
||||||
|
Dns: {},
|
||||||
|
Nameservers: {},
|
||||||
|
Events: {},
|
||||||
|
Policies: {},
|
||||||
|
Routes: {},
|
||||||
|
Users: {},
|
||||||
|
SetupKeys: {},
|
||||||
|
Pats: {},
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ var NetworkAdmin = RolePermissions{
|
|||||||
},
|
},
|
||||||
modules.Groups: {
|
modules.Groups: {
|
||||||
operations.Read: true,
|
operations.Read: true,
|
||||||
operations.Create: false,
|
operations.Create: true,
|
||||||
operations.Update: false,
|
operations.Update: true,
|
||||||
operations.Delete: false,
|
operations.Delete: true,
|
||||||
},
|
},
|
||||||
modules.Settings: {
|
modules.Settings: {
|
||||||
operations.Read: true,
|
operations.Read: true,
|
||||||
@@ -87,5 +87,11 @@ var NetworkAdmin = RolePermissions{
|
|||||||
operations.Update: true,
|
operations.Update: true,
|
||||||
operations.Delete: true,
|
operations.Delete: true,
|
||||||
},
|
},
|
||||||
|
modules.Peers: {
|
||||||
|
operations.Read: true,
|
||||||
|
operations.Create: false,
|
||||||
|
operations.Update: false,
|
||||||
|
operations.Delete: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -802,7 +802,7 @@ func (s *SqlStore) GetAccountByPeerPubKey(ctx context.Context, peerKey string) (
|
|||||||
|
|
||||||
func (s *SqlStore) GetAnyAccountID(ctx context.Context) (string, error) {
|
func (s *SqlStore) GetAnyAccountID(ctx context.Context) (string, error) {
|
||||||
var account types.Account
|
var account types.Account
|
||||||
result := s.db.WithContext(ctx).Select("id").Limit(1).Find(&account)
|
result := s.db.WithContext(ctx).Select("id").Order("created_at desc").Limit(1).Find(&account)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
return "", status.NewGetAccountFromStoreError(result.Error)
|
return "", status.NewGetAccountFromStoreError(result.Error)
|
||||||
}
|
}
|
||||||
@@ -1683,18 +1683,26 @@ func (s *SqlStore) SavePolicy(ctx context.Context, lockStrength LockingStrength,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlStore) DeletePolicy(ctx context.Context, lockStrength LockingStrength, accountID, policyID string) error {
|
func (s *SqlStore) DeletePolicy(ctx context.Context, lockStrength LockingStrength, accountID, policyID string) error {
|
||||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||||
Delete(&types.Policy{}, accountAndIDQueryCondition, accountID, policyID)
|
if err := tx.Where("policy_id = ?", policyID).Delete(&types.PolicyRule{}).Error; err != nil {
|
||||||
if err := result.Error; err != nil {
|
return fmt.Errorf("delete policy rules: %w", err)
|
||||||
log.WithContext(ctx).Errorf("failed to delete policy from store: %s", err)
|
}
|
||||||
return status.Errorf(status.Internal, "failed to delete policy from store")
|
|
||||||
}
|
|
||||||
|
|
||||||
if result.RowsAffected == 0 {
|
result := tx.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||||
return status.NewPolicyNotFoundError(policyID)
|
Where(accountAndIDQueryCondition, accountID, policyID).
|
||||||
}
|
Delete(&types.Policy{})
|
||||||
|
|
||||||
return nil
|
if err := result.Error; err != nil {
|
||||||
|
log.WithContext(ctx).Errorf("failed to delete policy from store: %s", err)
|
||||||
|
return status.Errorf(status.Internal, "failed to delete policy from store")
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.RowsAffected == 0 {
|
||||||
|
return status.NewPolicyNotFoundError(policyID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccountPostureChecks retrieves posture checks for an account.
|
// GetAccountPostureChecks retrieves posture checks for an account.
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ func Test_NewStore(t *testing.T) {
|
|||||||
|
|
||||||
runTestForAllEngines(t, "", func(t *testing.T, store Store) {
|
runTestForAllEngines(t, "", func(t *testing.T, store Store) {
|
||||||
if store == nil {
|
if store == nil {
|
||||||
t.Errorf("expected to create a new Store")
|
t.Fatalf("expected to create a new Store")
|
||||||
}
|
}
|
||||||
if len(store.GetAllAccounts(context.Background())) != 0 {
|
if len(store.GetAllAccounts(context.Background())) != 0 {
|
||||||
t.Errorf("expected to create a new empty Accounts map when creating a new FileStore")
|
t.Fatalf("expected to create a new empty Accounts map when creating a new FileStore")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1115,7 +1115,7 @@ func TestSqlite_CreateAndGetObjectInTransaction(t *testing.T) {
|
|||||||
|
|
||||||
group := &types.Group{
|
group := &types.Group{
|
||||||
ID: "group-id",
|
ID: "group-id",
|
||||||
AccountID: "account-id",
|
AccountID: "bf1c8084-ba50-4ce7-9439-34653001fc3b",
|
||||||
Name: "group-name",
|
Name: "group-name",
|
||||||
Issued: "api",
|
Issued: "api",
|
||||||
Peers: nil,
|
Peers: nil,
|
||||||
|
|||||||
@@ -315,6 +315,15 @@ func getMigrations(ctx context.Context) []migrationFunc {
|
|||||||
func(db *gorm.DB) error {
|
func(db *gorm.DB) error {
|
||||||
return migration.MigrateNewField[routerTypes.NetworkRouter](ctx, db, "enabled", true)
|
return migration.MigrateNewField[routerTypes.NetworkRouter](ctx, db, "enabled", true)
|
||||||
},
|
},
|
||||||
|
func(db *gorm.DB) error {
|
||||||
|
return migration.DropIndex[networkTypes.Network](ctx, db, "idx_networks_id")
|
||||||
|
},
|
||||||
|
func(db *gorm.DB) error {
|
||||||
|
return migration.DropIndex[resourceTypes.NetworkResource](ctx, db, "idx_network_resources_id")
|
||||||
|
},
|
||||||
|
func(db *gorm.DB) error {
|
||||||
|
return migration.DropIndex[routerTypes.NetworkRouter](ctx, db, "idx_network_routers_id")
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const (
|
|||||||
// Group of the peers for ACL
|
// Group of the peers for ACL
|
||||||
type Group struct {
|
type Group struct {
|
||||||
// ID of the group
|
// ID of the group
|
||||||
ID string
|
ID string `gorm:"primaryKey"`
|
||||||
|
|
||||||
// AccountID is a reference to Account that this object belongs
|
// AccountID is a reference to Account that this object belongs
|
||||||
AccountID string `json:"-" gorm:"index"`
|
AccountID string `json:"-" gorm:"index"`
|
||||||
|
|||||||
@@ -65,11 +65,6 @@ type UserInfo struct {
|
|||||||
LastLogin time.Time `json:"last_login"`
|
LastLogin time.Time `json:"last_login"`
|
||||||
Issued string `json:"issued"`
|
Issued string `json:"issued"`
|
||||||
IntegrationReference integration_reference.IntegrationReference `json:"-"`
|
IntegrationReference integration_reference.IntegrationReference `json:"-"`
|
||||||
Permissions UserPermissions `json:"permissions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserPermissions struct {
|
|
||||||
DashboardView string `json:"dashboard_view"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// User represents a user of the system
|
// User represents a user of the system
|
||||||
@@ -132,21 +127,18 @@ func (u *User) IsRegularUser() bool {
|
|||||||
return !u.HasAdminPower() && !u.IsServiceUser
|
return !u.HasAdminPower() && !u.IsServiceUser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRestrictable checks whether a user is in a restrictable role.
|
||||||
|
func (u *User) IsRestrictable() bool {
|
||||||
|
return u.Role == UserRoleUser || u.Role == UserRoleBillingAdmin
|
||||||
|
}
|
||||||
|
|
||||||
// ToUserInfo converts a User object to a UserInfo object.
|
// ToUserInfo converts a User object to a UserInfo object.
|
||||||
func (u *User) ToUserInfo(userData *idp.UserData, settings *Settings) (*UserInfo, error) {
|
func (u *User) ToUserInfo(userData *idp.UserData) (*UserInfo, error) {
|
||||||
autoGroups := u.AutoGroups
|
autoGroups := u.AutoGroups
|
||||||
if autoGroups == nil {
|
if autoGroups == nil {
|
||||||
autoGroups = []string{}
|
autoGroups = []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
dashboardViewPermissions := "full"
|
|
||||||
if !u.HasAdminPower() {
|
|
||||||
dashboardViewPermissions = "limited"
|
|
||||||
if settings.RegularUsersViewBlocked {
|
|
||||||
dashboardViewPermissions = "blocked"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if userData == nil {
|
if userData == nil {
|
||||||
return &UserInfo{
|
return &UserInfo{
|
||||||
ID: u.Id,
|
ID: u.Id,
|
||||||
@@ -159,9 +151,6 @@ func (u *User) ToUserInfo(userData *idp.UserData, settings *Settings) (*UserInfo
|
|||||||
IsBlocked: u.Blocked,
|
IsBlocked: u.Blocked,
|
||||||
LastLogin: u.GetLastLogin(),
|
LastLogin: u.GetLastLogin(),
|
||||||
Issued: u.Issued,
|
Issued: u.Issued,
|
||||||
Permissions: UserPermissions{
|
|
||||||
DashboardView: dashboardViewPermissions,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
if userData.ID != u.Id {
|
if userData.ID != u.Id {
|
||||||
@@ -184,9 +173,6 @@ func (u *User) ToUserInfo(userData *idp.UserData, settings *Settings) (*UserInfo
|
|||||||
IsBlocked: u.Blocked,
|
IsBlocked: u.Blocked,
|
||||||
LastLogin: u.GetLastLogin(),
|
LastLogin: u.GetLastLogin(),
|
||||||
Issued: u.Issued,
|
Issued: u.Issued,
|
||||||
Permissions: UserPermissions{
|
|
||||||
DashboardView: dashboardViewPermissions,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
nbContext "github.com/netbirdio/netbird/management/server/context"
|
nbContext "github.com/netbirdio/netbird/management/server/context"
|
||||||
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/idp"
|
"github.com/netbirdio/netbird/management/server/idp"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/permissions/modules"
|
"github.com/netbirdio/netbird/management/server/permissions/modules"
|
||||||
@@ -19,6 +20,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
"github.com/netbirdio/netbird/management/server/users"
|
||||||
"github.com/netbirdio/netbird/management/server/util"
|
"github.com/netbirdio/netbird/management/server/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -122,11 +124,6 @@ func (am *DefaultAccountManager) inviteNewUser(ctx context.Context, accountID, u
|
|||||||
CreatedAt: time.Now().UTC(),
|
CreatedAt: time.Now().UTC(),
|
||||||
}
|
}
|
||||||
|
|
||||||
settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = am.Store.SaveUser(ctx, store.LockingStrengthUpdate, newUser); err != nil {
|
if err = am.Store.SaveUser(ctx, store.LockingStrengthUpdate, newUser); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -138,7 +135,7 @@ func (am *DefaultAccountManager) inviteNewUser(ctx context.Context, accountID, u
|
|||||||
|
|
||||||
am.StoreEvent(ctx, userID, newUser.Id, accountID, activity.UserInvited, nil)
|
am.StoreEvent(ctx, userID, newUser.Id, accountID, activity.UserInvited, nil)
|
||||||
|
|
||||||
return newUser.ToUserInfo(idpUser, settings)
|
return newUser.ToUserInfo(idpUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
// createNewIdpUser validates the invite and creates a new user in the IdP
|
// createNewIdpUser validates the invite and creates a new user in the IdP
|
||||||
@@ -360,6 +357,7 @@ func (am *DefaultAccountManager) CreatePAT(ctx context.Context, accountID string
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @note this is essential to prevent non admin users with Pats create permission frpm creating one for a service user
|
||||||
if initiatorUserID != targetUserID && !(initiatorUser.HasAdminPower() && targetUser.IsServiceUser) {
|
if initiatorUserID != targetUserID && !(initiatorUser.HasAdminPower() && targetUser.IsServiceUser) {
|
||||||
return nil, status.NewAdminPermissionError()
|
return nil, status.NewAdminPermissionError()
|
||||||
}
|
}
|
||||||
@@ -727,19 +725,14 @@ func handleOwnerRoleTransfer(ctx context.Context, transaction store.Store, initi
|
|||||||
// If the AccountManager has a non-nil idpManager and the User is not a service user,
|
// If the AccountManager has a non-nil idpManager and the User is not a service user,
|
||||||
// it will attempt to look up the UserData from the cache.
|
// it will attempt to look up the UserData from the cache.
|
||||||
func (am *DefaultAccountManager) getUserInfo(ctx context.Context, user *types.User, accountID string) (*types.UserInfo, error) {
|
func (am *DefaultAccountManager) getUserInfo(ctx context.Context, user *types.User, accountID string) (*types.UserInfo, error) {
|
||||||
settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isNil(am.idpManager) && !user.IsServiceUser {
|
if !isNil(am.idpManager) && !user.IsServiceUser {
|
||||||
userData, err := am.lookupUserInCache(ctx, user.Id, accountID)
|
userData, err := am.lookupUserInCache(ctx, user.Id, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return user.ToUserInfo(userData, settings)
|
return user.ToUserInfo(userData)
|
||||||
}
|
}
|
||||||
return user.ToUserInfo(nil, settings)
|
return user.ToUserInfo(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateUserUpdate validates the update operation for a user.
|
// validateUserUpdate validates the update operation for a user.
|
||||||
@@ -879,17 +872,12 @@ func (am *DefaultAccountManager) BuildUserInfosForAccount(ctx context.Context, a
|
|||||||
queriedUsers = append(queriedUsers, usersFromIntegration...)
|
queriedUsers = append(queriedUsers, usersFromIntegration...)
|
||||||
}
|
}
|
||||||
|
|
||||||
settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
userInfosMap := make(map[string]*types.UserInfo)
|
userInfosMap := make(map[string]*types.UserInfo)
|
||||||
|
|
||||||
// in case of self-hosted, or IDP doesn't return anything, we will return the locally stored userInfo
|
// in case of self-hosted, or IDP doesn't return anything, we will return the locally stored userInfo
|
||||||
if len(queriedUsers) == 0 {
|
if len(queriedUsers) == 0 {
|
||||||
for _, accountUser := range accountUsers {
|
for _, accountUser := range accountUsers {
|
||||||
info, err := accountUser.ToUserInfo(nil, settings)
|
info, err := accountUser.ToUserInfo(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -902,7 +890,7 @@ func (am *DefaultAccountManager) BuildUserInfosForAccount(ctx context.Context, a
|
|||||||
for _, localUser := range accountUsers {
|
for _, localUser := range accountUsers {
|
||||||
var info *types.UserInfo
|
var info *types.UserInfo
|
||||||
if queriedUser, contains := findUserInIDPUserdata(localUser.Id, queriedUsers); contains {
|
if queriedUser, contains := findUserInIDPUserdata(localUser.Id, queriedUsers); contains {
|
||||||
info, err = localUser.ToUserInfo(queriedUser, settings)
|
info, err = localUser.ToUserInfo(queriedUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -912,14 +900,6 @@ func (am *DefaultAccountManager) BuildUserInfosForAccount(ctx context.Context, a
|
|||||||
name = localUser.ServiceUserName
|
name = localUser.ServiceUserName
|
||||||
}
|
}
|
||||||
|
|
||||||
dashboardViewPermissions := "full"
|
|
||||||
if !localUser.HasAdminPower() {
|
|
||||||
dashboardViewPermissions = "limited"
|
|
||||||
if settings.RegularUsersViewBlocked {
|
|
||||||
dashboardViewPermissions = "blocked"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info = &types.UserInfo{
|
info = &types.UserInfo{
|
||||||
ID: localUser.Id,
|
ID: localUser.Id,
|
||||||
Email: "",
|
Email: "",
|
||||||
@@ -929,7 +909,6 @@ func (am *DefaultAccountManager) BuildUserInfosForAccount(ctx context.Context, a
|
|||||||
Status: string(types.UserStatusActive),
|
Status: string(types.UserStatusActive),
|
||||||
IsServiceUser: localUser.IsServiceUser,
|
IsServiceUser: localUser.IsServiceUser,
|
||||||
NonDeletable: localUser.NonDeletable,
|
NonDeletable: localUser.NonDeletable,
|
||||||
Permissions: types.UserPermissions{DashboardView: dashboardViewPermissions},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
userInfosMap[info.ID] = info
|
userInfosMap[info.ID] = info
|
||||||
@@ -1239,8 +1218,10 @@ func validateUserInvite(invite *types.UserInfo) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentUserInfo retrieves the account's current user info
|
// GetCurrentUserInfo retrieves the account's current user info and permissions
|
||||||
func (am *DefaultAccountManager) GetCurrentUserInfo(ctx context.Context, accountID, userID string) (*types.UserInfo, error) {
|
func (am *DefaultAccountManager) GetCurrentUserInfo(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error) {
|
||||||
|
accountID, userID := userAuth.AccountId, userAuth.UserId
|
||||||
|
|
||||||
user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID)
|
user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthShare, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1258,10 +1239,25 @@ func (am *DefaultAccountManager) GetCurrentUserInfo(ctx context.Context, account
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settings, err := am.Store.GetAccountSettings(ctx, store.LockingStrengthShare, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
userInfo, err := am.getUserInfo(ctx, user, accountID)
|
userInfo, err := am.getUserInfo(ctx, user, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return userInfo, nil
|
userWithPermissions := &users.UserInfoWithPermissions{
|
||||||
|
UserInfo: userInfo,
|
||||||
|
Restricted: !userAuth.IsChild && user.IsRestrictable() && settings.RegularUsersViewBlocked,
|
||||||
|
}
|
||||||
|
|
||||||
|
permissions, err := am.permissionsManager.GetPermissionsByRole(ctx, user.Role)
|
||||||
|
if err == nil {
|
||||||
|
userWithPermissions.Permissions = permissions
|
||||||
|
}
|
||||||
|
|
||||||
|
return userWithPermissions, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ import (
|
|||||||
nbcache "github.com/netbirdio/netbird/management/server/cache"
|
nbcache "github.com/netbirdio/netbird/management/server/cache"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/permissions"
|
"github.com/netbirdio/netbird/management/server/permissions"
|
||||||
|
"github.com/netbirdio/netbird/management/server/permissions/modules"
|
||||||
|
"github.com/netbirdio/netbird/management/server/permissions/roles"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
|
"github.com/netbirdio/netbird/management/server/users"
|
||||||
"github.com/netbirdio/netbird/management/server/util"
|
"github.com/netbirdio/netbird/management/server/util"
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
@@ -1020,90 +1023,6 @@ func TestDefaultAccountManager_ListUsers(t *testing.T) {
|
|||||||
assert.Equal(t, 2, regular)
|
assert.Equal(t, 2, regular)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultAccountManager_ListUsers_DashboardPermissions(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
role types.UserRole
|
|
||||||
limitedViewSettings bool
|
|
||||||
expectedDashboardPermissions string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Regular user, no limited view settings",
|
|
||||||
role: types.UserRoleUser,
|
|
||||||
limitedViewSettings: false,
|
|
||||||
expectedDashboardPermissions: "limited",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Admin user, no limited view settings",
|
|
||||||
role: types.UserRoleAdmin,
|
|
||||||
limitedViewSettings: false,
|
|
||||||
expectedDashboardPermissions: "full",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Owner, no limited view settings",
|
|
||||||
role: types.UserRoleOwner,
|
|
||||||
limitedViewSettings: false,
|
|
||||||
expectedDashboardPermissions: "full",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Regular user, limited view settings",
|
|
||||||
role: types.UserRoleUser,
|
|
||||||
limitedViewSettings: true,
|
|
||||||
expectedDashboardPermissions: "blocked",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Admin user, limited view settings",
|
|
||||||
role: types.UserRoleAdmin,
|
|
||||||
limitedViewSettings: true,
|
|
||||||
expectedDashboardPermissions: "full",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Owner, limited view settings",
|
|
||||||
role: types.UserRoleOwner,
|
|
||||||
limitedViewSettings: true,
|
|
||||||
expectedDashboardPermissions: "full",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
|
||||||
store, cleanup, err := store.NewTestStoreFromSQL(context.Background(), "", t.TempDir())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error when creating store: %s", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(cleanup)
|
|
||||||
|
|
||||||
account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "")
|
|
||||||
account.Users["normal_user1"] = types.NewUser("normal_user1", testCase.role, false, false, "", []string{}, types.UserIssuedAPI)
|
|
||||||
account.Settings.RegularUsersViewBlocked = testCase.limitedViewSettings
|
|
||||||
delete(account.Users, mockUserID)
|
|
||||||
|
|
||||||
err = store.SaveAccount(context.Background(), account)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error when saving account: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
permissionsManager := permissions.NewManager(store)
|
|
||||||
am := DefaultAccountManager{
|
|
||||||
Store: store,
|
|
||||||
eventStore: &activity.InMemoryEventStore{},
|
|
||||||
permissionsManager: permissionsManager,
|
|
||||||
}
|
|
||||||
|
|
||||||
users, err := am.ListUsers(context.Background(), mockAccountID)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error when checking user role: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, 1, len(users))
|
|
||||||
|
|
||||||
userInfo, _ := users[0].ToUserInfo(nil, account.Settings)
|
|
||||||
assert.Equal(t, testCase.expectedDashboardPermissions, userInfo.Permissions.DashboardView)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDefaultAccountManager_ExternalCache(t *testing.T) {
|
func TestDefaultAccountManager_ExternalCache(t *testing.T) {
|
||||||
store, cleanup, err := store.NewTestStoreFromSQL(context.Background(), "", t.TempDir())
|
store, cleanup, err := store.NewTestStoreFromSQL(context.Background(), "", t.TempDir())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1654,121 +1573,154 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
|||||||
|
|
||||||
tt := []struct {
|
tt := []struct {
|
||||||
name string
|
name string
|
||||||
accountId string
|
userAuth nbcontext.UserAuth
|
||||||
userId string
|
|
||||||
expectedErr error
|
expectedErr error
|
||||||
expectedResult *types.UserInfo
|
expectedResult *users.UserInfoWithPermissions
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "not found",
|
name: "not found",
|
||||||
accountId: account1.Id,
|
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "not-found"},
|
||||||
userId: "not-found",
|
|
||||||
expectedErr: status.NewUserNotFoundError("not-found"),
|
expectedErr: status.NewUserNotFoundError("not-found"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not part of account",
|
name: "not part of account",
|
||||||
accountId: account1.Id,
|
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "account2Owner"},
|
||||||
userId: "account2Owner",
|
|
||||||
expectedErr: status.NewUserNotPartOfAccountError(),
|
expectedErr: status.NewUserNotPartOfAccountError(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "blocked",
|
name: "blocked",
|
||||||
accountId: account1.Id,
|
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "blocked-user"},
|
||||||
userId: "blocked-user",
|
|
||||||
expectedErr: status.NewUserBlockedError(),
|
expectedErr: status.NewUserBlockedError(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "service user",
|
name: "service user",
|
||||||
accountId: account1.Id,
|
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "service-user"},
|
||||||
userId: "service-user",
|
|
||||||
expectedErr: status.NewPermissionDeniedError(),
|
expectedErr: status.NewPermissionDeniedError(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "owner user",
|
name: "owner user",
|
||||||
accountId: account1.Id,
|
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "account1Owner"},
|
||||||
userId: "account1Owner",
|
expectedResult: &users.UserInfoWithPermissions{
|
||||||
expectedResult: &types.UserInfo{
|
UserInfo: &types.UserInfo{
|
||||||
ID: "account1Owner",
|
ID: "account1Owner",
|
||||||
Name: "",
|
Name: "",
|
||||||
Role: "owner",
|
Role: "owner",
|
||||||
AutoGroups: []string{},
|
AutoGroups: []string{},
|
||||||
Status: "active",
|
Status: "active",
|
||||||
IsServiceUser: false,
|
IsServiceUser: false,
|
||||||
IsBlocked: false,
|
IsBlocked: false,
|
||||||
NonDeletable: false,
|
NonDeletable: false,
|
||||||
LastLogin: time.Time{},
|
LastLogin: time.Time{},
|
||||||
Issued: "api",
|
Issued: "api",
|
||||||
IntegrationReference: integration_reference.IntegrationReference{},
|
IntegrationReference: integration_reference.IntegrationReference{},
|
||||||
Permissions: types.UserPermissions{
|
|
||||||
DashboardView: "full",
|
|
||||||
},
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.Owner),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "regular user",
|
name: "regular user",
|
||||||
accountId: account1.Id,
|
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "regular-user"},
|
||||||
userId: "regular-user",
|
expectedResult: &users.UserInfoWithPermissions{
|
||||||
expectedResult: &types.UserInfo{
|
UserInfo: &types.UserInfo{
|
||||||
ID: "regular-user",
|
ID: "regular-user",
|
||||||
Name: "",
|
Name: "",
|
||||||
Role: "user",
|
Role: "user",
|
||||||
Status: "active",
|
Status: "active",
|
||||||
IsServiceUser: false,
|
IsServiceUser: false,
|
||||||
IsBlocked: false,
|
IsBlocked: false,
|
||||||
NonDeletable: false,
|
NonDeletable: false,
|
||||||
LastLogin: time.Time{},
|
LastLogin: time.Time{},
|
||||||
Issued: "api",
|
Issued: "api",
|
||||||
IntegrationReference: integration_reference.IntegrationReference{},
|
IntegrationReference: integration_reference.IntegrationReference{},
|
||||||
Permissions: types.UserPermissions{
|
|
||||||
DashboardView: "limited",
|
|
||||||
},
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.User),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "admin user",
|
name: "admin user",
|
||||||
accountId: account1.Id,
|
userAuth: nbcontext.UserAuth{AccountId: account1.Id, UserId: "admin-user"},
|
||||||
userId: "admin-user",
|
expectedResult: &users.UserInfoWithPermissions{
|
||||||
expectedResult: &types.UserInfo{
|
UserInfo: &types.UserInfo{
|
||||||
ID: "admin-user",
|
ID: "admin-user",
|
||||||
Name: "",
|
Name: "",
|
||||||
Role: "admin",
|
Role: "admin",
|
||||||
Status: "active",
|
Status: "active",
|
||||||
IsServiceUser: false,
|
IsServiceUser: false,
|
||||||
IsBlocked: false,
|
IsBlocked: false,
|
||||||
NonDeletable: false,
|
NonDeletable: false,
|
||||||
LastLogin: time.Time{},
|
LastLogin: time.Time{},
|
||||||
Issued: "api",
|
Issued: "api",
|
||||||
IntegrationReference: integration_reference.IntegrationReference{},
|
IntegrationReference: integration_reference.IntegrationReference{},
|
||||||
Permissions: types.UserPermissions{
|
|
||||||
DashboardView: "full",
|
|
||||||
},
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.Admin),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "settings blocked regular user",
|
name: "settings blocked regular user",
|
||||||
accountId: account2.Id,
|
userAuth: nbcontext.UserAuth{AccountId: account2.Id, UserId: "settings-blocked-user"},
|
||||||
userId: "settings-blocked-user",
|
expectedResult: &users.UserInfoWithPermissions{
|
||||||
expectedResult: &types.UserInfo{
|
UserInfo: &types.UserInfo{
|
||||||
ID: "settings-blocked-user",
|
ID: "settings-blocked-user",
|
||||||
Name: "",
|
Name: "",
|
||||||
Role: "user",
|
Role: "user",
|
||||||
Status: "active",
|
Status: "active",
|
||||||
IsServiceUser: false,
|
IsServiceUser: false,
|
||||||
IsBlocked: false,
|
IsBlocked: false,
|
||||||
NonDeletable: false,
|
NonDeletable: false,
|
||||||
LastLogin: time.Time{},
|
LastLogin: time.Time{},
|
||||||
Issued: "api",
|
Issued: "api",
|
||||||
IntegrationReference: integration_reference.IntegrationReference{},
|
IntegrationReference: integration_reference.IntegrationReference{},
|
||||||
Permissions: types.UserPermissions{
|
|
||||||
DashboardView: "blocked",
|
|
||||||
},
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.User),
|
||||||
|
Restricted: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "settings blocked regular user child account",
|
||||||
|
userAuth: nbcontext.UserAuth{AccountId: account2.Id, UserId: "settings-blocked-user", IsChild: true},
|
||||||
|
expectedResult: &users.UserInfoWithPermissions{
|
||||||
|
UserInfo: &types.UserInfo{
|
||||||
|
ID: "settings-blocked-user",
|
||||||
|
Name: "",
|
||||||
|
Role: "user",
|
||||||
|
Status: "active",
|
||||||
|
IsServiceUser: false,
|
||||||
|
IsBlocked: false,
|
||||||
|
NonDeletable: false,
|
||||||
|
LastLogin: time.Time{},
|
||||||
|
Issued: "api",
|
||||||
|
IntegrationReference: integration_reference.IntegrationReference{},
|
||||||
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.User),
|
||||||
|
Restricted: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "settings blocked owner user",
|
||||||
|
userAuth: nbcontext.UserAuth{AccountId: account2.Id, UserId: "account2Owner"},
|
||||||
|
expectedResult: &users.UserInfoWithPermissions{
|
||||||
|
UserInfo: &types.UserInfo{
|
||||||
|
ID: "account2Owner",
|
||||||
|
Name: "",
|
||||||
|
Role: "owner",
|
||||||
|
AutoGroups: []string{},
|
||||||
|
Status: "active",
|
||||||
|
IsServiceUser: false,
|
||||||
|
IsBlocked: false,
|
||||||
|
NonDeletable: false,
|
||||||
|
LastLogin: time.Time{},
|
||||||
|
Issued: "api",
|
||||||
|
IntegrationReference: integration_reference.IntegrationReference{},
|
||||||
|
},
|
||||||
|
Permissions: mergeRolePermissions(roles.Owner),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tt {
|
for _, tc := range tt {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
result, err := am.GetCurrentUserInfo(context.Background(), tc.accountId, tc.userId)
|
result, err := am.GetCurrentUserInfo(context.Background(), tc.userAuth)
|
||||||
|
|
||||||
if tc.expectedErr != nil {
|
if tc.expectedErr != nil {
|
||||||
assert.Equal(t, err, tc.expectedErr)
|
assert.Equal(t, err, tc.expectedErr)
|
||||||
@@ -1780,3 +1732,17 @@ func TestDefaultAccountManager_GetCurrentUserInfo(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeRolePermissions(role roles.RolePermissions) roles.Permissions {
|
||||||
|
permissions := roles.Permissions{}
|
||||||
|
|
||||||
|
for k := range modules.All {
|
||||||
|
if rolePermissions, ok := role.Permissions[k]; ok {
|
||||||
|
permissions[k] = rolePermissions
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
permissions[k] = role.AutoAllowNew
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions
|
||||||
|
}
|
||||||
|
|||||||
14
management/server/users/user.go
Normal file
14
management/server/users/user.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package users
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/netbirdio/netbird/management/server/permissions/roles"
|
||||||
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Wrapped UserInfo with Role Permissions
|
||||||
|
type UserInfoWithPermissions struct {
|
||||||
|
*types.UserInfo
|
||||||
|
|
||||||
|
Permissions roles.Permissions
|
||||||
|
Restricted bool
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
import "google/protobuf/descriptor.proto";
|
|
||||||
import "google/protobuf/timestamp.proto";
|
|
||||||
import "google/protobuf/duration.proto";
|
|
||||||
|
|
||||||
option go_package = "/proto";
|
|
||||||
|
|
||||||
package daemon;
|
package daemon;
|
||||||
|
|
||||||
|
import "google/protobuf/descriptor.proto";
|
||||||
|
import "google/protobuf/duration.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
|
option go_package = "client/proto";
|
||||||
|
|
||||||
message EmptyRequest {}
|
message EmptyRequest {}
|
||||||
|
|
||||||
service DaemonService {
|
service DaemonService {
|
||||||
@@ -69,7 +69,6 @@ service DaemonService {
|
|||||||
rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) {}
|
rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
message LoginRequest {
|
message LoginRequest {
|
||||||
// setupKey netbird setup key.
|
// setupKey netbird setup key.
|
||||||
string setupKey = 1;
|
string setupKey = 1;
|
||||||
@@ -133,11 +132,10 @@ message LoginRequest {
|
|||||||
// This is needed because the generated code
|
// This is needed because the generated code
|
||||||
// omits initialized empty slices due to omitempty tags
|
// omits initialized empty slices due to omitempty tags
|
||||||
bool cleanDNSLabels = 27;
|
bool cleanDNSLabels = 27;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message LoginResponse {
|
message LoginResponse {
|
||||||
bool needsSSOLogin = 1;
|
bool needsSSOLogin = 1;
|
||||||
string userCode = 2;
|
string userCode = 2;
|
||||||
string verificationURI = 3;
|
string verificationURI = 3;
|
||||||
string verificationURIComplete = 4;
|
string verificationURIComplete = 4;
|
||||||
@@ -154,11 +152,11 @@ message UpRequest {}
|
|||||||
|
|
||||||
message UpResponse {}
|
message UpResponse {}
|
||||||
|
|
||||||
message StatusRequest{
|
message StatusRequest {
|
||||||
bool getFullPeerStatus = 1;
|
bool getFullPeerStatus = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message StatusResponse{
|
message StatusResponse {
|
||||||
// status of the server.
|
// status of the server.
|
||||||
string status = 1;
|
string status = 1;
|
||||||
FullStatus fullStatus = 2;
|
FullStatus fullStatus = 2;
|
||||||
@@ -228,7 +226,7 @@ message PeerState {
|
|||||||
message LocalPeerState {
|
message LocalPeerState {
|
||||||
string IP = 1;
|
string IP = 1;
|
||||||
string pubKey = 2;
|
string pubKey = 2;
|
||||||
bool kernelInterface = 3;
|
bool kernelInterface = 3;
|
||||||
string fqdn = 4;
|
string fqdn = 4;
|
||||||
bool rosenpassEnabled = 5;
|
bool rosenpassEnabled = 5;
|
||||||
bool rosenpassPermissive = 6;
|
bool rosenpassPermissive = 6;
|
||||||
@@ -266,8 +264,8 @@ message NSGroupState {
|
|||||||
// FullStatus contains the full state held by the Status instance
|
// FullStatus contains the full state held by the Status instance
|
||||||
message FullStatus {
|
message FullStatus {
|
||||||
ManagementState managementState = 1;
|
ManagementState managementState = 1;
|
||||||
SignalState signalState = 2;
|
SignalState signalState = 2;
|
||||||
LocalPeerState localPeerState = 3;
|
LocalPeerState localPeerState = 3;
|
||||||
repeated PeerState peers = 4;
|
repeated PeerState peers = 4;
|
||||||
repeated RelayState relays = 5;
|
repeated RelayState relays = 5;
|
||||||
repeated NSGroupState dns_servers = 6;
|
repeated NSGroupState dns_servers = 6;
|
||||||
@@ -277,8 +275,7 @@ message FullStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Networks
|
// Networks
|
||||||
message ListNetworksRequest {
|
message ListNetworksRequest {}
|
||||||
}
|
|
||||||
|
|
||||||
message ListNetworksResponse {
|
message ListNetworksResponse {
|
||||||
repeated Network routes = 1;
|
repeated Network routes = 1;
|
||||||
@@ -290,8 +287,7 @@ message SelectNetworksRequest {
|
|||||||
bool all = 3;
|
bool all = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SelectNetworksResponse {
|
message SelectNetworksResponse {}
|
||||||
}
|
|
||||||
|
|
||||||
message IPList {
|
message IPList {
|
||||||
repeated string ips = 1;
|
repeated string ips = 1;
|
||||||
@@ -330,7 +326,6 @@ message ForwardingRulesResponse {
|
|||||||
repeated ForwardingRule rules = 1;
|
repeated ForwardingRule rules = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// DebugBundler
|
// DebugBundler
|
||||||
message DebugBundleRequest {
|
message DebugBundleRequest {
|
||||||
bool anonymize = 1;
|
bool anonymize = 1;
|
||||||
@@ -356,8 +351,7 @@ enum LogLevel {
|
|||||||
TRACE = 7;
|
TRACE = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetLogLevelRequest {
|
message GetLogLevelRequest {}
|
||||||
}
|
|
||||||
|
|
||||||
message GetLogLevelResponse {
|
message GetLogLevelResponse {
|
||||||
LogLevel level = 1;
|
LogLevel level = 1;
|
||||||
@@ -367,8 +361,7 @@ message SetLogLevelRequest {
|
|||||||
LogLevel level = 1;
|
LogLevel level = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SetLogLevelResponse {
|
message SetLogLevelResponse {}
|
||||||
}
|
|
||||||
|
|
||||||
// State represents a daemon state entry
|
// State represents a daemon state entry
|
||||||
message State {
|
message State {
|
||||||
@@ -405,7 +398,6 @@ message DeleteStateResponse {
|
|||||||
int32 deleted_states = 1;
|
int32 deleted_states = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
message SetNetworkMapPersistenceRequest {
|
message SetNetworkMapPersistenceRequest {
|
||||||
bool enabled = 1;
|
bool enabled = 1;
|
||||||
}
|
}
|
||||||
@@ -445,7 +437,7 @@ message TracePacketResponse {
|
|||||||
bool final_disposition = 2;
|
bool final_disposition = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SubscribeRequest{}
|
message SubscribeRequest {}
|
||||||
|
|
||||||
message SystemEvent {
|
message SystemEvent {
|
||||||
enum Severity {
|
enum Severity {
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package flow;
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
option go_package = "/proto";
|
option go_package = "flow/proto";
|
||||||
|
|
||||||
package flow;
|
|
||||||
|
|
||||||
service FlowService {
|
service FlowService {
|
||||||
// Client to receiver streams of events and acknowledgements
|
// Client to receiver streams of events and acknowledgements
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto";
|
|
||||||
import "google/protobuf/duration.proto";
|
|
||||||
|
|
||||||
option go_package = "/proto";
|
|
||||||
|
|
||||||
package management;
|
package management;
|
||||||
|
|
||||||
service ManagementService {
|
import "google/protobuf/duration.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
|
option go_package = "management/proto";
|
||||||
|
|
||||||
|
service ManagementService {
|
||||||
// Login logs in peer. In case server returns codes.PermissionDenied this endpoint can be used to register Peer providing LoginRequest.setupKey
|
// Login logs in peer. In case server returns codes.PermissionDenied this endpoint can be used to register Peer providing LoginRequest.setupKey
|
||||||
// Returns encrypted LoginResponse in EncryptedMessage.Body
|
// Returns encrypted LoginResponse in EncryptedMessage.Body
|
||||||
rpc Login(EncryptedMessage) returns (EncryptedMessage) {}
|
rpc Login(EncryptedMessage) returns (EncryptedMessage) {}
|
||||||
@@ -44,7 +43,7 @@ service ManagementService {
|
|||||||
// After sync the peer if there is a change in peer posture check which needs to be evaluated by the client,
|
// After sync the peer if there is a change in peer posture check which needs to be evaluated by the client,
|
||||||
// sync meta will evaluate the checks and update the peer meta with the result.
|
// sync meta will evaluate the checks and update the peer meta with the result.
|
||||||
// EncryptedMessage of the request has a body of Empty.
|
// EncryptedMessage of the request has a body of Empty.
|
||||||
rpc SyncMeta(EncryptedMessage) returns (Empty) {}
|
rpc SyncMeta(EncryptedMessage) returns (Empty) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
message EncryptedMessage {
|
message EncryptedMessage {
|
||||||
@@ -64,7 +63,6 @@ message SyncRequest {
|
|||||||
|
|
||||||
// SyncResponse represents a state that should be applied to the local peer (e.g. Netbird servers config as well as local peer and remote peers configs)
|
// SyncResponse represents a state that should be applied to the local peer (e.g. Netbird servers config as well as local peer and remote peers configs)
|
||||||
message SyncResponse {
|
message SyncResponse {
|
||||||
|
|
||||||
// Global config
|
// Global config
|
||||||
NetbirdConfig netbirdConfig = 1;
|
NetbirdConfig netbirdConfig = 1;
|
||||||
|
|
||||||
@@ -84,7 +82,7 @@ message SyncResponse {
|
|||||||
repeated Checks Checks = 6;
|
repeated Checks Checks = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SyncMetaRequest {
|
message SyncMetaRequest {
|
||||||
// Meta data of the peer
|
// Meta data of the peer
|
||||||
PeerSystemMeta meta = 1;
|
PeerSystemMeta meta = 1;
|
||||||
}
|
}
|
||||||
@@ -105,7 +103,6 @@ message LoginRequest {
|
|||||||
// PeerKeys is additional peer info like SSH pub key and WireGuard public key.
|
// PeerKeys is additional peer info like SSH pub key and WireGuard public key.
|
||||||
// This message is sent on Login or register requests, or when a key rotation has to happen.
|
// This message is sent on Login or register requests, or when a key rotation has to happen.
|
||||||
message PeerKeys {
|
message PeerKeys {
|
||||||
|
|
||||||
// sshPubKey represents a public SSH key of the peer. Can be absent.
|
// sshPubKey represents a public SSH key of the peer. Can be absent.
|
||||||
bytes sshPubKey = 1;
|
bytes sshPubKey = 1;
|
||||||
// wgPubKey represents a public WireGuard key of the peer. Can be absent.
|
// wgPubKey represents a public WireGuard key of the peer. Can be absent.
|
||||||
@@ -244,7 +241,7 @@ message ProtectedHostConfig {
|
|||||||
// The properties are used to configure local Wireguard
|
// The properties are used to configure local Wireguard
|
||||||
message PeerConfig {
|
message PeerConfig {
|
||||||
// Peer's virtual IP address within the Netbird VPN (a Wireguard address config)
|
// Peer's virtual IP address within the Netbird VPN (a Wireguard address config)
|
||||||
string address = 1;
|
string address = 1;
|
||||||
// Netbird DNS server (a Wireguard DNS config)
|
// Netbird DNS server (a Wireguard DNS config)
|
||||||
string dns = 2;
|
string dns = 2;
|
||||||
|
|
||||||
@@ -299,7 +296,6 @@ message NetworkMap {
|
|||||||
// RemotePeerConfig represents a configuration of a remote peer.
|
// RemotePeerConfig represents a configuration of a remote peer.
|
||||||
// The properties are used to configure WireGuard Peers sections
|
// The properties are used to configure WireGuard Peers sections
|
||||||
message RemotePeerConfig {
|
message RemotePeerConfig {
|
||||||
|
|
||||||
// A WireGuard public key of a remote peer
|
// A WireGuard public key of a remote peer
|
||||||
string wgPubKey = 1;
|
string wgPubKey = 1;
|
||||||
|
|
||||||
@@ -311,7 +307,6 @@ message RemotePeerConfig {
|
|||||||
|
|
||||||
// Peer fully qualified domain name
|
// Peer fully qualified domain name
|
||||||
string fqdn = 4;
|
string fqdn = 4;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSHConfig represents SSH configurations of a peer.
|
// SSHConfig represents SSH configurations of a peer.
|
||||||
@@ -326,6 +321,7 @@ message SSHConfig {
|
|||||||
|
|
||||||
// DeviceAuthorizationFlowRequest empty struct for future expansion
|
// DeviceAuthorizationFlowRequest empty struct for future expansion
|
||||||
message DeviceAuthorizationFlowRequest {}
|
message DeviceAuthorizationFlowRequest {}
|
||||||
|
|
||||||
// DeviceAuthorizationFlow represents Device Authorization Flow information
|
// DeviceAuthorizationFlow represents Device Authorization Flow information
|
||||||
// that can be used by the client to login initiate a Oauth 2.0 device authorization grant flow
|
// that can be used by the client to login initiate a Oauth 2.0 device authorization grant flow
|
||||||
// see https://datatracker.ietf.org/doc/html/rfc8628
|
// see https://datatracker.ietf.org/doc/html/rfc8628
|
||||||
@@ -380,10 +376,10 @@ message ProviderConfig {
|
|||||||
message Route {
|
message Route {
|
||||||
string ID = 1;
|
string ID = 1;
|
||||||
string Network = 2;
|
string Network = 2;
|
||||||
int64 NetworkType = 3;
|
int64 NetworkType = 3;
|
||||||
string Peer = 4;
|
string Peer = 4;
|
||||||
int64 Metric = 5;
|
int64 Metric = 5;
|
||||||
bool Masquerade = 6;
|
bool Masquerade = 6;
|
||||||
string NetID = 7;
|
string NetID = 7;
|
||||||
repeated string Domains = 8;
|
repeated string Domains = 8;
|
||||||
bool keepRoute = 9;
|
bool keepRoute = 9;
|
||||||
@@ -422,8 +418,8 @@ message NameServerGroup {
|
|||||||
// NameServer represents a dns.NameServer
|
// NameServer represents a dns.NameServer
|
||||||
message NameServer {
|
message NameServer {
|
||||||
string IP = 1;
|
string IP = 1;
|
||||||
int64 NSType = 2;
|
int64 NSType = 2;
|
||||||
int64 Port = 3;
|
int64 Port = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RuleProtocol {
|
enum RuleProtocol {
|
||||||
@@ -445,7 +441,6 @@ enum RuleAction {
|
|||||||
DROP = 1;
|
DROP = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FirewallRule represents a firewall rule
|
// FirewallRule represents a firewall rule
|
||||||
message FirewallRule {
|
message FirewallRule {
|
||||||
string PeerIP = 1;
|
string PeerIP = 1;
|
||||||
@@ -468,7 +463,6 @@ message Checks {
|
|||||||
repeated string Files = 1;
|
repeated string Files = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
message PortInfo {
|
message PortInfo {
|
||||||
oneof portSelection {
|
oneof portSelection {
|
||||||
uint32 port = 1;
|
uint32 port = 1;
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package signalexchange;
|
||||||
|
|
||||||
import "google/protobuf/descriptor.proto";
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
option go_package = "/proto";
|
option go_package = "signal/proto";
|
||||||
|
|
||||||
package signalexchange;
|
|
||||||
|
|
||||||
service SignalExchange {
|
service SignalExchange {
|
||||||
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
|
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
|
||||||
@@ -16,7 +16,6 @@ service SignalExchange {
|
|||||||
// Used for sending through signal.
|
// Used for sending through signal.
|
||||||
// The body of this message is the Body message encrypted with the Wireguard private key and the remote Peer key
|
// The body of this message is the Body message encrypted with the Wireguard private key and the remote Peer key
|
||||||
message EncryptedMessage {
|
message EncryptedMessage {
|
||||||
|
|
||||||
// Wireguard public key
|
// Wireguard public key
|
||||||
string key = 2;
|
string key = 2;
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
option go_package = "/testprotos";
|
|
||||||
|
|
||||||
package testprotos;
|
package testprotos;
|
||||||
|
|
||||||
|
option go_package = "encryption/testprotos";
|
||||||
|
|
||||||
message TestMessage {
|
message TestMessage {
|
||||||
string body = 1;
|
string body = 1;
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,16 @@ func (d Dialer) Dial(ctx context.Context, address string) (net.Conn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the base TLS config
|
||||||
|
tlsClientConfig := quictls.ClientQUICTLSConfig()
|
||||||
|
|
||||||
|
// Set ServerName to hostname if not an IP address
|
||||||
|
host, _, splitErr := net.SplitHostPort(quicURL)
|
||||||
|
if splitErr == nil && net.ParseIP(host) == nil {
|
||||||
|
// It's a hostname, not an IP - modify directly
|
||||||
|
tlsClientConfig.ServerName = host
|
||||||
|
}
|
||||||
|
|
||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
KeepAlivePeriod: 30 * time.Second,
|
KeepAlivePeriod: 30 * time.Second,
|
||||||
MaxIdleTimeout: 4 * time.Minute,
|
MaxIdleTimeout: 4 * time.Minute,
|
||||||
@@ -47,7 +57,7 @@ func (d Dialer) Dial(ctx context.Context, address string) (net.Conn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
session, err := quic.Dial(ctx, udpConn, udpAddr, quictls.ClientQUICTLSConfig(), quicConfig)
|
session, err := quic.Dial(ctx, udpConn, udpAddr, tlsClientConfig, quicConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -61,12 +71,29 @@ func (d Dialer) Dial(ctx context.Context, address string) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func prepareURL(address string) (string, error) {
|
func prepareURL(address string) (string, error) {
|
||||||
if !strings.HasPrefix(address, "rel://") && !strings.HasPrefix(address, "rels://") {
|
var host string
|
||||||
|
var defaultPort string
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(address, "rels://"):
|
||||||
|
host = address[7:]
|
||||||
|
defaultPort = "443"
|
||||||
|
case strings.HasPrefix(address, "rel://"):
|
||||||
|
host = address[6:]
|
||||||
|
defaultPort = "80"
|
||||||
|
default:
|
||||||
return "", fmt.Errorf("unsupported scheme: %s", address)
|
return "", fmt.Errorf("unsupported scheme: %s", address)
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(address, "rels://") {
|
finalHost, finalPort, err := net.SplitHostPort(host)
|
||||||
return address[7:], nil
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "missing port") {
|
||||||
|
return host + ":" + defaultPort, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// return any other split error as is
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
return address[6:], nil
|
|
||||||
|
return finalHost + ":" + finalPort, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,16 +224,22 @@ check_use_bin_variable() {
|
|||||||
|
|
||||||
install_netbird() {
|
install_netbird() {
|
||||||
if [ -x "$(command -v netbird)" ]; then
|
if [ -x "$(command -v netbird)" ]; then
|
||||||
status_output=$(netbird status)
|
status_output="$(netbird status 2>&1 || true)"
|
||||||
if echo "$status_output" | grep -q 'Management: Connected' && echo "$status_output" | grep -q 'Signal: Connected'; then
|
|
||||||
echo "NetBird service is running, please stop it before proceeding"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$status_output" ]; then
|
if echo "$status_output" | grep -q 'failed to connect to daemon error: context deadline exceeded'; then
|
||||||
echo "NetBird seems to be installed already, please remove it before proceeding"
|
echo "Warning: could not reach NetBird daemon (timeout), proceeding anyway"
|
||||||
exit 1
|
else
|
||||||
fi
|
if echo "$status_output" | grep -q 'Management: Connected' && \
|
||||||
|
echo "$status_output" | grep -q 'Signal: Connected'; then
|
||||||
|
echo "NetBird service is running, please stop it before proceeding"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$status_output" ]; then
|
||||||
|
echo "NetBird seems to be installed already, please remove it before proceeding"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Run the installation, if a desktop environment is not detected
|
# Run the installation, if a desktop environment is not detected
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ func (s *SharedSocket) read(receiver receiver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadFrom reads packets received in the packetDemux channel
|
// ReadFrom reads packets received in the packetDemux channel
|
||||||
func (s *SharedSocket) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
func (s *SharedSocket) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||||
var pkt rcvdPacket
|
var pkt rcvdPacket
|
||||||
select {
|
select {
|
||||||
case <-s.ctx.Done():
|
case <-s.ctx.Done():
|
||||||
@@ -263,8 +263,7 @@ func (s *SharedSocket) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|||||||
|
|
||||||
decodedLayers := make([]gopacket.LayerType, 0, 3)
|
decodedLayers := make([]gopacket.LayerType, 0, 3)
|
||||||
|
|
||||||
err = parser.DecodeLayers(pkt.buf, &decodedLayers)
|
if err := parser.DecodeLayers(pkt.buf, &decodedLayers); err != nil {
|
||||||
if err != nil {
|
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,8 +272,8 @@ func (s *SharedSocket) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
|||||||
Port: int(udp.SrcPort),
|
Port: int(udp.SrcPort),
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(b, payload)
|
n := copy(b, payload)
|
||||||
return int(udp.Length), remoteAddr, nil
|
return n, remoteAddr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteTo builds a UDP packet and writes it using the specific IP version writer
|
// WriteTo builds a UDP packet and writes it using the specific IP version writer
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if ! which realpath > /dev/null 2>&1
|
|
||||||
then
|
|
||||||
echo realpath is not installed
|
|
||||||
echo run: brew install coreutils
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
old_pwd=$(pwd)
|
|
||||||
script_path=$(dirname $(realpath "$0"))
|
|
||||||
cd "$script_path"
|
|
||||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
|
||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
|
||||||
protoc -I ./ ./signalexchange.proto --go_out=../ --go-grpc_out=../
|
|
||||||
cd "$old_pwd"
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.35.1
|
||||||
// protoc v3.21.12
|
// protoc (unknown)
|
||||||
// source: signalexchange.proto
|
// source: signalexchange/signalexchange.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
@@ -58,11 +58,11 @@ func (x Body_Type) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (Body_Type) Descriptor() protoreflect.EnumDescriptor {
|
func (Body_Type) Descriptor() protoreflect.EnumDescriptor {
|
||||||
return file_signalexchange_proto_enumTypes[0].Descriptor()
|
return file_signalexchange_signalexchange_proto_enumTypes[0].Descriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Body_Type) Type() protoreflect.EnumType {
|
func (Body_Type) Type() protoreflect.EnumType {
|
||||||
return &file_signalexchange_proto_enumTypes[0]
|
return &file_signalexchange_signalexchange_proto_enumTypes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x Body_Type) Number() protoreflect.EnumNumber {
|
func (x Body_Type) Number() protoreflect.EnumNumber {
|
||||||
@@ -71,7 +71,7 @@ func (x Body_Type) Number() protoreflect.EnumNumber {
|
|||||||
|
|
||||||
// Deprecated: Use Body_Type.Descriptor instead.
|
// Deprecated: Use Body_Type.Descriptor instead.
|
||||||
func (Body_Type) EnumDescriptor() ([]byte, []int) {
|
func (Body_Type) EnumDescriptor() ([]byte, []int) {
|
||||||
return file_signalexchange_proto_rawDescGZIP(), []int{2, 0}
|
return file_signalexchange_signalexchange_proto_rawDescGZIP(), []int{2, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for sending through signal.
|
// Used for sending through signal.
|
||||||
@@ -91,11 +91,9 @@ type EncryptedMessage struct {
|
|||||||
|
|
||||||
func (x *EncryptedMessage) Reset() {
|
func (x *EncryptedMessage) Reset() {
|
||||||
*x = EncryptedMessage{}
|
*x = EncryptedMessage{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[0]
|
||||||
mi := &file_signalexchange_proto_msgTypes[0]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *EncryptedMessage) String() string {
|
func (x *EncryptedMessage) String() string {
|
||||||
@@ -105,8 +103,8 @@ func (x *EncryptedMessage) String() string {
|
|||||||
func (*EncryptedMessage) ProtoMessage() {}
|
func (*EncryptedMessage) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *EncryptedMessage) ProtoReflect() protoreflect.Message {
|
func (x *EncryptedMessage) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_signalexchange_proto_msgTypes[0]
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[0]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -118,7 +116,7 @@ func (x *EncryptedMessage) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use EncryptedMessage.ProtoReflect.Descriptor instead.
|
// Deprecated: Use EncryptedMessage.ProtoReflect.Descriptor instead.
|
||||||
func (*EncryptedMessage) Descriptor() ([]byte, []int) {
|
func (*EncryptedMessage) Descriptor() ([]byte, []int) {
|
||||||
return file_signalexchange_proto_rawDescGZIP(), []int{0}
|
return file_signalexchange_signalexchange_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *EncryptedMessage) GetKey() string {
|
func (x *EncryptedMessage) GetKey() string {
|
||||||
@@ -157,11 +155,9 @@ type Message struct {
|
|||||||
|
|
||||||
func (x *Message) Reset() {
|
func (x *Message) Reset() {
|
||||||
*x = Message{}
|
*x = Message{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[1]
|
||||||
mi := &file_signalexchange_proto_msgTypes[1]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Message) String() string {
|
func (x *Message) String() string {
|
||||||
@@ -171,8 +167,8 @@ func (x *Message) String() string {
|
|||||||
func (*Message) ProtoMessage() {}
|
func (*Message) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Message) ProtoReflect() protoreflect.Message {
|
func (x *Message) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_signalexchange_proto_msgTypes[1]
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[1]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -184,7 +180,7 @@ func (x *Message) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Message.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Message.ProtoReflect.Descriptor instead.
|
||||||
func (*Message) Descriptor() ([]byte, []int) {
|
func (*Message) Descriptor() ([]byte, []int) {
|
||||||
return file_signalexchange_proto_rawDescGZIP(), []int{1}
|
return file_signalexchange_signalexchange_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Message) GetKey() string {
|
func (x *Message) GetKey() string {
|
||||||
@@ -225,17 +221,15 @@ type Body struct {
|
|||||||
FeaturesSupported []uint32 `protobuf:"varint,6,rep,packed,name=featuresSupported,proto3" json:"featuresSupported,omitempty"`
|
FeaturesSupported []uint32 `protobuf:"varint,6,rep,packed,name=featuresSupported,proto3" json:"featuresSupported,omitempty"`
|
||||||
// RosenpassConfig is a Rosenpass config of the remote peer our peer tries to connect to
|
// RosenpassConfig is a Rosenpass config of the remote peer our peer tries to connect to
|
||||||
RosenpassConfig *RosenpassConfig `protobuf:"bytes,7,opt,name=rosenpassConfig,proto3" json:"rosenpassConfig,omitempty"`
|
RosenpassConfig *RosenpassConfig `protobuf:"bytes,7,opt,name=rosenpassConfig,proto3" json:"rosenpassConfig,omitempty"`
|
||||||
// relayServerAddress is an IP:port of the relay server
|
// relayServerAddress is url of the relay server
|
||||||
RelayServerAddress string `protobuf:"bytes,8,opt,name=relayServerAddress,proto3" json:"relayServerAddress,omitempty"`
|
RelayServerAddress string `protobuf:"bytes,8,opt,name=relayServerAddress,proto3" json:"relayServerAddress,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Body) Reset() {
|
func (x *Body) Reset() {
|
||||||
*x = Body{}
|
*x = Body{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[2]
|
||||||
mi := &file_signalexchange_proto_msgTypes[2]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Body) String() string {
|
func (x *Body) String() string {
|
||||||
@@ -245,8 +239,8 @@ func (x *Body) String() string {
|
|||||||
func (*Body) ProtoMessage() {}
|
func (*Body) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Body) ProtoReflect() protoreflect.Message {
|
func (x *Body) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_signalexchange_proto_msgTypes[2]
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[2]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -258,7 +252,7 @@ func (x *Body) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Body.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Body.ProtoReflect.Descriptor instead.
|
||||||
func (*Body) Descriptor() ([]byte, []int) {
|
func (*Body) Descriptor() ([]byte, []int) {
|
||||||
return file_signalexchange_proto_rawDescGZIP(), []int{2}
|
return file_signalexchange_signalexchange_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Body) GetType() Body_Type {
|
func (x *Body) GetType() Body_Type {
|
||||||
@@ -328,11 +322,9 @@ type Mode struct {
|
|||||||
|
|
||||||
func (x *Mode) Reset() {
|
func (x *Mode) Reset() {
|
||||||
*x = Mode{}
|
*x = Mode{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[3]
|
||||||
mi := &file_signalexchange_proto_msgTypes[3]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Mode) String() string {
|
func (x *Mode) String() string {
|
||||||
@@ -342,8 +334,8 @@ func (x *Mode) String() string {
|
|||||||
func (*Mode) ProtoMessage() {}
|
func (*Mode) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Mode) ProtoReflect() protoreflect.Message {
|
func (x *Mode) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_signalexchange_proto_msgTypes[3]
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -355,7 +347,7 @@ func (x *Mode) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Mode.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Mode.ProtoReflect.Descriptor instead.
|
||||||
func (*Mode) Descriptor() ([]byte, []int) {
|
func (*Mode) Descriptor() ([]byte, []int) {
|
||||||
return file_signalexchange_proto_rawDescGZIP(), []int{3}
|
return file_signalexchange_signalexchange_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Mode) GetDirect() bool {
|
func (x *Mode) GetDirect() bool {
|
||||||
@@ -377,11 +369,9 @@ type RosenpassConfig struct {
|
|||||||
|
|
||||||
func (x *RosenpassConfig) Reset() {
|
func (x *RosenpassConfig) Reset() {
|
||||||
*x = RosenpassConfig{}
|
*x = RosenpassConfig{}
|
||||||
if protoimpl.UnsafeEnabled {
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[4]
|
||||||
mi := &file_signalexchange_proto_msgTypes[4]
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms.StoreMessageInfo(mi)
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RosenpassConfig) String() string {
|
func (x *RosenpassConfig) String() string {
|
||||||
@@ -391,8 +381,8 @@ func (x *RosenpassConfig) String() string {
|
|||||||
func (*RosenpassConfig) ProtoMessage() {}
|
func (*RosenpassConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RosenpassConfig) ProtoReflect() protoreflect.Message {
|
func (x *RosenpassConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_signalexchange_proto_msgTypes[4]
|
mi := &file_signalexchange_signalexchange_proto_msgTypes[4]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
@@ -404,7 +394,7 @@ func (x *RosenpassConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use RosenpassConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RosenpassConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*RosenpassConfig) Descriptor() ([]byte, []int) {
|
func (*RosenpassConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_signalexchange_proto_rawDescGZIP(), []int{4}
|
return file_signalexchange_signalexchange_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RosenpassConfig) GetRosenpassPubKey() []byte {
|
func (x *RosenpassConfig) GetRosenpassPubKey() []byte {
|
||||||
@@ -421,92 +411,93 @@ func (x *RosenpassConfig) GetRosenpassServerAddr() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_signalexchange_proto protoreflect.FileDescriptor
|
var File_signalexchange_signalexchange_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_signalexchange_proto_rawDesc = []byte{
|
var file_signalexchange_signalexchange_proto_rawDesc = []byte{
|
||||||
0x0a, 0x14, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
|
0x0a, 0x23, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78,
|
0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e,
|
||||||
0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63,
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
0x68, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
|
||||||
0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x10, 0x45, 0x6e, 0x63, 0x72,
|
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
|
||||||
0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03,
|
0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x10, 0x45, 0x6e, 0x63, 0x72, 0x79,
|
||||||
0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1c,
|
0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||||
0x0a, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04,
|
|
||||||
0x62, 0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79,
|
|
||||||
0x22, 0x63, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
|
||||||
0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a,
|
0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a,
|
||||||
0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x04, 0x62,
|
0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x62,
|
||||||
0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x69, 0x67, 0x6e,
|
0x6f, 0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22,
|
||||||
0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52,
|
0x63, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||||
0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xa6, 0x03, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2d,
|
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09,
|
||||||
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x73,
|
0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x42, 0x6f,
|
0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x04, 0x62, 0x6f,
|
||||||
0x64, 0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a,
|
0x64, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61,
|
||||||
0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04,
|
||||||
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x77, 0x67, 0x4c, 0x69, 0x73,
|
0x62, 0x6f, 0x64, 0x79, 0x22, 0xa6, 0x03, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a,
|
||||||
0x74, 0x65, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x77,
|
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x73, 0x69,
|
||||||
0x67, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x6e,
|
0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x42, 0x6f, 0x64,
|
||||||
0x65, 0x74, 0x42, 0x69, 0x72, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20,
|
0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x65, 0x74, 0x42, 0x69, 0x72, 0x64, 0x56, 0x65, 0x72, 0x73,
|
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70,
|
||||||
0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
|
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x77, 0x67, 0x4c, 0x69, 0x73, 0x74,
|
||||||
0x0b, 0x32, 0x14, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e,
|
0x65, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x77, 0x67,
|
||||||
0x67, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a,
|
0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x65,
|
||||||
0x11, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
|
0x74, 0x42, 0x69, 0x72, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01,
|
||||||
0x65, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x11, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72,
|
0x28, 0x09, 0x52, 0x0e, 0x6e, 0x65, 0x74, 0x42, 0x69, 0x72, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||||
0x65, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x49, 0x0a, 0x0f, 0x72,
|
0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07,
|
0x32, 0x14, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63,
|
0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x11,
|
||||||
0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x52, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x43,
|
0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x72, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73,
|
0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x11, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x53,
|
0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x49, 0x0a, 0x0f, 0x72, 0x6f,
|
||||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x08, 0x20, 0x01,
|
0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, 0x20,
|
||||||
0x28, 0x09, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41,
|
0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68,
|
||||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x36, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09,
|
0x61, 0x6e, 0x67, 0x65, 0x2e, 0x52, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x43, 0x6f,
|
||||||
0x0a, 0x05, 0x4f, 0x46, 0x46, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4e, 0x53,
|
0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x72, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x43,
|
||||||
0x57, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x41, 0x4e, 0x44, 0x49, 0x44, 0x41,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65,
|
||||||
0x54, 0x45, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4f, 0x44, 0x45, 0x10, 0x04, 0x22, 0x2e,
|
0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28,
|
||||||
0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
0x09, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x36, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a,
|
||||||
0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x22, 0x6d,
|
0x05, 0x4f, 0x46, 0x46, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4e, 0x53, 0x57,
|
||||||
0x0a, 0x0f, 0x52, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
0x45, 0x52, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x41, 0x4e, 0x44, 0x49, 0x44, 0x41, 0x54,
|
||||||
0x67, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x50, 0x75,
|
0x45, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4f, 0x44, 0x45, 0x10, 0x04, 0x22, 0x2e, 0x0a,
|
||||||
0x62, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x72, 0x6f, 0x73, 0x65,
|
0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18,
|
||||||
0x6e, 0x70, 0x61, 0x73, 0x73, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x72,
|
0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x88,
|
||||||
0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64,
|
0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x22, 0x6d, 0x0a,
|
||||||
0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x72, 0x6f, 0x73, 0x65, 0x6e, 0x70,
|
0x0f, 0x52, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x61, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x32, 0xb9, 0x01,
|
0x12, 0x28, 0x0a, 0x0f, 0x72, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x50, 0x75, 0x62,
|
||||||
0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
|
0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x72, 0x6f, 0x73, 0x65, 0x6e,
|
||||||
0x12, 0x4c, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x20, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61,
|
0x70, 0x61, 0x73, 0x73, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x72, 0x6f,
|
||||||
0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70,
|
0x73, 0x65, 0x6e, 0x70, 0x61, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64,
|
||||||
0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x20, 0x2e, 0x73, 0x69, 0x67,
|
0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x72, 0x6f, 0x73, 0x65, 0x6e, 0x70, 0x61,
|
||||||
0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x45, 0x6e, 0x63, 0x72,
|
0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x32, 0xb9, 0x01, 0x0a,
|
||||||
0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x59,
|
0x0e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12,
|
||||||
0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12,
|
0x4c, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x20, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c,
|
||||||
0x20, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
|
0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74,
|
||||||
0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x20, 0x2e, 0x73, 0x69, 0x67, 0x6e,
|
||||||
0x65, 0x1a, 0x20, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e,
|
0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79,
|
||||||
0x67, 0x65, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73,
|
0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x59, 0x0a,
|
||||||
0x61, 0x67, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72,
|
0x0d, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x20,
|
||||||
0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e,
|
||||||
|
0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||||
|
0x1a, 0x20, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
|
||||||
|
0x65, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||||
|
0x67, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x0e, 0x5a, 0x0c, 0x73, 0x69, 0x67, 0x6e,
|
||||||
|
0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_signalexchange_proto_rawDescOnce sync.Once
|
file_signalexchange_signalexchange_proto_rawDescOnce sync.Once
|
||||||
file_signalexchange_proto_rawDescData = file_signalexchange_proto_rawDesc
|
file_signalexchange_signalexchange_proto_rawDescData = file_signalexchange_signalexchange_proto_rawDesc
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_signalexchange_proto_rawDescGZIP() []byte {
|
func file_signalexchange_signalexchange_proto_rawDescGZIP() []byte {
|
||||||
file_signalexchange_proto_rawDescOnce.Do(func() {
|
file_signalexchange_signalexchange_proto_rawDescOnce.Do(func() {
|
||||||
file_signalexchange_proto_rawDescData = protoimpl.X.CompressGZIP(file_signalexchange_proto_rawDescData)
|
file_signalexchange_signalexchange_proto_rawDescData = protoimpl.X.CompressGZIP(file_signalexchange_signalexchange_proto_rawDescData)
|
||||||
})
|
})
|
||||||
return file_signalexchange_proto_rawDescData
|
return file_signalexchange_signalexchange_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_signalexchange_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
var file_signalexchange_signalexchange_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
var file_signalexchange_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
var file_signalexchange_signalexchange_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
var file_signalexchange_proto_goTypes = []interface{}{
|
var file_signalexchange_signalexchange_proto_goTypes = []any{
|
||||||
(Body_Type)(0), // 0: signalexchange.Body.Type
|
(Body_Type)(0), // 0: signalexchange.Body.Type
|
||||||
(*EncryptedMessage)(nil), // 1: signalexchange.EncryptedMessage
|
(*EncryptedMessage)(nil), // 1: signalexchange.EncryptedMessage
|
||||||
(*Message)(nil), // 2: signalexchange.Message
|
(*Message)(nil), // 2: signalexchange.Message
|
||||||
@@ -514,7 +505,7 @@ var file_signalexchange_proto_goTypes = []interface{}{
|
|||||||
(*Mode)(nil), // 4: signalexchange.Mode
|
(*Mode)(nil), // 4: signalexchange.Mode
|
||||||
(*RosenpassConfig)(nil), // 5: signalexchange.RosenpassConfig
|
(*RosenpassConfig)(nil), // 5: signalexchange.RosenpassConfig
|
||||||
}
|
}
|
||||||
var file_signalexchange_proto_depIdxs = []int32{
|
var file_signalexchange_signalexchange_proto_depIdxs = []int32{
|
||||||
3, // 0: signalexchange.Message.body:type_name -> signalexchange.Body
|
3, // 0: signalexchange.Message.body:type_name -> signalexchange.Body
|
||||||
0, // 1: signalexchange.Body.type:type_name -> signalexchange.Body.Type
|
0, // 1: signalexchange.Body.type:type_name -> signalexchange.Body.Type
|
||||||
4, // 2: signalexchange.Body.mode:type_name -> signalexchange.Mode
|
4, // 2: signalexchange.Body.mode:type_name -> signalexchange.Mode
|
||||||
@@ -530,91 +521,29 @@ var file_signalexchange_proto_depIdxs = []int32{
|
|||||||
0, // [0:4] is the sub-list for field type_name
|
0, // [0:4] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_signalexchange_proto_init() }
|
func init() { file_signalexchange_signalexchange_proto_init() }
|
||||||
func file_signalexchange_proto_init() {
|
func file_signalexchange_signalexchange_proto_init() {
|
||||||
if File_signalexchange_proto != nil {
|
if File_signalexchange_signalexchange_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !protoimpl.UnsafeEnabled {
|
file_signalexchange_signalexchange_proto_msgTypes[3].OneofWrappers = []any{}
|
||||||
file_signalexchange_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*EncryptedMessage); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_signalexchange_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Message); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_signalexchange_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Body); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_signalexchange_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Mode); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_signalexchange_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*RosenpassConfig); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_signalexchange_proto_msgTypes[3].OneofWrappers = []interface{}{}
|
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_signalexchange_proto_rawDesc,
|
RawDescriptor: file_signalexchange_signalexchange_proto_rawDesc,
|
||||||
NumEnums: 1,
|
NumEnums: 1,
|
||||||
NumMessages: 5,
|
NumMessages: 5,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
GoTypes: file_signalexchange_proto_goTypes,
|
GoTypes: file_signalexchange_signalexchange_proto_goTypes,
|
||||||
DependencyIndexes: file_signalexchange_proto_depIdxs,
|
DependencyIndexes: file_signalexchange_signalexchange_proto_depIdxs,
|
||||||
EnumInfos: file_signalexchange_proto_enumTypes,
|
EnumInfos: file_signalexchange_signalexchange_proto_enumTypes,
|
||||||
MessageInfos: file_signalexchange_proto_msgTypes,
|
MessageInfos: file_signalexchange_signalexchange_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_signalexchange_proto = out.File
|
File_signalexchange_signalexchange_proto = out.File
|
||||||
file_signalexchange_proto_rawDesc = nil
|
file_signalexchange_signalexchange_proto_rawDesc = nil
|
||||||
file_signalexchange_proto_goTypes = nil
|
file_signalexchange_signalexchange_proto_goTypes = nil
|
||||||
file_signalexchange_proto_depIdxs = nil
|
file_signalexchange_signalexchange_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
|
// - protoc (unknown)
|
||||||
|
// source: signalexchange/signalexchange.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
|
|
||||||
@@ -11,8 +15,13 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.64.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
|
const (
|
||||||
|
SignalExchange_Send_FullMethodName = "/signalexchange.SignalExchange/Send"
|
||||||
|
SignalExchange_ConnectStream_FullMethodName = "/signalexchange.SignalExchange/ConnectStream"
|
||||||
|
)
|
||||||
|
|
||||||
// SignalExchangeClient is the client API for SignalExchange service.
|
// SignalExchangeClient is the client API for SignalExchange service.
|
||||||
//
|
//
|
||||||
@@ -21,7 +30,7 @@ type SignalExchangeClient interface {
|
|||||||
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
|
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
|
||||||
Send(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error)
|
Send(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error)
|
||||||
// Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer)
|
// Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer)
|
||||||
ConnectStream(ctx context.Context, opts ...grpc.CallOption) (SignalExchange_ConnectStreamClient, error)
|
ConnectStream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[EncryptedMessage, EncryptedMessage], error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type signalExchangeClient struct {
|
type signalExchangeClient struct {
|
||||||
@@ -33,67 +42,54 @@ func NewSignalExchangeClient(cc grpc.ClientConnInterface) SignalExchangeClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *signalExchangeClient) Send(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
func (c *signalExchangeClient) Send(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(EncryptedMessage)
|
out := new(EncryptedMessage)
|
||||||
err := c.cc.Invoke(ctx, "/signalexchange.SignalExchange/Send", in, out, opts...)
|
err := c.cc.Invoke(ctx, SignalExchange_Send_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *signalExchangeClient) ConnectStream(ctx context.Context, opts ...grpc.CallOption) (SignalExchange_ConnectStreamClient, error) {
|
func (c *signalExchangeClient) ConnectStream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[EncryptedMessage, EncryptedMessage], error) {
|
||||||
stream, err := c.cc.NewStream(ctx, &SignalExchange_ServiceDesc.Streams[0], "/signalexchange.SignalExchange/ConnectStream", opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
stream, err := c.cc.NewStream(ctx, &SignalExchange_ServiceDesc.Streams[0], SignalExchange_ConnectStream_FullMethodName, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
x := &signalExchangeConnectStreamClient{stream}
|
x := &grpc.GenericClientStream[EncryptedMessage, EncryptedMessage]{ClientStream: stream}
|
||||||
return x, nil
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignalExchange_ConnectStreamClient interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Send(*EncryptedMessage) error
|
type SignalExchange_ConnectStreamClient = grpc.BidiStreamingClient[EncryptedMessage, EncryptedMessage]
|
||||||
Recv() (*EncryptedMessage, error)
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type signalExchangeConnectStreamClient struct {
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *signalExchangeConnectStreamClient) Send(m *EncryptedMessage) error {
|
|
||||||
return x.ClientStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *signalExchangeConnectStreamClient) Recv() (*EncryptedMessage, error) {
|
|
||||||
m := new(EncryptedMessage)
|
|
||||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignalExchangeServer is the server API for SignalExchange service.
|
// SignalExchangeServer is the server API for SignalExchange service.
|
||||||
// All implementations must embed UnimplementedSignalExchangeServer
|
// All implementations must embed UnimplementedSignalExchangeServer
|
||||||
// for forward compatibility
|
// for forward compatibility.
|
||||||
type SignalExchangeServer interface {
|
type SignalExchangeServer interface {
|
||||||
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
|
// Synchronously connect to the Signal Exchange service offering connection candidates and waiting for connection candidates from the other party (remote peer)
|
||||||
Send(context.Context, *EncryptedMessage) (*EncryptedMessage, error)
|
Send(context.Context, *EncryptedMessage) (*EncryptedMessage, error)
|
||||||
// Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer)
|
// Connect to the Signal Exchange service offering connection candidates and maintain a channel for receiving candidates from the other party (remote peer)
|
||||||
ConnectStream(SignalExchange_ConnectStreamServer) error
|
ConnectStream(grpc.BidiStreamingServer[EncryptedMessage, EncryptedMessage]) error
|
||||||
mustEmbedUnimplementedSignalExchangeServer()
|
mustEmbedUnimplementedSignalExchangeServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnimplementedSignalExchangeServer must be embedded to have forward compatible implementations.
|
// UnimplementedSignalExchangeServer must be embedded to have
|
||||||
type UnimplementedSignalExchangeServer struct {
|
// forward compatible implementations.
|
||||||
}
|
//
|
||||||
|
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||||
|
// pointer dereference when methods are called.
|
||||||
|
type UnimplementedSignalExchangeServer struct{}
|
||||||
|
|
||||||
func (UnimplementedSignalExchangeServer) Send(context.Context, *EncryptedMessage) (*EncryptedMessage, error) {
|
func (UnimplementedSignalExchangeServer) Send(context.Context, *EncryptedMessage) (*EncryptedMessage, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Send not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Send not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedSignalExchangeServer) ConnectStream(SignalExchange_ConnectStreamServer) error {
|
func (UnimplementedSignalExchangeServer) ConnectStream(grpc.BidiStreamingServer[EncryptedMessage, EncryptedMessage]) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method ConnectStream not implemented")
|
return status.Errorf(codes.Unimplemented, "method ConnectStream not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedSignalExchangeServer) mustEmbedUnimplementedSignalExchangeServer() {}
|
func (UnimplementedSignalExchangeServer) mustEmbedUnimplementedSignalExchangeServer() {}
|
||||||
|
func (UnimplementedSignalExchangeServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
// UnsafeSignalExchangeServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeSignalExchangeServer may be embedded to opt out of forward compatibility for this service.
|
||||||
// Use of this interface is not recommended, as added methods to SignalExchangeServer will
|
// Use of this interface is not recommended, as added methods to SignalExchangeServer will
|
||||||
@@ -103,6 +99,13 @@ type UnsafeSignalExchangeServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterSignalExchangeServer(s grpc.ServiceRegistrar, srv SignalExchangeServer) {
|
func RegisterSignalExchangeServer(s grpc.ServiceRegistrar, srv SignalExchangeServer) {
|
||||||
|
// If the following call pancis, it indicates UnimplementedSignalExchangeServer was
|
||||||
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||||
|
t.testEmbeddedByValue()
|
||||||
|
}
|
||||||
s.RegisterService(&SignalExchange_ServiceDesc, srv)
|
s.RegisterService(&SignalExchange_ServiceDesc, srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +119,7 @@ func _SignalExchange_Send_Handler(srv interface{}, ctx context.Context, dec func
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/signalexchange.SignalExchange/Send",
|
FullMethod: SignalExchange_Send_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(SignalExchangeServer).Send(ctx, req.(*EncryptedMessage))
|
return srv.(SignalExchangeServer).Send(ctx, req.(*EncryptedMessage))
|
||||||
@@ -125,30 +128,11 @@ func _SignalExchange_Send_Handler(srv interface{}, ctx context.Context, dec func
|
|||||||
}
|
}
|
||||||
|
|
||||||
func _SignalExchange_ConnectStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
func _SignalExchange_ConnectStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
return srv.(SignalExchangeServer).ConnectStream(&signalExchangeConnectStreamServer{stream})
|
return srv.(SignalExchangeServer).ConnectStream(&grpc.GenericServerStream[EncryptedMessage, EncryptedMessage]{ServerStream: stream})
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignalExchange_ConnectStreamServer interface {
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
Send(*EncryptedMessage) error
|
type SignalExchange_ConnectStreamServer = grpc.BidiStreamingServer[EncryptedMessage, EncryptedMessage]
|
||||||
Recv() (*EncryptedMessage, error)
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type signalExchangeConnectStreamServer struct {
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *signalExchangeConnectStreamServer) Send(m *EncryptedMessage) error {
|
|
||||||
return x.ServerStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *signalExchangeConnectStreamServer) Recv() (*EncryptedMessage, error) {
|
|
||||||
m := new(EncryptedMessage)
|
|
||||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignalExchange_ServiceDesc is the grpc.ServiceDesc for SignalExchange service.
|
// SignalExchange_ServiceDesc is the grpc.ServiceDesc for SignalExchange service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
@@ -170,5 +154,5 @@ var SignalExchange_ServiceDesc = grpc.ServiceDesc{
|
|||||||
ClientStreams: true,
|
ClientStreams: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Metadata: "signalexchange.proto",
|
Metadata: "signalexchange/signalexchange.proto",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ const (
|
|||||||
ClientHeaderValue = "netbird"
|
ClientHeaderValue = "netbird"
|
||||||
// GetURLPath is the path for the GetURL request
|
// GetURLPath is the path for the GetURL request
|
||||||
GetURLPath = "/upload-url"
|
GetURLPath = "/upload-url"
|
||||||
|
|
||||||
|
DefaultBundleURL = "https://upload.debug.netbird.io" + GetURLPath
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetURLResponse is the response for the GetURL request
|
// GetURLResponse is the response for the GetURL request
|
||||||
|
|||||||
Reference in New Issue
Block a user