Skip to content

Commit 06935a7

Browse files
committed
Use random port for application service
1 parent 7ab71d4 commit 06935a7

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

internal/b/blueprints.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@ import (
1818
"crypto/rand"
1919
"encoding/hex"
2020
"fmt"
21+
"net"
2122
"strconv"
2223
"strings"
2324
)
2425

26+
var (
27+
// HostnameRunningComplement is the hostname of Complement from the perspective of a Homeserver.
28+
HostnameRunningComplement = "host.docker.internal"
29+
)
30+
2531
// KnownBlueprints lists static blueprints
2632
var KnownBlueprints = map[string]*Blueprint{
2733
BlueprintCleanHS.Name: &BlueprintCleanHS,
@@ -190,6 +196,22 @@ func normaliseUser(u string, hsName string) (string, error) {
190196
return u, nil
191197
}
192198

199+
// Asks the kernel for a free open port that is ready to use.
200+
// via https://github.com/phayes/freeport/blob/95f893ade6f232a5f1511d61735d89b1ae2df543/freeport.go#L7-L20
201+
func getFreePort() (int, error) {
202+
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
203+
if err != nil {
204+
return 0, err
205+
}
206+
207+
l, err := net.ListenTCP("tcp", addr)
208+
if err != nil {
209+
return 0, err
210+
}
211+
defer l.Close()
212+
return l.Addr().(*net.TCPAddr).Port, nil
213+
}
214+
193215
func normalizeApplicationService(as ApplicationService) (ApplicationService, error) {
194216
hsToken := make([]byte, 32)
195217
_, err := rand.Read(hsToken)
@@ -206,6 +228,18 @@ func normalizeApplicationService(as ApplicationService) (ApplicationService, err
206228
as.HSToken = hex.EncodeToString(hsToken)
207229
as.ASToken = hex.EncodeToString(asToken)
208230

231+
if as.URL == "" {
232+
// Since, we're just checking and not reserving the port, we could
233+
// potentially run into an issue where the port is no longer available when
234+
// we actually try to bind to it later on
235+
port, err := getFreePort()
236+
if err != nil {
237+
return as, err
238+
}
239+
240+
as.URL = fmt.Sprintf("http://%s:%d", HostnameRunningComplement, port)
241+
}
242+
209243
return as, err
210244
}
211245

internal/b/hs_with_application_service.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ var BlueprintHSWithApplicationService = MustValidate(Blueprint{
1515
ApplicationServices: []ApplicationService{
1616
{
1717
ID: "my_as_id",
18-
URL: "http://host.docker.internal:9111",
1918
SenderLocalpart: "the-bridge-user",
2019
RateLimited: false,
2120
},

tests/msc2716_test.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"io/ioutil"
1414
"net/http"
1515
"net/url"
16+
"regexp"
1617
"testing"
1718
"time"
1819

@@ -60,6 +61,9 @@ var createPrivateRoomOpts = map[string]interface{}{
6061
"room_version": "org.matrix.msc2716v3",
6162
}
6263

64+
// Find the URL and port of the application service in some registration yaml text
65+
var asURLRegexp = regexp.MustCompile(`url: '(.+):(\d+)'`)
66+
6367
func TestImportHistoricalMessages(t *testing.T) {
6468
deployment := Deploy(t, b.BlueprintHSWithApplicationService)
6569
defer deployment.Destroy(t)
@@ -312,6 +316,13 @@ func TestImportHistoricalMessages(t *testing.T) {
312316
t.Run("Historical events from batch_send do not get pushed out as application service transactions", func(t *testing.T) {
313317
t.Parallel()
314318

319+
asRegistration := deployment.HS["hs1"].ApplicationServices["my_as_id"]
320+
asURLMatches := asURLRegexp.FindStringSubmatch(asRegistration)
321+
if asURLMatches == nil {
322+
t.Fatalf("Unable to find application service `url` in registration=%s", asRegistration)
323+
}
324+
asPort := asURLMatches[2]
325+
315326
// Create a listener and handler to stub an application service listening
316327
// for transactions from a homeserver.
317328
handler := mux.NewRouter()
@@ -343,13 +354,22 @@ func TestImportHistoricalMessages(t *testing.T) {
343354
}).Methods("PUT")
344355

345356
srv := &http.Server{
346-
Addr: ":9111",
357+
Addr: fmt.Sprintf(":%s", asPort),
347358
Handler: handler,
348359
}
349360
go func() {
350-
srv.ListenAndServe()
361+
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
362+
// Note that running s.t.FailNow is not allowed in a separate goroutine
363+
// Tests will likely fail if the server is not listening anyways
364+
t.Logf("Failed to listen and serve our fake application service: %s", err)
365+
}
366+
}()
367+
defer func() {
368+
err := srv.Shutdown(context.Background())
369+
if err != nil {
370+
t.Fatalf("Failed to shutdown our fake application service: %s", err)
371+
}
351372
}()
352-
defer srv.Shutdown(context.Background())
353373
// ----------------------------------------------------------
354374

355375
// Create the room all of the action is going to happen in

0 commit comments

Comments
 (0)