Update version of gomatrixserverlib (#111)
This commit is contained in:
parent
9d4d18ae7f
commit
aa179d451c
24 changed files with 2363 additions and 20 deletions
|
|
@ -40,8 +40,16 @@ type UserInfo struct {
|
|||
|
||||
// NewClient makes a new Client
|
||||
func NewClient() *Client {
|
||||
return &Client{client: http.Client{Transport: newFederationTripper()}}
|
||||
}
|
||||
|
||||
type federationTripper struct {
|
||||
transport http.RoundTripper
|
||||
}
|
||||
|
||||
func newFederationTripper() *federationTripper {
|
||||
// TODO: Verify ceritificates
|
||||
tripper := federationTripper{
|
||||
return &federationTripper{
|
||||
transport: &http.Transport{
|
||||
// Set our own DialTLS function to avoid the default net/http SNI.
|
||||
// By default net/http and crypto/tls set the SNI to the target host.
|
||||
|
|
@ -66,14 +74,6 @@ func NewClient() *Client {
|
|||
},
|
||||
},
|
||||
}
|
||||
|
||||
return &Client{
|
||||
client: http.Client{Transport: &tripper},
|
||||
}
|
||||
}
|
||||
|
||||
type federationTripper struct {
|
||||
transport http.RoundTripper
|
||||
}
|
||||
|
||||
func makeHTTPSURL(u *url.URL, addr string) (httpsURL url.URL) {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ type EventReference struct {
|
|||
}
|
||||
|
||||
// An EventBuilder is used to build a new event.
|
||||
// These can be exchanged between matrix servers in the federation APIs when
|
||||
// joining or leaving a room.
|
||||
type EventBuilder struct {
|
||||
// The user ID of the user sending the event.
|
||||
Sender string `json:"sender"`
|
||||
|
|
@ -60,20 +62,22 @@ type EventBuilder struct {
|
|||
Redacts string `json:"redacts,omitempty"`
|
||||
// The depth of the event, This should be one greater than the maximum depth of the previous events.
|
||||
// The create event has a depth of 1.
|
||||
Depth int64 `json:"depth"`
|
||||
content []byte
|
||||
unsigned []byte
|
||||
Depth int64 `json:"depth"`
|
||||
// The JSON object for "content" key of the event.
|
||||
Content rawJSON `json:"content"`
|
||||
// The JSON object for the "unsigned" key
|
||||
Unsigned rawJSON `json:"unsigned,omitempty"`
|
||||
}
|
||||
|
||||
// SetContent sets the JSON content key of the event.
|
||||
func (eb *EventBuilder) SetContent(content interface{}) (err error) {
|
||||
eb.content, err = json.Marshal(content)
|
||||
eb.Content, err = json.Marshal(content)
|
||||
return
|
||||
}
|
||||
|
||||
// SetUnsigned sets the JSON unsigned key of the event.
|
||||
func (eb *EventBuilder) SetUnsigned(unsigned interface{}) (err error) {
|
||||
eb.unsigned, err = json.Marshal(unsigned)
|
||||
eb.Unsigned, err = json.Marshal(unsigned)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -113,8 +117,6 @@ func (eb *EventBuilder) Build(eventID string, now time.Time, origin ServerName,
|
|||
var event struct {
|
||||
EventBuilder
|
||||
EventID string `json:"event_id"`
|
||||
RawContent rawJSON `json:"content"`
|
||||
RawUnsigned rawJSON `json:"unsigned,omitempty"`
|
||||
OriginServerTS Timestamp `json:"origin_server_ts"`
|
||||
Origin ServerName `json:"origin"`
|
||||
}
|
||||
|
|
@ -125,8 +127,6 @@ func (eb *EventBuilder) Build(eventID string, now time.Time, origin ServerName,
|
|||
if event.AuthEvents == nil {
|
||||
event.AuthEvents = emptyEventReferenceList
|
||||
}
|
||||
event.RawContent = rawJSON(event.content)
|
||||
event.RawUnsigned = rawJSON(event.unsigned)
|
||||
event.OriginServerTS = AsTimestamp(now)
|
||||
event.Origin = origin
|
||||
event.EventID = eventID
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ func StateNeededForEventBuilder(builder *EventBuilder) (result StateNeeded, err
|
|||
// Extract the 'content' object from the event if it is m.room.member as we need to know 'membership'
|
||||
var content *memberContent
|
||||
if builder.Type == "m.room.member" {
|
||||
if err = json.Unmarshal(builder.content, &content); err != nil {
|
||||
if err = json.Unmarshal(builder.Content, &content); err != nil {
|
||||
err = errorf("unparsable member event content: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
|
|
|||
162
vendor/src/github.com/matrix-org/gomatrixserverlib/federationclient.go
vendored
Normal file
162
vendor/src/github.com/matrix-org/gomatrixserverlib/federationclient.go
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
package gomatrixserverlib
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// An FederationClient is a matrix federation client that adds
|
||||
// "Authorization: X-Matrix" headers to requests that need ed25519 signatures
|
||||
type FederationClient struct {
|
||||
Client
|
||||
serverName ServerName
|
||||
serverKeyID KeyID
|
||||
serverPrivateKey ed25519.PrivateKey
|
||||
}
|
||||
|
||||
// NewFederationClient makes a new FederationClient
|
||||
func NewFederationClient(
|
||||
serverName ServerName, keyID KeyID, privateKey ed25519.PrivateKey,
|
||||
) *FederationClient {
|
||||
return &FederationClient{
|
||||
Client: Client{client: http.Client{Transport: newFederationTripper()}},
|
||||
serverName: serverName,
|
||||
serverKeyID: keyID,
|
||||
serverPrivateKey: privateKey,
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *FederationClient) doRequest(r FederationRequest, resBody interface{}) error {
|
||||
if err := r.Sign(ac.serverName, ac.serverKeyID, ac.serverPrivateKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req, err := r.HTTPRequest()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := ac.client.Do(req)
|
||||
if res != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
contents, err := ioutil.ReadAll(res.Body)
|
||||
if res.StatusCode/100 != 2 { // not 2xx
|
||||
// Adapted from https://github.com/matrix-org/gomatrix/blob/master/client.go
|
||||
var wrap error
|
||||
var respErr gomatrix.RespError
|
||||
if _ = json.Unmarshal(contents, &respErr); respErr.ErrCode != "" {
|
||||
wrap = respErr
|
||||
}
|
||||
|
||||
// If we failed to decode as RespError, don't just drop the HTTP body, include it in the
|
||||
// HTTP error instead (e.g proxy errors which return HTML).
|
||||
msg := "Failed to " + r.Method() + " JSON to " + r.RequestURI()
|
||||
if wrap == nil {
|
||||
msg = msg + ": " + string(contents)
|
||||
}
|
||||
|
||||
return gomatrix.HTTPError{
|
||||
Code: res.StatusCode,
|
||||
Message: msg,
|
||||
WrappedError: wrap,
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(contents, resBody)
|
||||
}
|
||||
|
||||
// SendTransaction sends a transaction
|
||||
func (ac *FederationClient) SendTransaction(t Transaction) (res RespSend, err error) {
|
||||
path := "/_matrix/federation/v1/send/" + string(t.TransactionID) + "/"
|
||||
req := NewFederationRequest("PUT", t.Destination, path)
|
||||
if err = req.SetContent(t); err != nil {
|
||||
return
|
||||
}
|
||||
err = ac.doRequest(req, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// MakeJoin makes a join m.room.member event for a room on a remote matrix server.
|
||||
// This is used to join a room the local server isn't a member of.
|
||||
// We need to query a remote server because if we aren't in the room we don't
|
||||
// know what to use for the "prev_events" in the join event.
|
||||
// The remote server should return us a m.room.member event for our local user
|
||||
// with the "prev_events" filled out.
|
||||
// If this successfully returns an acceptable event we will sign it with our
|
||||
// server's key and pass it to SendJoin.
|
||||
// See https://matrix.org/docs/spec/server_server/unstable.html#joining-rooms
|
||||
func (ac *FederationClient) MakeJoin(s ServerName, roomID, userID string) (res RespMakeJoin, err error) {
|
||||
path := "/_matrix/federation/v1/make_join/" +
|
||||
url.PathEscape(roomID) + "/" +
|
||||
url.PathEscape(userID)
|
||||
req := NewFederationRequest("GET", s, path)
|
||||
err = ac.doRequest(req, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// SendJoin sends a join m.room.member event obtained using MakeJoin via a
|
||||
// remote matrix server.
|
||||
// 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) SendJoin(s ServerName, event Event) (res RespSendJoin, err error) {
|
||||
path := "/_matrix/federation/v1/send_join/" +
|
||||
url.PathEscape(event.RoomID()) + "/" +
|
||||
url.PathEscape(event.EventID())
|
||||
req := NewFederationRequest("PUT", s, path)
|
||||
if err = req.SetContent(event); err != nil {
|
||||
return
|
||||
}
|
||||
err = ac.doRequest(req, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// LookupState retrieves the room state for a room at an event from a
|
||||
// remote matrix server as full matrix events.
|
||||
func (ac *FederationClient) LookupState(s ServerName, roomID, eventID string) (res RespState, err error) {
|
||||
path := "/_matrix/federation/v1/state/" +
|
||||
url.PathEscape(roomID) +
|
||||
"/?event_id=" +
|
||||
url.QueryEscape(eventID)
|
||||
req := NewFederationRequest("GET", s, path)
|
||||
err = ac.doRequest(req, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// LookupStateIDs retrieves the room state for a room at an event from a
|
||||
// remote matrix server as lists of matrix event IDs.
|
||||
func (ac *FederationClient) LookupStateIDs(s ServerName, roomID, eventID string) (res RespStateIDs, err error) {
|
||||
path := "/_matrix/federation/v1/state_ids/" +
|
||||
url.PathEscape(roomID) +
|
||||
"/?event_id=" +
|
||||
url.QueryEscape(eventID)
|
||||
req := NewFederationRequest("GET", s, path)
|
||||
err = ac.doRequest(req, &res)
|
||||
return
|
||||
}
|
||||
|
||||
// LookupRoomAlias looks up a room alias hosted on the remote server.
|
||||
// The domain part of the roomAlias must match the name of the server it is
|
||||
// being looked up on.
|
||||
// If the room alias doesn't exist on the remote server then a 404 gomatrix.HTTPError
|
||||
// is returned.
|
||||
func (ac *FederationClient) LookupRoomAlias(s ServerName, roomAlias string) (res RespDirectory, err error) {
|
||||
path := "/_matrix/federation/v1/query/directory?room_alias=" +
|
||||
url.QueryEscape(roomAlias)
|
||||
req := NewFederationRequest("GET", s, path)
|
||||
err = ac.doRequest(req, &res)
|
||||
return
|
||||
}
|
||||
106
vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go
vendored
Normal file
106
vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
package gomatrixserverlib
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// A RespSend is the content of a response to PUT /_matrix/federation/v1/send/{txnID}/
|
||||
type RespSend struct {
|
||||
// Map of event ID to the result of processing that event.
|
||||
PDUs map[string]PDUResult `json:"pdus"`
|
||||
}
|
||||
|
||||
// A PDUResult is the result of processing a matrix room event.
|
||||
type PDUResult struct {
|
||||
// If not empty then this is a human readable description of a problem
|
||||
// encountered processing an event.
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// A RespStateIDs is the content of a response to GET /_matrix/federation/v1/state_ids/{roomID}/{eventID}
|
||||
type RespStateIDs struct {
|
||||
// A list of state event IDs for the state of the room before the requested event.
|
||||
StateEventIDs []string `json:"pdu_ids"`
|
||||
// A list of event IDs needed to authenticate the state events.
|
||||
AuthEventIDs []string `json:"auth_chain_ids"`
|
||||
}
|
||||
|
||||
// A RespState is the content of a response to GET /_matrix/federation/v1/state/{roomID}/{eventID}
|
||||
type RespState struct {
|
||||
// A list of events giving the state of the room before the request event.
|
||||
StateEvents []Event `json:"pdus"`
|
||||
// A list of events needed to authenticate the state events.
|
||||
AuthEvents []Event `json:"auth_chain"`
|
||||
}
|
||||
|
||||
// A RespMakeJoin is the content of a response to GET /_matrix/federation/v1/make_join/{roomID}/{userID}
|
||||
type RespMakeJoin struct {
|
||||
// An incomplete m.room.member event for a user on the requesting server
|
||||
// generated by the responding server.
|
||||
// See https://matrix.org/docs/spec/server_server/unstable.html#joining-rooms
|
||||
JoinEvent EventBuilder `json:"event"`
|
||||
}
|
||||
|
||||
// A RespSendJoin is the content of a response to PUT /_matrix/federation/v1/send_join/{roomID}/{eventID}
|
||||
type RespSendJoin RespState
|
||||
|
||||
// MarshalJSON implements json.Marshaller
|
||||
func (r RespSendJoin) MarshalJSON() ([]byte, error) {
|
||||
// SendJoinResponses contain the same data as a StateResponse but are
|
||||
// formatted slightly differently on the wire:
|
||||
// 1) The "pdus" field is renamed to "state".
|
||||
// 2) The object is placed as the second element of a two element list
|
||||
// where the first element is the constant integer 200.
|
||||
//
|
||||
//
|
||||
// So a state response of:
|
||||
//
|
||||
// {"pdus": x, "auth_chain": y}
|
||||
//
|
||||
// Becomes:
|
||||
//
|
||||
// [200, {"state": x, "auth_chain": y}]
|
||||
//
|
||||
// (This protocol oddity is the result of a typo in the synapse matrix
|
||||
// server, and is preserved to maintain compatibility.)
|
||||
|
||||
return json.Marshal([]interface{}{200, respSendJoinFields{
|
||||
r.StateEvents, r.AuthEvents,
|
||||
}})
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaller
|
||||
func (r *RespSendJoin) UnmarshalJSON(data []byte) error {
|
||||
var tuple []rawJSON
|
||||
if err := json.Unmarshal(data, &tuple); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(tuple) != 2 {
|
||||
return fmt.Errorf("gomatrixserverlib: invalid send join response, invalid length: %d != 2", len(tuple))
|
||||
}
|
||||
var fields respSendJoinFields
|
||||
if err := json.Unmarshal(tuple[1], &fields); err != nil {
|
||||
return err
|
||||
}
|
||||
r.StateEvents = fields.StateEvents
|
||||
r.AuthEvents = fields.AuthEvents
|
||||
return nil
|
||||
}
|
||||
|
||||
type respSendJoinFields struct {
|
||||
StateEvents []Event `json:"state"`
|
||||
AuthEvents []Event `json:"auth_chain"`
|
||||
}
|
||||
|
||||
// A RespDirectory is the content of a response to GET /_matrix/federation/v1/query/directory
|
||||
// This is returned when looking up a room alias from a remote server.
|
||||
// See https://matrix.org/docs/spec/server_server/unstable.html#directory
|
||||
type RespDirectory struct {
|
||||
// The matrix room ID the room alias corresponds to.
|
||||
RoomID string `json:"room_id"`
|
||||
// A list of matrix servers that the directory server thinks could be used
|
||||
// to join the room. The joining server may need to try multiple servers
|
||||
// before it finds one that it can use to join the room.
|
||||
Servers []ServerName `json:"servers"`
|
||||
}
|
||||
47
vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes_test.go
vendored
Normal file
47
vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes_test.go
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package gomatrixserverlib
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRespSendJoinMarshalJSON(t *testing.T) {
|
||||
inputData := `{"pdus":[],"auth_chain":[]}`
|
||||
var input RespState
|
||||
if err := json.Unmarshal([]byte(inputData), &input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
gotBytes, err := json.Marshal(RespSendJoin(input))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := `[200,{"state":[],"auth_chain":[]}]`
|
||||
got := string(gotBytes)
|
||||
|
||||
if want != got {
|
||||
t.Errorf("json.Marshal(RespSendJoin(%q)): wanted %q, got %q", inputData, want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRespSendJoinUnmarshalJSON(t *testing.T) {
|
||||
inputData := `[200,{"state":[],"auth_chain":[]}]`
|
||||
var input RespSendJoin
|
||||
if err := json.Unmarshal([]byte(inputData), &input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
gotBytes, err := json.Marshal(RespState(input))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := `{"pdus":[],"auth_chain":[]}`
|
||||
got := string(gotBytes)
|
||||
|
||||
if want != got {
|
||||
t.Errorf("json.Marshal(RespSendJoin(%q)): wanted %q, got %q", inputData, want, got)
|
||||
}
|
||||
|
||||
}
|
||||
31
vendor/src/github.com/matrix-org/gomatrixserverlib/transaction.go
vendored
Normal file
31
vendor/src/github.com/matrix-org/gomatrixserverlib/transaction.go
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package gomatrixserverlib
|
||||
|
||||
// A Transaction is used to push data from one matrix server to another matrix
|
||||
// server.
|
||||
type Transaction struct {
|
||||
// The ID of the transaction.
|
||||
TransactionID TransactionID `json:"transaction_id"`
|
||||
// The server that sent the transaction.
|
||||
Origin ServerName `json:"origin"`
|
||||
// The server that should receive the transaction.
|
||||
Destination ServerName `json:"destination"`
|
||||
// The millisecond posix timestamp on the origin server when the
|
||||
// transaction was created.
|
||||
OriginServerTS Timestamp `json:"origin_server_ts"`
|
||||
// The IDs of the most recent transactions sent by the origin server to
|
||||
// the destination server. Multiple transactions can be sent by the origin
|
||||
// server to the destination server in parallel so there may be more than
|
||||
// one previous transaction.
|
||||
PreviousIDs []TransactionID `json:"previous_ids"`
|
||||
// The room events pushed from the origin server to the destination server
|
||||
// by this transaction. The events should either be events that originate
|
||||
// on the origin server or be join m.room.member events.
|
||||
PDUs []Event `json:"pdus"`
|
||||
}
|
||||
|
||||
// A TransactionID identifies a transaction sent by a matrix server to another
|
||||
// matrix server. The ID must be unique amoungst the transactions sent from the
|
||||
// origin server to the destination, but doesn't have to be globally unique.
|
||||
// The ID must be safe to insert into a URL path segment. The ID should have a
|
||||
// format matching '^[0-9A-Za-z\-_]*$'
|
||||
type TransactionID string
|
||||
Loading…
Add table
Add a link
Reference in a new issue