Skip to content
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
22 changes: 22 additions & 0 deletions federationclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,32 @@ func (ac *FederationClient) MakeJoin(
// See https://matrix.org/docs/spec/server_server/unstable.html#joining-rooms
func (ac *FederationClient) SendJoin(
ctx context.Context, s ServerName, event *Event,
) (res RespSendJoin, err error) {
return ac.sendJoin(ctx, s, event, false)
}

// SendJoinPartialState sends a join m.room.member event obtained using MakeJoin via a
// remote matrix server, with a parameter indicating we support partial state in
// the response.
// This is used to join a room the local server isn't a member of.
// See https://matrix.org/docs/spec/server_server/unstable.html#joining-rooms
func (ac *FederationClient) SendJoinPartialState(
ctx context.Context, s ServerName, event *Event,
) (res RespSendJoin, err error) {
return ac.sendJoin(ctx, s, event, true)
}

// sendJoin is an internal implementation shared between SendJoin and SendJoinPartialState
func (ac *FederationClient) sendJoin(
ctx context.Context, s ServerName, event *Event, partialState bool,
) (res RespSendJoin, err error) {
path := federationPathPrefixV2 + "/send_join/" +
url.PathEscape(event.RoomID()) + "/" +
url.PathEscape(event.EventID())
if partialState {
path += "?org.matrix.msc3706.partial_state=true"
}

req := NewFederationRequest("PUT", s, path)
if err = req.SetContent(event); err != nil {
return
Expand Down
25 changes: 24 additions & 1 deletion federationtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,10 @@ type RespSendJoin struct {
// The returned join event from the remote server. Used for restricted joins,
// but not guaranteed to be present as it's only since MSC3083.
Event *Event `json:"event,omitempty"`
// true if the state is incomplete
PartialState bool `json:"org.matrix.msc3706.partial_state"`
// a list of servers in the room. Only returned if partial_state is set.
ServersInRoom []string `json:"org.matrix.msc3706.servers_in_room"`
}

// MarshalJSON implements json.Marshaller
Expand All @@ -488,7 +492,17 @@ func (r RespSendJoin) MarshalJSON() ([]byte, error) {
if len(fields.StateEvents) == 0 {
fields.StateEvents = EventJSONs{}
}
return json.Marshal(fields)

if !r.PartialState {
return json.Marshal(fields)
}

partialJoinFields := respSendJoinPartialStateFields{
respSendJoinFields: fields,
PartialState: true,
ServersInRoom: r.ServersInRoom,
}
return json.Marshal(partialJoinFields)
}

// ToRespState returns a new RespState with the same data from the given RespPeek
Expand All @@ -505,12 +519,21 @@ func (r RespPeek) ToRespState() RespState {
}
}

// respSendJoinFields is an intermediate struct used in RespSendJoin.MarshalJSON
type respSendJoinFields struct {
StateEvents EventJSONs `json:"state"`
AuthEvents EventJSONs `json:"auth_chain"`
Origin ServerName `json:"origin"`
}

// respSendJoinPartialStateFields extends respSendJoinFields with the fields added
// when the response has incomplete state.
type respSendJoinPartialStateFields struct {
respSendJoinFields
PartialState bool `json:"org.matrix.msc3706.partial_state"`
ServersInRoom []string `json:"org.matrix.msc3706.servers_in_room"`
}

// ToRespState returns a new RespState with the same data from the given RespSendJoin
func (r RespSendJoin) ToRespState() RespState {
if len(r.StateEvents) == 0 {
Expand Down
50 changes: 42 additions & 8 deletions federationtypes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ package gomatrixserverlib

import (
"encoding/json"
"strings"
"testing"
"unicode"

"github.com/google/go-cmp/cmp"
)

const emptyRespStateResponse = `{"pdus":[],"auth_chain":[]}`
Expand Down Expand Up @@ -90,38 +94,68 @@ func TestRespStateUnmarshalJSON(t *testing.T) {
}

func TestRespSendJoinMarshalJSON(t *testing.T) {
// we unmarshall and marshall an empty send-join response, and check it round-trips correctly.
inputData := `{"state":[],"auth_chain":[],"origin":""}`
var input RespSendJoin
if err := json.Unmarshal([]byte(inputData), &input); err != nil {
t.Fatal(err)
}

want := RespSendJoin{
StateEvents: []RawJSON{},
AuthEvents: []RawJSON{},
Origin: "",
}
if !cmp.Equal(input, want, cmp.AllowUnexported(RespSendJoin{})) {
t.Errorf("json.Unmarshal(%s): wanted %+v, got %+v", inputData, want, input)
}

gotBytes, err := json.Marshal(input)
if err != nil {
t.Fatal(err)
}

got := string(gotBytes)

if emptyRespSendJoinResponse != got {
t.Errorf("json.Marshal(RespSendJoin(%q)): wanted %q, got %q", inputData, emptyRespStateResponse, got)
t.Errorf("json.Marshal(%+v): wanted '%s', got '%s'", input, emptyRespSendJoinResponse, got)
}
}

func TestRespSendJoinUnmarshalJSON(t *testing.T) {
inputData := `{"state":[],"auth_chain":[],"origin":""}`
func TestRespSendJoinMarshalJSONPartialState(t *testing.T) {
inputData := `{
"state":[],"auth_chain":[],"origin":"o1",
"org.matrix.msc3706.partial_state":true,
"org.matrix.msc3706.servers_in_room":["s1", "s2"]
}`

var input RespSendJoin
if err := json.Unmarshal([]byte(inputData), &input); err != nil {
t.Fatal(err)
}

want := RespSendJoin{
StateEvents: []RawJSON{},
AuthEvents: []RawJSON{},
Origin: "o1",
PartialState: true,
ServersInRoom: []string{"s1", "s2"},
}
if !cmp.Equal(input, want, cmp.AllowUnexported(RespSendJoin{})) {
t.Errorf("json.Unmarshal(%s): wanted %+v, got %+v", inputData, want, input)
}

gotBytes, err := json.Marshal(input)
if err != nil {
t.Fatal(err)
}
got := string(gotBytes)

if emptyRespSendJoinResponse != got {
t.Errorf("json.Marshal(RespSendJoin(%q)): wanted %q, got %q", inputData, emptyRespStateResponse, got)
// the result should be the input, with spaces removed
wantJSON := strings.Map(func(r rune) rune {
if unicode.IsSpace(r) {
return -1
}
return r
}, inputData)
if wantJSON != got {
t.Errorf("json.Marshal(%+v):\n wanted: '%s'\n got: '%s'", input, wantJSON, got)
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/matrix-org/gomatrixserverlib

require (
github.com/frankban/quicktest v1.7.2 // indirect
github.com/google/go-cmp v0.4.0 // indirect
github.com/google/go-cmp v0.4.0
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/kr/pretty v0.2.0 // indirect
github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26
Expand Down