-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathlistener.patch
94 lines (89 loc) · 2.54 KB
/
listener.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
diff --git a/collector/internal/telemetryapi/listener.go b/collector/internal/telemetryapi/listener.go
index 8499d4e..62a6461 100644
--- a/collector/internal/telemetryapi/listener.go
+++ b/collector/internal/telemetryapi/listener.go
@@ -17,18 +17,32 @@ package telemetryapi
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"io"
+ "math/rand"
+ "net"
"net/http"
"os"
+ "syscall"
"time"
"github.com/golang-collections/go-datastructures/queue"
"go.uber.org/zap"
)
-const defaultListenerPort = "53612"
-const initialQueueSize = 5
+const (
+ initialQueueSize = 5
+ maxRetries = 5
+ // Define ephemeral port range (typical range is 49152-65535)
+ minPort = 49152
+ maxPort = 65535
+)
+
+// getRandomPort returns a random port number within the ephemeral range
+func getRandomPort() string {
+ return fmt.Sprintf("%d", rand.Intn(maxPort-minPort)+minPort)
+}
// Listener is used to listen to the Telemetry API
type Listener struct {
@@ -46,26 +60,48 @@ func NewListener(logger *zap.Logger) *Listener {
}
}
-func listenOnAddress() string {
+func (s *Listener) tryBindPort() (net.Listener, string, error) {
+ for i := 0; i < maxRetries; i++ {
+ port := getRandomPort()
+ address := listenOnAddress(port)
+
+ l, err := net.Listen("tcp", address)
+ if err != nil {
+ if errors.Is(err, syscall.EADDRINUSE) {
+ s.logger.Debug("Port in use, trying another",
+ zap.String("address", address))
+ continue
+ }
+ return nil, "", err
+ }
+ return l, address, nil
+ }
+
+ return nil, "", fmt.Errorf("failed to find available port after %d attempts", maxRetries)
+}
+
+func listenOnAddress(port string) string {
envAwsLocal, ok := os.LookupEnv("AWS_SAM_LOCAL")
var addr string
if ok && envAwsLocal == "true" {
- addr = ":" + defaultListenerPort
+ addr = ":" + port
} else {
- addr = "sandbox.localdomain:" + defaultListenerPort
+ addr = "sandbox.localdomain:" + port
}
-
return addr
}
// Start the server in a goroutine where the log events will be sent
func (s *Listener) Start() (string, error) {
- address := listenOnAddress()
+ listener, address, err := s.tryBindPort()
+ if err != nil {
+ return "", fmt.Errorf("failed to find available port: %w", err)
+ }
s.logger.Info("Listening for requests", zap.String("address", address))
s.httpServer = &http.Server{Addr: address}
http.HandleFunc("/", s.httpHandler)
go func() {
- err := s.httpServer.ListenAndServe()
+ err := s.httpServer.Serve(listener)
if err != http.ErrServerClosed {
s.logger.Error("Unexpected stop on HTTP Server", zap.Error(err))
s.Shutdown()