Skip to content

Commit

Permalink
Implement MSC2659
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Mar 11, 2023
1 parent 83fcdcf commit c036250
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 7 deletions.
12 changes: 12 additions & 0 deletions appservice/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ func (as *AppService) Start() {
as.Router.HandleFunc("/_matrix/app/v1/transactions/{txnID}", as.PutTransaction).Methods(http.MethodPut)
as.Router.HandleFunc("/_matrix/app/v1/rooms/{roomAlias}", as.GetRoom).Methods(http.MethodGet)
as.Router.HandleFunc("/_matrix/app/v1/users/{userID}", as.GetUser).Methods(http.MethodGet)
as.Router.HandleFunc("/_matrix/app/v1/ping", as.PostPing).Methods(http.MethodPost)
as.Router.HandleFunc("/_matrix/app/unstable/fi.mau.msc2659/ping", as.PostPing).Methods(http.MethodPost)
as.Router.HandleFunc("/_matrix/mau/live", as.GetLive).Methods(http.MethodGet)
as.Router.HandleFunc("/_matrix/mau/ready", as.GetReady).Methods(http.MethodGet)

Expand Down Expand Up @@ -289,6 +291,16 @@ func (as *AppService) GetUser(w http.ResponseWriter, r *http.Request) {
}
}

func (as *AppService) PostPing(w http.ResponseWriter, r *http.Request) {
if !as.CheckServerToken(w, r) {
return
}

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte("{}"))
}

func (as *AppService) GetLive(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
if as.Live {
Expand Down
41 changes: 34 additions & 7 deletions bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package bridge

import (
"encoding/json"
"errors"
"fmt"
"net/url"
Expand Down Expand Up @@ -291,15 +292,40 @@ func (br *Bridge) ensureConnection() {
}
br.ZLog.Err(err).Msg("Failed to connect to homeserver, retrying in 10 seconds...")
time.Sleep(10 * time.Second)
continue
} else if resp.UserID != br.Bot.UserID {
br.ZLog.WithLevel(zerolog.FatalLevel).
Stringer("got_user_id", resp.UserID).
Stringer("expected_user_id", br.Bot.UserID).
Msg("Unexpected user ID in whoami call")
os.Exit(17)
}

if br.SpecVersions.UnstableFeatures["fi.mau.msc2659"] && br.AS.Host.Port != 0 {
resp, err := br.Bot.AppservicePing()
if err != nil {
evt := br.ZLog.WithLevel(zerolog.FatalLevel).Err(err)
var httpErr mautrix.HTTPError
if errors.As(err, &httpErr) && httpErr.RespError != nil {
if val, ok := httpErr.RespError.ExtraData["body"].(string); ok {
val = strings.TrimSpace(val)
valBytes := []byte(val)
if json.Valid(valBytes) {
evt.RawJSON("body", valBytes)
} else {
evt.Str("body", val)
}
}
}
evt.Msg("Homeserver -> bridge connection is not working")
os.Exit(13)
}
br.ZLog.Debug().Int64("duration_ms", resp.DurationMS).Msg("Homeserver -> bridge connection works")
} else {
break
br.ZLog.Debug().Msg("Homeserver does not support checking status of homeserver -> bridge connection")
}

break
}
}

Expand Down Expand Up @@ -518,6 +544,13 @@ func (br *Bridge) start() {
br.LogDBUpgradeErrorAndExit("matrix_state", err)
}

if br.AS.Host.Port != 0 {
br.ZLog.Debug().Msg("Starting application service HTTP server")
go br.AS.Start()
} else {
br.ZLog.Debug().Msg("Appservice port not configured, not starting HTTP server")
}

br.ZLog.Debug().Msg("Checking connection to homeserver")
br.ensureConnection()
go br.fetchMediaConfig()
Expand All @@ -530,12 +563,6 @@ func (br *Bridge) start() {
}
}

if br.AS.Host.Port != 0 {
br.ZLog.Debug().Msg("Starting application service HTTP server")
go br.AS.Start()
} else {
br.ZLog.Debug().Msg("Appservice port not configured, not starting HTTP server")
}
br.ZLog.Debug().Msg("Starting event processor")
br.EventProcessor.Start()

Expand Down
11 changes: 11 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1963,6 +1963,17 @@ func (cli *Client) BatchSend(roomID id.RoomID, req *ReqBatchSend) (resp *RespBat
return
}

func (cli *Client) AppservicePing() (resp *RespAppservicePing, err error) {
_, err = cli.MakeFullRequest(FullRequest{
Method: http.MethodPost,
URL: cli.BuildClientURL("unstable", "fi.mau.msc2659", "appservice", "ping"),
ResponseJSON: &resp,
// This endpoint intentionally returns 50x, so don't retry
MaxAttempts: 1,
})
return
}

func (cli *Client) BeeperMergeRooms(req *ReqBeeperMergeRoom) (resp *RespBeeperMergeRoom, err error) {
urlPath := cli.BuildClientURL("unstable", "com.beeper.chatmerging", "merge")
_, err = cli.MakeRequest(http.MethodPost, urlPath, req, &resp)
Expand Down
5 changes: 5 additions & 0 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ var (
MIncompatibleRoomVersion = RespError{ErrCode: "M_INCOMPATIBLE_ROOM_VERSION"}
// The client specified a parameter that has the wrong value.
MInvalidParam = RespError{ErrCode: "M_INVALID_PARAM"}

MSC2659URLNotSet = RespError{ErrCode: "FI.MAU.MSC2659_URL_NOT_SET"}
MSC2659BadStatus = RespError{ErrCode: "FI.MAU.MSC2659_BAD_STATUS"}
MSC2659ConnectionTimeout = RespError{ErrCode: "FI.MAU.MSC2659_CONNECTION_TIMEOUT"}
MSC2659ConnectionFailed = RespError{ErrCode: "FI.MAU.MSC2659_CONNECTION_FAILED"}
)

// HTTPError An HTTP Error response, which may wrap an underlying native Go Error.
Expand Down
4 changes: 4 additions & 0 deletions responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,10 @@ type StrippedStateWithTime struct {
Timestamp jsontime.UnixMilli `json:"origin_server_ts"`
}

type RespAppservicePing struct {
DurationMS int64 `json:"duration"`
}

type RespBeeperMergeRoom RespCreateRoom

type RespBeeperSplitRoom struct {
Expand Down

0 comments on commit c036250

Please sign in to comment.