Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use stable identifiers for faster joins #583

Merged
merged 12 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,24 @@ require (
github.com/docker/go-units v0.4.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/gorilla/mux v1.8.0
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
github.com/matrix-org/gomatrixserverlib v0.0.0-20220830164018-c71e518537a2
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
github.com/matrix-org/gomatrixserverlib v0.0.0-20230113181222-67e060196d05
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/sirupsen/logrus v1.9.0
github.com/tidwall/gjson v1.14.3
github.com/tidwall/gjson v1.14.4
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 // indirect
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
golang.org/x/tools v0.1.9
golang.org/x/tools v0.1.12
gonum.org/v1/plot v0.11.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gotest.tools/v3 v3.0.3 // indirect
maunium.net/go/mautrix v0.11.0
)
64 changes: 64 additions & 0 deletions go.sum

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions internal/federation/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
func MakeJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request) {
// Check federation signature
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
req, time.Now(), gomatrixserverlib.ServerName(s.serverName), s.keyRing,
req, time.Now(), gomatrixserverlib.ServerName(s.serverName), nil, s.keyRing,
)
if fedReq == nil {
w.WriteHeader(errResp.Code)
Expand Down Expand Up @@ -125,7 +125,7 @@ func MakeRespMakeKnock(s *Server, room *ServerRoom, userID string) (resp gomatri
// the current server is returned to the joining server.
func SendJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request, expectPartialState bool, omitServersInRoom bool) {
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
req, time.Now(), gomatrixserverlib.ServerName(s.serverName), s.keyRing,
req, time.Now(), gomatrixserverlib.ServerName(s.serverName), nil, s.keyRing,
)
if fedReq == nil {
w.WriteHeader(errResp.Code)
Expand All @@ -136,7 +136,7 @@ func SendJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request

// if we expect a partial-state join, the request should have a "partial_state" flag
queryParams := req.URL.Query()
partialState := queryParams.Get("org.matrix.msc3706.partial_state")
partialState := queryParams.Get("omit_members")
if expectPartialState && partialState != "true" {
log.Printf("Not a partial-state request: got %v, want %s",
partialState, "true")
Expand Down Expand Up @@ -187,11 +187,11 @@ func SendJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request

// return state and auth chain
b, err := json.Marshal(gomatrixserverlib.RespSendJoin{
Origin: gomatrixserverlib.ServerName(s.serverName),
AuthEvents: gomatrixserverlib.NewEventJSONsFromEvents(authEvents),
StateEvents: gomatrixserverlib.NewEventJSONsFromEvents(stateEvents),
PartialState: expectPartialState,
ServersInRoom: serversInRoom,
Origin: gomatrixserverlib.ServerName(s.serverName),
AuthEvents: gomatrixserverlib.NewEventJSONsFromEvents(authEvents),
StateEvents: gomatrixserverlib.NewEventJSONsFromEvents(stateEvents),
MembersOmitted: expectPartialState,
ServersInRoom: serversInRoom,
})
if err != nil {
w.WriteHeader(500)
Expand Down Expand Up @@ -238,7 +238,7 @@ func HandleInviteRequests(inviteCallback func(*gomatrixserverlib.Event)) func(*S
// https://matrix.org/docs/spec/server_server/r0.1.4#put-matrix-federation-v2-invite-roomid-eventid
s.mux.Handle("/_matrix/federation/v2/invite/{roomID}/{eventID}", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
req, time.Now(), gomatrixserverlib.ServerName(s.serverName), s.keyRing,
req, time.Now(), gomatrixserverlib.ServerName(s.serverName), nil, s.keyRing,
)
if fedReq == nil {
w.WriteHeader(errResp.Code)
Expand Down Expand Up @@ -491,7 +491,7 @@ func HandleTransactionRequests(pduCallback func(*gomatrixserverlib.Event), eduCa

// Check federation signature
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
req, time.Now(), gomatrixserverlib.ServerName(srv.serverName), srv.keyRing,
req, time.Now(), gomatrixserverlib.ServerName(srv.serverName), nil, srv.keyRing,
)
if fedReq == nil {
log.Printf(
Expand Down
23 changes: 15 additions & 8 deletions internal/federation/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,13 @@ func (s *Server) FederationClient(deployment *docker.Deployment) *gomatrixserver
if !s.listening {
s.t.Fatalf("FederationClient() called before Listen() - this is not supported because Listen() chooses a high-numbered port and thus changes the server name and thus changes the way federation requests are signed. Ensure you Listen() first!")
}
identity := gomatrixserverlib.SigningIdentity{
ServerName: gomatrixserverlib.ServerName(s.ServerName()),
KeyID: s.KeyID,
PrivateKey: s.Priv,
}
f := gomatrixserverlib.NewFederationClient(
gomatrixserverlib.ServerName(s.serverName), s.KeyID, s.Priv,
[]*gomatrixserverlib.SigningIdentity{&identity},
gomatrixserverlib.WithTransport(&docker.RoundTripper{Deployment: deployment}),
)
return f
Expand Down Expand Up @@ -336,17 +341,18 @@ func (s *Server) MustCreateEvent(t *testing.T, room *ServerRoom, ev b.Event) *go
// It returns the resultant room.
func (s *Server) MustJoinRoom(t *testing.T, deployment *docker.Deployment, remoteServer gomatrixserverlib.ServerName, roomID string, userID string) *ServerRoom {
t.Helper()
origin := gomatrixserverlib.ServerName(s.serverName)
fedClient := s.FederationClient(deployment)
makeJoinResp, err := fedClient.MakeJoin(context.Background(), remoteServer, roomID, userID, SupportedRoomVersions())
makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, remoteServer, roomID, userID, SupportedRoomVersions())
if err != nil {
t.Fatalf("MustJoinRoom: make_join failed: %v", err)
}
roomVer := makeJoinResp.RoomVersion
joinEvent, err := makeJoinResp.JoinEvent.Build(time.Now(), gomatrixserverlib.ServerName(s.serverName), s.KeyID, s.Priv, roomVer)
joinEvent, err := makeJoinResp.JoinEvent.Build(time.Now(), origin, s.KeyID, s.Priv, roomVer)
if err != nil {
t.Fatalf("MustJoinRoom: failed to sign event: %v", err)
}
sendJoinResp, err := fedClient.SendJoin(context.Background(), gomatrixserverlib.ServerName(remoteServer), joinEvent)
sendJoinResp, err := fedClient.SendJoin(context.Background(), origin, remoteServer, joinEvent)
if err != nil {
t.Fatalf("MustJoinRoom: send_join failed: %v", err)
}
Expand All @@ -366,17 +372,18 @@ func (s *Server) MustJoinRoom(t *testing.T, deployment *docker.Deployment, remot
// Leaves a room. If this is rejecting an invite then a make_leave request is made first, before send_leave.
func (s *Server) MustLeaveRoom(t *testing.T, deployment *docker.Deployment, remoteServer gomatrixserverlib.ServerName, roomID string, userID string) {
t.Helper()
origin := gomatrixserverlib.ServerName(s.serverName)
fedClient := s.FederationClient(deployment)
var leaveEvent *gomatrixserverlib.Event
room := s.rooms[roomID]
if room == nil {
// e.g rejecting an invite
makeLeaveResp, err := fedClient.MakeLeave(context.Background(), remoteServer, roomID, userID)
makeLeaveResp, err := fedClient.MakeLeave(context.Background(), origin, remoteServer, roomID, userID)
if err != nil {
t.Fatalf("MustLeaveRoom: (rejecting invite) make_leave failed: %v", err)
}
roomVer := makeLeaveResp.RoomVersion
leaveEvent, err = makeLeaveResp.LeaveEvent.Build(time.Now(), gomatrixserverlib.ServerName(s.serverName), s.KeyID, s.Priv, roomVer)
leaveEvent, err = makeLeaveResp.LeaveEvent.Build(time.Now(), origin, s.KeyID, s.Priv, roomVer)
if err != nil {
t.Fatalf("MustLeaveRoom: (rejecting invite) failed to sign event: %v", err)
}
Expand All @@ -391,7 +398,7 @@ func (s *Server) MustLeaveRoom(t *testing.T, deployment *docker.Deployment, remo
},
})
}
err := fedClient.SendLeave(context.Background(), gomatrixserverlib.ServerName(remoteServer), leaveEvent)
err := fedClient.SendLeave(context.Background(), origin, remoteServer, leaveEvent)
if err != nil {
t.Fatalf("MustLeaveRoom: send_leave failed: %v", err)
}
Expand All @@ -407,7 +414,7 @@ func (s *Server) ValidFederationRequest(t *testing.T, handler func(fr *gomatrixs
return func(w http.ResponseWriter, req *http.Request) {
// Check federation signature
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
req, time.Now(), gomatrixserverlib.ServerName(s.serverName), s.keyRing,
req, time.Now(), gomatrixserverlib.ServerName(s.serverName), nil, s.keyRing,
)
if fedReq == nil {
t.Errorf(
Expand Down
2 changes: 1 addition & 1 deletion tests/direct_messaging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func TestIsDirectFlagFederation(t *testing.T) {
t.Fatalf("failed to make invite request: %s", err)
}
_, since := alice.MustSync(t, client.SyncReq{})
_, err = srv.FederationClient(deployment).SendInviteV2(context.Background(), "hs1", inviteReq)
_, err = srv.FederationClient(deployment).SendInviteV2(context.Background(), gomatrixserverlib.ServerName(srv.ServerName()), "hs1", inviteReq)
if err != nil {
t.Fatalf("failed to send invite v2: %s", err)
}
Expand Down
2 changes: 1 addition & 1 deletion tests/federation_event_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func TestEventAuth(t *testing.T) {
getEventAuth := func(t *testing.T, eventID string, wantAuthEventIDs []string) {
t.Helper()
t.Logf("/event_auth for %s - want %v", eventID, wantAuthEventIDs)
eventAuthResp, err := srv.FederationClient(deployment).GetEventAuth(context.Background(), "hs1", room.Version, roomID, eventID)
eventAuthResp, err := srv.FederationClient(deployment).GetEventAuth(context.Background(), gomatrixserverlib.ServerName(srv.ServerName()), "hs1", room.Version, roomID, eventID)
must.NotError(t, "failed to /event_auth", err)
if len(eventAuthResp.AuthEvents) == 0 {
t.Fatalf("/event_auth returned 0 auth events")
Expand Down
3 changes: 3 additions & 0 deletions tests/federation_query_profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,13 @@ func TestInboundFederationProfile(t *testing.T) {
)
cancel := srv.Listen()
defer cancel()
origin := gomatrixserverlib.ServerName(srv.ServerName())

// sytest: Non-numeric ports in server names are rejected
t.Run("Non-numeric ports in server names are rejected", func(t *testing.T) {
fedReq := gomatrixserverlib.NewFederationRequest(
"GET",
origin,
"hs1",
"/_matrix/federation/v1/query/profile"+
"?user_id=@user1:localhost:http"+
Expand Down Expand Up @@ -114,6 +116,7 @@ func TestInboundFederationProfile(t *testing.T) {

fedReq := gomatrixserverlib.NewFederationRequest(
"GET",
origin,
"hs1",
"/_matrix/federation/v1/query/profile"+
"?user_id=@alice:hs1"+
Expand Down
7 changes: 6 additions & 1 deletion tests/federation_room_get_missing_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test
fedClient := srv.FederationClient(deployment)
resp, err := fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{
TransactionID: "wut",
Origin: gomatrixserverlib.ServerName(srv.ServerName()),
Destination: gomatrixserverlib.ServerName("hs1"),
PDUs: []json.RawMessage{
sentEvent.JSON(),
Expand Down Expand Up @@ -306,6 +307,7 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test

resp, err = fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{
TransactionID: "t2",
Origin: gomatrixserverlib.ServerName(srv.ServerName()),
Destination: gomatrixserverlib.ServerName("hs1"),
PDUs: []json.RawMessage{
message3.JSON(),
Expand Down Expand Up @@ -367,7 +369,10 @@ func TestInboundCanReturnMissingEvents(t *testing.T) {
room := srv.MustJoinRoom(t, deployment, "hs1", roomID, charlie)
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(charlie, roomID))

req := gomatrixserverlib.NewFederationRequest("POST", "hs1",
req := gomatrixserverlib.NewFederationRequest(
"POST",
gomatrixserverlib.ServerName(srv.ServerName()),
"hs1",
fmt.Sprintf("/_matrix/federation/v1/get_missing_events/%s", roomID),
)

Expand Down
12 changes: 6 additions & 6 deletions tests/federation_room_join_partial_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1560,7 +1560,7 @@ func TestPartialStateJoin(t *testing.T) {
fedClient2 := testServer2.FederationClient(deployment)

// charlie sends a make_join
_, err := fedClient2.MakeJoin(context.Background(), "hs1", roomID, testServer2.UserID("charlie"), federation.SupportedRoomVersions())
_, err := fedClient2.MakeJoin(context.Background(), gomatrixserverlib.ServerName(testServer2.ServerName()), "hs1", roomID, testServer2.UserID("charlie"), federation.SupportedRoomVersions())

if err == nil {
t.Errorf("MakeJoin returned 200, want 404")
Expand Down Expand Up @@ -1627,7 +1627,7 @@ func TestPartialStateJoin(t *testing.T) {

// SendJoin should return a 404 because the homeserver under test has not
// finished its partial join.
_, err = fedClient2.SendJoin(context.Background(), "hs1", joinEvent)
_, err = fedClient2.SendJoin(context.Background(), gomatrixserverlib.ServerName(testServer2.ServerName()), "hs1", joinEvent)
if err == nil {
t.Errorf("SendJoin returned 200, want 404")
} else if httpError, ok := err.(gomatrix.HTTPError); ok {
Expand Down Expand Up @@ -1733,7 +1733,7 @@ func TestPartialStateJoin(t *testing.T) {
fedClient2 := testServer2.FederationClient(deployment)

// charlie sends a make_knock
_, err := fedClient2.MakeKnock(context.Background(), "hs1", roomID, testServer2.UserID("charlie"), federation.SupportedRoomVersions())
_, err := fedClient2.MakeKnock(context.Background(), gomatrixserverlib.ServerName(testServer2.ServerName()), "hs1", roomID, testServer2.UserID("charlie"), federation.SupportedRoomVersions())

if err == nil {
t.Errorf("MakeKnock returned 200, want 404")
Expand Down Expand Up @@ -1800,7 +1800,7 @@ func TestPartialStateJoin(t *testing.T) {

// SendKnock should return a 404 because the homeserver under test has not
// finished its partial join.
_, err = fedClient2.SendKnock(context.Background(), "hs1", knockEvent)
_, err = fedClient2.SendKnock(context.Background(), gomatrixserverlib.ServerName(testServer2.ServerName()), "hs1", knockEvent)
if err == nil {
t.Errorf("SendKnock returned 200, want 404")
} else if httpError, ok := err.(gomatrix.HTTPError); ok {
Expand Down Expand Up @@ -3323,7 +3323,7 @@ func testReceiveEventDuringPartialStateJoin(
// is resolved. For now, we use this to check whether Synapse has calculated the partial state
// flag for the last event correctly.

stateReq := gomatrixserverlib.NewFederationRequest("GET", "hs1",
stateReq := gomatrixserverlib.NewFederationRequest("GET", gomatrixserverlib.ServerName(psjResult.Server.ServerName()), "hs1",
fmt.Sprintf("/_matrix/federation/v1/state_ids/%s?event_id=%s",
url.PathEscape(psjResult.ServerRoom.RoomID),
url.QueryEscape(event.EventID()),
Expand Down Expand Up @@ -3367,7 +3367,7 @@ func testReceiveEventDuringPartialStateJoin(
)

// check the server's idea of the state at the event. We do this by making a `state_ids` request over federation
stateReq = gomatrixserverlib.NewFederationRequest("GET", "hs1",
stateReq = gomatrixserverlib.NewFederationRequest("GET", gomatrixserverlib.ServerName(psjResult.Server.ServerName()), "hs1",
fmt.Sprintf("/_matrix/federation/v1/state_ids/%s?event_id=%s",
url.PathEscape(psjResult.ServerRoom.RoomID),
url.QueryEscape(event.EventID()),
Expand Down
22 changes: 12 additions & 10 deletions tests/federation_room_join_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ func TestBannedUserCannotSendJoin(t *testing.T) {
federation.HandleTransactionRequests(nil, nil),
)
cancel := srv.Listen()
origin := gomatrixserverlib.ServerName(srv.ServerName())
defer cancel()

fedClient := srv.FederationClient(deployment)
Expand All @@ -289,7 +290,7 @@ func TestBannedUserCannotSendJoin(t *testing.T) {
})

// charlie sends a make_join for a different user
makeJoinResp, err := fedClient.MakeJoin(context.Background(), "hs1", roomID, srv.UserID("charlie2"), federation.SupportedRoomVersions())
makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, "hs1", roomID, srv.UserID("charlie2"), federation.SupportedRoomVersions())
must.NotError(t, "MakeJoin", err)

// ... and does a switcheroo to turn it into a join for himself
Expand All @@ -299,7 +300,7 @@ func TestBannedUserCannotSendJoin(t *testing.T) {
must.NotError(t, "JoinEvent.Build", err)

// SendJoin should return a 403.
_, err = fedClient.SendJoin(context.Background(), "hs1", joinEvent)
_, err = fedClient.SendJoin(context.Background(), origin, "hs1", joinEvent)
if err == nil {
t.Errorf("SendJoin returned 200, want 403")
} else if httpError, ok := err.(gomatrix.HTTPError); ok {
Expand Down Expand Up @@ -380,7 +381,7 @@ func testValidationForSendMembershipEndpoint(t *testing.T, baseApiPath, expected
url.PathEscape(event.EventID()),
)
t.Logf("PUT %s", path)
req := gomatrixserverlib.NewFederationRequest("PUT", "hs1", path)
req := gomatrixserverlib.NewFederationRequest("PUT", gomatrixserverlib.ServerName(srv.ServerName()), "hs1", path)
if err := req.SetContent(event); err != nil {
t.Errorf("req.SetContent: %v", err)
return
Expand Down Expand Up @@ -469,6 +470,7 @@ func TestSendJoinPartialStateResponse(t *testing.T) {
)
cancel := srv.Listen()
defer cancel()
origin := gomatrixserverlib.ServerName(srv.ServerName())

// annoyingly we can't get to the room that alice and bob already share (see https://github.com/matrix-org/complement/issues/254)
// so we have to create a new one.
Expand All @@ -481,25 +483,25 @@ func TestSendJoinPartialStateResponse(t *testing.T) {
// now we send a make_join...
charlie := srv.UserID("charlie")
fedClient := srv.FederationClient(deployment)
makeJoinResp, err := fedClient.MakeJoin(context.Background(), "hs1", roomID, charlie, federation.SupportedRoomVersions())
makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, "hs1", roomID, charlie, federation.SupportedRoomVersions())
if err != nil {
t.Fatalf("make_join failed: %v", err)
}

// ... construct a signed join event ...
roomVer := makeJoinResp.RoomVersion
joinEvent, err := makeJoinResp.JoinEvent.Build(time.Now(), gomatrixserverlib.ServerName(srv.ServerName()), srv.KeyID, srv.Priv, roomVer)
joinEvent, err := makeJoinResp.JoinEvent.Build(time.Now(), origin, srv.KeyID, srv.Priv, roomVer)
if err != nil {
t.Fatalf("failed to sign join event: %v", err)
}

// and send_join it, with the magic param
sendJoinResp, err := fedClient.SendJoinPartialState(context.Background(), "hs1", joinEvent)
sendJoinResp, err := fedClient.SendJoinPartialState(context.Background(), origin, "hs1", joinEvent)
if err != nil {
t.Fatalf("send_join failed: %v", err)
}

if !sendJoinResp.PartialState {
if !sendJoinResp.MembersOmitted {
t.Skip("Server does not support partial_state")
}

Expand All @@ -519,16 +521,16 @@ func TestSendJoinPartialStateResponse(t *testing.T) {
})

// check the returned auth events match those expected.
// Now that we include heroes in the partial join response,
// all of the events are included under "state" and so we don't expect any
// Now that we include heroes in the partial join response,
// all of the events are included under "state" and so we don't expect any
// extra auth_events.
// TODO: add in a second e.g. power_levels event so that we add stuff to the
// auth chain.
var returnedAuthEventKeys []interface{}
for _, ev := range sendJoinResp.AuthEvents {
returnedAuthEventKeys = append(returnedAuthEventKeys, typeAndStateKeyForEvent(gjson.ParseBytes(ev)))
}
must.CheckOffAll(t, returnedAuthEventKeys, []interface{}{ })
must.CheckOffAll(t, returnedAuthEventKeys, []interface{}{})

// check the server list. Only one, so we can use HaveInOrder even though the list is unordered
must.HaveInOrder(t, sendJoinResp.ServersInRoom, []string{"hs1"})
Expand Down