From fdc3772b52d6638017b8dbb707ebbdbbad7dfe5a Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Thu, 10 Jun 2021 02:55:22 +0200 Subject: [PATCH] use "[]byte" instead of "json.RawMessage" if posible --- clientapi/auth/user_interactive_test.go | 4 ++-- clientapi/routing/account_data.go | 4 ++-- clientapi/routing/createroom.go | 2 +- clientapi/routing/keys.go | 5 ++--- clientapi/routing/room_tagging.go | 2 +- clientapi/routing/routing.go | 3 +-- clientapi/routing/sendtodevice.go | 3 +-- clientapi/routing/state.go | 4 ++-- federationapi/routing/keys.go | 4 ++-- federationapi/routing/send_test.go | 14 +++++++------- federationsender/queue/destinationqueue.go | 2 +- keyserver/api/api.go | 7 +++---- keyserver/internal/internal.go | 18 +++++++++--------- keyserver/storage/interface.go | 3 +-- .../storage/postgres/one_time_keys_table.go | 13 ++++++------- keyserver/storage/shared/storage.go | 3 +-- .../storage/sqlite3/one_time_keys_table.go | 13 ++++++------- keyserver/storage/tables/interface.go | 5 ++--- roomserver/api/perform.go | 3 +-- roomserver/internal/alias.go | 2 +- roomserver/roomserver_test.go | 8 ++++---- .../storage/sqlite3/state_block_table.go | 2 +- syncapi/storage/storage_test.go | 2 +- syncapi/types/types.go | 10 +++++----- userapi/api/api.go | 13 ++++++------- userapi/internal/api.go | 9 ++++----- userapi/storage/accounts/interface.go | 7 +++---- .../accounts/postgres/account_data_table.go | 17 ++++++++--------- userapi/storage/accounts/postgres/storage.go | 11 +++++------ .../accounts/sqlite3/account_data_table.go | 17 ++++++++--------- userapi/storage/accounts/sqlite3/storage.go | 11 +++++------ 31 files changed, 102 insertions(+), 119 deletions(-) diff --git a/clientapi/auth/user_interactive_test.go b/clientapi/auth/user_interactive_test.go index 0b7df3545..4b8b9cc21 100644 --- a/clientapi/auth/user_interactive_test.go +++ b/clientapi/auth/user_interactive_test.go @@ -62,7 +62,7 @@ func TestUserInteractivePasswordLogin(t *testing.T) { UserID: fmt.Sprintf("@alice:%s", serverName), } // valid password requests - testCases := []json.RawMessage{ + testCases := [][]byte{ // deprecated form []byte(`{ "auth": { @@ -101,7 +101,7 @@ func TestUserInteractivePasswordBadLogin(t *testing.T) { } // invalid password requests testCases := []struct { - body json.RawMessage + body []byte wantRes util.JSONResponse }{ { diff --git a/clientapi/routing/account_data.go b/clientapi/routing/account_data.go index 22e635139..6b1f495fe 100644 --- a/clientapi/routing/account_data.go +++ b/clientapi/routing/account_data.go @@ -53,7 +53,7 @@ func GetAccountData( return util.ErrorResponse(fmt.Errorf("userAPI.QueryAccountData: %w", err)) } - var data json.RawMessage + var data []byte var ok bool if roomID != "" { data, ok = dataRes.RoomAccountData[roomID][dataType] @@ -118,7 +118,7 @@ func SaveAccountData( UserID: userID, DataType: dataType, RoomID: roomID, - AccountData: json.RawMessage(body), + AccountData: []byte(body), } dataRes := api.InputAccountDataResponse{} if err := userAPI.InputAccountData(req.Context(), &dataReq, &dataRes); err != nil { diff --git a/clientapi/routing/createroom.go b/clientapi/routing/createroom.go index 2d8867466..3180e1fc3 100644 --- a/clientapi/routing/createroom.go +++ b/clientapi/routing/createroom.go @@ -48,7 +48,7 @@ type createRoomRequest struct { RoomAliasName string `json:"room_alias_name"` GuestCanJoin bool `json:"guest_can_join"` RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"` - PowerLevelContentOverride json.RawMessage `json:"power_level_content_override"` + PowerLevelContentOverride []byte `json:"power_level_content_override"` } const ( diff --git a/clientapi/routing/keys.go b/clientapi/routing/keys.go index e22336428..e3a99a0d1 100644 --- a/clientapi/routing/keys.go +++ b/clientapi/routing/keys.go @@ -15,7 +15,6 @@ package routing import ( - "encoding/json" "net/http" "time" @@ -27,8 +26,8 @@ import ( ) type uploadKeysRequest struct { - DeviceKeys json.RawMessage `json:"device_keys"` - OneTimeKeys map[string]json.RawMessage `json:"one_time_keys"` + DeviceKeys []byte `json:"device_keys"` + OneTimeKeys map[string][]byte `json:"one_time_keys"` } func UploadKeys(req *http.Request, keyAPI api.KeyInternalAPI, device *userapi.Device) util.JSONResponse { diff --git a/clientapi/routing/room_tagging.go b/clientapi/routing/room_tagging.go index c683cc949..ade291f68 100644 --- a/clientapi/routing/room_tagging.go +++ b/clientapi/routing/room_tagging.go @@ -205,7 +205,7 @@ func saveTagData( UserID: userID, RoomID: roomID, DataType: "m.tag", - AccountData: json.RawMessage(newTagData), + AccountData: []byte(newTagData), } dataRes := api.InputAccountDataResponse{} return userAPI.InputAccountData(req.Context(), &dataReq, &dataRes) diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index 9f980e0a9..00ced89ed 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -15,7 +15,6 @@ package routing import ( - "encoding/json" "net/http" "strings" @@ -482,7 +481,7 @@ func Setup( r0mux.Handle("/pushrules/", httputil.MakeExternalAPI("push_rules", func(req *http.Request) util.JSONResponse { // TODO: Implement push rules API - res := json.RawMessage(`{ + res := []byte(`{ "global": { "content": [], "override": [], diff --git a/clientapi/routing/sendtodevice.go b/clientapi/routing/sendtodevice.go index 768e8e0e7..cfb8fe272 100644 --- a/clientapi/routing/sendtodevice.go +++ b/clientapi/routing/sendtodevice.go @@ -13,7 +13,6 @@ package routing import ( - "encoding/json" "net/http" "github.com/matrix-org/dendrite/clientapi/httputil" @@ -39,7 +38,7 @@ func SendToDevice( } var httpReq struct { - Messages map[string]map[string]json.RawMessage `json:"messages"` + Messages map[string]map[string][]byte `json:"messages"` } resErr := httputil.UnmarshalJSONRequest(req, &httpReq) if resErr != nil { diff --git a/clientapi/routing/state.go b/clientapi/routing/state.go index 088e412c6..6d3f22d3b 100644 --- a/clientapi/routing/state.go +++ b/clientapi/routing/state.go @@ -30,8 +30,8 @@ import ( type stateEventInStateResp struct { gomatrixserverlib.ClientEvent - PrevContent json.RawMessage `json:"prev_content,omitempty"` - ReplacesState string `json:"replaces_state,omitempty"` + PrevContent []byte `json:"prev_content,omitempty"` + ReplacesState string `json:"replaces_state,omitempty"` } // OnIncomingStateRequest is called when a client makes a /rooms/{roomID}/state diff --git a/federationapi/routing/keys.go b/federationapi/routing/keys.go index 1f39094bc..65575e1b9 100644 --- a/federationapi/routing/keys.go +++ b/federationapi/routing/keys.go @@ -184,9 +184,9 @@ func NotaryKeys( } var response struct { - ServerKeys []json.RawMessage `json:"server_keys"` + ServerKeys [][]byte `json:"server_keys"` } - response.ServerKeys = []json.RawMessage{} + response.ServerKeys = [][]byte{} for serverName := range req.ServerKeys { var keys *gomatrixserverlib.ServerKeys diff --git a/federationapi/routing/send_test.go b/federationapi/routing/send_test.go index b14cbd35a..9d188979f 100644 --- a/federationapi/routing/send_test.go +++ b/federationapi/routing/send_test.go @@ -22,7 +22,7 @@ const ( var ( testRoomVersion = gomatrixserverlib.RoomVersionV1 - testData = []json.RawMessage{ + testData = [][]byte{ []byte(`{"auth_events":[],"content":{"creator":"@userid:kaer.morhen"},"depth":0,"event_id":"$0ok8ynDp7kjc95e3:kaer.morhen","hashes":{"sha256":"17kPoH+h0Dk4Omn7Sus0qMb6+oGcf+CZFEgDhv7UKWs"},"origin":"kaer.morhen","origin_server_ts":0,"prev_events":[],"prev_state":[],"room_id":"!roomid:kaer.morhen","sender":"@userid:kaer.morhen","signatures":{"kaer.morhen":{"ed25519:auto":"jP4a04f5/F10Pw95FPpdCyKAO44JOwUQ/MZOOeA/RTU1Dn+AHPMzGSaZnuGjRr/xQuADt+I3ctb5ZQfLKNzHDw"}},"state_key":"","type":"m.room.create"}`), []byte(`{"auth_events":[["$0ok8ynDp7kjc95e3:kaer.morhen",{"sha256":"sWCi6Ckp9rDimQON+MrUlNRkyfZ2tjbPbWfg2NMB18Q"}]],"content":{"membership":"join"},"depth":1,"event_id":"$LEwEu0kxrtu5fOiS:kaer.morhen","hashes":{"sha256":"B7M88PhXf3vd1LaFtjQutFu4x/w7fHD28XKZ4sAsJTo"},"origin":"kaer.morhen","origin_server_ts":0,"prev_events":[["$0ok8ynDp7kjc95e3:kaer.morhen",{"sha256":"sWCi6Ckp9rDimQON+MrUlNRkyfZ2tjbPbWfg2NMB18Q"}]],"prev_state":[],"room_id":"!roomid:kaer.morhen","sender":"@userid:kaer.morhen","signatures":{"kaer.morhen":{"ed25519:auto":"p2vqmuJn7ZBRImctSaKbXCAxCcBlIjPH9JHte1ouIUGy84gpu4eLipOvSBCLL26hXfC0Zrm4WUto6Hr+ohdrCg"}},"state_key":"@userid:kaer.morhen","type":"m.room.member"}`), []byte(`{"auth_events":[["$0ok8ynDp7kjc95e3:kaer.morhen",{"sha256":"sWCi6Ckp9rDimQON+MrUlNRkyfZ2tjbPbWfg2NMB18Q"}],["$LEwEu0kxrtu5fOiS:kaer.morhen",{"sha256":"1aKajq6DWHru1R1HJjvdWMEavkJJHGaTmPvfuERUXaA"}]],"content":{"join_rule":"public"},"depth":2,"event_id":"$SMHlqUrNhhBBRLeN:kaer.morhen","hashes":{"sha256":"vIuJQvmMjrGxshAkj1SXe0C4RqvMbv4ZADDw9pFCWqQ"},"origin":"kaer.morhen","origin_server_ts":0,"prev_events":[["$LEwEu0kxrtu5fOiS:kaer.morhen",{"sha256":"1aKajq6DWHru1R1HJjvdWMEavkJJHGaTmPvfuERUXaA"}]],"prev_state":[],"room_id":"!roomid:kaer.morhen","sender":"@userid:kaer.morhen","signatures":{"kaer.morhen":{"ed25519:auto":"hBMsb3Qppo3RaqqAl4JyTgaiWEbW5hlckATky6PrHun+F3YM203TzG7w9clwuQU5F5pZoB1a6nw+to0hN90FAw"}},"state_key":"","type":"m.room.join_rules"}`), @@ -363,7 +363,7 @@ func (c *txnFedClient) LookupMissingEvents(ctx context.Context, s gomatrixserver return c.getMissingEvents(missing) } -func mustCreateTransaction(rsAPI api.RoomserverInternalAPI, fedClient txnFederationClient, pdus []json.RawMessage) *txnReq { +func mustCreateTransaction(rsAPI api.RoomserverInternalAPI, fedClient txnFederationClient, pdus [][]byte) *txnReq { t := &txnReq{ rsAPI: rsAPI, eduAPI: &testEDUProducer{}, @@ -447,7 +447,7 @@ func TestBasicTransaction(t *testing.T) { } }, } - pdus := []json.RawMessage{ + pdus := [][]byte{ testData[len(testData)-1], // a message event } txn := mustCreateTransaction(rsAPI, &txnFedClient{}, pdus) @@ -467,7 +467,7 @@ func TestTransactionFailAuthChecks(t *testing.T) { } }, } - pdus := []json.RawMessage{ + pdus := [][]byte{ testData[len(testData)-1], // a message event } txn := mustCreateTransaction(rsAPI, &txnFedClient{}, pdus) @@ -552,7 +552,7 @@ func TestTransactionFetchMissingPrevEvents(t *testing.T) { }, } - pdus := []json.RawMessage{ + pdus := [][]byte{ inputEvent.JSON(), } txn := mustCreateTransaction(rsAPI, cli, pdus) @@ -715,7 +715,7 @@ func TestTransactionFetchMissingStateByStateIDs(t *testing.T) { // /event for event B returns it getEvent: map[string]gomatrixserverlib.Transaction{ eventB.EventID(): { - PDUs: []json.RawMessage{ + PDUs: [][]byte{ eventB.JSON(), }, }, @@ -737,7 +737,7 @@ func TestTransactionFetchMissingStateByStateIDs(t *testing.T) { }, } - pdus := []json.RawMessage{ + pdus := [][]byte{ eventD.JSON(), } txn := mustCreateTransaction(rsAPI, cli, pdus) diff --git a/federationsender/queue/destinationqueue.go b/federationsender/queue/destinationqueue.go index 33f77a426..5e7126f90 100644 --- a/federationsender/queue/destinationqueue.go +++ b/federationsender/queue/destinationqueue.go @@ -391,7 +391,7 @@ func (oq *destinationQueue) nextTransaction( if pdu == nil || pdu.pdu == nil { continue } - // Append the JSON of the event, since this is a json.RawMessage type in the + // Append the JSON of the event, since this is a []byte type in the // gomatrixserverlib.Transaction struct t.PDUs = append(t.PDUs, pdu.pdu.JSON()) pduReceipts = append(pduReceipts, pdu.receipt) diff --git a/keyserver/api/api.go b/keyserver/api/api.go index 5cb287bc1..ed2fba500 100644 --- a/keyserver/api/api.go +++ b/keyserver/api/api.go @@ -16,7 +16,6 @@ package api import ( "context" - "encoding/json" "strings" "time" @@ -83,7 +82,7 @@ type OneTimeKeys struct { // The device ID of this device DeviceID string // A map of algorithm:key_id => key JSON - KeyJSON map[string]json.RawMessage + KeyJSON map[string][]byte } // Split a key in KeyJSON into algorithm and key ID @@ -144,7 +143,7 @@ type PerformClaimKeysRequest struct { type PerformClaimKeysResponse struct { // Map of user_id to device_id to algorithm:key_id to key JSON - OneTimeKeys map[string]map[string]map[string]json.RawMessage + OneTimeKeys map[string]map[string]map[string][]byte // Map of remote server domain to error JSON Failures map[string]interface{} // Set if there was a fatal error processing this action @@ -161,7 +160,7 @@ type QueryKeysResponse struct { // Map of remote server domain to error JSON Failures map[string]interface{} // Map of user_id to device_id to device_key - DeviceKeys map[string]map[string]json.RawMessage + DeviceKeys map[string]map[string][]byte // Set if there was a fatal error processing this query Error *KeyError } diff --git a/keyserver/internal/internal.go b/keyserver/internal/internal.go index f53a07619..936b1cd57 100644 --- a/keyserver/internal/internal.go +++ b/keyserver/internal/internal.go @@ -80,7 +80,7 @@ func (a *KeyInternalAPI) PerformUploadKeys(ctx context.Context, req *api.Perform } func (a *KeyInternalAPI) PerformClaimKeys(ctx context.Context, req *api.PerformClaimKeysRequest, res *api.PerformClaimKeysResponse) { - res.OneTimeKeys = make(map[string]map[string]map[string]json.RawMessage) + res.OneTimeKeys = make(map[string]map[string]map[string][]byte) res.Failures = make(map[string]interface{}) // wrap request map in a top-level by-domain map domainToDeviceKeys := make(map[string]map[string]map[string]string) @@ -108,11 +108,11 @@ func (a *KeyInternalAPI) PerformClaimKeys(ctx context.Context, req *api.PerformC for _, key := range keys { _, ok := res.OneTimeKeys[key.UserID] if !ok { - res.OneTimeKeys[key.UserID] = make(map[string]map[string]json.RawMessage) + res.OneTimeKeys[key.UserID] = make(map[string]map[string][]byte) } _, ok = res.OneTimeKeys[key.UserID][key.DeviceID] if !ok { - res.OneTimeKeys[key.UserID][key.DeviceID] = make(map[string]json.RawMessage) + res.OneTimeKeys[key.UserID][key.DeviceID] = make(map[string][]byte) } for keyID, keyJSON := range key.KeyJSON { res.OneTimeKeys[key.UserID][key.DeviceID][keyID] = keyJSON @@ -165,9 +165,9 @@ func (a *KeyInternalAPI) claimRemoteKeys( keysClaimed := 0 for result := range resultCh { for userID, nest := range result.OneTimeKeys { - res.OneTimeKeys[userID] = make(map[string]map[string]json.RawMessage) + res.OneTimeKeys[userID] = make(map[string]map[string][]byte) for deviceID, nest2 := range nest { - res.OneTimeKeys[userID][deviceID] = make(map[string]json.RawMessage) + res.OneTimeKeys[userID][deviceID] = make(map[string][]byte) for keyIDWithAlgo, otk := range nest2 { keyJSON, err := json.Marshal(otk) if err != nil { @@ -220,7 +220,7 @@ func (a *KeyInternalAPI) QueryDeviceMessages(ctx context.Context, req *api.Query } func (a *KeyInternalAPI) QueryKeys(ctx context.Context, req *api.QueryKeysRequest, res *api.QueryKeysResponse) { - res.DeviceKeys = make(map[string]map[string]json.RawMessage) + res.DeviceKeys = make(map[string]map[string][]byte) res.Failures = make(map[string]interface{}) // make a map from domain to device keys domainToDeviceKeys := make(map[string]map[string][]string) @@ -254,7 +254,7 @@ func (a *KeyInternalAPI) QueryKeys(ctx context.Context, req *api.QueryKeysReques } if res.DeviceKeys[userID] == nil { - res.DeviceKeys[userID] = make(map[string]json.RawMessage) + res.DeviceKeys[userID] = make(map[string][]byte) } for _, dk := range deviceKeys { if len(dk.KeyJSON) == 0 { @@ -335,7 +335,7 @@ func (a *KeyInternalAPI) queryRemoteKeys( for result := range resultCh { for userID, nest := range result.DeviceKeys { - res.DeviceKeys[userID] = make(map[string]json.RawMessage) + res.DeviceKeys[userID] = make(map[string][]byte) for deviceID, deviceKey := range nest { keyJSON, err := json.Marshal(deviceKey) if err != nil { @@ -432,7 +432,7 @@ func (a *KeyInternalAPI) populateResponseWithDeviceKeysFromDatabase( return fmt.Errorf("DeviceKeysForUser %s returned no keys but wanted all keys, falling back to remote", userID) } if res.DeviceKeys[userID] == nil { - res.DeviceKeys[userID] = make(map[string]json.RawMessage) + res.DeviceKeys[userID] = make(map[string][]byte) } for _, key := range keys { diff --git a/keyserver/storage/interface.go b/keyserver/storage/interface.go index 0ec62f567..fc2aa078d 100644 --- a/keyserver/storage/interface.go +++ b/keyserver/storage/interface.go @@ -16,7 +16,6 @@ package storage import ( "context" - "encoding/json" "github.com/matrix-org/dendrite/keyserver/api" "github.com/matrix-org/gomatrixserverlib" @@ -25,7 +24,7 @@ import ( type Database interface { // ExistingOneTimeKeys returns a map of keyIDWithAlgorithm to key JSON for the given parameters. If no keys exist with this combination // of user/device/key/algorithm 4-uple then it is omitted from the map. Returns an error when failing to communicate with the database. - ExistingOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string]json.RawMessage, error) + ExistingOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string][]byte, error) // StoreOneTimeKeys persists the given one-time keys. StoreOneTimeKeys(ctx context.Context, keys api.OneTimeKeys) (*api.OneTimeKeysCount, error) diff --git a/keyserver/storage/postgres/one_time_keys_table.go b/keyserver/storage/postgres/one_time_keys_table.go index cc397ba84..5b7f68916 100644 --- a/keyserver/storage/postgres/one_time_keys_table.go +++ b/keyserver/storage/postgres/one_time_keys_table.go @@ -17,7 +17,6 @@ package postgres import ( "context" "database/sql" - "encoding/json" "time" "github.com/lib/pq" @@ -94,14 +93,14 @@ func NewPostgresOneTimeKeysTable(db *sql.DB) (tables.OneTimeKeys, error) { return s, nil } -func (s *oneTimeKeysStatements) SelectOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string]json.RawMessage, error) { +func (s *oneTimeKeysStatements) SelectOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string][]byte, error) { rows, err := s.selectKeysStmt.QueryContext(ctx, userID, deviceID, pq.Array(keyIDsWithAlgorithms)) if err != nil { return nil, err } defer internal.CloseAndLogIfError(ctx, rows, "selectKeysStmt: rows.close() failed") - result := make(map[string]json.RawMessage) + result := make(map[string][]byte) var ( algorithmWithID string keyJSONStr string @@ -110,7 +109,7 @@ func (s *oneTimeKeysStatements) SelectOneTimeKeys(ctx context.Context, userID, d if err := rows.Scan(&algorithmWithID, &keyJSONStr); err != nil { return nil, err } - result[algorithmWithID] = json.RawMessage(keyJSONStr) + result[algorithmWithID] = []byte(keyJSONStr) } return result, rows.Err() } @@ -172,7 +171,7 @@ func (s *oneTimeKeysStatements) InsertOneTimeKeys(ctx context.Context, txn *sql. func (s *oneTimeKeysStatements) SelectAndDeleteOneTimeKey( ctx context.Context, txn *sql.Tx, userID, deviceID, algorithm string, -) (map[string]json.RawMessage, error) { +) (map[string][]byte, error) { var keyID string var keyJSON string err := sqlutil.TxStmtContext(ctx, txn, s.selectKeyByAlgorithmStmt).QueryRowContext(ctx, userID, deviceID, algorithm).Scan(&keyID, &keyJSON) @@ -183,7 +182,7 @@ func (s *oneTimeKeysStatements) SelectAndDeleteOneTimeKey( return nil, err } _, err = sqlutil.TxStmtContext(ctx, txn, s.deleteOneTimeKeyStmt).ExecContext(ctx, userID, deviceID, algorithm, keyID) - return map[string]json.RawMessage{ - algorithm + ":" + keyID: json.RawMessage(keyJSON), + return map[string][]byte{ + algorithm + ":" + keyID: []byte(keyJSON), }, err } diff --git a/keyserver/storage/shared/storage.go b/keyserver/storage/shared/storage.go index de757f294..04734b982 100644 --- a/keyserver/storage/shared/storage.go +++ b/keyserver/storage/shared/storage.go @@ -17,7 +17,6 @@ package shared import ( "context" "database/sql" - "encoding/json" "github.com/matrix-org/dendrite/internal/sqlutil" "github.com/matrix-org/dendrite/keyserver/api" @@ -34,7 +33,7 @@ type Database struct { StaleDeviceListsTable tables.StaleDeviceLists } -func (d *Database) ExistingOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string]json.RawMessage, error) { +func (d *Database) ExistingOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string][]byte, error) { return d.OneTimeKeysTable.SelectOneTimeKeys(ctx, userID, deviceID, keyIDsWithAlgorithms) } diff --git a/keyserver/storage/sqlite3/one_time_keys_table.go b/keyserver/storage/sqlite3/one_time_keys_table.go index 185b88612..f048d155d 100644 --- a/keyserver/storage/sqlite3/one_time_keys_table.go +++ b/keyserver/storage/sqlite3/one_time_keys_table.go @@ -17,7 +17,6 @@ package sqlite3 import ( "context" "database/sql" - "encoding/json" "time" "github.com/matrix-org/dendrite/internal" @@ -93,7 +92,7 @@ func NewSqliteOneTimeKeysTable(db *sql.DB) (tables.OneTimeKeys, error) { return s, nil } -func (s *oneTimeKeysStatements) SelectOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string]json.RawMessage, error) { +func (s *oneTimeKeysStatements) SelectOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string][]byte, error) { rows, err := s.selectKeysStmt.QueryContext(ctx, userID, deviceID) if err != nil { return nil, err @@ -105,7 +104,7 @@ func (s *oneTimeKeysStatements) SelectOneTimeKeys(ctx context.Context, userID, d wantSet[ka] = true } - result := make(map[string]json.RawMessage) + result := make(map[string][]byte) for rows.Next() { var keyID string var algorithm string @@ -115,7 +114,7 @@ func (s *oneTimeKeysStatements) SelectOneTimeKeys(ctx context.Context, userID, d } keyIDWithAlgo := algorithm + ":" + keyID if wantSet[keyIDWithAlgo] { - result[keyIDWithAlgo] = json.RawMessage(keyJSONStr) + result[keyIDWithAlgo] = []byte(keyJSONStr) } } return result, rows.Err() @@ -180,7 +179,7 @@ func (s *oneTimeKeysStatements) InsertOneTimeKeys( func (s *oneTimeKeysStatements) SelectAndDeleteOneTimeKey( ctx context.Context, txn *sql.Tx, userID, deviceID, algorithm string, -) (map[string]json.RawMessage, error) { +) (map[string][]byte, error) { var keyID string var keyJSON string err := sqlutil.TxStmtContext(ctx, txn, s.selectKeyByAlgorithmStmt).QueryRowContext(ctx, userID, deviceID, algorithm).Scan(&keyID, &keyJSON) @@ -197,7 +196,7 @@ func (s *oneTimeKeysStatements) SelectAndDeleteOneTimeKey( if keyJSON == "" { return nil, nil } - return map[string]json.RawMessage{ - algorithm + ":" + keyID: json.RawMessage(keyJSON), + return map[string][]byte{ + algorithm + ":" + keyID: []byte(keyJSON), }, err } diff --git a/keyserver/storage/tables/interface.go b/keyserver/storage/tables/interface.go index b70c9bce6..f8177b10e 100644 --- a/keyserver/storage/tables/interface.go +++ b/keyserver/storage/tables/interface.go @@ -17,19 +17,18 @@ package tables import ( "context" "database/sql" - "encoding/json" "github.com/matrix-org/dendrite/keyserver/api" "github.com/matrix-org/gomatrixserverlib" ) type OneTimeKeys interface { - SelectOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string]json.RawMessage, error) + SelectOneTimeKeys(ctx context.Context, userID, deviceID string, keyIDsWithAlgorithms []string) (map[string][]byte, error) CountOneTimeKeys(ctx context.Context, userID, deviceID string) (*api.OneTimeKeysCount, error) InsertOneTimeKeys(ctx context.Context, txn *sql.Tx, keys api.OneTimeKeys) (*api.OneTimeKeysCount, error) // SelectAndDeleteOneTimeKey selects a single one time key matching the user/device/algorithm specified and returns the algo:key_id => JSON. // Returns an empty map if the key does not exist. - SelectAndDeleteOneTimeKey(ctx context.Context, txn *sql.Tx, userID, deviceID, algorithm string) (map[string]json.RawMessage, error) + SelectAndDeleteOneTimeKey(ctx context.Context, txn *sql.Tx, userID, deviceID, algorithm string) (map[string][]byte, error) } type DeviceKeys interface { diff --git a/roomserver/api/perform.go b/roomserver/api/perform.go index 51cbcb1ad..4ff7935b8 100644 --- a/roomserver/api/perform.go +++ b/roomserver/api/perform.go @@ -1,7 +1,6 @@ package api import ( - "encoding/json" "fmt" "net/http" @@ -54,7 +53,7 @@ func (p *PerformError) JSONResponse() util.JSONResponse { return util.JSONResponse{ Code: p.RemoteCode, // TODO: Should we assert this is in fact JSON? E.g gjson parse? - JSON: json.RawMessage(p.Msg), + JSON: []byte(p.Msg), } default: return util.ErrorResponse(p) diff --git a/roomserver/internal/alias.go b/roomserver/internal/alias.go index f15881d75..bd8daa672 100644 --- a/roomserver/internal/alias.go +++ b/roomserver/internal/alias.go @@ -204,7 +204,7 @@ func (r *RoomserverInternalAPI) sendUpdatedAliasesEvent( if err != nil { return err } - err = builder.SetContent(json.RawMessage(rawContent)) + err = builder.SetContent([]byte(rawContent)) if err != nil { return err } diff --git a/roomserver/roomserver_test.go b/roomserver/roomserver_test.go index 5c9540071..7a563de58 100644 --- a/roomserver/roomserver_test.go +++ b/roomserver/roomserver_test.go @@ -49,7 +49,7 @@ func (p *dummyProducer) SendMessage(msg *sarama.ProducerMessage) (partition int3 return 0, 0, nil } be := msg.Value.(sarama.ByteEncoder) - b := json.RawMessage(be) + b := []byte(be) fmt.Println("SENDING >>>>>>>> ", string(b)) var out api.OutputEvent err = json.Unmarshal(b, &out) @@ -143,7 +143,7 @@ func mustCreateEvents(t *testing.T, roomVer gomatrixserverlib.RoomVersion, event return } -func mustLoadRawEvents(t *testing.T, ver gomatrixserverlib.RoomVersion, events []json.RawMessage) []*gomatrixserverlib.HeaderedEvent { +func mustLoadRawEvents(t *testing.T, ver gomatrixserverlib.RoomVersion, events [][]byte) []*gomatrixserverlib.HeaderedEvent { t.Helper() hs := make([]*gomatrixserverlib.HeaderedEvent, len(events)) for i := range events { @@ -186,7 +186,7 @@ func mustCreateRoomserverAPI(t *testing.T) (api.RoomserverInternalAPI, *dummyPro ), dp } -func mustSendEvents(t *testing.T, ver gomatrixserverlib.RoomVersion, events []json.RawMessage) (api.RoomserverInternalAPI, *dummyProducer, []*gomatrixserverlib.HeaderedEvent) { +func mustSendEvents(t *testing.T, ver gomatrixserverlib.RoomVersion, events [][]byte) (api.RoomserverInternalAPI, *dummyProducer, []*gomatrixserverlib.HeaderedEvent) { t.Helper() rsAPI, dp := mustCreateRoomserverAPI(t) hevents := mustLoadRawEvents(t, ver, events) @@ -197,7 +197,7 @@ func mustSendEvents(t *testing.T, ver gomatrixserverlib.RoomVersion, events []js } func TestOutputRedactedEvent(t *testing.T) { - redactionEvents := []json.RawMessage{ + redactionEvents := [][]byte{ // create event []byte(`{"auth_events":[],"content":{"creator":"@userid:kaer.morhen"},"depth":0,"event_id":"$N4us6vqqq3RjvpKd:kaer.morhen","hashes":{"sha256":"WTdrCn/YsiounXcJPsLP8xT0ZjHiO5Ov0NvXYmK2onE"},"origin":"kaer.morhen","origin_server_ts":0,"prev_events":[],"prev_state":[],"room_id":"!roomid:kaer.morhen","sender":"@userid:kaer.morhen","signatures":{"kaer.morhen":{"ed25519:auto":"9+5JcpaN5b5KlHYHGp6r+GoNDH98lbfzGYwjfxensa5C5D/bDACaYnMDLnhwsHOE5nxgI+jT/GV271pz6PMSBQ"}},"state_key":"","type":"m.room.create"}`), // join event diff --git a/roomserver/storage/sqlite3/state_block_table.go b/roomserver/storage/sqlite3/state_block_table.go index cfb2a49e5..c224a08a6 100644 --- a/roomserver/storage/sqlite3/state_block_table.go +++ b/roomserver/storage/sqlite3/state_block_table.go @@ -123,7 +123,7 @@ func (s *stateBlockStatements) BulkSelectStateBlockEntries( i := 0 for ; rows.Next(); i++ { var stateBlockNID types.StateBlockNID - var result json.RawMessage + var result []byte if err = rows.Scan(&stateBlockNID, &result); err != nil { return nil, err } diff --git a/syncapi/storage/storage_test.go b/syncapi/storage/storage_test.go index 864322001..e5eed0b36 100644 --- a/syncapi/storage/storage_test.go +++ b/syncapi/storage/storage_test.go @@ -557,7 +557,7 @@ func TestSendToDeviceBehaviour(t *testing.T) { streamPos, err := db.StoreNewSendForDeviceMessage(ctx, "alice", "one", gomatrixserverlib.SendToDeviceEvent{ Sender: "bob", Type: "m.type", - Content: json.RawMessage("{}"), + Content: []byte("{}"), }) if err != nil { t.Fatal(err) diff --git a/syncapi/types/types.go b/syncapi/types/types.go index 49fa1a166..a097285de 100644 --- a/syncapi/types/types.go +++ b/syncapi/types/types.go @@ -351,9 +351,9 @@ func NewStreamTokenFromString(tok string) (token StreamingToken, err error) { // PrevEventRef represents a reference to a previous event in a state event upgrade type PrevEventRef struct { - PrevContent json.RawMessage `json:"prev_content"` - ReplacesState string `json:"replaces_state"` - PrevSender string `json:"prev_sender"` + PrevContent []byte `json:"prev_content"` + ReplacesState string `json:"replaces_state"` + PrevSender string `json:"prev_sender"` } // Response represents a /sync API response. See https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync @@ -445,14 +445,14 @@ func NewJoinResponse() *JoinResponse { // InviteResponse represents a /sync response for a room which is under the 'invite' key. type InviteResponse struct { InviteState struct { - Events []json.RawMessage `json:"events"` + Events [][]byte `json:"events"` } `json:"invite_state"` } // NewInviteResponse creates an empty response with initialised arrays. func NewInviteResponse(event *gomatrixserverlib.HeaderedEvent) *InviteResponse { res := InviteResponse{} - res.InviteState.Events = []json.RawMessage{} + res.InviteState.Events = [][]byte{} // First see if there's invite_room_state in the unsigned key of the invite. // If there is then unmarshal it into the response. This will contain the diff --git a/userapi/api/api.go b/userapi/api/api.go index 407350123..30184e411 100644 --- a/userapi/api/api.go +++ b/userapi/api/api.go @@ -16,7 +16,6 @@ package api import ( "context" - "encoding/json" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/gomatrixserverlib" @@ -44,10 +43,10 @@ type UserInternalAPI interface { // InputAccountDataRequest is the request for InputAccountData type InputAccountDataRequest struct { - UserID string // required: the user to set account data for - RoomID string // optional: the room to associate the account data with - DataType string // required: the data type of the data - AccountData json.RawMessage // required: the message content + UserID string // required: the user to set account data for + RoomID string // optional: the room to associate the account data with + DataType string // required: the data type of the data + AccountData []byte // required: the message content } // InputAccountDataResponse is the response for InputAccountData @@ -113,8 +112,8 @@ type QueryAccountDataRequest struct { // QueryAccountDataResponse is the response for QueryAccountData type QueryAccountDataResponse struct { - GlobalAccountData map[string]json.RawMessage // type -> data - RoomAccountData map[string]map[string]json.RawMessage // room -> type -> data + GlobalAccountData map[string][]byte // type -> data + RoomAccountData map[string]map[string][]byte // room -> type -> data } // QueryDevicesRequest is the request for QueryDevices diff --git a/userapi/internal/api.go b/userapi/internal/api.go index 21933c1c4..2988fceea 100644 --- a/userapi/internal/api.go +++ b/userapi/internal/api.go @@ -17,7 +17,6 @@ package internal import ( "context" "database/sql" - "encoding/json" "errors" "fmt" @@ -315,17 +314,17 @@ func (a *UserInternalAPI) QueryAccountData(ctx context.Context, req *api.QueryAc return fmt.Errorf("cannot query account data of remote users: got %s want %s", domain, a.ServerName) } if req.DataType != "" { - var data json.RawMessage + var data []byte data, err = a.AccountDB.GetAccountDataByType(ctx, local, req.RoomID, req.DataType) if err != nil { return err } - res.RoomAccountData = make(map[string]map[string]json.RawMessage) - res.GlobalAccountData = make(map[string]json.RawMessage) + res.RoomAccountData = make(map[string]map[string][]byte) + res.GlobalAccountData = make(map[string][]byte) if data != nil { if req.RoomID != "" { if _, ok := res.RoomAccountData[req.RoomID]; !ok { - res.RoomAccountData[req.RoomID] = make(map[string]json.RawMessage) + res.RoomAccountData[req.RoomID] = make(map[string][]byte) } res.RoomAccountData[req.RoomID][req.DataType] = data } else { diff --git a/userapi/storage/accounts/interface.go b/userapi/storage/accounts/interface.go index 5aa61b909..e2cf47e8d 100644 --- a/userapi/storage/accounts/interface.go +++ b/userapi/storage/accounts/interface.go @@ -16,7 +16,6 @@ package accounts import ( "context" - "encoding/json" "errors" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" @@ -36,13 +35,13 @@ type Database interface { // account already exists, it will return nil, ErrUserExists. CreateAccount(ctx context.Context, localpart, plaintextPassword, appserviceID string) (*api.Account, error) CreateGuestAccount(ctx context.Context) (*api.Account, error) - SaveAccountData(ctx context.Context, localpart, roomID, dataType string, content json.RawMessage) error - GetAccountData(ctx context.Context, localpart string) (global map[string]json.RawMessage, rooms map[string]map[string]json.RawMessage, err error) + SaveAccountData(ctx context.Context, localpart, roomID, dataType string, content []byte) error + GetAccountData(ctx context.Context, localpart string) (global map[string][]byte, rooms map[string]map[string][]byte, err error) // GetAccountDataByType returns account data matching a given // localpart, room ID and type. // If no account data could be found, returns nil // Returns an error if there was an issue with the retrieval - GetAccountDataByType(ctx context.Context, localpart, roomID, dataType string) (data json.RawMessage, err error) + GetAccountDataByType(ctx context.Context, localpart, roomID, dataType string) (data []byte, err error) GetNewNumericLocalpart(ctx context.Context) (int64, error) SaveThreePIDAssociation(ctx context.Context, threepid, localpart, medium string) (err error) RemoveThreePIDAssociation(ctx context.Context, threepid string, medium string) (err error) diff --git a/userapi/storage/accounts/postgres/account_data_table.go b/userapi/storage/accounts/postgres/account_data_table.go index 09eb26113..5444be4bd 100644 --- a/userapi/storage/accounts/postgres/account_data_table.go +++ b/userapi/storage/accounts/postgres/account_data_table.go @@ -17,7 +17,6 @@ package postgres import ( "context" "database/sql" - "encoding/json" "github.com/matrix-org/dendrite/internal" "github.com/matrix-org/dendrite/internal/sqlutil" @@ -74,7 +73,7 @@ func (s *accountDataStatements) prepare(db *sql.DB) (err error) { } func (s *accountDataStatements) insertAccountData( - ctx context.Context, txn *sql.Tx, localpart, roomID, dataType string, content json.RawMessage, + ctx context.Context, txn *sql.Tx, localpart, roomID, dataType string, content []byte, ) (err error) { stmt := sqlutil.TxStmt(txn, s.insertAccountDataStmt) _, err = stmt.ExecContext(ctx, localpart, roomID, dataType, content) @@ -84,8 +83,8 @@ func (s *accountDataStatements) insertAccountData( func (s *accountDataStatements) selectAccountData( ctx context.Context, localpart string, ) ( - /* global */ map[string]json.RawMessage, - /* rooms */ map[string]map[string]json.RawMessage, + /* global */ map[string][]byte, + /* rooms */ map[string]map[string][]byte, error, ) { rows, err := s.selectAccountDataStmt.QueryContext(ctx, localpart) @@ -94,8 +93,8 @@ func (s *accountDataStatements) selectAccountData( } defer internal.CloseAndLogIfError(ctx, rows, "selectAccountData: rows.close() failed") - global := map[string]json.RawMessage{} - rooms := map[string]map[string]json.RawMessage{} + global := map[string][]byte{} + rooms := map[string]map[string][]byte{} for rows.Next() { var roomID string @@ -108,7 +107,7 @@ func (s *accountDataStatements) selectAccountData( if roomID != "" { if _, ok := rooms[roomID]; !ok { - rooms[roomID] = map[string]json.RawMessage{} + rooms[roomID] = map[string][]byte{} } rooms[roomID][dataType] = content } else { @@ -121,7 +120,7 @@ func (s *accountDataStatements) selectAccountData( func (s *accountDataStatements) selectAccountDataByType( ctx context.Context, localpart, roomID, dataType string, -) (data json.RawMessage, err error) { +) (data []byte, err error) { var bytes []byte stmt := s.selectAccountDataByTypeStmt if err = stmt.QueryRowContext(ctx, localpart, roomID, dataType).Scan(&bytes); err != nil { @@ -130,6 +129,6 @@ func (s *accountDataStatements) selectAccountDataByType( } return } - data = json.RawMessage(bytes) + data = []byte(bytes) return } diff --git a/userapi/storage/accounts/postgres/storage.go b/userapi/storage/accounts/postgres/storage.go index c5e74ed15..6946832a5 100644 --- a/userapi/storage/accounts/postgres/storage.go +++ b/userapi/storage/accounts/postgres/storage.go @@ -17,7 +17,6 @@ package postgres import ( "context" "database/sql" - "encoding/json" "errors" "strconv" "time" @@ -198,7 +197,7 @@ func (d *Database) createAccount( if err = d.profiles.insertProfile(ctx, txn, localpart); err != nil { return nil, err } - if err = d.accountDatas.insertAccountData(ctx, txn, localpart, "", "m.push_rules", json.RawMessage(`{ + if err = d.accountDatas.insertAccountData(ctx, txn, localpart, "", "m.push_rules", []byte(`{ "global": { "content": [], "override": [], @@ -218,7 +217,7 @@ func (d *Database) createAccount( // update the corresponding row with the new content // Returns a SQL error if there was an issue with the insertion/update func (d *Database) SaveAccountData( - ctx context.Context, localpart, roomID, dataType string, content json.RawMessage, + ctx context.Context, localpart, roomID, dataType string, content []byte, ) error { return sqlutil.WithTransaction(d.db, func(txn *sql.Tx) error { return d.accountDatas.insertAccountData(ctx, txn, localpart, roomID, dataType, content) @@ -229,8 +228,8 @@ func (d *Database) SaveAccountData( // If no account data could be found, returns an empty arrays // Returns an error if there was an issue with the retrieval func (d *Database) GetAccountData(ctx context.Context, localpart string) ( - global map[string]json.RawMessage, - rooms map[string]map[string]json.RawMessage, + global map[string][]byte, + rooms map[string]map[string][]byte, err error, ) { return d.accountDatas.selectAccountData(ctx, localpart) @@ -242,7 +241,7 @@ func (d *Database) GetAccountData(ctx context.Context, localpart string) ( // Returns an error if there was an issue with the retrieval func (d *Database) GetAccountDataByType( ctx context.Context, localpart, roomID, dataType string, -) (data json.RawMessage, err error) { +) (data []byte, err error) { return d.accountDatas.selectAccountDataByType( ctx, localpart, roomID, dataType, ) diff --git a/userapi/storage/accounts/sqlite3/account_data_table.go b/userapi/storage/accounts/sqlite3/account_data_table.go index 870a37065..1475627aa 100644 --- a/userapi/storage/accounts/sqlite3/account_data_table.go +++ b/userapi/storage/accounts/sqlite3/account_data_table.go @@ -17,7 +17,6 @@ package sqlite3 import ( "context" "database/sql" - "encoding/json" "github.com/matrix-org/dendrite/internal/sqlutil" ) @@ -75,7 +74,7 @@ func (s *accountDataStatements) prepare(db *sql.DB) (err error) { } func (s *accountDataStatements) insertAccountData( - ctx context.Context, txn *sql.Tx, localpart, roomID, dataType string, content json.RawMessage, + ctx context.Context, txn *sql.Tx, localpart, roomID, dataType string, content []byte, ) error { _, err := sqlutil.TxStmt(txn, s.insertAccountDataStmt).ExecContext(ctx, localpart, roomID, dataType, content) return err @@ -84,8 +83,8 @@ func (s *accountDataStatements) insertAccountData( func (s *accountDataStatements) selectAccountData( ctx context.Context, localpart string, ) ( - /* global */ map[string]json.RawMessage, - /* rooms */ map[string]map[string]json.RawMessage, + /* global */ map[string][]byte, + /* rooms */ map[string]map[string][]byte, error, ) { rows, err := s.selectAccountDataStmt.QueryContext(ctx, localpart) @@ -93,8 +92,8 @@ func (s *accountDataStatements) selectAccountData( return nil, nil, err } - global := map[string]json.RawMessage{} - rooms := map[string]map[string]json.RawMessage{} + global := map[string][]byte{} + rooms := map[string]map[string][]byte{} for rows.Next() { var roomID string @@ -107,7 +106,7 @@ func (s *accountDataStatements) selectAccountData( if roomID != "" { if _, ok := rooms[roomID]; !ok { - rooms[roomID] = map[string]json.RawMessage{} + rooms[roomID] = map[string][]byte{} } rooms[roomID][dataType] = content } else { @@ -120,7 +119,7 @@ func (s *accountDataStatements) selectAccountData( func (s *accountDataStatements) selectAccountDataByType( ctx context.Context, localpart, roomID, dataType string, -) (data json.RawMessage, err error) { +) (data []byte, err error) { var bytes []byte stmt := s.selectAccountDataByTypeStmt if err = stmt.QueryRowContext(ctx, localpart, roomID, dataType).Scan(&bytes); err != nil { @@ -129,6 +128,6 @@ func (s *accountDataStatements) selectAccountDataByType( } return } - data = json.RawMessage(bytes) + data = []byte(bytes) return } diff --git a/userapi/storage/accounts/sqlite3/storage.go b/userapi/storage/accounts/sqlite3/storage.go index c0f7118cb..9b8f19e41 100644 --- a/userapi/storage/accounts/sqlite3/storage.go +++ b/userapi/storage/accounts/sqlite3/storage.go @@ -17,7 +17,6 @@ package sqlite3 import ( "context" "database/sql" - "encoding/json" "errors" "strconv" "sync" @@ -228,7 +227,7 @@ func (d *Database) createAccount( if err = d.profiles.insertProfile(ctx, txn, localpart); err != nil { return nil, err } - if err = d.accountDatas.insertAccountData(ctx, txn, localpart, "", "m.push_rules", json.RawMessage(`{ + if err = d.accountDatas.insertAccountData(ctx, txn, localpart, "", "m.push_rules", []byte(`{ "global": { "content": [], "override": [], @@ -248,7 +247,7 @@ func (d *Database) createAccount( // update the corresponding row with the new content // Returns a SQL error if there was an issue with the insertion/update func (d *Database) SaveAccountData( - ctx context.Context, localpart, roomID, dataType string, content json.RawMessage, + ctx context.Context, localpart, roomID, dataType string, content []byte, ) error { d.accountDatasMu.Lock() defer d.accountDatasMu.Unlock() @@ -261,8 +260,8 @@ func (d *Database) SaveAccountData( // If no account data could be found, returns an empty arrays // Returns an error if there was an issue with the retrieval func (d *Database) GetAccountData(ctx context.Context, localpart string) ( - global map[string]json.RawMessage, - rooms map[string]map[string]json.RawMessage, + global map[string][]byte, + rooms map[string]map[string][]byte, err error, ) { return d.accountDatas.selectAccountData(ctx, localpart) @@ -274,7 +273,7 @@ func (d *Database) GetAccountData(ctx context.Context, localpart string) ( // Returns an error if there was an issue with the retrieval func (d *Database) GetAccountDataByType( ctx context.Context, localpart, roomID, dataType string, -) (data json.RawMessage, err error) { +) (data []byte, err error) { return d.accountDatas.selectAccountDataByType( ctx, localpart, roomID, dataType, )