diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cec1d86..4ea00e8 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -37,6 +37,20 @@ jobs: args: --timeout=2m0s skip-cache: true + modernize: + name: golang + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-go@v5 + with: + go-version: "1.24" + + - name: moderize + run: | + go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -test ./... + dependencies: name: dependencies runs-on: ubuntu-latest diff --git a/allowed_ips.go b/allowed_ips.go index f401ec6..669255e 100644 --- a/allowed_ips.go +++ b/allowed_ips.go @@ -83,7 +83,7 @@ func parseIPNet(s string) (*net.IPNet, error) { func ParseAllowedIps(allowed string) (*AllowedIps, error) { var allowedIps []*net.IPNet - for _, ip := range strings.Split(allowed, ",") { + for ip := range strings.SplitSeq(allowed, ",") { ip = strings.TrimSpace(ip) if ip != "" { i, err := parseIPNet(ip) diff --git a/api_signaling.go b/api_signaling.go index 693261c..16a6361 100644 --- a/api_signaling.go +++ b/api_signaling.go @@ -29,7 +29,6 @@ import ( "net" "net/url" "slices" - "sort" "strings" "time" @@ -290,27 +289,19 @@ func NewWelcomeServerMessage(version string, feature ...string) *WelcomeServerMe Features: feature, } if len(feature) > 0 { - sort.Strings(message.Features) + slices.Sort(message.Features) } return message } func (m *WelcomeServerMessage) AddFeature(feature ...string) { - newFeatures := make([]string, len(m.Features)) - copy(newFeatures, m.Features) + newFeatures := slices.Clone(m.Features) for _, feat := range feature { - found := false - for _, f := range newFeatures { - if f == feat { - found = true - break - } - } - if !found { + if !slices.Contains(newFeatures, feat) { newFeatures = append(newFeatures, feat) } } - sort.Strings(newFeatures) + slices.Sort(newFeatures) m.Features = newFeatures } @@ -318,8 +309,8 @@ func (m *WelcomeServerMessage) RemoveFeature(feature ...string) { newFeatures := make([]string, len(m.Features)) copy(newFeatures, m.Features) for _, feat := range feature { - idx := sort.SearchStrings(newFeatures, feat) - if idx < len(newFeatures) && newFeatures[idx] == feat { + idx, found := slices.BinarySearch(newFeatures, feat) + if found { newFeatures = append(newFeatures[:idx], newFeatures[idx+1:]...) } } diff --git a/api_signaling_test.go b/api_signaling_test.go index 3b08fc0..b384a7a 100644 --- a/api_signaling_test.go +++ b/api_signaling_test.go @@ -24,7 +24,7 @@ package signaling import ( "encoding/json" "fmt" - "sort" + "slices" "strings" "testing" @@ -399,12 +399,12 @@ func assertEqualStrings(t *testing.T, expected, result []string) { if expected == nil { expected = make([]string, 0) } else { - sort.Strings(expected) + slices.Sort(expected) } if result == nil { result = make([]string, 0) } else { - sort.Strings(result) + slices.Sort(result) } assert.Equal(t, expected, result) @@ -418,11 +418,11 @@ func Test_Welcome_AddRemoveFeature(t *testing.T) { msg.AddFeature("one", "two", "one") assertEqualStrings(t, []string{"one", "two"}, msg.Features) - assert.True(sort.StringsAreSorted(msg.Features), "features should be sorted, got %+v", msg.Features) + assert.True(slices.IsSorted(msg.Features), "features should be sorted, got %+v", msg.Features) msg.AddFeature("three") assertEqualStrings(t, []string{"one", "two", "three"}, msg.Features) - assert.True(sort.StringsAreSorted(msg.Features), "features should be sorted, got %+v", msg.Features) + assert.True(slices.IsSorted(msg.Features), "features should be sorted, got %+v", msg.Features) msg.RemoveFeature("three", "one") assertEqualStrings(t, []string{"two"}, msg.Features) diff --git a/backend_configuration_test.go b/backend_configuration_test.go index d51ba2f..f882acd 100644 --- a/backend_configuration_test.go +++ b/backend_configuration_test.go @@ -25,7 +25,7 @@ import ( "context" "net/url" "reflect" - "sort" + "slices" "strings" "testing" @@ -36,7 +36,6 @@ import ( func testUrls(t *testing.T, config *BackendConfiguration, valid_urls []string, invalid_urls []string) { for _, u := range valid_urls { - u := u t.Run(u, func(t *testing.T) { assert := assert.New(t) parsed, err := url.ParseRequestURI(u) @@ -49,7 +48,6 @@ func testUrls(t *testing.T, config *BackendConfiguration, valid_urls []string, i }) } for _, u := range invalid_urls { - u := u t.Run(u, func(t *testing.T) { assert := assert.New(t) parsed, _ := url.ParseRequestURI(u) @@ -60,7 +58,6 @@ func testUrls(t *testing.T, config *BackendConfiguration, valid_urls []string, i func testBackends(t *testing.T, config *BackendConfiguration, valid_urls [][]string, invalid_urls []string) { for _, entry := range valid_urls { - entry := entry t.Run(entry[0], func(t *testing.T) { assert := assert.New(t) u := entry[0] @@ -75,7 +72,6 @@ func testBackends(t *testing.T, config *BackendConfiguration, valid_urls [][]str }) } for _, u := range invalid_urls { - u := u t.Run(u, func(t *testing.T) { assert := assert.New(t) parsed, _ := url.ParseRequestURI(u) @@ -448,11 +444,9 @@ func TestBackendReloadRemoveBackendFromSharedHost(t *testing.T) { } func sortBackends(backends []*Backend) []*Backend { - result := make([]*Backend, len(backends)) - copy(result, backends) - - sort.Slice(result, func(i, j int) bool { - return result[i].Id() < result[j].Id() + result := slices.Clone(backends) + slices.SortFunc(result, func(a, b *Backend) int { + return strings.Compare(a.Id(), b.Id()) }) return result } diff --git a/backend_server.go b/backend_server.go index f39eea8..25c3211 100644 --- a/backend_server.go +++ b/backend_server.go @@ -84,7 +84,7 @@ func NewBackendServer(config *goconf.ConfigFile, hub *Hub, version string) (*Bac turnvalid := 24 * time.Hour var turnserverslist []string - for _, s := range strings.Split(turnservers, ",") { + for s := range strings.SplitSeq(turnservers, ",") { s = strings.TrimSpace(s) if s != "" { turnserverslist = append(turnserverslist, s) diff --git a/backend_server_test.go b/backend_server_test.go index 5c138c6..a90b2d2 100644 --- a/backend_server_test.go +++ b/backend_server_test.go @@ -1317,7 +1317,6 @@ func TestBackendServer_StatsAllowedIps(t *testing.T) { } for _, addr := range allowed { - addr := addr t.Run(addr, func(t *testing.T) { t.Parallel() assert := assert.New(t) @@ -1357,7 +1356,6 @@ func TestBackendServer_StatsAllowedIps(t *testing.T) { } for _, addr := range notAllowed { - addr := addr t.Run(addr, func(t *testing.T) { t.Parallel() r := &http.Request{ diff --git a/backend_storage_static.go b/backend_storage_static.go index 1ca6751..fb88ef9 100644 --- a/backend_storage_static.go +++ b/backend_storage_static.go @@ -88,7 +88,7 @@ func NewBackendStorageStatic(config *goconf.ConfigFile) (BackendStorage, error) } else if allowedUrls, _ := config.GetString("backend", "allowed"); allowedUrls != "" { // Old-style configuration, only hosts are configured and are using a common secret. allowMap := make(map[string]bool) - for _, u := range strings.Split(allowedUrls, ",") { + for u := range strings.SplitSeq(allowedUrls, ",") { u = strings.TrimSpace(u) if idx := strings.IndexByte(u, '/'); idx != -1 { log.Printf("WARNING: Removing path from allowed hostname \"%s\", check your configuration!", u) @@ -265,7 +265,7 @@ func (s *backendStorageStatic) UpsertHost(host string, backends []*Backend, seen func getConfiguredBackendIDs(backendIds string) (ids []string) { seen := make(map[string]bool) - for _, id := range strings.Split(backendIds, ",") { + for id := range strings.SplitSeq(backendIds, ",") { id = strings.TrimSpace(id) if id == "" { continue diff --git a/backoff.go b/backoff.go index 27af0f9..0a37075 100644 --- a/backoff.go +++ b/backoff.go @@ -71,10 +71,6 @@ func (b *exponentialBackoff) Wait(ctx context.Context) { waiter, cancel := b.getContextWithTimeout(ctx, b.nextWait) defer cancel() - b.nextWait = b.nextWait * 2 - if b.nextWait > b.maxWait { - b.nextWait = b.maxWait - } - + b.nextWait = min(b.nextWait*2, b.maxWait) <-waiter.Done() } diff --git a/capabilities_test.go b/capabilities_test.go index 02e7f21..e74e732 100644 --- a/capabilities_test.go +++ b/capabilities_test.go @@ -554,7 +554,7 @@ func TestConcurrentExpired(t *testing.T) { var numCached atomic.Uint32 var numFetched atomic.Uint32 var finished sync.WaitGroup - for i := 0; i < count; i++ { + for range count { finished.Add(1) go func() { defer finished.Done() diff --git a/client/main.go b/client/main.go index ef803fe..701ebf8 100644 --- a/client/main.go +++ b/client/main.go @@ -542,7 +542,7 @@ func main() { urls := make([]url.URL, 0) urlstrings := make([]string, 0) - for _, host := range strings.Split(*addr, ",") { + for host := range strings.SplitSeq(*addr, ",") { u := url.URL{ Scheme: "ws", Host: host, diff --git a/clientsession.go b/clientsession.go index 819c074..38188a6 100644 --- a/clientsession.go +++ b/clientsession.go @@ -27,6 +27,7 @@ import ( "fmt" "log" "net/url" + "slices" "strings" "sync" "sync/atomic" @@ -183,12 +184,7 @@ func (s *ClientSession) GetFeatures() []string { } func (s *ClientSession) HasFeature(feature string) bool { - for _, f := range s.features { - if f == feature { - return true - } - } - return false + return slices.Contains(s.features, feature) } // HasPermission checks if the session has the passed permissions. @@ -216,12 +212,9 @@ func (s *ClientSession) hasAnyPermissionLocked(permission ...Permission) bool { return false } - for _, p := range permission { - if s.hasPermissionLocked(p) { - return true - } - } - return false + return slices.ContainsFunc(permission, func(p Permission) bool { + return s.hasPermissionLocked(p) + }) } func (s *ClientSession) hasPermissionLocked(permission Permission) bool { diff --git a/clientsession_test.go b/clientsession_test.go index 81c3a06..c668bff 100644 --- a/clientsession_test.go +++ b/clientsession_test.go @@ -118,7 +118,6 @@ func Test_permissionsEqual(t *testing.T) { }, } for idx, test := range tests { - test := test t.Run(strconv.Itoa(idx), func(t *testing.T) { t.Parallel() equal := permissionsEqual(test.a, test.b) diff --git a/closer_test.go b/closer_test.go index ab23621..f51f3f3 100644 --- a/closer_test.go +++ b/closer_test.go @@ -33,7 +33,7 @@ func TestCloserMulti(t *testing.T) { var wg sync.WaitGroup count := 10 - for i := 0; i < count; i++ { + for range count { wg.Add(1) go func() { defer wg.Done() diff --git a/concurrentmap_test.go b/concurrentmap_test.go index 990a520..a723db5 100644 --- a/concurrentmap_test.go +++ b/concurrentmap_test.go @@ -76,7 +76,7 @@ func TestConcurrentStringStringMap(t *testing.T) { var wg sync.WaitGroup concurrency := 100 count := 1000 - for x := 0; x < concurrency; x++ { + for x := range concurrency { wg.Add(1) go func(x int) { defer wg.Done() diff --git a/deferred_executor_test.go b/deferred_executor_test.go index 8fa96ce..0e5f04b 100644 --- a/deferred_executor_test.go +++ b/deferred_executor_test.go @@ -71,7 +71,7 @@ func TestDeferredExecutor_Order(t *testing.T) { } done := make(chan struct{}) - for x := 0; x < 10; x++ { + for x := range 10 { e.Execute(getFunc(x)) } @@ -80,7 +80,7 @@ func TestDeferredExecutor_Order(t *testing.T) { }) <-done - for x := 0; x < 10; x++ { + for x := range 10 { assert.Equal(t, entries[x], x, "Unexpected at position %d", x) } } diff --git a/etcd_client.go b/etcd_client.go index e232fce..806f7b3 100644 --- a/etcd_client.go +++ b/etcd_client.go @@ -103,7 +103,7 @@ func (c *EtcdClient) getConfigStringWithFallback(config *goconf.ConfigFile, opti func (c *EtcdClient) load(config *goconf.ConfigFile, ignoreErrors bool) error { var endpoints []string if endpointsString := c.getConfigStringWithFallback(config, "endpoints"); endpointsString != "" { - for _, ep := range strings.Split(endpointsString, ",") { + for ep := range strings.SplitSeq(endpointsString, ",") { ep := strings.TrimSpace(ep) if ep != "" { endpoints = append(endpoints, ep) diff --git a/flags_test.go b/flags_test.go index 1665167..336e39c 100644 --- a/flags_test.go +++ b/flags_test.go @@ -54,7 +54,7 @@ func runConcurrentFlags(t *testing.T, count int, f func()) { start.Add(1) var ready sync.WaitGroup var done sync.WaitGroup - for i := 0; i < count; i++ { + for range count { done.Add(1) ready.Add(1) go func() { diff --git a/geoip_test.go b/geoip_test.go index 4d1a1e1..0aa1aa7 100644 --- a/geoip_test.go +++ b/geoip_test.go @@ -46,8 +46,6 @@ func testGeoLookupReader(t *testing.T, reader *GeoLookup) { } for ip, expected := range tests { - ip := ip - expected := expected t.Run(ip, func(t *testing.T) { country, err := reader.LookupCountry(net.ParseIP(ip)) if !assert.NoError(t, err, "Could not lookup %s", ip) { @@ -113,8 +111,6 @@ func TestGeoLookupContinent(t *testing.T) { } for country, expected := range tests { - country := country - expected := expected t.Run(country, func(t *testing.T) { continents := LookupContinents(country) if !assert.Equal(t, len(expected), len(continents), "Continents didn't match for %s: got %s, expected %s", country, continents, expected) { diff --git a/grpc_client.go b/grpc_client.go index fac9d0c..a27f1b0 100644 --- a/grpc_client.go +++ b/grpc_client.go @@ -29,6 +29,7 @@ import ( "io" "log" "net" + "slices" "strings" "sync" "sync/atomic" @@ -531,13 +532,7 @@ func (c *GrpcClients) isClientAvailable(target string, client *GrpcClient) bool return false } - for _, entry := range entries.clients { - if entry == client { - return true - } - } - - return false + return slices.Contains(entries.clients, client) } func (c *GrpcClients) getServerIdWithTimeout(ctx context.Context, client *GrpcClient) (string, string, error) { @@ -617,7 +612,7 @@ func (c *GrpcClients) loadTargetsStatic(config *goconf.ConfigFile, fromReload bo } targets, _ := config.GetString("grpc", "targets") - for _, target := range strings.Split(targets, ",") { + for target := range strings.SplitSeq(targets, ",") { target = strings.TrimSpace(target) if target == "" { continue diff --git a/hub.go b/hub.go index fcd227e..080dbe6 100644 --- a/hub.go +++ b/hub.go @@ -284,7 +284,7 @@ func NewHub(config *goconf.ConfigFile, events AsyncEvents, rpcServer *GrpcServer } decodeCaches := make([]*LruCache, 0, numDecodeCaches) - for i := 0; i < numDecodeCaches; i++ { + for range numDecodeCaches { decodeCaches = append(decodeCaches, NewLruCache(decodeCacheSize)) } diff --git a/hub_test.go b/hub_test.go index c279ba0..f3c2b44 100644 --- a/hub_test.go +++ b/hub_test.go @@ -802,7 +802,7 @@ func TestWebsocketFeatures(t *testing.T) { assert.True(strings.HasPrefix(serverHeader, "nextcloud-spreed-signaling/"), "expected valid server header, got \"%s\"", serverHeader) features := response.Header.Get("X-Spreed-Signaling-Features") featuresList := make(map[string]bool) - for _, f := range strings.Split(features, ",") { + for f := range strings.SplitSeq(features, ",") { f = strings.TrimSpace(f) if f != "" { _, found := featuresList[f] @@ -1274,7 +1274,7 @@ func TestSessionIdsUnordered(t *testing.T) { var mu sync.Mutex publicSessionIds := make([]string, 0) var wg sync.WaitGroup - for i := 0; i < 20; i++ { + for range 20 { wg.Add(1) go func() { defer wg.Done() diff --git a/lru_test.go b/lru_test.go index 98fbb66..93445ac 100644 --- a/lru_test.go +++ b/lru_test.go @@ -32,12 +32,12 @@ func TestLruUnbound(t *testing.T) { assert := assert.New(t) lru := NewLruCache(0) count := 10 - for i := 0; i < count; i++ { + for i := range count { key := fmt.Sprintf("%d", i) lru.Set(key, i) } assert.Equal(count, lru.Len()) - for i := 0; i < count; i++ { + for i := range count { key := fmt.Sprintf("%d", i) if value := lru.Get(key); assert.NotNil(value, "No value found for %s", key) { assert.EqualValues(i, value) @@ -46,7 +46,7 @@ func TestLruUnbound(t *testing.T) { // The first key ("0") is now the oldest. lru.RemoveOldest() assert.Equal(count-1, lru.Len()) - for i := 0; i < count; i++ { + for i := range count { key := fmt.Sprintf("%d", i) value := lru.Get(key) if i == 0 { @@ -76,7 +76,7 @@ func TestLruUnbound(t *testing.T) { // The last key ("9") is now the oldest. lru.RemoveOldest() assert.Equal(count-2, lru.Len()) - for i := 0; i < count; i++ { + for i := range count { key := fmt.Sprintf("%d", i) value := lru.Get(key) if i == 0 || i == count-1 { @@ -91,7 +91,7 @@ func TestLruUnbound(t *testing.T) { key := fmt.Sprintf("%d", count/2) lru.Remove(key) assert.Equal(count-3, lru.Len()) - for i := 0; i < count; i++ { + for i := range count { key := fmt.Sprintf("%d", i) value := lru.Get(key) if i == 0 || i == count-1 || i == count/2 { @@ -108,13 +108,13 @@ func TestLruBound(t *testing.T) { size := 2 lru := NewLruCache(size) count := 10 - for i := 0; i < count; i++ { + for i := range count { key := fmt.Sprintf("%d", i) lru.Set(key, i) } assert.Equal(size, lru.Len()) // Only the last "size" entries have been stored. - for i := 0; i < count; i++ { + for i := range count { key := fmt.Sprintf("%d", i) value := lru.Get(key) if i < count-size { diff --git a/mcu_janus.go b/mcu_janus.go index 1383fcd..a9f095b 100644 --- a/mcu_janus.go +++ b/mcu_janus.go @@ -339,10 +339,7 @@ func (m *mcuJanus) scheduleReconnect(err error) { log.Printf("Reconnect to Janus gateway failed (%s), reconnecting in %s", err, m.reconnectInterval) } - m.reconnectInterval = m.reconnectInterval * 2 - if m.reconnectInterval > maxReconnectInterval { - m.reconnectInterval = maxReconnectInterval - } + m.reconnectInterval = min(m.reconnectInterval*2, maxReconnectInterval) } func (m *mcuJanus) ConnectionInterrupted() { diff --git a/mcu_janus_publisher.go b/mcu_janus_publisher.go index 283d274..11253b7 100644 --- a/mcu_janus_publisher.go +++ b/mcu_janus_publisher.go @@ -250,8 +250,7 @@ func (p *mcuJanusPublisher) SendMessage(ctx context.Context, message *MessageCli } func getFmtpValue(fmtp string, key string) (string, bool) { - parts := strings.Split(fmtp, ";") - for _, part := range parts { + for part := range strings.SplitSeq(fmtp, ";") { kv := strings.SplitN(part, "=", 2) if len(kv) != 2 { continue diff --git a/mcu_janus_test.go b/mcu_janus_test.go index e0f923d..1c08884 100644 --- a/mcu_janus_test.go +++ b/mcu_janus_test.go @@ -24,6 +24,7 @@ package signaling import ( "context" "encoding/json" + "maps" "strings" "sync" "sync/atomic" @@ -101,9 +102,7 @@ func NewTestJanusGateway(t *testing.T) *TestJanusGateway { func (g *TestJanusGateway) registerHandlers(handlers map[string]TestJanusHandler) { g.mu.Lock() defer g.mu.Unlock() - for name, handler := range handlers { - g.handlers[name] = handler - } + maps.Copy(g.handlers, handlers) } func (g *TestJanusGateway) Info(ctx context.Context) (*InfoMsg, error) { diff --git a/mcu_proxy.go b/mcu_proxy.go index aea111c..556b034 100644 --- a/mcu_proxy.go +++ b/mcu_proxy.go @@ -35,7 +35,6 @@ import ( "net/url" "os" "slices" - "sort" "strconv" "strings" "sync" @@ -766,10 +765,7 @@ func (c *mcuProxyConnection) scheduleReconnect() { jitter := rand.Int64N(interval) - (interval / 2) c.reconnectTimer.Reset(time.Duration(interval + jitter)) - interval = interval * 2 - if interval > int64(maxReconnectInterval) { - interval = int64(maxReconnectInterval) - } + interval = min(interval*2, int64(maxReconnectInterval)) c.reconnectInterval.Store(interval) } @@ -1569,7 +1565,7 @@ func (m *mcuProxy) loadContinentsMap(config *goconf.ConfigFile) error { } var values []string - for _, v := range strings.Split(value, ",") { + for v := range strings.SplitSeq(value, ",") { v = strings.ToUpper(strings.TrimSpace(v)) if !IsValidContinent(v) { log.Printf("Ignore unknown continent %s for override %s", v, option) @@ -1872,32 +1868,14 @@ func (m *mcuProxy) setContinentsMap(continentsMap map[string][]string) { type mcuProxyConnectionsList []*mcuProxyConnection -func (l mcuProxyConnectionsList) Len() int { - return len(l) -} - -func (l mcuProxyConnectionsList) Less(i, j int) bool { - return l[i].Load() < l[j].Load() -} - -func (l mcuProxyConnectionsList) Swap(i, j int) { - l[i], l[j] = l[j], l[i] -} - -func (l mcuProxyConnectionsList) Sort() { - sort.Sort(l) -} - func ContinentsOverlap(a, b []string) bool { if len(a) == 0 || len(b) == 0 { return false } for _, checkA := range a { - for _, checkB := range b { - if checkA == checkB { - return true - } + if slices.Contains(b, checkA) { + return true } } return false @@ -1958,10 +1936,10 @@ func (m *mcuProxy) getSortedConnections(initiator McuInitiator) []*mcuProxyConne if m.connRequests.Add(1)%connectionSortRequests == 0 || m.nextSort.Load() <= now { m.nextSort.Store(now + int64(connectionSortInterval)) - sorted := make(mcuProxyConnectionsList, len(connections)) - copy(sorted, connections) - - sorted.Sort() + sorted := slices.Clone(connections) + slices.SortFunc(sorted, func(a, b *mcuProxyConnection) int { + return int(a.Load() - b.Load()) + }) m.connectionsMu.Lock() m.connections = sorted diff --git a/mcu_proxy_test.go b/mcu_proxy_test.go index 18571c8..6ddde24 100644 --- a/mcu_proxy_test.go +++ b/mcu_proxy_test.go @@ -106,8 +106,6 @@ func Test_sortConnectionsForCountry(t *testing.T) { } for country, test := range testcases { - country := country - test := test t.Run(country, func(t *testing.T) { sorted := sortConnectionsForCountry(test[0], country, nil) for idx, conn := range sorted { @@ -178,8 +176,6 @@ func Test_sortConnectionsForCountryWithOverride(t *testing.T) { "OC": {"AS", "NA"}, } for country, test := range testcases { - country := country - test := test t.Run(country, func(t *testing.T) { sorted := sortConnectionsForCountry(test[0], country, continentMap) for idx, conn := range sorted { diff --git a/mcu_test.go b/mcu_test.go index 2dcf9ef..defebda 100644 --- a/mcu_test.go +++ b/mcu_test.go @@ -26,6 +26,7 @@ import ( "errors" "fmt" "log" + "maps" "sync" "sync/atomic" @@ -107,10 +108,7 @@ func (m *TestMCU) GetPublishers() map[string]*TestMCUPublisher { m.mu.Lock() defer m.mu.Unlock() - result := make(map[string]*TestMCUPublisher, len(m.publishers)) - for id, pub := range m.publishers { - result[id] = pub - } + result := maps.Clone(m.publishers) return result } diff --git a/natsclient_test.go b/natsclient_test.go index bc92bfb..473a543 100644 --- a/natsclient_test.go +++ b/natsclient_test.go @@ -94,7 +94,7 @@ func testNatsClient_Subscribe(t *testing.T, client NatsClient) { } }() <-ready - for i := int32(0); i < maxPublish; i++ { + for range maxPublish { assert.NoError(client.Publish("foo", []byte("hello"))) // Allow NATS goroutines to process messages. diff --git a/notifier_test.go b/notifier_test.go index c40d7f0..5313275 100644 --- a/notifier_test.go +++ b/notifier_test.go @@ -115,7 +115,7 @@ func TestNotifierDuplicate(t *testing.T) { var wgStart sync.WaitGroup var wgEnd sync.WaitGroup - for i := 0; i < 2; i++ { + for range 2 { wgStart.Add(1) wgEnd.Add(1) diff --git a/proxy/main.go b/proxy/main.go index 706f220..260805b 100644 --- a/proxy/main.go +++ b/proxy/main.go @@ -100,7 +100,7 @@ func main() { writeTimeout = defaultWriteTimeout } - for _, address := range strings.Split(addr, " ") { + for address := range strings.SplitSeq(addr, " ") { go func(address string) { log.Println("Listening on", address) listener, err := net.Listen("tcp", address) diff --git a/proxy/proxy_remote.go b/proxy/proxy_remote.go index b16ade2..150403b 100644 --- a/proxy/proxy_remote.go +++ b/proxy/proxy_remote.go @@ -176,10 +176,7 @@ func (c *RemoteConnection) scheduleReconnect() { jitter := rand.Int64N(interval) - (interval / 2) c.reconnectTimer.Reset(time.Duration(interval + jitter)) - interval = interval * 2 - if interval > int64(maxReconnectInterval) { - interval = int64(maxReconnectInterval) - } + interval = min(interval*2, int64(maxReconnectInterval)) c.reconnectInterval.Store(interval) } diff --git a/proxy/proxy_server_test.go b/proxy/proxy_server_test.go index 95dba73..43d4139 100644 --- a/proxy/proxy_server_test.go +++ b/proxy/proxy_server_test.go @@ -316,7 +316,7 @@ func TestWebsocketFeatures(t *testing.T) { } features := response.Header.Get("X-Spreed-Signaling-Features") featuresList := make(map[string]bool) - for _, f := range strings.Split(features, ",") { + for f := range strings.SplitSeq(features, ",") { f = strings.TrimSpace(f) if f != "" { if _, found := featuresList[f]; found { diff --git a/proxy/proxy_tokens_static.go b/proxy/proxy_tokens_static.go index 9ad7917..37c23e4 100644 --- a/proxy/proxy_tokens_static.go +++ b/proxy/proxy_tokens_static.go @@ -25,7 +25,7 @@ import ( "fmt" "log" "os" - "sort" + "slices" "sync/atomic" "github.com/dlintw/goconf" @@ -110,7 +110,7 @@ func (t *tokensStatic) load(config *goconf.ConfigFile, ignoreErrors bool) error for k := range tokenKeys { keyIds = append(keyIds, k) } - sort.Strings(keyIds) + slices.Sort(keyIds) log.Printf("Enabled token keys: %v", keyIds) } t.setTokenKeys(tokenKeys) diff --git a/proxy_config_static.go b/proxy_config_static.go index bea279f..3731ddb 100644 --- a/proxy_config_static.go +++ b/proxy_config_static.go @@ -24,6 +24,7 @@ package signaling import ( "errors" "log" + "maps" "net" "net/url" "strings" @@ -81,13 +82,10 @@ func (p *proxyConfigStatic) configure(config *goconf.ConfigFile, fromReload bool p.dnsDiscovery = dnsDiscovery } - remove := make(map[string]*ipList) - for u, ips := range p.connectionsMap { - remove[u] = ips - } + remove := maps.Clone(p.connectionsMap) mcuUrl, _ := GetStringOptionWithEnv(config, "mcu", "url") - for _, u := range strings.Split(mcuUrl, " ") { + for u := range strings.SplitSeq(mcuUrl, " ") { u = strings.TrimSpace(u) if u == "" { continue diff --git a/room.go b/room.go index 4687aec..e1790b9 100644 --- a/room.go +++ b/room.go @@ -27,6 +27,7 @@ import ( "encoding/json" "fmt" "log" + "maps" "net/url" "strconv" "strings" @@ -615,15 +616,11 @@ func (r *Room) getClusteredInternalSessionsRLocked() (internal map[string]*Inter if internal == nil { internal = make(map[string]*InternalSessionData, len(clientInternal)) } - for sid, s := range clientInternal { - internal[sid] = s - } + maps.Copy(internal, clientInternal) if virtual == nil { virtual = make(map[string]*VirtualSessionData, len(clientVirtual)) } - for sid, s := range clientVirtual { - virtual[sid] = s - } + maps.Copy(virtual, clientVirtual) }(client) } wg.Wait() diff --git a/room_ping.go b/room_ping.go index 5902068..46a7355 100644 --- a/room_ping.go +++ b/room_ping.go @@ -167,10 +167,7 @@ func (p *RoomPing) sendPingsDirect(ctx context.Context, roomId string, url *url. func (p *RoomPing) sendPingsCombined(url *url.URL, entries []BackendPingEntry, limit int, timeout time.Duration) { total := len(entries) for idx := 0; idx < total; idx += limit { - end := idx + limit - if end > total { - end = total - } + end := min(idx+limit, total) tosend := entries[idx:end] ctx, cancel := context.WithTimeout(context.Background(), timeout) diff --git a/server/main.go b/server/main.go index 97becd6..c8b2a66 100644 --- a/server/main.go +++ b/server/main.go @@ -289,10 +289,7 @@ func main() { } case <-mcuRetryTimer.C: // Retry connection - mcuRetry = mcuRetry * 2 - if mcuRetry > maxMcuRetry { - mcuRetry = maxMcuRetry - } + mcuRetry = min(mcuRetry*2, maxMcuRetry) } } if mcu != nil { @@ -344,7 +341,7 @@ func main() { if writeTimeout <= 0 { writeTimeout = defaultWriteTimeout } - for _, address := range strings.Split(saddr, " ") { + for address := range strings.SplitSeq(saddr, " ") { go func(address string) { log.Println("Listening on", address) listener, err := createTLSListener(address, cert, key) @@ -377,7 +374,7 @@ func main() { writeTimeout = defaultWriteTimeout } - for _, address := range strings.Split(addr, " ") { + for address := range strings.SplitSeq(addr, " ") { go func(address string) { log.Println("Listening on", address) listener, err := createListener(address) diff --git a/single_notifier_test.go b/single_notifier_test.go index 7b95beb..a26d03a 100644 --- a/single_notifier_test.go +++ b/single_notifier_test.go @@ -115,7 +115,7 @@ func TestSingleNotifierDuplicate(t *testing.T) { var wgStart sync.WaitGroup var wgEnd sync.WaitGroup - for i := 0; i < 2; i++ { + for range 2 { wgStart.Add(1) wgEnd.Add(1) diff --git a/testclient_test.go b/testclient_test.go index d5bcf5a..4165265 100644 --- a/testclient_test.go +++ b/testclient_test.go @@ -636,7 +636,7 @@ func (c *TestClient) DrainMessages(ctx context.Context) error { return err case <-c.messageChan: n := len(c.messageChan) - for i := 0; i < n; i++ { + for range n { <-c.messageChan } case <-ctx.Done(): @@ -657,7 +657,7 @@ func (c *TestClient) GetPendingMessages(ctx context.Context) ([]*ServerMessage, } result = append(result, &m) n := len(c.messageChan) - for i := 0; i < n; i++ { + for range n { var m ServerMessage msg = <-c.messageChan if err := json.Unmarshal(msg, &m); err != nil { diff --git a/throttle.go b/throttle.go index dcd5332..8c96eac 100644 --- a/throttle.go +++ b/throttle.go @@ -257,10 +257,7 @@ func (t *memoryThrottler) getDelay(count int) time.Duration { return maxThrottleDelay } - delay := time.Duration(100*intPow(2, count)) * time.Millisecond - if delay > maxThrottleDelay { - delay = maxThrottleDelay - } + delay := min(time.Duration(100*intPow(2, count))*time.Millisecond, maxThrottleDelay) return delay } diff --git a/throttle_test.go b/throttle_test.go index a95102a..20a3599 100644 --- a/throttle_test.go +++ b/throttle_test.go @@ -145,7 +145,7 @@ func TestThrottler_Bruteforce(t *testing.T) { ctx := context.Background() - for i := 0; i < maxBruteforceAttempts; i++ { + for i := range maxBruteforceAttempts { timing.now = timing.now.Add(time.Millisecond) throttle, err := th.CheckBruteforce(ctx, "192.168.0.1", "action1") assert.NoError(err) @@ -292,7 +292,7 @@ func TestThrottler_Negative(t *testing.T) { ctx := context.Background() - for i := 0; i < maxBruteforceAttempts*10; i++ { + for i := range maxBruteforceAttempts * 10 { timing.now = timing.now.Add(time.Millisecond) throttle, err := th.CheckBruteforce(ctx, "192.168.0.1", "action1") if err != nil { diff --git a/transient_data.go b/transient_data.go index 59bfd97..ac3ffb9 100644 --- a/transient_data.go +++ b/transient_data.go @@ -22,6 +22,7 @@ package signaling import ( + "maps" "reflect" "sync" "time" @@ -256,8 +257,6 @@ func (t *TransientData) GetData() StringMap { defer t.mu.Unlock() result := make(StringMap) - for k, v := range t.data { - result[k] = v - } + maps.Copy(result, t.data) return result }